[clang-tools-extra] 517828a - [clangd] Bundle code completion items when the include paths differ, but resolve to the same file.
Adam Czachorowski via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 3 07:34:13 PST 2020
Author: Adam Czachorowski
Date: 2020-12-03T16:33:15+01:00
New Revision: 517828a31b0d1b7cfd1fd261046746bd8778420a
URL: https://github.com/llvm/llvm-project/commit/517828a31b0d1b7cfd1fd261046746bd8778420a
DIFF: https://github.com/llvm/llvm-project/commit/517828a31b0d1b7cfd1fd261046746bd8778420a.diff
LOG: [clangd] Bundle code completion items when the include paths differ, but resolve to the same file.
This can happen when, for example, merging results from an external
index that generates IncludeHeaders with full URI rather than just
literal include.
Differential Revision: https://reviews.llvm.org/D92494
Added:
Modified:
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 1d85439f53af..cc6b5dbc9904 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -173,9 +173,22 @@ struct CompletionCandidate {
// Returns a token identifying the overload set this is part of.
// 0 indicates it's not part of any overload set.
- size_t overloadSet(const CodeCompleteOptions &Opts) const {
+ size_t overloadSet(const CodeCompleteOptions &Opts, llvm::StringRef FileName,
+ IncludeInserter *Inserter) const {
if (!Opts.BundleOverloads.getValueOr(false))
return 0;
+
+ // Depending on the index implementation, we can see
diff erent header
+ // strings (literal or URI) mapping to the same file. We still want to
+ // bundle those, so we must resolve the header to be included here.
+ std::string HeaderForHash;
+ if (Inserter)
+ if (auto Header = headerToInsertIfAllowed(Opts))
+ if (auto HeaderFile = toHeaderFile(*Header, FileName))
+ if (auto Spelled =
+ Inserter->calculateIncludePath(*HeaderFile, FileName))
+ HeaderForHash = *Spelled;
+
llvm::SmallString<256> Scratch;
if (IndexResult) {
switch (IndexResult->SymInfo.Kind) {
@@ -192,7 +205,7 @@ struct CompletionCandidate {
// This could break #include insertion.
return llvm::hash_combine(
(IndexResult->Scope + IndexResult->Name).toStringRef(Scratch),
- headerToInsertIfAllowed(Opts).getValueOr(""));
+ HeaderForHash);
default:
return 0;
}
@@ -206,8 +219,7 @@ struct CompletionCandidate {
llvm::raw_svector_ostream OS(Scratch);
D->printQualifiedName(OS);
}
- return llvm::hash_combine(Scratch,
- headerToInsertIfAllowed(Opts).getValueOr(""));
+ return llvm::hash_combine(Scratch, HeaderForHash);
}
assert(IdentifierResult);
return 0;
@@ -1570,7 +1582,8 @@ class CodeCompleteFlow {
assert(IdentifierResult);
C.Name = IdentifierResult->Name;
}
- if (auto OverloadSet = C.overloadSet(Opts)) {
+ if (auto OverloadSet = C.overloadSet(
+ Opts, FileName, Inserter ? Inserter.getPointer() : nullptr)) {
auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
if (Ret.second)
Bundles.emplace_back();
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index a7e1c6c48143..a19c6a83e954 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1628,6 +1628,29 @@ TEST(CompletionTest, OverloadBundling) {
EXPECT_EQ(A.SnippetSuffix, "($0)");
}
+TEST(CompletionTest, OverloadBundlingSameFileDifferentURI) {
+ clangd::CodeCompleteOptions Opts;
+ Opts.BundleOverloads = true;
+
+ Symbol SymX = sym("ns::X", index::SymbolKind::Function, "@F@\\0#");
+ Symbol SymY = sym("ns::X", index::SymbolKind::Function, "@F@\\0#I#");
+ std::string BarHeader = testPath("bar.h");
+ auto BarURI = URI::create(BarHeader).toString();
+ SymX.CanonicalDeclaration.FileURI = BarURI.c_str();
+ SymY.CanonicalDeclaration.FileURI = BarURI.c_str();
+ // The include header is
diff erent, but really it's the same file.
+ SymX.IncludeHeaders.emplace_back("\"bar.h\"", 1);
+ SymY.IncludeHeaders.emplace_back(BarURI.c_str(), 1);
+
+ auto Results = completions("void f() { ::ns::^ }", {SymX, SymY}, Opts);
+ // Expect both results are bundled, despite the
diff erent-but-same
+ // IncludeHeader.
+ ASSERT_EQ(1u, Results.Completions.size());
+ const auto &R = Results.Completions.front();
+ EXPECT_EQ("X", R.Name);
+ EXPECT_EQ(2u, R.BundleSize);
+}
+
TEST(CompletionTest, DocumentationFromChangedFileCrash) {
MockFS FS;
auto FooH = testPath("foo.h");
More information about the cfe-commits
mailing list