aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2025-05-21 16:41:04 +0200
committerGitHub <noreply@github.com>2025-05-21 16:41:04 +0200
commitc46a394df998afa86e43c772f52f95cf697656b0 (patch)
tree2e392f2c323f5690eef8760a827ca23828cadb77 /clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
parent32946ddd2e5ab83505e832b7ef43bc10bd6dce68 (diff)
downloadllvm-c46a394df998afa86e43c772f52f95cf697656b0.zip
llvm-c46a394df998afa86e43c772f52f95cf697656b0.tar.gz
llvm-c46a394df998afa86e43c772f52f95cf697656b0.tar.bz2
[clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (#140600)
These mimick the same options from clangd and allow using the check to only check for unused includes or missing includes.
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp77
1 files changed, 45 insertions, 32 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 7638bbc..52a94f3 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
: ClangTidyCheck(Name, Context),
IgnoreHeaders(
utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
- DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
+ DeduplicateFindings(Options.get("DeduplicateFindings", true)),
+ UnusedIncludes(Options.get("UnusedIncludes", true)),
+ MissingIncludes(Options.get("MissingIncludes", true)) {
for (const auto &Header : IgnoreHeaders) {
if (!llvm::Regex{Header}.isValid())
configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -68,12 +70,19 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
HeaderSuffix += "$";
IgnoreHeadersRegex.emplace_back(HeaderSuffix);
}
+
+ if (UnusedIncludes == false && MissingIncludes == false)
+ this->configurationDiag("The check 'misc-include-cleaner' will not "
+ "perform any analysis because 'UnusedIncludes' and "
+ "'MissingIncludes' are both false.");
}
void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IgnoreHeaders",
utils::options::serializeStringList(IgnoreHeaders));
Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
+ Options.store(Opts, "UnusedIncludes", UnusedIncludes);
+ Options.store(Opts, "MissingIncludes", MissingIncludes);
}
bool IncludeCleanerCheck::isLanguageVersionSupported(
@@ -200,39 +209,43 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
if (!FileStyle)
FileStyle = format::getLLVMStyle();
- for (const auto *Inc : Unused) {
- diag(Inc->HashLocation, "included header %0 is not used directly")
- << llvm::sys::path::filename(Inc->Spelled,
- llvm::sys::path::Style::posix)
- << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
- SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
- SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+ if (UnusedIncludes) {
+ for (const auto *Inc : Unused) {
+ diag(Inc->HashLocation, "included header %0 is not used directly")
+ << llvm::sys::path::filename(Inc->Spelled,
+ llvm::sys::path::Style::posix)
+ << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+ }
}
- tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
- FileStyle->IncludeStyle);
- // Deduplicate insertions when running in bulk fix mode.
- llvm::StringSet<> InsertedHeaders{};
- for (const auto &Inc : Missing) {
- std::string Spelling = include_cleaner::spellHeader(
- {Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
- bool Angled = llvm::StringRef{Spelling}.starts_with("<");
- // We might suggest insertion of an existing include in edge cases, e.g.,
- // include is present in a PP-disabled region, or spelling of the header
- // turns out to be the same as one of the unresolved includes in the
- // main file.
- if (auto Replacement =
- HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
- Angled, tooling::IncludeDirective::Include)) {
- DiagnosticBuilder DB =
- diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
- "no header providing \"%0\" is directly included")
- << Inc.SymRef.Target.name();
- if (areDiagsSelfContained() ||
- InsertedHeaders.insert(Replacement->getReplacementText()).second) {
- DB << FixItHint::CreateInsertion(
- SM->getComposedLoc(SM->getMainFileID(), Replacement->getOffset()),
- Replacement->getReplacementText());
+ if (MissingIncludes) {
+ tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
+ FileStyle->IncludeStyle);
+ // Deduplicate insertions when running in bulk fix mode.
+ llvm::StringSet<> InsertedHeaders{};
+ for (const auto &Inc : Missing) {
+ std::string Spelling = include_cleaner::spellHeader(
+ {Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
+ bool Angled = llvm::StringRef{Spelling}.starts_with("<");
+ // We might suggest insertion of an existing include in edge cases, e.g.,
+ // include is present in a PP-disabled region, or spelling of the header
+ // turns out to be the same as one of the unresolved includes in the
+ // main file.
+ if (auto Replacement = HeaderIncludes.insert(
+ llvm::StringRef{Spelling}.trim("\"<>"), Angled,
+ tooling::IncludeDirective::Include)) {
+ DiagnosticBuilder DB =
+ diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
+ "no header providing \"%0\" is directly included")
+ << Inc.SymRef.Target.name();
+ if (areDiagsSelfContained() ||
+ InsertedHeaders.insert(Replacement->getReplacementText()).second) {
+ DB << FixItHint::CreateInsertion(
+ SM->getComposedLoc(SM->getMainFileID(), Replacement->getOffset()),
+ Replacement->getReplacementText());
+ }
}
}
}