tom-anders created this revision. Herald added subscribers: wenlei, kadircet, arphaman. Herald added a project: All. tom-anders added reviewers: nridge, sammccall, kadircet. tom-anders published this revision for review. Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov. Herald added a project: clang-tools-extra.
This stores SymbolDocumentation in the index and uses it in Hover. CodeCompletion and SignatureHelp still use the unparsed comment for now. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D134132 Files: clang-tools-extra/clangd/CodeComplete.cpp clang-tools-extra/clangd/Hover.cpp clang-tools-extra/clangd/index/Merge.cpp clang-tools-extra/clangd/index/Serialization.cpp clang-tools-extra/clangd/index/Symbol.h clang-tools-extra/clangd/index/SymbolCollector.cpp clang-tools-extra/clangd/index/YAMLSerialization.cpp clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp clang-tools-extra/clangd/unittests/HoverTests.cpp clang-tools-extra/clangd/unittests/IndexTests.cpp clang-tools-extra/clangd/unittests/SerializationTests.cpp clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp +++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp @@ -50,7 +50,7 @@ return (arg.Name + arg.Signature).str() == Label; } MATCHER_P(returnType, D, "") { return arg.ReturnType == D; } -MATCHER_P(doc, D, "") { return arg.Documentation == D; } +MATCHER_P(doc, D, "") { return arg.Documentation.CommentText == D; } MATCHER_P(snippet, S, "") { return (arg.Name + arg.CompletionSnippetSuffix).str() == S; } Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/SerializationTests.cpp +++ clang-tools-extra/clangd/unittests/SerializationTests.cpp @@ -8,6 +8,7 @@ #include "Headers.h" #include "RIFF.h" +#include "SymbolDocumentationMatchers.h" #include "index/Serialization.h" #include "support/Logger.h" #include "clang/Tooling/CompilationDatabase.h" @@ -48,7 +49,22 @@ Line: 1 Column: 1 Flags: 129 -Documentation: 'Foo doc' +Documentation: + Brief: 'Foo brief' + Returns: 'Foo returns' + Description: 'Foo description' + Notes: + - 'Foo note 1' + - 'Foo note 2' + Warnings: + - 'Foo warning 1' + - 'Foo warning 2' + Parameters: + - Name: 'param1' + Description: 'Foo param 1' + - Name: 'param2' + Description: 'Foo param 2' + CommentText: 'Full text would be here' ReturnType: 'int' IncludeHeaders: - Header: 'include1' @@ -141,7 +157,20 @@ EXPECT_THAT(Sym1, qName("clang::Foo1")); EXPECT_EQ(Sym1.Signature, ""); - EXPECT_EQ(Sym1.Documentation, "Foo doc"); + + SymbolDocumentationRef ExpectedDocumentation; + ExpectedDocumentation.Brief = "Foo brief"; + ExpectedDocumentation.Returns = "Foo returns"; + ExpectedDocumentation.Description = "Foo description"; + ExpectedDocumentation.Notes = {"Foo note 1", "Foo note 2"}; + ExpectedDocumentation.Warnings = {"Foo warning 1", "Foo warning 2"}; + ExpectedDocumentation.Parameters = { + {"param1", "Foo param 1"}, + {"param2", "Foo param 2"}, + }; + ExpectedDocumentation.CommentText = "Full text would be here"; + EXPECT_THAT(Sym1.Documentation, matchesDoc(ExpectedDocumentation)); + EXPECT_EQ(Sym1.ReturnType, "int"); EXPECT_EQ(StringRef(Sym1.CanonicalDeclaration.FileURI), "file:///path/foo.h"); EXPECT_EQ(Sym1.Origin, SymbolOrigin::Static); Index: clang-tools-extra/clangd/unittests/IndexTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/IndexTests.cpp +++ clang-tools-extra/clangd/unittests/IndexTests.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Annotations.h" +#include "SymbolDocumentationMatchers.h" #include "SyncAPI.h" #include "TestIndex.h" #include "TestTU.h" @@ -391,7 +392,7 @@ R.References = 2; L.Signature = "()"; // present in left only R.CompletionSnippetSuffix = "{$1:0}"; // present in right only - R.Documentation = "--doc--"; + R.Documentation = SymbolDocumentationRef::descriptionOnly("--doc--"); L.Origin = SymbolOrigin::Preamble; R.Origin = SymbolOrigin::Static; R.Type = "expectedType"; @@ -402,7 +403,8 @@ EXPECT_EQ(M.References, 3u); EXPECT_EQ(M.Signature, "()"); EXPECT_EQ(M.CompletionSnippetSuffix, "{$1:0}"); - EXPECT_EQ(M.Documentation, "--doc--"); + EXPECT_THAT(M.Documentation, + matchesDoc(SymbolDocumentationRef::descriptionOnly("--doc--"))); EXPECT_EQ(M.Type, "expectedType"); EXPECT_EQ(M.Origin, SymbolOrigin::Preamble | SymbolOrigin::Static | SymbolOrigin::Merge); @@ -546,16 +548,18 @@ Symbol L, R; L.ID = R.ID = SymbolID("x"); L.Definition.FileURI = "file:/x.h"; - R.Documentation = "Forward declarations because x.h is too big to include"; + R.Documentation = SymbolDocumentationRef::descriptionOnly( + "Forward declarations because x.h is too big to include"); for (auto ClassLikeKind : {SymbolKind::Class, SymbolKind::Struct, SymbolKind::Union}) { L.SymInfo.Kind = ClassLikeKind; - EXPECT_EQ(mergeSymbol(L, R).Documentation, ""); + ASSERT_TRUE(mergeSymbol(L, R).Documentation.empty()); } L.SymInfo.Kind = SymbolKind::Function; - R.Documentation = "Documentation from non-class symbols should be included"; - EXPECT_EQ(mergeSymbol(L, R).Documentation, R.Documentation); + R.Documentation = SymbolDocumentationRef::descriptionOnly( + "Documentation from non-class symbols should be included"); + EXPECT_THAT(mergeSymbol(L, R).Documentation, matchesDoc(R.Documentation)); } MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") { Index: clang-tools-extra/clangd/unittests/HoverTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HoverTests.cpp +++ clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -2770,7 +2770,8 @@ // Create a tiny index, so tests above can verify documentation is fetched. Symbol IndexSym = func("indexSymbol"); - IndexSym.Documentation = "comment from index"; + IndexSym.Documentation = + SymbolDocumentationRef::descriptionOnly("comment from index"); SymbolSlab::Builder Symbols; Symbols.insert(IndexSym); auto Index = @@ -2827,7 +2828,8 @@ auto AST = TU.build(); Symbol IndexSym; IndexSym.ID = getSymbolID(&findDecl(AST, "X")); - IndexSym.Documentation = "comment from index"; + IndexSym.Documentation = + SymbolDocumentationRef::descriptionOnly("comment from index"); SymbolSlab::Builder Symbols; Symbols.insert(IndexSym); auto Index = @@ -2836,9 +2838,7 @@ for (const auto &P : T.points()) { auto H = getHover(AST, P, format::getLLVMStyle(), Index.get()); ASSERT_TRUE(H); - ASSERT_THAT(H->Documentation, - matchesDoc(SymbolDocumentationOwned::descriptionOnly( - std::string(IndexSym.Documentation)))); + ASSERT_THAT(H->Documentation.toRef(), matchesDoc(IndexSym.Documentation)); } } Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -2335,9 +2335,9 @@ TEST(SignatureHelpTest, IndexDocumentation) { Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#"); - Foo0.Documentation = "doc from the index"; + Foo0.Documentation.CommentText = "doc from the index"; Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#"); - Foo1.Documentation = "doc from the index"; + Foo1.Documentation.CommentText = "doc from the index"; Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#"); StringRef Sig0 = R"cpp( Index: clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp =================================================================== --- clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp +++ clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp @@ -3,6 +3,11 @@ // This introduces a symbol, a reference and a relation. struct Bar : public Foo { - // This introduces an OverriddenBy relation by implementing Foo::Func. + /// \brief This introduces an OverriddenBy relation by implementing Foo::Func. + /// \details And it also introduces some doxygen! + /// \param foo bar + /// \warning !!! + /// \note a note + /// \return nothing void Func() override {} }; Index: clang-tools-extra/clangd/index/YAMLSerialization.cpp =================================================================== --- clang-tools-extra/clangd/index/YAMLSerialization.cpp +++ clang-tools-extra/clangd/index/YAMLSerialization.cpp @@ -30,6 +30,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Symbol::IncludeHeaderWithReferences) LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Ref) +LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::ParameterDocumentationRef) namespace { using RefBundle = @@ -59,11 +60,13 @@ using clang::clangd::FileDigest; using clang::clangd::IncludeGraph; using clang::clangd::IncludeGraphNode; +using clang::clangd::ParameterDocumentationRef; using clang::clangd::Ref; using clang::clangd::RefKind; using clang::clangd::Relation; using clang::clangd::RelationKind; using clang::clangd::Symbol; +using clang::clangd::SymbolDocumentationRef; using clang::clangd::SymbolID; using clang::clangd::SymbolLocation; using clang::index::SymbolInfo; @@ -174,6 +177,28 @@ } }; +template <> struct MappingTraits<ParameterDocumentationRef> { + static void mapping(IO &IO, ParameterDocumentationRef &P) { + IO.mapRequired("Name", P.Name); + IO.mapRequired("Description", P.Description); + } +}; + +template <> struct MappingTraits<SymbolDocumentationRef> { + static void mapping(IO &IO, SymbolDocumentationRef &Doc) { + IO.mapOptional("Brief", Doc.Brief); + IO.mapOptional("Returns", Doc.Returns); + + IO.mapOptional("Notes", Doc.Notes); + IO.mapOptional("Warnings", Doc.Warnings); + + IO.mapOptional("Parameters", Doc.Parameters); + + IO.mapOptional("Description", Doc.Description); + IO.mapOptional("CommentText", Doc.CommentText); + } +}; + template <> struct MappingTraits<Symbol> { static void mapping(IO &IO, Symbol &Sym) { MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, Sym.ID); Index: clang-tools-extra/clangd/index/SymbolCollector.cpp =================================================================== --- clang-tools-extra/clangd/index/SymbolCollector.cpp +++ clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -912,17 +912,17 @@ *ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator, *CompletionTUInfo, /*IncludeBriefComments*/ false); - std::string Documentation = - formatDocumentation(*CCS, getDocumentation(Ctx, SymbolCompletion, - /*CommentsFromHeaders=*/true) - .CommentText); + + const SymbolDocumentationOwned Documentation = + getDocumentation(Ctx, SymbolCompletion, /*CommentsFromHeaders=*/true); + if (!(S.Flags & Symbol::IndexedForCodeCompletion)) { if (Opts.StoreAllDocumentation) - S.Documentation = Documentation; + S.Documentation = Documentation.toRef(); Symbols.insert(S); return Symbols.find(S.ID); } - S.Documentation = Documentation; + S.Documentation = Documentation.toRef(); std::string Signature; std::string SnippetSuffix; getSignature(*CCS, &Signature, &SnippetSuffix); Index: clang-tools-extra/clangd/index/Symbol.h =================================================================== --- clang-tools-extra/clangd/index/Symbol.h +++ clang-tools-extra/clangd/index/Symbol.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_H +#include "SymbolDocumentation.h" #include "index/SymbolID.h" #include "index/SymbolLocation.h" #include "index/SymbolOrigin.h" @@ -73,7 +74,7 @@ /// Only set when the symbol is indexed for completion. llvm::StringRef CompletionSnippetSuffix; /// Documentation including comment for the symbol declaration. - llvm::StringRef Documentation; + SymbolDocumentationRef 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. @@ -150,7 +151,20 @@ CB(S.TemplateSpecializationArgs); CB(S.Signature); CB(S.CompletionSnippetSuffix); - CB(S.Documentation); + + CB(S.Documentation.Brief); + CB(S.Documentation.Returns); + for (auto &Note : S.Documentation.Notes) + CB(Note); + for (auto &Warning : S.Documentation.Warnings) + CB(Warning); + for (auto &ParamDoc : S.Documentation.Parameters) { + CB(ParamDoc.Name); + CB(ParamDoc.Description); + } + CB(S.Documentation.Description); + CB(S.Documentation.CommentText); + CB(S.ReturnType); CB(S.Type); auto RawCharPointerCB = [&CB](const char *&P) { Index: clang-tools-extra/clangd/index/Serialization.cpp =================================================================== --- clang-tools-extra/clangd/index/Serialization.cpp +++ clang-tools-extra/clangd/index/Serialization.cpp @@ -283,6 +283,57 @@ return Loc; } +void writeSymbolDocumentation(const SymbolDocumentationRef &Doc, + const StringTableOut &Strings, + llvm::raw_ostream &OS) { + writeVar(Strings.index(Doc.Brief), OS); + writeVar(Strings.index(Doc.Returns), OS); + + writeVar(Doc.Notes.size(), OS); + for (const auto &Note : Doc.Notes) + writeVar(Strings.index(Note), OS); + + writeVar(Doc.Warnings.size(), OS); + for (const auto &Warning : Doc.Warnings) + writeVar(Strings.index(Warning), OS); + + writeVar(Doc.Parameters.size(), OS); + for (const auto &ParamDoc : Doc.Parameters) { + writeVar(Strings.index(ParamDoc.Name), OS); + writeVar(Strings.index(ParamDoc.Description), OS); + } + + writeVar(Strings.index(Doc.Description), OS); + writeVar(Strings.index(Doc.CommentText), OS); +} + +SymbolDocumentationRef +readSymbolDocumentation(Reader &Data, llvm::ArrayRef<llvm::StringRef> Strings) { + SymbolDocumentationRef Doc; + Doc.Brief = Data.consumeString(Strings); + Doc.Returns = Data.consumeString(Strings); + + if (!Data.consumeSize(Doc.Notes)) + return Doc; + for (auto &Note : Doc.Notes) + Note = Data.consumeString(Strings); + + if (!Data.consumeSize(Doc.Warnings)) + return Doc; + for (auto &Warning : Doc.Warnings) + Warning = Data.consumeString(Strings); + + if (!Data.consumeSize(Doc.Parameters)) + return Doc; + for (auto &ParamDoc : Doc.Parameters) + ParamDoc = {Data.consumeString(Strings), Data.consumeString(Strings)}; + + Doc.Description = Data.consumeString(Strings); + Doc.CommentText = Data.consumeString(Strings); + + return Doc; +} + IncludeGraphNode readIncludeGraphNode(Reader &Data, llvm::ArrayRef<llvm::StringRef> Strings) { IncludeGraphNode IGN; @@ -325,7 +376,7 @@ OS.write(static_cast<uint8_t>(Sym.Flags)); writeVar(Strings.index(Sym.Signature), OS); writeVar(Strings.index(Sym.CompletionSnippetSuffix), OS); - writeVar(Strings.index(Sym.Documentation), OS); + writeSymbolDocumentation(Sym.Documentation, Strings, OS); writeVar(Strings.index(Sym.ReturnType), OS); writeVar(Strings.index(Sym.Type), OS); @@ -354,7 +405,7 @@ Sym.Origin = Origin; Sym.Signature = Data.consumeString(Strings); Sym.CompletionSnippetSuffix = Data.consumeString(Strings); - Sym.Documentation = Data.consumeString(Strings); + Sym.Documentation = readSymbolDocumentation(Data, Strings); Sym.ReturnType = Data.consumeString(Strings); Sym.Type = Data.consumeString(Strings); if (!Data.consumeSize(Sym.IncludeHeaders)) @@ -455,7 +506,7 @@ // The current versioning scheme is simple - non-current versions are rejected. // If you make a breaking change, bump this version number to invalidate stored // data. Later we may want to support some backward compatibility. -constexpr static uint32_t Version = 17; +constexpr static uint32_t Version = 18; llvm::Expected<IndexFileIn> readRIFF(llvm::StringRef Data, SymbolOrigin Origin) { Index: clang-tools-extra/clangd/index/Merge.cpp =================================================================== --- clang-tools-extra/clangd/index/Merge.cpp +++ clang-tools-extra/clangd/index/Merge.cpp @@ -227,7 +227,7 @@ S.Signature = O.Signature; if (S.CompletionSnippetSuffix == "") S.CompletionSnippetSuffix = O.CompletionSnippetSuffix; - if (S.Documentation == "") { + if (S.Documentation.empty()) { // Don't accept documentation from bare forward class declarations, if there // is a definition and it didn't provide one. S is often an undocumented // class, and O is a non-canonical forward decl preceded by an irrelevant Index: clang-tools-extra/clangd/Hover.cpp =================================================================== --- clang-tools-extra/clangd/Hover.cpp +++ clang-tools-extra/clangd/Hover.cpp @@ -333,8 +333,7 @@ LookupRequest Req; Req.IDs.insert(ID); Index->lookup(Req, [&](const Symbol &S) { - Hover.Documentation = - SymbolDocumentationOwned::descriptionOnly(std::string(S.Documentation)); + Hover.Documentation = S.Documentation.toOwned(); }); } Index: clang-tools-extra/clangd/CodeComplete.cpp =================================================================== --- clang-tools-extra/clangd/CodeComplete.cpp +++ clang-tools-extra/clangd/CodeComplete.cpp @@ -425,12 +425,11 @@ } }; if (C.IndexResult) { - SetDoc(C.IndexResult->Documentation); + SetDoc(C.IndexResult->Documentation.CommentText); } else if (C.SemaResult) { const auto DocComment = getDocumentation(*ASTCtx, *C.SemaResult, - /*CommentsFromHeaders=*/false) - .CommentText; - SetDoc(formatDocumentation(*SemaCCS, DocComment)); + /*CommentsFromHeaders=*/false); + SetDoc(formatDocumentation(*SemaCCS, DocComment.CommentText)); } } if (Completion.Deprecated) { @@ -985,8 +984,7 @@ Candidate.getFunction() ? getDeclDocumentation(S.getASTContext(), *Candidate.getFunction()) - .CommentText - : "")); + : SymbolDocumentationOwned{})); } // Sema does not load the docs from the preamble, so we need to fetch extra @@ -1001,7 +999,7 @@ } Index->lookup(IndexRequest, [&](const Symbol &S) { if (!S.Documentation.empty()) - FetchedDocs[S.ID] = std::string(S.Documentation); + FetchedDocs[S.ID] = std::string(S.Documentation.CommentText); }); vlog("SigHelp: requested docs for {0} symbols from the index, got {1} " "symbols with non-empty docs in the response", @@ -1110,15 +1108,17 @@ // FIXME(ioeric): consider moving CodeCompletionString logic here to // CompletionString.h. - ScoredSignature processOverloadCandidate(const OverloadCandidate &Candidate, - const CodeCompletionString &CCS, - llvm::StringRef DocComment) const { + ScoredSignature + processOverloadCandidate(const OverloadCandidate &Candidate, + const CodeCompletionString &CCS, + const SymbolDocumentationOwned &DocComment) const { SignatureInformation Signature; SignatureQualitySignals Signal; const char *ReturnType = nullptr; markup::Document OverloadComment; - parseDocumentation(formatDocumentation(CCS, DocComment), OverloadComment); + parseDocumentation(formatDocumentation(CCS, DocComment.CommentText), + OverloadComment); Signature.documentation = renderDoc(OverloadComment, DocumentationFormat); Signal.Kind = Candidate.getKind();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits