@@ -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,20 @@ 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 (
76
+ " The check 'misc-include-cleaner' will not "
77
+ " perform any analysis because 'UnusedIncludes' and "
78
+ " 'MissingIncludes' are both false." );
71
79
}
72
80
73
81
void IncludeCleanerCheck::storeOptions (ClangTidyOptions::OptionMap &Opts) {
74
82
Options.store (Opts, " IgnoreHeaders" ,
75
83
utils::options::serializeStringList (IgnoreHeaders));
76
84
Options.store (Opts, " DeduplicateFindings" , DeduplicateFindings);
85
+ Options.store (Opts, " UnusedIncludes" , UnusedIncludes);
86
+ Options.store (Opts, " MissingIncludes" , MissingIncludes);
77
87
}
78
88
79
89
bool IncludeCleanerCheck::isLanguageVersionSupported (
@@ -200,39 +210,43 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
200
210
if (!FileStyle)
201
211
FileStyle = format::getLLVMStyle ();
202
212
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
+ }
210
222
}
211
223
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
+ }
236
250
}
237
251
}
238
252
}
0 commit comments