diff options
6 files changed, 33 insertions, 24 deletions
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index ab8a22d6b45..1a95b6ba6bf 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -313,7 +313,7 @@ llvm::Optional<SymbolID> getSymbolID(const CodeCompletionResult &R) {  /// completion (e.g. "ns::ab?").  struct SpecifiedScope {    /// The scope specifier as written. For example, for completion "ns::ab?", the -  /// written scope specifier is "ns::". Doesn't include leading "::". +  /// written scope specifier is "ns".    std::string Written;    // If this scope specifier is recognized in Sema (e.g. as a namespace    // context), this will be set to the fully qualfied name of the corresponding @@ -321,7 +321,8 @@ struct SpecifiedScope {    std::string Resolved;    llvm::StringRef forIndex() { -    return Resolved.empty() ? Written.ltrim('::') : Resolved; +    llvm::StringRef Chosen = Resolved.empty() ? Written : Resolved; +    return Chosen.trim(':');    }  }; @@ -630,14 +631,15 @@ SpecifiedScope getSpecifiedScope(Sema &S, const CXXScopeSpec &SS) {    auto SpecifierRange = SS.getRange();    Info.Written = Lexer::getSourceText(        CharSourceRange::getCharRange(SpecifierRange), SM, clang::LangOptions()); -  if (!Info.Written.empty()) -    Info.Written += "::"; // Sema excludes the trailing ::.    if (SS.isValid()) {      DeclContext *DC = S.computeDeclContext(SS);      if (auto *NS = llvm::dyn_cast<NamespaceDecl>(DC)) { -      Info.Resolved = NS->getQualifiedNameAsString() + "::"; +      Info.Resolved = NS->getQualifiedNameAsString();      } else if (llvm::dyn_cast<TranslationUnitDecl>(DC) != nullptr) { -      Info.Resolved = ""; +      Info.Resolved = "::"; +      // Sema does not include the suffix "::" in the range of SS, so we add +      // it back here. +      Info.Written = "::";      }    }    return Info; diff --git a/clang-tools-extra/clangd/index/Index.h b/clang-tools-extra/clangd/index/Index.h index a3eb298fdc5..a70d38b768f 100644 --- a/clang-tools-extra/clangd/index/Index.h +++ b/clang-tools-extra/clangd/index/Index.h @@ -114,9 +114,10 @@ struct Symbol {    SymbolID ID;    // The symbol information, like symbol kind.    index::SymbolInfo SymInfo; -  // The unqualified name of the symbol, e.g. "bar" (for ns::bar). +  // The unqualified name of the symbol, e.g. "bar" (for "n1::n2::bar").    llvm::StringRef Name; -  // The containing namespace. e.g. "" (global), "ns::" (top-level namespace). +  // The scope (e.g. namespace) of the symbol, e.g. "n1::n2" (for +  // "n1::n2::bar").    llvm::StringRef Scope;    // The location of the canonical declaration of the symbol.    // @@ -220,11 +221,12 @@ struct FuzzyFindRequest {    /// un-qualified identifiers and should not contain qualifiers like "::".    std::string Query;    /// \brief If this is non-empty, symbols must be in at least one of the scopes -  /// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz::" -  /// is provided, the matched symbols must be defined in namespace xyz but not -  /// namespace xyz::abc. +  /// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz" +  /// is provided, the matched symbols must be defined in scope "xyz" but not +  /// "xyz::abc".    /// -  /// The global scope is "", a top level scope is "foo::", etc. +  /// A scope must be fully qualified without leading or trailing "::" e.g. +  /// "n1::n2". "" is interpreted as the global namespace, and "::" is invalid.    std::vector<std::string> Scopes;    /// \brief The number of top candidates to return. The index may choose to    /// return more than this, e.g. if it doesn't know which candidates are best. diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index e7fae173a16..92402c5ec6c 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -56,14 +56,14 @@ std::string makeAbsolutePath(const SourceManager &SM, StringRef Path) {    return AbsolutePath.str();  } -// "a::b::c", return {"a::b::", "c"}. Scope is empty if there's no qualifier. +// "a::b::c", return {"a::b", "c"}. Scope is empty if it doesn't exist.  std::pair<llvm::StringRef, llvm::StringRef>  splitQualifiedName(llvm::StringRef QName) {    assert(!QName.startswith("::") && "Qualified names should not start with ::");    size_t Pos = QName.rfind("::");    if (Pos == llvm::StringRef::npos)      return {StringRef(), QName}; -  return {QName.substr(0, Pos + 2), QName.substr(Pos + 2)}; +  return {QName.substr(0, Pos), QName.substr(Pos + 2)};  }  bool shouldFilterDecl(const NamedDecl *ND, ASTContext *ASTCtx, @@ -147,10 +147,12 @@ bool SymbolCollector::handleDeclOccurence(      SymbolLocation Location = {FilePath, SM.getFileOffset(D->getLocStart()),                                 SM.getFileOffset(D->getLocEnd())};      std::string QName = ND->getQualifiedNameAsString(); +    auto ScopeAndName = splitQualifiedName(QName);      Symbol S;      S.ID = std::move(ID); -    std::tie(S.Scope, S.Name) = splitQualifiedName(QName); +    S.Scope = ScopeAndName.first; +    S.Name = ScopeAndName.second;      S.SymInfo = index::getSymbolInfo(D);      S.CanonicalDeclaration = Location; diff --git a/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp b/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp index 40005509176..7eb7b137248 100644 --- a/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp +++ b/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp @@ -155,8 +155,8 @@ Symbol sym(StringRef QName, index::SymbolKind Kind, StringRef USRFormat) {      Sym.Scope = "";    } else {      Sym.Name = QName.substr(Pos + 2); -    Sym.Scope = QName.substr(0, Pos + 2); -    USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns +    Sym.Scope = QName.substr(0, Pos); +    USR += "@N@" + replace(Sym.Scope, "::", "@N@"); // ns:: -> @N@ns    }    USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#    Sym.ID = SymbolID(USR); diff --git a/clang-tools-extra/unittests/clangd/FileIndexTests.cpp b/clang-tools-extra/unittests/clangd/FileIndexTests.cpp index 85352bc924c..adae1f1b3b9 100644 --- a/clang-tools-extra/unittests/clangd/FileIndexTests.cpp +++ b/clang-tools-extra/unittests/clangd/FileIndexTests.cpp @@ -78,7 +78,8 @@ std::vector<std::string> match(const SymbolIndex &I,    std::vector<std::string> Matches;    auto Ctx = Context::empty();    I.fuzzyFind(Ctx, Req, [&](const Symbol &Sym) { -    Matches.push_back((Sym.Scope + Sym.Name).str()); +    Matches.push_back( +        (Sym.Scope + (Sym.Scope.empty() ? "" : "::") + Sym.Name).str());    });    return Matches;  } @@ -109,7 +110,7 @@ TEST(FileIndexTest, IndexAST) {    FuzzyFindRequest Req;    Req.Query = ""; -  Req.Scopes = {"ns::"}; +  Req.Scopes = {"ns"};    EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X"));  } @@ -138,7 +139,7 @@ TEST(FileIndexTest, IndexMultiASTAndDeduplicate) {    FuzzyFindRequest Req;    Req.Query = ""; -  Req.Scopes = {"ns::"}; +  Req.Scopes = {"ns"};    EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X", "ns::ff"));  } @@ -151,7 +152,7 @@ TEST(FileIndexTest, RemoveAST) {    FuzzyFindRequest Req;    Req.Query = ""; -  Req.Scopes = {"ns::"}; +  Req.Scopes = {"ns"};    EXPECT_THAT(match(M, Req), UnorderedElementsAre("ns::f", "ns::X"));    M.update(Ctx, "f1", nullptr); diff --git a/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp b/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp index c17d535067c..87932574618 100644 --- a/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp +++ b/clang-tools-extra/unittests/clangd/SymbolCollectorTests.cpp @@ -43,7 +43,9 @@ MATCHER_P(Plain, Text, "") { return arg.CompletionPlainInsertText == Text; }  MATCHER_P(Snippet, S, "") {    return arg.CompletionSnippetInsertText == S;  } -MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; } +MATCHER_P(QName, Name, "") { +  return (arg.Scope + (arg.Scope.empty() ? "" : "::") + arg.Name).str() == Name; +}  namespace clang {  namespace clangd { @@ -289,7 +291,7 @@ TEST_F(SymbolCollectorTest, YAMLConversions) {  ---  ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856  Name:   'Foo1' -Scope:   'clang::' +Scope:   'clang'  SymInfo:    Kind:            Function    Lang:            Cpp @@ -309,7 +311,7 @@ Detail:  ---  ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF858  Name:   'Foo2' -Scope:   'clang::' +Scope:   'clang'  SymInfo:    Kind:            Function    Lang:            Cpp  | 

