#include cleanup in Visual Studio

Mryam Girmay

We are gradually rolling out this feature in Visual Studio 2022 version 17.8 to monitor some data. This means that not everyone will have access to the feature immediately after its release.

We are thrilled to announce the return of #include cleanup, a tool that helps you maintain clean code, now available in Visual Studio 17.8 Preview 1. To start using this feature, make sure to update to the latest version of Visual Studio Preview.

#include cleanup 

Visual Studio now offers #include cleanup, a feature that improves the quality of your code by generating suggestions to remove unused headers and add direct headers. Our suggested workflow is to first go through the direct include suggestions to add direct headers where indirect headers are used, followed by removing the unused includes.

Remove unused #include statements 

This feature provides suggestions to remove unused headers from your files, enhancing code cleanliness. When an unused include is detected, it is visually dimmed by default. By hovering over the dimmed include, a quick action (indicated by three dots in the default view) prompt will appear, notifying you about the unused include in the file. You can click on the light bulb to remove the unused include or all unused includes. This makes it easier to clean up your code and ensures that you keep only the necessary includes to keep your code well-organized.

Gif showing remove unused includes.
Gif showing remove unused includes.

Add transitively used #include statements 

In Visual Studio, there is an existing feature that alerts users when an include is used but not added to the file. This is indicated by a squiggle and suggests adding the required include. Currently, we have added a new feature that provides suggestions for adding direct includes when your file has indirect dependencies. Including indirect dependencies can result in longer compilation times. However, with the help of direct include suggestions, you can optimize compilation time by including only the essential direct dependencies.

In instances where the direct include for certain content is missing, a quick action (indicated by three dots in the default view) will appear. Hovering over it will inform you that content from that transitive include is being used. Then, you have the option to either add the direct include individually or add all transitively used includes. By choosing to include all transitively used includes, all the direct headers will be automatically added wherever indirect headers are used in the file. After including the direct dependencies, it is crucial to remove any unused includes, retaining only those that are necessary.

Gif showing add direct include suggestion.
Gif showing add direct include suggestion.

To quickly perform code cleanup, you can configure code cleanup by adding “Add transitively used and remove unused #include statements (C++)”. Once this setup is complete, you’ll have the convenience of adding all transitively used includes and removing all unused includes with just a single click on the broom icon. This streamlines the process and ensures that your code remains clean.

Gif displaying Configure Code Cleanup
Gif displaying Configure Code Cleanup.

By default, #include cleanup is disabled, but you can enable it by navigating to Tools > Options > Text Editor > C/C++ > IntelliSense and selecting “Enable #include cleanup.” Once enabled, you have the flexibility to adjust the settings and configure different levels to meet your specific needs and preferences.

Image displaying Code cleanup setting.
Image displaying code cleanup setting.

Customization Options

You have the flexibility to customize how the #include cleanup generates suggestions, allowing it to seamlessly adapt and integrate with intricate and extensive codebases. By making these changes or adjustments, you can ensure that the process better aligns with the specific needs and complexities of your project, resulting in a more efficient and effective code cleanup. In the EditorConfig (EditorConfig settings), you can add a single header, and if you want to include multiple headers, you should separate them using commas.

Exclude Files 

To exclude specific includes from #include cleanup suggestions, you can utilize EditorConfig. This allows you to categorize and define which files should not be considered for suggestions, providing greater control over the suggestions generated by #include cleanup. Examples of excluding single and multiple files (exclude vcruntime.h and vcruntime_string.h from cleanup suggestions):

cpp_include_cleanup_excluded_files = vcruntime.h
cpp_include_cleanup_excluded_files = vcruntime.h,vcruntime_string.h
Required Files

In cases where headers require other headers, and you don’t want suggestions generated, you can specify the dependencies in the EditorConfig. This ensures that required files won’t be marked as unused. Examples of single and multiple required files (atlwin.h requires altbase.h and atlcom.h requires altbase.h):

