kbobyrev created this revision. kbobyrev added a reviewer: sammccall. Herald added subscribers: usaxena95, arphaman. Herald added a project: All. kbobyrev requested review of this revision. Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov. Herald added a project: clang-tools-extra.
This introduces filtering out inclusions based on the resolved path. This mechanism will be important for disabling warnings for headers that we can not diagnose correctly yet. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D123488 Files: clang-tools-extra/clangd/Config.h clang-tools-extra/clangd/ConfigCompile.cpp clang-tools-extra/clangd/ConfigFragment.h clang-tools-extra/clangd/IncludeCleaner.cpp clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -1675,6 +1675,9 @@ Annotations Test(R"cpp( $fix[[ $diag[[#include "unused.h"]] ]] + // These two will be ignored by the filter. + #include "ignore.h" + #include "ignore_regex.h" #include "used.h" #include <system_header.h> @@ -1693,12 +1696,22 @@ #pragma once void used() {} )cpp"; + TU.AdditionalFiles["ignore.h"] = R"cpp( + #pragma once + void ignore() {} + )cpp"; + TU.AdditionalFiles["ignore_regex.h"] = R"cpp( + #pragma once + void ignore_regex() {} + )cpp"; TU.AdditionalFiles["system/system_header.h"] = ""; TU.ExtraArgs = {"-isystem" + testPath("system")}; // Off by default. EXPECT_THAT(*TU.build().getDiagnostics(), IsEmpty()); Config Cfg; Cfg.Diagnostics.UnusedIncludes = Config::UnusedIncludesPolicy::Strict; + // Set filtering. + Cfg.Diagnostics.Includes.IgnoreHeader.emplace_back(llvm::Regex("ignore.*.h")); WithContextValue WithCfg(Config::Key, std::move(Cfg)); EXPECT_THAT( *TU.build().getDiagnostics(), Index: clang-tools-extra/clangd/IncludeCleaner.cpp =================================================================== --- clang-tools-extra/clangd/IncludeCleaner.cpp +++ clang-tools-extra/clangd/IncludeCleaner.cpp @@ -23,10 +23,12 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Tooling/Syntax/Tokens.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Regex.h" namespace clang { namespace clangd { @@ -233,7 +235,8 @@ } } -static bool mayConsiderUnused(const Inclusion &Inc, ParsedAST &AST) { +static bool mayConsiderUnused(const Inclusion &Inc, ParsedAST &AST, + llvm::ArrayRef<llvm::Regex> IgnoreHeader) { if (Inc.BehindPragmaKeep) return false; @@ -258,6 +261,12 @@ FE->getName()); return false; } + for (auto &Matcher : IgnoreHeader) { + if (Matcher.match(Inc.Resolved)) { + dlog("{0} header is filterred out", FE->getName()); + return false; + } + } return true; } @@ -369,6 +378,7 @@ const llvm::DenseSet<IncludeStructure::HeaderID> &ReferencedFiles, const llvm::StringSet<> &ReferencedPublicHeaders) { trace::Span Tracer("IncludeCleaner::getUnused"); + const Config &Cfg = Config::current(); std::vector<const Inclusion *> Unused; for (const Inclusion &MFI : AST.getIncludeStructure().MainFileIncludes) { if (!MFI.HeaderID) @@ -377,7 +387,8 @@ continue; auto IncludeID = static_cast<IncludeStructure::HeaderID>(*MFI.HeaderID); bool Used = ReferencedFiles.contains(IncludeID); - if (!Used && !mayConsiderUnused(MFI, AST)) { + if (!Used && + !mayConsiderUnused(MFI, AST, Cfg.Diagnostics.Includes.IgnoreHeader)) { dlog("{0} was not used, but is not eligible to be diagnosed as unused", MFI.Written); continue; Index: clang-tools-extra/clangd/ConfigFragment.h =================================================================== --- clang-tools-extra/clangd/ConfigFragment.h +++ clang-tools-extra/clangd/ConfigFragment.h @@ -232,6 +232,15 @@ /// - None llvm::Optional<Located<std::string>> UnusedIncludes; + /// Controls IncludeCleaner diagnostics. + struct IncludesBlock { + /// Regexes that will be used to avoid diagnosing certain includes. These + /// regexes are anchored on the right and will be matched against the + /// resolved include path. + std::vector<Located<std::string>> IgnoreHeader; + }; + IncludesBlock Includes; + /// Controls how clang-tidy will run over the code base. /// /// The settings are merged with any settings found in .clang-tidy Index: clang-tools-extra/clangd/ConfigCompile.cpp =================================================================== --- clang-tools-extra/clangd/ConfigCompile.cpp +++ clang-tools-extra/clangd/ConfigCompile.cpp @@ -432,6 +432,7 @@ Out.Apply.push_back([Val](const Params &, Config &C) { C.Diagnostics.UnusedIncludes = *Val; }); + compile(std::move(F.Includes)); compile(std::move(F.ClangTidy)); } @@ -507,6 +508,31 @@ } } + void compile(Fragment::DiagnosticsBlock::IncludesBlock &&F) { +#ifdef CLANGD_PATH_CASE_INSENSITIVE + static llvm::Regex::RegexFlags Flags = llvm::Regex::IgnoreCase; +#else + static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags; +#endif + for (auto &HeaderPattern : F.IgnoreHeader) { + // Anchor on the right. + std::string AnchoredPattern = "(" + *HeaderPattern + ")$"; + llvm::Regex CompiledRegex(AnchoredPattern, Flags); + std::string RegexError; + if (!CompiledRegex.isValid(RegexError)) { + diag(Warning, + llvm::formatv("Incorrect regular expression: {0}", *HeaderPattern) + .str(), + HeaderPattern.Range); + continue; + } + Out.Apply.push_back([&CompiledRegex](const Params &, Config &C) { + C.Diagnostics.Includes.IgnoreHeader.emplace_back( + std::move(CompiledRegex)); + }); + } + } + void compile(Fragment::CompletionBlock &&F) { if (F.AllScopes) { Out.Apply.push_back( Index: clang-tools-extra/clangd/Config.h =================================================================== --- clang-tools-extra/clangd/Config.h +++ clang-tools-extra/clangd/Config.h @@ -29,6 +29,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Support/Regex.h" #include <string> #include <vector> @@ -100,6 +101,12 @@ } ClangTidy; UnusedIncludesPolicy UnusedIncludes = None; + + /// IncludeCleaner will not diagnose usages of these headers matched by + /// these regexes. + struct { + std::vector<llvm::Regex> IgnoreHeader; + } Includes; } Diagnostics; /// Style of the codebase.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits