@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
5959 : ClangTidyCheck(Name, Context),
6060 IgnoreHeaders (
6161 utils::options::parseStringList (Options.get(" IgnoreHeaders" , " " ))),
62- DeduplicateFindings(Options.get(" DeduplicateFindings" , true )) {
62+ DeduplicateFindings(Options.get(" DeduplicateFindings" , true )),
63+ UnusedIncludes(Options.get(" UnusedIncludes" , true )),
64+ MissingIncludes(Options.get(" MissingIncludes" , true )) {
6365 for (const auto &Header : IgnoreHeaders) {
6466 if (!llvm::Regex{Header}.isValid ())
6567 configurationDiag (" Invalid ignore headers regex '%0'" ) << Header;
@@ -68,12 +70,19 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
6870 HeaderSuffix += " $" ;
6971 IgnoreHeadersRegex.emplace_back (HeaderSuffix);
7072 }
73+
74+ if (UnusedIncludes == false && MissingIncludes == false )
75+ this ->configurationDiag (" The check 'misc-include-cleaner' will not "
76+ " perform any analysis because 'UnusedIncludes' and "
77+ " 'MissingIncludes' are both false." );
7178}
7279
7380void IncludeCleanerCheck::storeOptions (ClangTidyOptions::OptionMap &Opts) {
7481 Options.store (Opts, " IgnoreHeaders" ,
7582 utils::options::serializeStringList (IgnoreHeaders));
7683 Options.store (Opts, " DeduplicateFindings" , DeduplicateFindings);
84+ Options.store (Opts, " UnusedIncludes" , UnusedIncludes);
85+ Options.store (Opts, " MissingIncludes" , MissingIncludes);
7786}
7887
7988bool IncludeCleanerCheck::isLanguageVersionSupported (
@@ -200,39 +209,43 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
200209 if (!FileStyle)
201210 FileStyle = format::getLLVMStyle ();
202211
203- for (const auto *Inc : Unused) {
204- diag (Inc->HashLocation , " included header %0 is not used directly" )
205- << llvm::sys::path::filename (Inc->Spelled ,
206- llvm::sys::path::Style::posix)
207- << FixItHint::CreateRemoval (CharSourceRange::getCharRange (
208- SM->translateLineCol (SM->getMainFileID (), Inc->Line , 1 ),
209- SM->translateLineCol (SM->getMainFileID (), Inc->Line + 1 , 1 )));
212+ if (UnusedIncludes) {
213+ for (const auto *Inc : Unused) {
214+ diag (Inc->HashLocation , " included header %0 is not used directly" )
215+ << llvm::sys::path::filename (Inc->Spelled ,
216+ llvm::sys::path::Style::posix)
217+ << FixItHint::CreateRemoval (CharSourceRange::getCharRange (
218+ SM->translateLineCol (SM->getMainFileID (), Inc->Line , 1 ),
219+ SM->translateLineCol (SM->getMainFileID (), Inc->Line + 1 , 1 )));
220+ }
210221 }
211222
212- tooling::HeaderIncludes HeaderIncludes (getCurrentMainFile (), Code,
213- FileStyle->IncludeStyle );
214- // Deduplicate insertions when running in bulk fix mode.
215- llvm::StringSet<> InsertedHeaders{};
216- for (const auto &Inc : Missing) {
217- std::string Spelling = include_cleaner::spellHeader (
218- {Inc.Missing , PP->getHeaderSearchInfo (), MainFile});
219- bool Angled = llvm::StringRef{Spelling}.starts_with (" <" );
220- // We might suggest insertion of an existing include in edge cases, e.g.,
221- // include is present in a PP-disabled region, or spelling of the header
222- // turns out to be the same as one of the unresolved includes in the
223- // main file.
224- if (auto Replacement =
225- HeaderIncludes.insert (llvm::StringRef{Spelling}.trim (" \" <>" ),
226- Angled, tooling::IncludeDirective::Include)) {
227- DiagnosticBuilder DB =
228- diag (SM->getSpellingLoc (Inc.SymRef .RefLocation ),
229- " no header providing \" %0\" is directly included" )
230- << Inc.SymRef .Target .name ();
231- if (areDiagsSelfContained () ||
232- InsertedHeaders.insert (Replacement->getReplacementText ()).second ) {
233- DB << FixItHint::CreateInsertion (
234- SM->getComposedLoc (SM->getMainFileID (), Replacement->getOffset ()),
235- Replacement->getReplacementText ());
223+ if (MissingIncludes) {
224+ tooling::HeaderIncludes HeaderIncludes (getCurrentMainFile (), Code,
225+ FileStyle->IncludeStyle );
226+ // Deduplicate insertions when running in bulk fix mode.
227+ llvm::StringSet<> InsertedHeaders{};
228+ for (const auto &Inc : Missing) {
229+ std::string Spelling = include_cleaner::spellHeader (
230+ {Inc.Missing , PP->getHeaderSearchInfo (), MainFile});
231+ bool Angled = llvm::StringRef{Spelling}.starts_with (" <" );
232+ // We might suggest insertion of an existing include in edge cases, e.g.,
233+ // include is present in a PP-disabled region, or spelling of the header
234+ // turns out to be the same as one of the unresolved includes in the
235+ // main file.
236+ if (auto Replacement = HeaderIncludes.insert (
237+ llvm::StringRef{Spelling}.trim (" \" <>" ), Angled,
238+ tooling::IncludeDirective::Include)) {
239+ DiagnosticBuilder DB =
240+ diag (SM->getSpellingLoc (Inc.SymRef .RefLocation ),
241+ " no header providing \" %0\" is directly included" )
242+ << Inc.SymRef .Target .name ();
243+ if (areDiagsSelfContained () ||
244+ InsertedHeaders.insert (Replacement->getReplacementText ()).second ) {
245+ DB << FixItHint::CreateInsertion (
246+ SM->getComposedLoc (SM->getMainFileID (), Replacement->getOffset ()),
247+ Replacement->getReplacementText ());
248+ }
236249 }
237250 }
238251 }
0 commit comments