Index: clang-tools-extra/trunk/clangd/index/Index.h =================================================================== --- clang-tools-extra/trunk/clangd/index/Index.h +++ clang-tools-extra/trunk/clangd/index/Index.h @@ -185,19 +185,23 @@ SymbolOrigin Origin = SymbolOrigin::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. + /// Only set when the symbol is indexed for completion. llvm::StringRef Signature; /// What to insert when completing this symbol, after the symbol name. /// This is in LSP snippet syntax (e.g. "({$0})" for a no-args function). /// (When snippets are disabled, the symbol name alone is used). + /// Only set when the symbol is indexed for completion. llvm::StringRef CompletionSnippetSuffix; /// Documentation including comment for the symbol declaration. llvm::StringRef Documentation; /// Type when this symbol is used in an expression. (Short display form). /// e.g. return type of a function, or type of a variable. + /// Only set when the symbol is indexed for completion. llvm::StringRef ReturnType; /// Raw representation of the OpaqueType of the symbol, used for scoring /// purposes. + /// Only set when the symbol is indexed for completion. llvm::StringRef Type; struct IncludeHeaderWithReferences { @@ -223,12 +227,15 @@ /// - If we haven't seen a definition, this covers all declarations. /// - If we have seen a definition, this covers declarations visible from /// any definition. + /// Only set when the symbol is indexed for completion. llvm::SmallVector IncludeHeaders; enum SymbolFlag : uint8_t { None = 0, /// Whether or not this symbol is meant to be used for the code completion. /// See also isIndexedForCodeCompletion(). + /// Note that we don't store completion information (signature, snippet, + /// type, inclues) if the symbol is not indexed for code completion. IndexedForCodeCompletion = 1 << 0, /// Indicates if the symbol is deprecated. Deprecated = 1 << 1, Index: clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp =================================================================== --- clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp +++ clang-tools-extra/trunk/clangd/index/SymbolCollector.cpp @@ -530,6 +530,10 @@ getTokenLocation(Loc, SM, Opts, ASTCtx->getLangOpts(), FileURI)) S.CanonicalDeclaration = *DeclLoc; + S.Origin = Opts.Origin; + if (ND.getAvailability() == AR_Deprecated) + S.Flags |= Symbol::Deprecated; + // Add completion info. // FIXME: we may want to choose a different redecl, or combine from several. assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set."); @@ -539,13 +543,28 @@ *ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator, *CompletionTUInfo, /*IncludeBriefComments*/ false); - std::string Signature; - std::string SnippetSuffix; - getSignature(*CCS, &Signature, &SnippetSuffix); std::string Documentation = formatDocumentation(*CCS, getDocComment(Ctx, SymbolCompletion, /*CommentsFromHeaders=*/true)); + // For symbols not indexed for completion (class members), we also store their + // docs in the index, because Sema doesn't load the docs from the preamble, we + // rely on the index to get the docs. + // FIXME: this can be optimized by only storing the docs in dynamic index -- + // dynamic index should index these symbols when Sema completes a member + // completion. + S.Documentation = Documentation; + if (!(S.Flags & Symbol::IndexedForCodeCompletion)) { + Symbols.insert(S); + return Symbols.find(S.ID); + } + + std::string Signature; + std::string SnippetSuffix; + getSignature(*CCS, &Signature, &SnippetSuffix); + S.Signature = Signature; + S.CompletionSnippetSuffix = SnippetSuffix; std::string ReturnType = getReturnType(*CCS); + S.ReturnType = ReturnType; std::string Include; if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) { @@ -555,10 +574,6 @@ QName, SM, SM.getExpansionLoc(ND.getLocation()), Opts)) Include = std::move(*Header); } - S.Signature = Signature; - S.CompletionSnippetSuffix = SnippetSuffix; - S.Documentation = Documentation; - S.ReturnType = ReturnType; if (!Include.empty()) S.IncludeHeaders.emplace_back(Include, 1); @@ -569,9 +584,6 @@ S.Type = TypeStorage->raw(); } - S.Origin = Opts.Origin; - if (ND.getAvailability() == AR_Deprecated) - S.Flags |= Symbol::Deprecated; Symbols.insert(S); return Symbols.find(S.ID); } Index: clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp +++ clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp @@ -654,10 +654,15 @@ void Foo::ssf() {} )"; runSymbolCollector(Header, Main); - EXPECT_THAT(Symbols, - UnorderedElementsAre(QName("Foo"), QName("Foo::f"), - QName("Foo::g"), QName("Foo::sf"), - QName("Foo::ssf"), QName("Foo::x"))); + EXPECT_THAT( + Symbols, + UnorderedElementsAre( + QName("Foo"), + AllOf(QName("Foo::f"), ReturnType(""), ForCodeCompletion(false)), + AllOf(QName("Foo::g"), ReturnType(""), ForCodeCompletion(false)), + AllOf(QName("Foo::sf"), ReturnType(""), ForCodeCompletion(false)), + AllOf(QName("Foo::ssf"), ReturnType(""), ForCodeCompletion(false)), + AllOf(QName("Foo::x"), ReturnType(""), ForCodeCompletion(false)))); } TEST_F(SymbolCollectorTest, Scopes) {