[clangd] Use resolved path when checking AngledHeaders/QuotedHeaders in IncludeInserter (#148371)

This makes IncludeInserter's behavior consistent with include-cleaner,
as discussed in https://github.com/llvm/llvm-project/pull/140594.
This commit is contained in:
Harald-R 2025-08-08 10:57:28 +03:00 committed by GitHub
parent 29cde86ecc
commit ff0093cecd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 20 additions and 8 deletions

View File

@ -315,7 +315,7 @@ struct Fragment {
/// 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.
/// Matching is performed against the header text, not its absolute path
/// Matching is performed against the absolute path of the header
/// within the project.
std::vector<Located<std::string>> QuotedHeaders;
/// List of regexes for headers that should always be included with a
@ -323,7 +323,7 @@ struct Fragment {
/// 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.
/// Matching is performed against the header text, not its absolute path
/// Matching is performed against the absolute path of the header
/// within the project.
std::vector<Located<std::string>> AngledHeaders;
};

View File

@ -304,16 +304,17 @@ 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;
auto HeaderPath = llvm::sys::path::convert_to_slash(InsertedHeader.File);
bool IsAngled = false;
for (auto &Filter : AngledHeaders) {
if (Filter(Suggested)) {
if (Filter(HeaderPath)) {
IsAngled = true;
break;
}
}
bool IsQuoted = false;
for (auto &Filter : QuotedHeaders) {
if (Filter(Suggested)) {
if (Filter(HeaderPath)) {
IsQuoted = true;
break;
}
@ -324,7 +325,7 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader,
if (IsAngled && IsQuoted) {
elog("Header '{0}' matches both quoted and angled regexes, default will "
"be used.",
Suggested);
HeaderPath);
}
IsAngled = IsAngledByDefault;
}

View File

@ -938,7 +938,7 @@ TEST(CompletionTest, IncludeInsertionRespectsQuotedAngledConfig) {
{
Config C;
C.Style.AngledHeaders.push_back(
[](auto header) { return header == "bar.h"; });
[](auto header) { return header.contains("bar.h"); });
WithContextValue WithCfg(Config::Key, std::move(C));
Results = completions(TU, Test.point(), {Sym});
EXPECT_THAT(Results.Completions,
@ -947,7 +947,7 @@ TEST(CompletionTest, IncludeInsertionRespectsQuotedAngledConfig) {
{
Config C;
C.Style.QuotedHeaders.push_back(
[](auto header) { return header == "bar.h"; });
[](auto header) { return header.contains("bar.h"); });
WithContextValue WithCfg(Config::Key, std::move(C));
Results = completions(TU, Test.point(), {Sym});
EXPECT_THAT(Results.Completions,

View File

@ -344,6 +344,17 @@ TEST_F(HeadersTest, ShortenIncludesInSearchPathBracketed) {
EXPECT_EQ(calculate(BarHeader), "<sub/bar.h>");
}
TEST_F(HeadersTest, ShortenIncludesInSearchPathBracketedFilterByFullPath) {
// The filter receives the full path of the header, so it is able to filter by
// the parent directory, even if it is part of the include search path
AngledHeaders.push_back([](auto Path) {
llvm::Regex Pattern("sub/.*");
return Pattern.match(Path);
});
std::string BarHeader = testPath("sub/bar.h");
EXPECT_EQ(calculate(BarHeader), "<bar.h>");
}
TEST_F(HeadersTest, ShortenedIncludeNotInSearchPath) {
std::string BarHeader =
llvm::sys::path::convert_to_slash(testPath("sub-2/bar.h"));

View File

@ -136,7 +136,7 @@ struct Header {
}
StringRef verbatim() const { return std::get<Verbatim>(Storage); }
/// For phiscal files, either absolute path or path relative to the execution
/// For physical files, either absolute path or path relative to the execution
/// root. Otherwise just the spelling without surrounding quotes/brackets.
llvm::StringRef resolvedPath() const;