cpp_include_cleanup_required_files = atlwin.h:altbase.h
cpp_include_cleanup_required_files = atlwin.h:altbase.h,atlcom.h:altbase.h
Files Replacement

This feature also supports the remapping of facade headers. If a file is intended to represent a different file, you can redirect the usage of the first file to the usage of the second file in EditorConfig. Examples of single and multiple replaced files (replace stdio.h by cstdio, and replace stdint.h by cstdint):

cpp_include_cleanup_replacement_files = stdio.h:cstdio
cpp_include_cleanup_replacement_files = stdio.h:cstdio,stdint.h:cstdint
Alternate Files 

In certain situations, you may have alternative options for including a file, such as facade files. When the usage of one file can be considered as an alternative to the usage of another file, you can specify this relationship in EditorConfig. By doing so, you can prevent #include cleanup from generating suggestions for alternate matches. Examples of single and multiple alternate files (windows.h is an alternate for minwindef.h and windows.h is an alternate for winerror.h):

cpp_include_cleanup_alternate_files = windows.h:minwindef.h
cpp_include_cleanup_alternate_files = windows.h:minwindef.h,windows.h:winerror.h

Send us your feedback! 

Explore #Include Cleanup by downloading the latest version of Visual Studio Preview. We genuinely value your feedback as it plays a crucial role in shaping our development process. Please share your thoughts in the comments below, on Developer Community, or reach out to us on Twitter (@VisualC) or via email at visualcpp@microsoft.com. Your input is highly appreciated! 

 

29 comments

