[clang-tools-extra] [clangd] Allow specifying what headers are always included via "" or <> (PR #67749)
kleines Filmröllchen via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 4 02:55:01 PST 2024
https://github.com/kleinesfilmroellchen updated https://github.com/llvm/llvm-project/pull/67749
>From 8a2b22e69f82e3f4caa271b57b998d1c03b21d39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= <filmroellchen at serenityos.org>
Date: Thu, 4 Jan 2024 11:53:23 +0100
Subject: [PATCH] [clangd] Allow specifying what headers are always included
via "" or <>
Projects can now add config fragments like this to their .clangd:
```yaml
Style:
QuotedHeaders: "src/.*"
AngledHeaders: ["path/sdk/.*", "third-party/.*"]
```
to force headers inserted via the --header-insertion=iwyu mode matching
at least one of the regexes to have <> (AngledHeaders) or ""
(QuotedHeaders) around them, respectively. For other headers (and in
conflicting cases where both styles have a matching regex), the current
system header detection remains.
Ref https://github.com/clangd/clangd/issues/1247
Based on https://reviews.llvm.org/D145843
This solution does not affect other clang tools like clang-format.
---
clang-tools-extra/clangd/CodeComplete.cpp | 15 ++++--
clang-tools-extra/clangd/Config.h | 4 ++
clang-tools-extra/clangd/ConfigCompile.cpp | 49 +++++++++++++++++++
clang-tools-extra/clangd/ConfigFragment.h | 13 +++++
clang-tools-extra/clangd/ConfigYAML.cpp | 8 +++
clang-tools-extra/clangd/Headers.cpp | 34 +++++++++++--
clang-tools-extra/clangd/Headers.h | 11 ++++-
clang-tools-extra/clangd/IncludeCleaner.h | 1 -
clang-tools-extra/clangd/ParsedAST.cpp | 3 +-
.../clangd/unittests/ConfigCompileTests.cpp | 36 ++++++++++++++
.../clangd/unittests/ConfigYAMLTests.cpp | 8 ++-
.../clangd/unittests/HeadersTests.cpp | 29 +++++++++--
12 files changed, 193 insertions(+), 18 deletions(-)
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 0e5f08cec440ce..419bd659898506 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -21,6 +21,7 @@
#include "AST.h"
#include "CodeCompletionStrings.h"
#include "Compiler.h"
+#include "Config.h"
#include "ExpectedTypes.h"
#include "Feature.h"
#include "FileDistance.h"
@@ -786,8 +787,8 @@ SpecifiedScope getQueryScopes(CodeCompletionContext &CCContext,
llvm::StringRef SpelledSpecifier = Lexer::getSourceText(
CharSourceRange::getCharRange(SemaSpecifier->getRange()),
CCSema.SourceMgr, clang::LangOptions());
- if (SpelledSpecifier.consume_front("::"))
- Scopes.QueryScopes = {""};
+ if (SpelledSpecifier.consume_front("::"))
+ Scopes.QueryScopes = {""};
Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);
// Sema excludes the trailing "::".
if (!Scopes.UnresolvedQualifier->empty())
@@ -1580,7 +1581,7 @@ class CodeCompleteFlow {
CompletionPrefix HeuristicPrefix;
std::optional<FuzzyMatcher> Filter; // Initialized once Sema runs.
Range ReplacedRange;
- std::vector<std::string> QueryScopes; // Initialized once Sema runs.
+ std::vector<std::string> QueryScopes; // Initialized once Sema runs.
std::vector<std::string> AccessibleScopes; // Initialized once Sema runs.
// Initialized once QueryScopes is initialized, if there are scopes.
std::optional<ScopeDistance> ScopeProximity;
@@ -1639,7 +1640,9 @@ class CodeCompleteFlow {
Inserter.emplace(
SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, Style,
SemaCCInput.ParseInput.CompileCommand.Directory,
- &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo());
+ &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo(),
+ Config::current().Style.QuotedHeaders,
+ Config::current().Style.AngledHeaders);
for (const auto &Inc : Includes.MainFileIncludes)
Inserter->addExisting(Inc);
@@ -1722,7 +1725,9 @@ class CodeCompleteFlow {
auto Style = getFormatStyleForFile(FileName, Content, TFS);
// This will only insert verbatim headers.
Inserter.emplace(FileName, Content, Style,
- /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr);
+ /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr,
+ Config::current().Style.QuotedHeaders,
+ Config::current().Style.AngledHeaders);
auto Identifiers = collectIdentifiers(Content, Style);
std::vector<RawIdentifier> IdentifierResults;
diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h
index 4371c80a6c5877..12ed1420c93e19 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -123,6 +123,10 @@ struct Config {
// declarations, always spell out the whole name (with or without leading
// ::). All nested namespaces are affected as well.
std::vector<std::string> FullyQualifiedNamespaces;
+
+ // List of regexes for inserting certain headers with <> or "".
+ std::vector<std::function<bool(llvm::StringRef)>> QuotedHeaders;
+ std::vector<std::function<bool(llvm::StringRef)>> AngledHeaders;
} Style;
/// Configures code completion feature.
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp
index 5bb2eb4a9f803f..def0ee30e8fc6e 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -483,6 +483,55 @@ struct FragmentCompiler {
FullyQualifiedNamespaces.begin(), FullyQualifiedNamespaces.end());
});
}
+ auto QuotedFilter = compileHeaderRegexes(F.QuotedHeaders);
+ if (QuotedFilter.has_value()) {
+ Out.Apply.push_back(
+ [QuotedFilter = *QuotedFilter](const Params &, Config &C) {
+ C.Style.QuotedHeaders.emplace_back(QuotedFilter);
+ });
+ }
+ auto AngledFilter = compileHeaderRegexes(F.AngledHeaders);
+ if (AngledFilter.has_value()) {
+ Out.Apply.push_back(
+ [AngledFilter = *AngledFilter](const Params &, Config &C) {
+ C.Style.AngledHeaders.emplace_back(AngledFilter);
+ });
+ }
+ }
+
+ auto compileHeaderRegexes(llvm::ArrayRef<Located<std::string>> HeaderPatterns)
+ -> std::optional<std::function<bool(llvm::StringRef)>> {
+ // TODO: Share this code with Diagnostics.Includes.IgnoreHeader
+#ifdef CLANGD_PATH_CASE_INSENSITIVE
+ static llvm::Regex::RegexFlags Flags = llvm::Regex::IgnoreCase;
+#else
+ static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags;
+#endif
+ auto Filters = std::make_shared<std::vector<llvm::Regex>>();
+ for (auto &HeaderPattern : HeaderPatterns) {
+ // Anchor on the right.
+ std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
+ llvm::Regex CompiledRegex(AnchoredPattern, Flags);
+ std::string RegexError;
+ if (!CompiledRegex.isValid(RegexError)) {
+ diag(Warning,
+ llvm::formatv("Invalid regular expression '{0}': {1}",
+ *HeaderPattern, RegexError)
+ .str(),
+ HeaderPattern.Range);
+ continue;
+ }
+ Filters->push_back(std::move(CompiledRegex));
+ }
+ if (Filters->empty())
+ return std::nullopt;
+ auto Filter = [Filters](llvm::StringRef Path) {
+ for (auto &Regex : *Filters)
+ if (Regex.match(Path))
+ return true;
+ return false;
+ };
+ return Filter;
}
void appendTidyCheckSpec(std::string &CurSpec,
diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h
index 7fa61108c78a05..81474bbd86a598 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -296,6 +296,19 @@ struct Fragment {
// ::). All nested namespaces are affected as well.
// Affects availability of the AddUsing tweak.
std::vector<Located<std::string>> FullyQualifiedNamespaces;
+
+ /// List of regexes for headers that should always be included with a
+ /// ""-style include. By default, and in case of a conflict with
+ /// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and
+ /// AngledHeaders), system headers use <> and non-system headers use "".
+ /// These can match any suffix of the header file in question.
+ std::vector<Located<std::string>> QuotedHeaders;
+ /// List of regexes for headers that should always be included with a
+ /// <>-style include. By default, and in case of a conflict with
+ /// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and
+ /// AngledHeaders), system headers use <> and non-system headers use "".
+ /// These can match any suffix of the header file in question.
+ std::vector<Located<std::string>> AngledHeaders;
};
StyleBlock Style;
diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp
index ce09af819247ae..ec7c91fe33b0f2 100644
--- a/clang-tools-extra/clangd/ConfigYAML.cpp
+++ b/clang-tools-extra/clangd/ConfigYAML.cpp
@@ -117,6 +117,14 @@ class Parser {
if (auto Values = scalarValues(N))
F.FullyQualifiedNamespaces = std::move(*Values);
});
+ Dict.handle("QuotedHeaders", [&](Node &N) {
+ if (auto Values = scalarValues(N))
+ F.QuotedHeaders = std::move(*Values);
+ });
+ Dict.handle("AngledHeaders", [&](Node &N) {
+ if (auto Values = scalarValues(N))
+ F.AngledHeaders = std::move(*Values);
+ });
Dict.parse(N);
}
diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp
index 076e636e0e2819..5bd53d249ab60c 100644
--- a/clang-tools-extra/clangd/Headers.cpp
+++ b/clang-tools-extra/clangd/Headers.cpp
@@ -9,6 +9,7 @@
#include "Headers.h"
#include "Preamble.h"
#include "SourceCode.h"
+#include "support/Logger.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -30,8 +31,7 @@ namespace clangd {
class IncludeStructure::RecordHeaders : public PPCallbacks {
public:
RecordHeaders(const CompilerInstance &CI, IncludeStructure *Out)
- : SM(CI.getSourceManager()),
- Out(Out) {}
+ : SM(CI.getSourceManager()), Out(Out) {}
// Record existing #includes - both written and resolved paths. Only #includes
// in the main file are collected.
@@ -286,11 +286,11 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader,
assert(InsertedHeader.valid());
if (InsertedHeader.Verbatim)
return InsertedHeader.File;
- bool IsAngled = false;
+ bool IsAngledByDefault = false;
std::string Suggested;
if (HeaderSearchInfo) {
Suggested = HeaderSearchInfo->suggestPathToFileForDiagnostics(
- InsertedHeader.File, BuildDir, IncludingFile, &IsAngled);
+ InsertedHeader.File, BuildDir, IncludingFile, &IsAngledByDefault);
} else {
// Calculate include relative to including file only.
StringRef IncludingDir = llvm::sys::path::parent_path(IncludingFile);
@@ -303,9 +303,33 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader,
// FIXME: should we allow (some limited number of) "../header.h"?
if (llvm::sys::path::is_absolute(Suggested))
return std::nullopt;
+ bool IsAngled = false;
+ for (auto Filter : AngledHeaders) {
+ if (Filter(Suggested)) {
+ IsAngled = true;
+ break;
+ }
+ }
+ bool IsQuoted = false;
+ for (auto Filter : QuotedHeaders) {
+ if (Filter(Suggested)) {
+ IsQuoted = true;
+ break;
+ }
+ }
+ // No filters apply, or both filters apply (a bug), use system default.
+ if (IsAngled == IsQuoted) {
+ // Probably a bug in the config regex.
+ if (IsAngled && IsQuoted) {
+ elog("Header '{0}' matches both quoted and angled regexes, default will "
+ "be used.",
+ Suggested);
+ }
+ IsAngled = IsAngledByDefault;
+ }
if (IsAngled)
Suggested = "<" + Suggested + ">";
- else
+ else // if (IsQuoted)
Suggested = "\"" + Suggested + "\"";
return Suggested;
}
diff --git a/clang-tools-extra/clangd/Headers.h b/clang-tools-extra/clangd/Headers.h
index 41cf3de6bba350..e1f3eaa3397bf6 100644
--- a/clang-tools-extra/clangd/Headers.h
+++ b/clang-tools-extra/clangd/Headers.h
@@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H
+#include "Config.h"
#include "Protocol.h"
#include "SourceCode.h"
#include "index/Symbol.h"
@@ -33,6 +34,8 @@
namespace clang {
namespace clangd {
+using HeaderFilter = llvm::ArrayRef<std::function<bool(llvm::StringRef)>>;
+
/// Returns true if \p Include is literal include like "path" or <path>.
bool isLiteralInclude(llvm::StringRef Include);
@@ -211,10 +214,12 @@ class IncludeInserter {
// include path of non-verbatim header will not be shortened.
IncludeInserter(StringRef FileName, StringRef Code,
const format::FormatStyle &Style, StringRef BuildDir,
- HeaderSearch *HeaderSearchInfo)
+ HeaderSearch *HeaderSearchInfo, HeaderFilter QuotedHeaders,
+ HeaderFilter AngledHeaders)
: FileName(FileName), Code(Code), BuildDir(BuildDir),
HeaderSearchInfo(HeaderSearchInfo),
- Inserter(FileName, Code, Style.IncludeStyle) {}
+ Inserter(FileName, Code, Style.IncludeStyle),
+ QuotedHeaders(QuotedHeaders), AngledHeaders(AngledHeaders) {}
void addExisting(const Inclusion &Inc);
@@ -258,6 +263,8 @@ class IncludeInserter {
HeaderSearch *HeaderSearchInfo = nullptr;
llvm::StringSet<> IncludedHeaders; // Both written and resolved.
tooling::HeaderIncludes Inserter; // Computers insertion replacement.
+ HeaderFilter QuotedHeaders;
+ HeaderFilter AngledHeaders;
};
} // namespace clangd
diff --git a/clang-tools-extra/clangd/IncludeCleaner.h b/clang-tools-extra/clangd/IncludeCleaner.h
index b3ba3a716083e8..7e289ef4c13532 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.h
+++ b/clang-tools-extra/clangd/IncludeCleaner.h
@@ -55,7 +55,6 @@ struct IncludeCleanerFindings {
IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST);
-using HeaderFilter = llvm::ArrayRef<std::function<bool(llvm::StringRef)>>;
std::vector<Diag>
issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code,
const IncludeCleanerFindings &Findings,
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp
index 14a91797f4d2ea..95b802fd81b0f2 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -628,7 +628,8 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS);
auto Inserter = std::make_shared<IncludeInserter>(
Filename, Inputs.Contents, Style, BuildDir.get(),
- &Clang->getPreprocessor().getHeaderSearchInfo());
+ &Clang->getPreprocessor().getHeaderSearchInfo(),
+ Cfg.Style.QuotedHeaders, Cfg.Style.AngledHeaders);
ArrayRef<Inclusion> MainFileIncludes;
if (Preamble) {
MainFileIncludes = Preamble->Includes.MainFileIncludes;
diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
index f0ffc429c0ca90..0eea7ff01b4805 100644
--- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
@@ -539,6 +539,42 @@ TEST_F(ConfigCompileTests, Style) {
Frag.Style.FullyQualifiedNamespaces.push_back(std::string("bar"));
EXPECT_TRUE(compileAndApply());
EXPECT_THAT(Conf.Style.FullyQualifiedNamespaces, ElementsAre("foo", "bar"));
+
+ {
+ Frag = {};
+ EXPECT_TRUE(Conf.Style.QuotedHeaders.empty())
+ << Conf.Style.QuotedHeaders.size();
+ Frag.Style.QuotedHeaders.push_back(Located<std::string>("foo.h"));
+ Frag.Style.QuotedHeaders.push_back(Located<std::string>(".*inc"));
+ EXPECT_TRUE(compileAndApply());
+ auto HeaderFilter = [this](llvm::StringRef Path) {
+ for (auto &Filter : Conf.Style.QuotedHeaders) {
+ if (Filter(Path))
+ return true;
+ }
+ return false;
+ };
+ EXPECT_TRUE(HeaderFilter("foo.h"));
+ EXPECT_FALSE(HeaderFilter("bar.h"));
+ }
+
+ {
+ Frag = {};
+ EXPECT_TRUE(Conf.Style.AngledHeaders.empty())
+ << Conf.Style.AngledHeaders.size();
+ Frag.Style.AngledHeaders.push_back(Located<std::string>("foo.h"));
+ Frag.Style.AngledHeaders.push_back(Located<std::string>(".*inc"));
+ EXPECT_TRUE(compileAndApply());
+ auto HeaderFilter = [this](llvm::StringRef Path) {
+ for (auto &Filter : Conf.Style.AngledHeaders) {
+ if (Filter(Path))
+ return true;
+ }
+ return false;
+ };
+ EXPECT_TRUE(HeaderFilter("foo.h"));
+ EXPECT_FALSE(HeaderFilter("bar.h"));
+ }
}
} // namespace
} // namespace config
diff --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
index 44a6647d4c0a81..8f8ecc52b4034a 100644
--- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
@@ -282,13 +282,19 @@ TEST(ParseYAML, Style) {
CapturedDiags Diags;
Annotations YAML(R"yaml(
Style:
- FullyQualifiedNamespaces: [foo, bar])yaml");
+ FullyQualifiedNamespaces: [foo, bar]
+ AngledHeaders: ["foo", "bar"]
+ QuotedHeaders: ["baz", "baar"])yaml");
auto Results =
Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
ASSERT_THAT(Diags.Diagnostics, IsEmpty());
ASSERT_EQ(Results.size(), 1u);
EXPECT_THAT(Results[0].Style.FullyQualifiedNamespaces,
ElementsAre(val("foo"), val("bar")));
+ EXPECT_THAT(Results[0].Style.AngledHeaders,
+ ElementsAre(val("foo"), val("bar")));
+ EXPECT_THAT(Results[0].Style.QuotedHeaders,
+ ElementsAre(val("baz"), val("baar")));
}
} // namespace
} // namespace config
diff --git a/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
index dc6adaee112571..751383e3b4650a 100644
--- a/clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -107,7 +107,8 @@ class HeadersTest : public ::testing::Test {
IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
CDB.getCompileCommand(MainFile)->Directory,
- &Clang->getPreprocessor().getHeaderSearchInfo());
+ &Clang->getPreprocessor().getHeaderSearchInfo(),
+ QuotedHeaders, AngledHeaders);
for (const auto &Inc : Inclusions)
Inserter.addExisting(Inc);
auto Inserted = ToHeaderFile(Preferred);
@@ -127,7 +128,8 @@ class HeadersTest : public ::testing::Test {
IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
CDB.getCompileCommand(MainFile)->Directory,
- &Clang->getPreprocessor().getHeaderSearchInfo());
+ &Clang->getPreprocessor().getHeaderSearchInfo(),
+ QuotedHeaders, AngledHeaders);
auto Edit = Inserter.insert(VerbatimHeader, Directive);
Action.EndSourceFile();
return Edit;
@@ -139,6 +141,8 @@ class HeadersTest : public ::testing::Test {
std::string Subdir = testPath("sub");
std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
IgnoringDiagConsumer IgnoreDiags;
+ std::vector<std::function<bool(llvm::StringRef)>> QuotedHeaders;
+ std::vector<std::function<bool(llvm::StringRef)>> AngledHeaders;
std::unique_ptr<CompilerInstance> Clang;
};
@@ -304,6 +308,9 @@ TEST_F(HeadersTest, InsertInclude) {
std::string Path = testPath("sub/bar.h");
FS.Files[Path] = "";
EXPECT_EQ(calculate(Path), "\"bar.h\"");
+
+ AngledHeaders.push_back([](auto Path) { return true; });
+ EXPECT_EQ(calculate(Path), "<bar.h>");
}
TEST_F(HeadersTest, DoNotInsertIfInSameFile) {
@@ -326,6 +333,17 @@ TEST_F(HeadersTest, ShortenIncludesInSearchPath) {
EXPECT_EQ(calculate(BarHeader), "\"sub/bar.h\"");
}
+TEST_F(HeadersTest, ShortenIncludesInSearchPathBracketed) {
+ AngledHeaders.push_back([](auto Path) { return true; });
+ std::string BarHeader = testPath("sub/bar.h");
+ EXPECT_EQ(calculate(BarHeader), "<bar.h>");
+
+ SearchDirArg = (llvm::Twine("-I") + Subdir + "/..").str();
+ CDB.ExtraClangFlags = {SearchDirArg.c_str()};
+ BarHeader = testPath("sub/bar.h");
+ EXPECT_EQ(calculate(BarHeader), "<sub/bar.h>");
+}
+
TEST_F(HeadersTest, ShortenedIncludeNotInSearchPath) {
std::string BarHeader =
llvm::sys::path::convert_to_slash(testPath("sub-2/bar.h"));
@@ -338,6 +356,10 @@ TEST_F(HeadersTest, PreferredHeader) {
std::string BazHeader = testPath("sub/baz.h");
EXPECT_EQ(calculate(BarHeader, BazHeader), "\"baz.h\"");
+
+ AngledHeaders.push_back([](auto Path) { return true; });
+ std::string BiffHeader = testPath("sub/biff.h");
+ EXPECT_EQ(calculate(BarHeader, BiffHeader), "<biff.h>");
}
TEST_F(HeadersTest, DontInsertDuplicatePreferred) {
@@ -370,7 +392,8 @@ TEST_F(HeadersTest, PreferInserted) {
TEST(Headers, NoHeaderSearchInfo) {
std::string MainFile = testPath("main.cpp");
IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
- /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr);
+ /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr,
+ /*QuotedHeaders=*/{}, /*AngledHeaders=*/{});
auto HeaderPath = testPath("sub/bar.h");
auto Inserting = HeaderFile{HeaderPath, /*Verbatim=*/false};
More information about the cfe-commits
mailing list