[clang] [clang-tools-extra] [llvm] [clangd] introduce doxygen parser (PR #150790)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 6 14:27:33 PDT 2025
================
@@ -1388,9 +1393,166 @@ static std::string formatOffset(uint64_t OffsetInBits) {
return Offset;
}
-markup::Document HoverInfo::present() const {
+markup::Document HoverInfo::presentDoxygen() const {
+ // NOTE: this function is currently almost identical to presentDefault().
+ // This is to have a minimal change when introducing the doxygen parser.
+ // This function will be changed when rearranging the output for doxygen
+ // parsed documentation.
+
markup::Document Output;
+ // Header contains a text of the form:
+ // variable `var`
+ //
+ // class `X`
+ //
+ // function `foo`
+ //
+ // expression
+ //
+ // Note that we are making use of a level-3 heading because VSCode renders
+ // level 1 and 2 headers in a huge font, see
+ // https://github.com/microsoft/vscode/issues/88417 for details.
+ markup::Paragraph &Header = Output.addHeading(3);
+ if (Kind != index::SymbolKind::Unknown)
+ Header.appendText(index::getSymbolKindString(Kind)).appendSpace();
+ assert(!Name.empty() && "hover triggered on a nameless symbol");
+
+ Header.appendCode(Name);
+
+ if (!Provider.empty()) {
+ markup::Paragraph &DI = Output.addParagraph();
+ DI.appendText("provided by");
+ DI.appendSpace();
+ DI.appendCode(Provider);
+ Output.addRuler();
+ }
+
+ // Put a linebreak after header to increase readability.
+ Output.addRuler();
+ // Print Types on their own lines to reduce chances of getting line-wrapped by
+ // editor, as they might be long.
+ if (ReturnType) {
+ // For functions we display signature in a list form, e.g.:
+ // → `x`
+ // Parameters:
+ // - `bool param1`
+ // - `int param2 = 5`
+ Output.addParagraph().appendText("→ ").appendCode(
+ llvm::to_string(*ReturnType));
+ }
+
+ SymbolDocCommentVisitor SymbolDoc(Documentation, CommentOpts);
+
+ if (Parameters && !Parameters->empty()) {
+ Output.addParagraph().appendText("Parameters:");
+ markup::BulletList &L = Output.addBulletList();
+ for (const auto &Param : *Parameters) {
+ markup::Paragraph &P = L.addItem().addParagraph();
+ P.appendCode(llvm::to_string(Param));
+
+ if (SymbolDoc.isParameterDocumented(llvm::to_string(Param.Name))) {
+ P.appendText(" -");
+ SymbolDoc.parameterDocToMarkup(llvm::to_string(Param.Name), P);
+ }
+ }
+ }
+ // Don't print Type after Parameters or ReturnType as this will just duplicate
+ // the information
+ if (Type && !ReturnType && !Parameters)
+ Output.addParagraph().appendText("Type: ").appendCode(
+ llvm::to_string(*Type));
+
+ if (Value) {
+ markup::Paragraph &P = Output.addParagraph();
+ P.appendText("Value = ");
+ P.appendCode(*Value);
+ }
+
+ if (Offset)
+ Output.addParagraph().appendText("Offset: " + formatOffset(*Offset));
+ if (Size) {
+ auto &P = Output.addParagraph().appendText("Size: " + formatSize(*Size));
+ if (Padding && *Padding != 0) {
+ P.appendText(
+ llvm::formatv(" (+{0} padding)", formatSize(*Padding)).str());
+ }
+ if (Align)
+ P.appendText(", alignment " + formatSize(*Align));
+ }
+ if (CalleeArgInfo) {
+ assert(CallPassType);
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ OS << "Passed ";
+ if (CallPassType->PassBy != HoverInfo::PassType::Value) {
+ OS << "by ";
+ if (CallPassType->PassBy == HoverInfo::PassType::ConstRef)
+ OS << "const ";
+ OS << "reference ";
+ }
+ if (CalleeArgInfo->Name)
+ OS << "as " << CalleeArgInfo->Name;
+ else if (CallPassType->PassBy == HoverInfo::PassType::Value)
+ OS << "by value";
+ if (CallPassType->Converted && CalleeArgInfo->Type)
+ OS << " (converted to " << CalleeArgInfo->Type->Type << ")";
+ Output.addParagraph().appendText(OS.str());
+ }
+
+ SymbolDoc.docToMarkup(Output);
+
+ if (!Definition.empty()) {
+ Output.addRuler();
+ std::string Buffer;
+
+ if (!Definition.empty()) {
+ // Append scope comment, dropping trailing "::".
+ // Note that we don't print anything for global namespace, to not annoy
+ // non-c++ projects or projects that are not making use of namespaces.
+ if (!LocalScope.empty()) {
+ // Container name, e.g. class, method, function.
+ // We might want to propagate some info about container type to print
+ // function foo, class X, method X::bar, etc.
+ Buffer +=
+ "// In " + llvm::StringRef(LocalScope).rtrim(':').str() + '\n';
+ } else if (NamespaceScope && !NamespaceScope->empty()) {
+ Buffer += "// In namespace " +
+ llvm::StringRef(*NamespaceScope).rtrim(':').str() + '\n';
+ }
+
+ if (!AccessSpecifier.empty()) {
+ Buffer += AccessSpecifier + ": ";
+ }
+
+ Buffer += Definition;
+ }
+
+ Output.addCodeBlock(Buffer, DefinitionLanguage);
+ }
+
+ if (!UsedSymbolNames.empty()) {
+ Output.addRuler();
+ markup::Paragraph &P = Output.addParagraph();
+ P.appendText("provides ");
+
+ const std::vector<std::string>::size_type SymbolNamesLimit = 5;
----------------
tcottin wrote:
I refactored the common parts into own functions now
https://github.com/llvm/llvm-project/pull/150790
More information about the llvm-commits
mailing list