Comments are closed. Login to edit/delete your existing comments

  • Johannes Holzhäuer 0

    This looks really promising. I have found two “bugs” though.
    1. It will not honor forward declarations.
    2. It will not honor include paths and put the header relative to the current cpp file

    Would be nice if that will be fixed

    edit: after trying it out more I get even more errors. sometimes includes are put somewhere in the file or it includes a cpp file or it removes lines from cpp file. seems not to be ready yet.

    • Roger B 0

      Do you have Developer Community feedback links for these? I can confirm that the forward decls are indeed not honored and would like to upvote the feedback if so etc.

      • Raul PerezMicrosoft employee 0

        Thank you both for trying out the feature and providing feedback. If you haven’t please go ahead and share your feedback via Developer Community as that helps us track and prioritize issues.

        We’re aware of the forward declaration issues and are looking into it. For the other 2 I would like to follow up as both of those scenarios should be working right now so we’d really like to understand what’s going on in your particular scenario so that we can improve it. For example, to determine the include path the code is following the core guidelines so it’s finding the “shortest” path based on include paths and determining if it’s local or not. It only uses relative paths as the last resorts if it couldn’t find a valid path so it’s possible that the code base in setup in a way that we’re not properly pulling in those paths and we’d definitely love to fix that.

  • Roger B 0

    Quite pleased to see something like “include what you use” built into VS itself! With the myriad of ways headers can be abused I hope that investment in this tool continues!

  • deadpin 0

    Seems rather promising! Like what another poster has mentioned it will take some time to build up trust that the “include what you use” semantic isn’t somehow being invalidated with this feature. I’ll definitely be using this from now on though. Awesome work getting it to this point.

    Curious though. Will this be runnable “all up”? I.e. Make it a part of Build Insights in some way so you can run it over the entire project and get back a report or .diff/.patch file that you can apply in a bulk fashion?

    Edit: Ok, yeah, I’m also seeing it be really weird, but only sometimes, where it includes .c/.cc files. Does this have some form of logging that says “because of type X, header Foo is being included”? Without that, I’m not sure I have any hope of filing a good bug report on what it’s doing…

  • Mason Boswell 1

    Can this be used with just the command line tools?

    • anonymous 0

      this comment has been deleted.

    • Wim L 0

      I’m also interested in a command line tool option.
      So it can be automated in CI, or at least give a warning.

      • Mryam GirmayMicrosoft employee 0

        Hello,
        No, it doesn’t currently support the use of command line tools. However, we appreciate you raising the question and showing interest in different usage scenarios. I have created Command line tool option for #include cleanup, please upvote it.

  • Luc Nanquette 0

    Really nice to see this being implemented.
    But it’s still a bit buggy. SFML includes are marked as not needed, even though they are used in all my files 😉

    Edit:
    Ok, so it seems that only the overhead includes like SFML/Graphics.hpp or SFML/Window.hpp are not recognized.
    It wants me to include all headers one by one like SFML/Graphics/RenderTarget.hpp or SFML/Window/Window.hpp, and so on ….

    • Raul PerezMicrosoft employee 0

      Hi Luc,

      Thanks for trying the feature out and the feedback. If I’m understanding correctly SML/Window.hpp is using a facade pattern. If your preference is to use the facade vs the individual files you can add an editorconfig file and add this setting where you’d replace the entries for the ones in your facade header:

      cpp_include_cleanup_alternate_files = SFML/Window.hpp:SFML/Header1.h, SFML/Window.hpp:SFML/Header2.h
  • Tom Kirby-Green 0

    Love this. Transitive and redundant includes are a massive bother and goodness knows, for most of us, it’s going to be a long, long time until C++ Modules becomes part of our day to day experience, so I really appreciate the investment here when it comes to improving the existing (and massively dominant) infrastructure. Kudos to all involved <3.

  • Joan Marce i Igual 0

    Will this support Include What You Use directives?
    Like how you can make a header that exports other headers and so.

    • Mryam GirmayMicrosoft employee 0

      Hi Joan.
      Thank you for your feedback! Currently, the feature does not support Include What You Use directives. We are continuously working on improving the tool, and your input is valuable to us. Feel free to share your suggestions in Developer Community

    • Raul PerezMicrosoft employee 0

      Hi Joan,

      I’ll reiterate Mryam’s note about sharing your suggestions in Developer Community. If you haven’t had a chance to do so yet we were looking at this and two of us had two different interpretations of your comment so wanted to ask a clarifying question. Are you asking about in source suppressions, in source suppressions using the exact same syntax as Include What You Use or just having the ability to customize the tool? If it’s the later it sounds like you’re taking about a facade like header (such as Windows.h) and if so you can setup an editorconfig file with this setting:

      cpp_include_cleanup_alternate_files = windows.h:minwindef.h,windows.h:winerror.h

      And replace the file names with the headers you’re want mapped.

  • Krzysztof Kawa 1

    Would it be possible to add some way for a library to specify the replacement and alternate files? Let’s say my project uses stl, boost and Qt, which are all enormous in size and number of files/classes. I can’t imagine specifying hundreds (if not thousands) of rules manually separately for every project.

    Also would it be possible that the Microsoft provided libraries (like stl, atl or winapi headers for example) had those rules applied by default? It’s not practical to put the burden of producing those rules on the users, especially given that some of the dependencies are considered internal and could change from version to version.

    • Raul PerezMicrosoft employee 0

      Hi Krysztof,

      Thanks for the feedback. Having a way for libraries themselves to specify settings is something on our roadmap but I don’t have any more immediate news on that. We are however adding some of the bigger more populate libraries to the default lists. In order to help us prioritize please open a suggestion for libraries that are important to you on Developer Community which other folks can upvote.

  • Tony Riviere 2

    It would be nice to have an option to use either “” or for includes based on custom rules.
    Typically, in my code base I use “” for my own includes and for third-party includes (including the std, Qt, and other headers which have a certain pattern in their location path). This allows me to set up different level of warnings for “external headers” which are identified by .

    • Raul PerezMicrosoft employee 0

      Hi Tony,

      Thanks for the feedback. Could you please open a suggestion ticket with that request in Developer Community? We’re certainly interested in what other kind of customizations would be useful aside from the ones already included.

  • A A 0

    Great feature and a great article, but do the images in this blog post really have to be 5 MB in size (total)? Could have used JPEG with no problems, and saved my mobile Internet traffic.

Feedback usabilla icon