[clang-tools-extra] r335334 - [clangd] Expose qualified symbol names in CompletionItem (C++ structure only, no json).

Eric Liu via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 22 03:46:59 PDT 2018


Author: ioeric
Date: Fri Jun 22 03:46:59 2018
New Revision: 335334

URL: http://llvm.org/viewvc/llvm-project?rev=335334&view=rev
Log:
[clangd] Expose qualified symbol names in CompletionItem (C++ structure only, no json).

Summary:
The qualified name can be used to match a completion item to its corresponding
symbol. This can be useful for tools that measure code completion quality.
Qualified names are not precise for identifying symbols; we need to figure out a
better way to identify completion items.

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, cfe-commits

Differential Revision: https://reviews.llvm.org/D48425

Modified:
    clang-tools-extra/trunk/clangd/AST.cpp
    clang-tools-extra/trunk/clangd/AST.h
    clang-tools-extra/trunk/clangd/CodeComplete.cpp
    clang-tools-extra/trunk/clangd/Protocol.h
    clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp
    clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp

Modified: clang-tools-extra/trunk/clangd/AST.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/AST.cpp?rev=335334&r1=335333&r2=335334&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/AST.cpp (original)
+++ clang-tools-extra/trunk/clangd/AST.cpp Fri Jun 22 03:46:59 2018
@@ -38,5 +38,20 @@ SourceLocation findNameLoc(const clang::
   return SpellingLoc;
 }
 
+std::string printQualifiedName(const NamedDecl &ND) {
+  std::string QName;
+  llvm::raw_string_ostream OS(QName);
+  PrintingPolicy Policy(ND.getASTContext().getLangOpts());
+  // Note that inline namespaces are treated as transparent scopes. This
+  // reflects the way they're most commonly used for lookup. Ideally we'd
+  // include them, but at query time it's hard to find all the inline
+  // namespaces to query: the preamble doesn't have a dedicated list.
+  Policy.SuppressUnwrittenScope = true;
+  ND.printQualifiedName(OS, Policy);
+  OS.flush();
+  assert(!StringRef(QName).startswith("::"));
+  return QName;
+}
+
 } // namespace clangd
 } // namespace clang

Modified: clang-tools-extra/trunk/clangd/AST.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/AST.h?rev=335334&r1=335333&r2=335334&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/AST.h (original)
+++ clang-tools-extra/trunk/clangd/AST.h Fri Jun 22 03:46:59 2018
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H_
 
+#include "clang/AST/Decl.h"
 #include "clang/Basic/SourceLocation.h"
 
 namespace clang {
@@ -28,6 +29,10 @@ namespace clangd {
 /// decl occurs in the code.
 SourceLocation findNameLoc(const clang::Decl *D);
 
+/// Returns the qualified name of ND. The scope doesn't contain unwritten scopes
+/// like inline namespaces.
+std::string printQualifiedName(const NamedDecl &ND);
+
 } // namespace clangd
 } // namespace clang
 

Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=335334&r1=335333&r2=335334&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original)
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Fri Jun 22 03:46:59 2018
@@ -19,6 +19,7 @@
 //===---------------------------------------------------------------------===//
 
 #include "CodeComplete.h"
+#include "AST.h"
 #include "CodeCompletionStrings.h"
 #include "Compiler.h"
 #include "FuzzyMatch.h"
@@ -243,6 +244,8 @@ struct CompletionCandidate {
                        const IncludeInserter &Includes,
                        llvm::StringRef SemaDocComment) const {
     assert(bool(SemaResult) == bool(SemaCCS));
+    assert(SemaResult || IndexResult);
+
     CompletionItem I;
     bool InsertingInclude = false; // Whether a new #include will be added.
     if (SemaResult) {
@@ -253,8 +256,14 @@ struct CompletionCandidate {
         I.filterText = Text;
       I.documentation = formatDocumentation(*SemaCCS, SemaDocComment);
       I.detail = getDetail(*SemaCCS);
+      if (SemaResult->Kind == CodeCompletionResult::RK_Declaration)
+        if (const auto *D = SemaResult->getDeclaration())
+          if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
+            I.SymbolScope = splitQualifiedName(printQualifiedName(*ND)).first;
     }
     if (IndexResult) {
+      if (I.SymbolScope.empty())
+        I.SymbolScope = IndexResult->Scope;
       if (I.kind == CompletionItemKind::Missing)
         I.kind = toCompletionItemKind(IndexResult->SymInfo.Kind);
       // FIXME: reintroduce a way to show the index source for debugging.

Modified: clang-tools-extra/trunk/clangd/Protocol.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=335334&r1=335333&r2=335334&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.h (original)
+++ clang-tools-extra/trunk/clangd/Protocol.h Fri Jun 22 03:46:59 2018
@@ -734,6 +734,12 @@ struct CompletionItem {
   //
   // data?: any - A data entry field that is preserved on a completion item
   //              between a completion and a completion resolve request.
+
+  // C++ extension that is only expected to be used by users of ClangdServer's
+  // C++ API. Not serialized from/to json.
+  /// The containing scope (e.g. namespace) of the symbol this item corresponds
+  /// to, e.g. "" (global scope), "ns::" (top-level namespace).
+  std::string SymbolScope;
 };
 json::Expr toJSON(const CompletionItem &);
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CompletionItem &);

Modified: clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp?rev=335334&r1=335333&r2=335334&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp Fri Jun 22 03:46:59 2018
@@ -363,20 +363,9 @@ const Symbol *SymbolCollector::addDeclar
   auto &Ctx = ND.getASTContext();
   auto &SM = Ctx.getSourceManager();
 
-  std::string QName;
-  llvm::raw_string_ostream OS(QName);
-  PrintingPolicy Policy(ASTCtx->getLangOpts());
-  // Note that inline namespaces are treated as transparent scopes. This
-  // reflects the way they're most commonly used for lookup. Ideally we'd
-  // include them, but at query time it's hard to find all the inline
-  // namespaces to query: the preamble doesn't have a dedicated list.
-  Policy.SuppressUnwrittenScope = true;
-  ND.printQualifiedName(OS, Policy);
-  OS.flush();
-  assert(!StringRef(QName).startswith("::"));
-
   Symbol S;
   S.ID = std::move(ID);
+  std::string QName = printQualifiedName(ND);
   std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
   // FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
   // for consistency with CodeCompletionString and a clean name/signature split.

Modified: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp?rev=335334&r1=335333&r2=335334&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Fri Jun 22 03:46:59 2018
@@ -44,6 +44,7 @@ class IgnoreDiagnostics : public Diagnos
 
 // GMock helpers for matching completion items.
 MATCHER_P(Named, Name, "") { return arg.insertText == Name; }
+MATCHER_P(Scope, Name, "") { return arg.SymbolScope == Name; }
 MATCHER_P(Labeled, Label, "") {
   std::string Indented;
   if (!StringRef(Label).startswith(
@@ -1251,6 +1252,17 @@ TEST(CompletionTest, CompleteOnInvalidLi
       Failed());
 }
 
+TEST(CompletionTest, QualifiedNames) {
+  auto Results = completions(
+      R"cpp(
+          namespace ns { int local; void both(); }
+          void f() { ::ns::^ }
+      )cpp",
+      {func("ns::both"), cls("ns::Index")});
+  // We get results from both index and sema, with no duplicates.
+  EXPECT_THAT(Results.items, UnorderedElementsAre(Scope("ns::"), Scope("ns::"),
+                                                  Scope("ns::")));
+}
 
 } // namespace
 } // namespace clangd




More information about the cfe-commits mailing list