Skip to content

Commit 8b2faee

Browse files
committed
[clangd] Change index scope convention from "outer::inner" to "outer::inner::"
Global scope is "" (was "") Top-level namespace scope is "ns::" (was "ns") Nested namespace scope is "ns::ns::" (was "ns::ns") This composes more naturally: - qname = scope + name - full scope = resolved scope + unresolved scope (D42073 was the trigger) It removes a wart from the old way: "foo::" has one more separator than "". Another alternative that has these properties is "::ns", but that lacks the property that both the scope and the name are substrings of the qname as produced by clang. This is re-landing r322996 which didn't build. llvm-svn: 323000
1 parent 5435b68 commit 8b2faee

File tree

6 files changed

+25
-33
lines changed

6 files changed

+25
-33
lines changed

clang-tools-extra/clangd/CodeComplete.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -313,16 +313,16 @@ llvm::Optional<SymbolID> getSymbolID(const CodeCompletionResult &R) {
313313
/// completion (e.g. "ns::ab?").
314314
struct SpecifiedScope {
315315
/// The scope specifier as written. For example, for completion "ns::ab?", the
316-
/// written scope specifier is "ns".
316+
/// written scope specifier is "ns::".
317317
std::string Written;
318318
// If this scope specifier is recognized in Sema (e.g. as a namespace
319319
// context), this will be set to the fully qualfied name of the corresponding
320320
// context.
321321
std::string Resolved;
322322

323323
llvm::StringRef forIndex() {
324-
llvm::StringRef Chosen = Resolved.empty() ? Written : Resolved;
325-
return Chosen.trim(':');
324+
return Resolved.empty() ? StringRef(Written).ltrim("::")
325+
: StringRef(Resolved);
326326
}
327327
};
328328

@@ -631,15 +631,14 @@ SpecifiedScope getSpecifiedScope(Sema &S, const CXXScopeSpec &SS) {
631631
auto SpecifierRange = SS.getRange();
632632
Info.Written = Lexer::getSourceText(
633633
CharSourceRange::getCharRange(SpecifierRange), SM, clang::LangOptions());
634+
if (!Info.Written.empty())
635+
Info.Written += "::"; // Sema excludes the trailing ::.
634636
if (SS.isValid()) {
635637
DeclContext *DC = S.computeDeclContext(SS);
636638
if (auto *NS = llvm::dyn_cast<NamespaceDecl>(DC)) {
637-
Info.Resolved = NS->getQualifiedNameAsString();
639+
Info.Resolved = NS->getQualifiedNameAsString() + "::";
638640
} else if (llvm::dyn_cast<TranslationUnitDecl>(DC) != nullptr) {
639-
Info.Resolved = "::";
640-
// Sema does not include the suffix "::" in the range of SS, so we add
641-
// it back here.
642-
Info.Written = "::";
641+
Info.Resolved = "";
643642
}
644643
}
645644
return Info;

clang-tools-extra/clangd/index/Index.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,9 @@ struct Symbol {
114114
SymbolID ID;
115115
// The symbol information, like symbol kind.
116116
index::SymbolInfo SymInfo;
117-
// The unqualified name of the symbol, e.g. "bar" (for "n1::n2::bar").
117+
// The unqualified name of the symbol, e.g. "bar" (for ns::bar).
118118
llvm::StringRef Name;
119-
// The scope (e.g. namespace) of the symbol, e.g. "n1::n2" (for
120-
// "n1::n2::bar").
119+
// The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
121120
llvm::StringRef Scope;
122121
// The location of the canonical declaration of the symbol.
123122
//
@@ -221,12 +220,11 @@ struct FuzzyFindRequest {
221220
/// un-qualified identifiers and should not contain qualifiers like "::".
222221
std::string Query;
223222
/// \brief If this is non-empty, symbols must be in at least one of the scopes
224-
/// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz"
225-
/// is provided, the matched symbols must be defined in scope "xyz" but not
226-
/// "xyz::abc".
223+
/// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz::"
224+
/// is provided, the matched symbols must be defined in namespace xyz but not
225+
/// namespace xyz::abc.
227226
///
228-
/// A scope must be fully qualified without leading or trailing "::" e.g.
229-
/// "n1::n2". "" is interpreted as the global namespace, and "::" is invalid.
227+
/// The global scope is "", a top level scope is "foo::", etc.
230228
std::vector<std::string> Scopes;
231229
/// \brief The number of top candidates to return. The index may choose to
232230
/// return more than this, e.g. if it doesn't know which candidates are best.

clang-tools-extra/clangd/index/SymbolCollector.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ std::string makeAbsolutePath(const SourceManager &SM, StringRef Path) {
5656
return AbsolutePath.str();
5757
}
5858

59-
// "a::b::c", return {"a::b", "c"}. Scope is empty if it doesn't exist.
59+
// "a::b::c", return {"a::b::", "c"}. Scope is empty if there's no qualifier.
6060
std::pair<llvm::StringRef, llvm::StringRef>
6161
splitQualifiedName(llvm::StringRef QName) {
6262
assert(!QName.startswith("::") && "Qualified names should not start with ::");
6363
size_t Pos = QName.rfind("::");
6464
if (Pos == llvm::StringRef::npos)
6565
return {StringRef(), QName};
66-
return {QName.substr(0, Pos), QName.substr(Pos + 2)};
66+
return {QName.substr(0, Pos + 2), QName.substr(Pos + 2)};
6767
}
6868

6969
bool shouldFilterDecl(const NamedDecl *ND, ASTContext *ASTCtx,
@@ -147,12 +147,10 @@ bool SymbolCollector::handleDeclOccurence(
147147
SymbolLocation Location = {FilePath, SM.getFileOffset(D->getLocStart()),
148148
SM.getFileOffset(D->getLocEnd())};
149149
std::string QName = ND->getQualifiedNameAsString();
150-
auto ScopeAndName = splitQualifiedName(QName);
151150

152151
Symbol S;
153152
S.ID = std::move(ID);
154-
S.Scope = ScopeAndName.first;
155-
S.Name = ScopeAndName.second;
153+
std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
156154
S.SymInfo = index::getSymbolInfo(D);
157155
S.CanonicalDeclaration = Location;
158156

clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ Symbol sym(StringRef QName, index::SymbolKind Kind, StringRef USRFormat) {
155155
Sym.Scope = "";
156156
} else {
157157
Sym.Name = QName.substr(Pos + 2);
158-
Sym.Scope = QName.substr(0, Pos);
159-
USR += "@N@" + replace(Sym.Scope, "::", "@N@"); // ns:: -> @N@ns
158+
Sym.Scope = QName.substr(0, Pos + 2);
159+
USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns
160160
}
161161
USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
162162
Sym.ID = SymbolID(USR);

clang-tools-extra/unittests/clangd/FileIndexTests.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ std::vector<std::string> match(const SymbolIndex &I,
7878
std::vector<std::string> Matches;
7979
auto Ctx = Context::empty();
8080
I.fuzzyFind(Ctx, Req, [&](const Symbol &Sym) {
81-
Matches.push_back(
82-
(Sym.Scope + (Sym.Scope.empty() ? "" : "::") + Sym.Name).str());
81+
Matches.push_back((Sym.Scope + Sym.Name).str());
8382
});
8483
return Matches;
8584
}
@@ -110,7 +109,7 @@ TEST(FileIndexTest, IndexAST) {
110109

111110
FuzzyFindRequest Req;
112111
Req.Query = "";
113-
Req.Scopes = {"ns"};
112+
Req.Scopes = {"ns::"};
114113
EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X"));
115114
}
116115

@@ -139,7 +138,7 @@ TEST(FileIndexTest, IndexMultiASTAndDeduplicate) {
139138

140139
FuzzyFindRequest Req;
141140
Req.Query = "";
142-
Req.Scopes = {"ns"};
141+
Req.Scopes = {"ns::"};
143142
EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X", "ns::ff"));
144143
}
145144

@@ -152,7 +151,7 @@ TEST(FileIndexTest, RemoveAST) {
152151

153152
FuzzyFindRequest Req;
154153
Req.Query = "";
155-
Req.Scopes = {"ns"};
154+
Req.Scopes = {"ns::"};
156155
EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X"));
157156

158157
M.update(Ctx, "f1", nullptr);

clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ MATCHER_P(Plain, Text, "") { return arg.CompletionPlainInsertText == Text; }
4343
MATCHER_P(Snippet, S, "") {
4444
return arg.CompletionSnippetInsertText == S;
4545
}
46-
MATCHER_P(QName, Name, "") {
47-
return (arg.Scope + (arg.Scope.empty() ? "" : "::") + arg.Name).str() == Name;
48-
}
46+
MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
4947

5048
namespace clang {
5149
namespace clangd {
@@ -291,7 +289,7 @@ TEST_F(SymbolCollectorTest, YAMLConversions) {
291289
---
292290
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
293291
Name: 'Foo1'
294-
Scope: 'clang'
292+
Scope: 'clang::'
295293
SymInfo:
296294
Kind: Function
297295
Lang: Cpp
@@ -311,7 +309,7 @@ CompletionPlainInsertText: 'plain'
311309
---
312310
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF858
313311
Name: 'Foo2'
314-
Scope: 'clang'
312+
Scope: 'clang::'
315313
SymInfo:
316314
Kind: Function
317315
Lang: Cpp

0 commit comments

Comments
 (0)