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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits