@@ -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,20 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
6870 HeaderSuffix += " $" ;
6971 IgnoreHeadersRegex.emplace_back (HeaderSuffix);
7072 }
73+
74+ if (UnusedIncludes == false && MissingIncludes == false )
75+ this ->configurationDiag (
76+ " The check 'misc-include-cleaner' will not "
77+ " perform any analysis because 'UnusedIncludes' and "
78+ " 'MissingIncludes' are both false." );
7179}
7280
7381void IncludeCleanerCheck::storeOptions (ClangTidyOptions::OptionMap &Opts) {
7482 Options.store (Opts, " IgnoreHeaders" ,
7583 utils::options::serializeStringList (IgnoreHeaders));
7684 Options.store (Opts, " DeduplicateFindings" , DeduplicateFindings);
85+ Options.store (Opts, " UnusedIncludes" , UnusedIncludes);
86+ Options.store (Opts, " MissingIncludes" , MissingIncludes);
7787}
7888
7989bool IncludeCleanerCheck::isLanguageVersionSupported (
@@ -200,39 +210,43 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
200210 if (!FileStyle)
201211 FileStyle = format::getLLVMStyle ();
202212
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 )));
213+ if (UnusedIncludes) {
214+ for (const auto *Inc : Unused) {
215+ diag (Inc->HashLocation , " included header %0 is not used directly" )
216+ << llvm::sys::path::filename (Inc->Spelled ,
217+ llvm::sys::path::Style::posix)
218+ << FixItHint::CreateRemoval (CharSourceRange::getCharRange (
219+ SM->translateLineCol (SM->getMainFileID (), Inc->Line , 1 ),
220+ SM->translateLineCol (SM->getMainFileID (), Inc->Line + 1 , 1 )));
221+ }
210222 }
211223
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 ());
224+ if (MissingIncludes) {
225+ tooling::HeaderIncludes HeaderIncludes (getCurrentMainFile (), Code,
226+ FileStyle->IncludeStyle );
227+ // Deduplicate insertions when running in bulk fix mode.
228+ llvm::StringSet<> InsertedHeaders{};
229+ for (const auto &Inc : Missing) {
230+ std::string Spelling = include_cleaner::spellHeader (
231+ {Inc.Missing , PP->getHeaderSearchInfo (), MainFile});
232+ bool Angled = llvm::StringRef{Spelling}.starts_with (" <" );
233+ // We might suggest insertion of an existing include in edge cases, e.g.,
234+ // include is present in a PP-disabled region, or spelling of the header
235+ // turns out to be the same as one of the unresolved includes in the
236+ // main file.
237+ if (auto Replacement = HeaderIncludes.insert (
238+ llvm::StringRef{Spelling}.trim (" \" <>" ), Angled,
239+ tooling::IncludeDirective::Include)) {
240+ DiagnosticBuilder DB =
241+ diag (SM->getSpellingLoc (Inc.SymRef .RefLocation ),
242+ " no header providing \" %0\" is directly included" )
243+ << Inc.SymRef .Target .name ();
244+ if (areDiagsSelfContained () ||
245+ InsertedHeaders.insert (Replacement->getReplacementText ()).second ) {
246+ DB << FixItHint::CreateInsertion (
247+ SM->getComposedLoc (SM->getMainFileID (), Replacement->getOffset ()),
248+ Replacement->getReplacementText ());
249+ }
236250 }
237251 }
238252 }
0 commit comments