Author: sammccall Date: Wed Jul 4 23:20:41 2018 New Revision: 336309 URL: http://llvm.org/viewvc/llvm-project?rev=336309&view=rev Log: [clangd] Track origins of symbols (various indexes, Sema).
Summary: Surface it in the completion items C++ API, and when a flag is set. Reviewers: ioeric Subscribers: ilya-biryukov, MaskRay, jkorous, cfe-commits Differential Revision: https://reviews.llvm.org/D48938 Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp clang-tools-extra/trunk/clangd/CodeComplete.h clang-tools-extra/trunk/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp clang-tools-extra/trunk/clangd/index/FileIndex.cpp clang-tools-extra/trunk/clangd/index/Index.cpp clang-tools-extra/trunk/clangd/index/Index.h clang-tools-extra/trunk/clangd/index/Merge.cpp clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp clang-tools-extra/trunk/clangd/index/SymbolCollector.h clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original) +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Wed Jul 4 23:20:41 2018 @@ -41,6 +41,7 @@ #include "clang/Sema/Sema.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/Support/Format.h" +#include "llvm/Support/ScopedPrinter.h" #include <queue> // We log detailed candidate here if you run with -debug-only=codecomplete. @@ -266,6 +267,8 @@ struct CodeCompletionBuilder { : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments) { add(C, SemaCCS); if (C.SemaResult) { + Completion.Origin = + static_cast<SymbolOrigin>(Completion.Origin | SymbolOrigin::AST); Completion.Name = llvm::StringRef(SemaCCS->getTypedText()); if (Completion.Scope.empty()) if (C.SemaResult->Kind == CodeCompletionResult::RK_Declaration) @@ -277,6 +280,8 @@ struct CodeCompletionBuilder { toCompletionItemKind(C.SemaResult->Kind, C.SemaResult->Declaration); } if (C.IndexResult) { + Completion.Origin = + static_cast<SymbolOrigin>(Completion.Origin | C.IndexResult->Origin); if (Completion.Scope.empty()) Completion.Scope = C.IndexResult->Scope; if (Completion.Kind == CompletionItemKind::Missing) @@ -1144,17 +1149,18 @@ private: Relevance.NameMatch = *FuzzyScore; else return; - unsigned SemaResult = 0, IndexResult = 0; + SymbolOrigin Origin = SymbolOrigin::Unknown; for (const auto &Candidate : Bundle) { if (Candidate.IndexResult) { Quality.merge(*Candidate.IndexResult); Relevance.merge(*Candidate.IndexResult); - ++IndexResult; + Origin = + static_cast<SymbolOrigin>(Origin | Candidate.IndexResult->Origin); } if (Candidate.SemaResult) { Quality.merge(*Candidate.SemaResult); Relevance.merge(*Candidate.SemaResult); - ++SemaResult; + Origin = static_cast<SymbolOrigin>(Origin | SymbolOrigin::AST); } } @@ -1167,15 +1173,13 @@ private: ? Scores.Total / Relevance.NameMatch : Scores.Quality; - LLVM_DEBUG(llvm::dbgs() << "CodeComplete: " << First.Name << "(" - << IndexResult << " index) " - << "(" << SemaResult << " sema)" - << " = " << Scores.Total << "\n" + LLVM_DEBUG(llvm::dbgs() << "CodeComplete: " << First.Name << " (" << Origin + << ") = " << Scores.Total << "\n" << Quality << Relevance << "\n"); - NSema += bool(SemaResult); - NIndex += bool(IndexResult); - NBoth += SemaResult && IndexResult; + NSema += bool(Origin & SymbolOrigin::AST); + NIndex += bool(Origin & ~SymbolOrigin::AST); + NBoth += (Origin & SymbolOrigin::AST) && (Origin & ~SymbolOrigin::AST); if (Candidates.push({std::move(Bundle), Scores})) Incomplete = true; } @@ -1243,7 +1247,9 @@ CompletionItem CodeCompletion::render(co CompletionItem LSP; LSP.label = (HeaderInsertion ? Opts.IncludeIndicator.Insert : Opts.IncludeIndicator.NoInsert) + + (Opts.ShowOrigins ? "[" + llvm::to_string(Origin) + "]" : "") + RequiredQualifier + Name + Signature; + LSP.kind = Kind; LSP.detail = BundleSize > 1 ? llvm::formatv("[{0} overloads]", BundleSize) : ReturnType; Modified: clang-tools-extra/trunk/clangd/CodeComplete.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.h?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/CodeComplete.h (original) +++ clang-tools-extra/trunk/clangd/CodeComplete.h Wed Jul 4 23:20:41 2018 @@ -67,6 +67,9 @@ struct CodeCompleteOptions { std::string NoInsert = " "; } IncludeIndicator; + /// Expose origins of completion items in the label (for debugging). + bool ShowOrigins = false; + // Populated internally by clangd, do not set. /// If `Index` is set, it is used to augment the code completion /// results. @@ -103,6 +106,7 @@ struct CodeCompletion { // - Documentation may be from one symbol, or a combination of several // Other fields should apply equally to all bundled completions. unsigned BundleSize = 1; + SymbolOrigin Origin = SymbolOrigin::Unknown; // The header through which this symbol could be included. // Quoted string as expected by an #include directive, e.g. "<memory>". // Empty for non-symbol completions, or when not known. Modified: clang-tools-extra/trunk/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp (original) +++ clang-tools-extra/trunk/clangd/global-symbol-builder/GlobalSymbolBuilderMain.cpp Wed Jul 4 23:20:41 2018 @@ -112,6 +112,7 @@ public: CollectorOpts.FallbackDir = AssumedHeaderDir; CollectorOpts.CollectIncludePath = true; CollectorOpts.CountReferences = true; + CollectorOpts.Origin = SymbolOrigin::Static; auto Includes = llvm::make_unique<CanonicalIncludes>(); addSystemHeadersMapping(Includes.get()); CollectorOpts.Includes = Includes.get(); Modified: clang-tools-extra/trunk/clangd/index/FileIndex.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/FileIndex.cpp?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/index/FileIndex.cpp (original) +++ clang-tools-extra/trunk/clangd/index/FileIndex.cpp Wed Jul 4 23:20:41 2018 @@ -27,6 +27,7 @@ SymbolSlab indexAST(ASTContext &AST, std CollectorOpts.CountReferences = false; if (!URISchemes.empty()) CollectorOpts.URISchemes = URISchemes; + CollectorOpts.Origin = SymbolOrigin::Dynamic; SymbolCollector Collector(std::move(CollectorOpts)); Collector.setPreprocessor(PP); Modified: clang-tools-extra/trunk/clangd/index/Index.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Index.cpp?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/index/Index.cpp (original) +++ clang-tools-extra/trunk/clangd/index/Index.cpp Wed Jul 4 23:20:41 2018 @@ -44,6 +44,16 @@ void operator>>(StringRef Str, SymbolID std::copy(HexString.begin(), HexString.end(), ID.HashValue.begin()); } +raw_ostream &operator<<(raw_ostream &OS, SymbolOrigin O) { + if (O == SymbolOrigin::Unknown) + return OS << "unknown"; + constexpr static char Sigils[] = "ADSM4567"; + for (unsigned I = 0; I < sizeof(Sigils); ++I) + if (O & static_cast<SymbolOrigin>(1 << I)) + OS << Sigils[I]; + return OS; +} + raw_ostream &operator<<(raw_ostream &OS, const Symbol &S) { return OS << S.Scope << S.Name; } Modified: clang-tools-extra/trunk/clangd/index/Index.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Index.h?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/index/Index.h (original) +++ clang-tools-extra/trunk/clangd/index/Index.h Wed Jul 4 23:20:41 2018 @@ -117,6 +117,19 @@ template <> struct DenseMapInfo<clang::c namespace clang { namespace clangd { +// Describes the source of information about a symbol. +// Mainly useful for debugging, e.g. understanding code completion reuslts. +// This is a bitfield as information can be combined from several sources. +enum SymbolOrigin : uint8_t { + Unknown = 0, + AST = 1 << 0, // Directly from the AST (indexes should not set this). + Dynamic = 1 << 1, // From the dynamic index of opened files. + Static = 1 << 2, // From the static, externally-built index. + Merge = 1 << 3, // A non-trivial index merge was performed. + // Remaining bits reserved for index implementations. +}; +raw_ostream &operator<<(raw_ostream &, SymbolOrigin); + // The class presents a C++ symbol, e.g. class, function. // // WARNING: Symbols do not own much of their underlying data - typically strings @@ -157,6 +170,8 @@ struct Symbol { /// Whether or not this symbol is meant to be used for the code completion. /// See also isIndexedForCodeCompletion(). bool IsIndexedForCodeCompletion = false; + /// Where this symbol came from. Usually an index provides a constant value. + SymbolOrigin Origin = Unknown; /// A brief description of the symbol that can be appended in the completion /// candidate list. For example, "(X x, Y y) const" is a function signature. llvm::StringRef Signature; Modified: clang-tools-extra/trunk/clangd/index/Merge.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Merge.cpp?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/index/Merge.cpp (original) +++ clang-tools-extra/trunk/clangd/index/Merge.cpp Wed Jul 4 23:20:41 2018 @@ -115,6 +115,9 @@ mergeSymbol(const Symbol &L, const Symbo } else S.Detail = O.Detail; } + + S.Origin = + static_cast<SymbolOrigin>(S.Origin | O.Origin | SymbolOrigin::Merge); return S; } 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=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp (original) +++ clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp Wed Jul 4 23:20:41 2018 @@ -411,6 +411,7 @@ const Symbol *SymbolCollector::addDeclar Detail.IncludeHeader = Include; S.Detail = &Detail; + S.Origin = Opts.Origin; Symbols.insert(S); return Symbols.find(S.ID); } Modified: clang-tools-extra/trunk/clangd/index/SymbolCollector.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/SymbolCollector.h?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/index/SymbolCollector.h (original) +++ clang-tools-extra/trunk/clangd/index/SymbolCollector.h Wed Jul 4 23:20:41 2018 @@ -52,6 +52,8 @@ public: const CanonicalIncludes *Includes = nullptr; // Populate the Symbol.References field. bool CountReferences = false; + // Every symbol collected will be stamped with this origin. + SymbolOrigin Origin = SymbolOrigin::Unknown; }; SymbolCollector(Options Opts); Modified: clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp (original) +++ clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp Wed Jul 4 23:20:41 2018 @@ -143,6 +143,12 @@ static llvm::cl::opt<bool> EnableIndex( "Clang uses an index built from symbols in opened files"), llvm::cl::init(true)); +static llvm::cl::opt<bool> + ShowOrigins("debug-origin", + llvm::cl::desc("Show origins of completion items"), + llvm::cl::init(clangd::CodeCompleteOptions().ShowOrigins), + llvm::cl::Hidden); + static llvm::cl::opt<Path> YamlSymbolFile( "yaml-symbol-file", llvm::cl::desc( @@ -261,6 +267,7 @@ int main(int argc, char *argv[]) { CCOpts.IncludeIneligibleResults = IncludeIneligibleResults; CCOpts.Limit = LimitResults; CCOpts.BundleOverloads = CompletionStyle != Detailed; + CCOpts.ShowOrigins = ShowOrigins; // Initialize and run ClangdLSPServer. ClangdLSPServer LSPServer(Out, CCOpts, CompileCommandsDirPath, Opts); 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=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Wed Jul 4 23:20:41 2018 @@ -59,6 +59,7 @@ MATCHER_P(InsertInclude, IncludeHeader, } MATCHER(InsertInclude, "") { return bool(arg.HeaderInsertion); } MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; } +MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; } // Shorthand for Contains(Named(Name)). Matcher<const std::vector<CodeCompletion> &> Has(std::string Name) { @@ -137,6 +138,7 @@ Symbol sym(StringRef QName, index::Symbo Sym.ID = SymbolID(USR); Sym.SymInfo.Kind = Kind; Sym.IsIndexedForCodeCompletion = true; + Sym.Origin = SymbolOrigin::Static; return Sym; } Symbol func(StringRef Name) { // Assumes the function has no args. @@ -511,9 +513,12 @@ TEST(CompletionTest, SemaIndexMerge) { )cpp", {func("ns::both"), cls("ns::Index")}); // We get results from both index and sema, with no duplicates. - EXPECT_THAT( - Results.Completions, - UnorderedElementsAre(Named("local"), Named("Index"), Named("both"))); + EXPECT_THAT(Results.Completions, + UnorderedElementsAre( + AllOf(Named("local"), Origin(SymbolOrigin::AST)), + AllOf(Named("Index"), Origin(SymbolOrigin::Static)), + AllOf(Named("both"), + Origin(SymbolOrigin::AST | SymbolOrigin::Static)))); } TEST(CompletionTest, SemaIndexMergeWithLimit) { @@ -1252,6 +1257,8 @@ TEST(CompletionTest, Render) { C.Header = "\"foo.h\""; C.Kind = CompletionItemKind::Method; C.Score.Total = 1.0; + C.Origin = + static_cast<SymbolOrigin>(SymbolOrigin::AST | SymbolOrigin::Static); CodeCompleteOptions Opts; Opts.IncludeIndicator.Insert = "^"; @@ -1278,6 +1285,10 @@ TEST(CompletionTest, Render) { EXPECT_EQ(R.label, "^Foo::x(bool) const"); EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty())); + Opts.ShowOrigins = true; + R = C.render(Opts); + EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const"); + C.BundleSize = 2; R = C.render(Opts); EXPECT_EQ(R.detail, "[2 overloads]\n\"foo.h\""); Modified: clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/IndexTests.cpp Wed Jul 4 23:20:41 2018 @@ -282,6 +282,8 @@ TEST(MergeTest, Merge) { DetR.Documentation = "--doc--"; L.Detail = &DetL; R.Detail = &DetR; + L.Origin = SymbolOrigin::Dynamic; + R.Origin = SymbolOrigin::Static; Symbol::Details Scratch; Symbol M = mergeSymbol(L, R, &Scratch); @@ -293,6 +295,8 @@ TEST(MergeTest, Merge) { ASSERT_TRUE(M.Detail); EXPECT_EQ(M.Detail->ReturnType, "DetL"); EXPECT_EQ(M.Detail->Documentation, "--doc--"); + EXPECT_EQ(M.Origin, + SymbolOrigin::Dynamic | SymbolOrigin::Static | SymbolOrigin::Merge); } TEST(MergeTest, PreferSymbolWithDefn) { Modified: clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp?rev=336309&r1=336308&r2=336309&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp Wed Jul 4 23:20:41 2018 @@ -985,6 +985,13 @@ TEST_F(SymbolCollectorTest, ReferencesIn AllOf(QName("Y"), Refs(1)))); } +TEST_F(SymbolCollectorTest, Origin) { + CollectorOpts.Origin = SymbolOrigin::Static; + runSymbolCollector("class Foo {};", /*Main=*/""); + EXPECT_THAT(Symbols, UnorderedElementsAre( + Field(&Symbol::Origin, SymbolOrigin::Static))); +} + } // namespace } // namespace clangd } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits