@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
59
59
: ClangTidyCheck(Name, Context),
60
60
IgnoreHeaders (
61
61
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 )) {
63
65
for (const auto &Header : IgnoreHeaders) {
64
66
if (!llvm::Regex{Header}.isValid ())
65
67
configurationDiag (" Invalid ignore headers regex '%0'" ) << Header;
@@ -68,12 +70,19 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
68
70
HeaderSuffix += " $" ;
69
71
IgnoreHeadersRegex.emplace_back (HeaderSuffix);
70
72
}
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." );
71
78
}
72
79
73
80
void IncludeCleanerCheck::storeOptions (ClangTidyOptions::OptionMap &Opts) {
74
81
Options.store (Opts, " IgnoreHeaders" ,
75
82
utils::options::serializeStringList (IgnoreHeaders));
76
83
Options.store (Opts, " DeduplicateFindings" , DeduplicateFindings);
84
+ Options.store (Opts, " UnusedIncludes" , UnusedIncludes);
85
+ Options.store (Opts, " MissingIncludes" , MissingIncludes);
77
86
}
78
87
79
88
bool IncludeCleanerCheck::isLanguageVersionSupported (
@@ -200,39 +209,43 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
200
209
if (!FileStyle)
201
210
FileStyle = format::getLLVMStyle ();
202
211
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
+ }
210
221
}
211
222
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
+ }
236
249
}
237
250
}
238
251
}
0 commit comments