Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions clang-tools-extra/clangd/Hover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1589,13 +1589,11 @@ markup::Document HoverInfo::presentDoxygen() const {
P.appendText(" - ");
SymbolDoc.returnToMarkup(P);
}

SymbolDoc.retvalsToMarkup(Output);
Output.addRuler();
}

// add specially handled doxygen commands.
SymbolDoc.warningsToMarkup(Output);
SymbolDoc.notesToMarkup(Output);

// add any other documentation.
SymbolDoc.docToMarkup(Output);

Expand Down
111 changes: 63 additions & 48 deletions clang-tools-extra/clangd/SymbolDocumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,20 @@ void commandToMarkup(markup::Paragraph &Out, StringRef Command,
StringRef Args) {
Out.appendBoldText(commandMarkerAsString(CommandMarker) + Command.str());
Out.appendSpace();
if (!Args.empty()) {
Out.appendEmphasizedText(Args.str());
if (!Args.empty())
Out.appendCode(Args.str());
}

template <typename T> std::string getArgText(const T *Command) {
std::string ArgText;
for (unsigned I = 0; I < Command->getNumArgs(); ++I) {
if (!ArgText.empty())
ArgText += " ";
ArgText += Command->getArgText(I);
}
return ArgText;
}

} // namespace

class ParagraphToMarkupDocument
Expand Down Expand Up @@ -70,12 +80,7 @@ class ParagraphToMarkupDocument
void visitInlineCommandComment(const comments::InlineCommandComment *C) {

if (C->getNumArgs() > 0) {
std::string ArgText;
for (unsigned I = 0; I < C->getNumArgs(); ++I) {
if (!ArgText.empty())
ArgText += " ";
ArgText += C->getArgText(I);
}
std::string ArgText = getArgText(C);

switch (C->getRenderKind()) {
case comments::InlineCommandRenderKind::Monospaced:
Expand Down Expand Up @@ -158,10 +163,9 @@ class ParagraphToString
void visitInlineCommandComment(const comments::InlineCommandComment *C) {
Out << commandMarkerAsString(C->getCommandMarker());
Out << C->getCommandName(Traits);
if (C->getNumArgs() > 0) {
for (unsigned I = 0; I < C->getNumArgs(); ++I)
Out << " " << C->getArgText(I);
}
std::string ArgText = getArgText(C);
if (!ArgText.empty())
Out << " " << ArgText;
Out << " ";
}

Expand Down Expand Up @@ -210,16 +214,27 @@ class BlockCommentToMarkupDocument
Traits)
.visit(B->getParagraph());
break;
case comments::CommandTraits::KCI_note:
case comments::CommandTraits::KCI_warning:
commandToHeadedParagraph(B);
break;
case comments::CommandTraits::KCI_retval: {
// The \retval command describes the return value given as its single
// argument in the corresponding paragraph.
// Note: We know that we have exactly one argument but not if it has an
// associated paragraph.
auto &P = Out.addParagraph().appendCode(getArgText(B));
if (B->getParagraph() && !B->getParagraph()->isWhitespace()) {
P.appendText(" - ");
ParagraphToMarkupDocument(P, Traits).visit(B->getParagraph());
}
return;
}
default: {
// Some commands have arguments, like \throws.
// The arguments are not part of the paragraph.
// We need reconstruct them here.
std::string ArgText;
for (unsigned I = 0; I < B->getNumArgs(); ++I) {
if (!ArgText.empty())
ArgText += " ";
ArgText += B->getArgText(I);
}
std::string ArgText = getArgText(B);
auto &P = Out.addParagraph();
commandToMarkup(P, B->getCommandName(Traits), B->getCommandMarker(),
ArgText);
Expand Down Expand Up @@ -262,6 +277,19 @@ class BlockCommentToMarkupDocument
markup::Document &Out;
const comments::CommandTraits &Traits;
StringRef CommentEscapeMarker;

/// Emphasize the given command in a paragraph.
/// Uses the command name with the first letter capitalized as the heading.
void commandToHeadedParagraph(const comments::BlockCommandComment *B) {
Out.addRuler();
auto &P = Out.addParagraph();
std::string Heading = B->getCommandName(Traits).slice(0, 1).upper() +
B->getCommandName(Traits).drop_front().str();
P.appendBoldText(Heading + ":");
P.appendText(" \n");
ParagraphToMarkupDocument(P, Traits).visit(B->getParagraph());
Out.addRuler();
}
};

void SymbolDocCommentVisitor::visitBlockCommandComment(
Expand All @@ -282,36 +310,22 @@ void SymbolDocCommentVisitor::visitBlockCommandComment(
}
break;
case comments::CommandTraits::KCI_retval:
RetvalParagraphs.push_back(B->getParagraph());
return;
case comments::CommandTraits::KCI_warning:
WarningParagraphs.push_back(B->getParagraph());
return;
case comments::CommandTraits::KCI_note:
NoteParagraphs.push_back(B->getParagraph());
// Only consider retval commands having an argument.
// The argument contains the described return value which is needed to
// convert it to markup.
if (B->getNumArgs() == 1)
RetvalCommands.push_back(B);
return;
default:
break;
}

// For all other commands, we store them in the UnhandledCommands map.
// For all other commands, we store them in the BlockCommands map.
// This allows us to keep the order of the comments.
UnhandledCommands[CommentPartIndex] = B;
BlockCommands[CommentPartIndex] = B;
CommentPartIndex++;
}

void SymbolDocCommentVisitor::paragraphsToMarkup(
markup::Document &Out,
const llvm::SmallVectorImpl<const comments::ParagraphComment *> &Paragraphs)
const {
if (Paragraphs.empty())
return;

for (const auto *P : Paragraphs) {
ParagraphToMarkupDocument(Out.addParagraph(), Traits).visit(P);
}
}

void SymbolDocCommentVisitor::briefToMarkup(markup::Paragraph &Out) const {
if (!BriefParagraph)
return;
Expand All @@ -324,14 +338,6 @@ void SymbolDocCommentVisitor::returnToMarkup(markup::Paragraph &Out) const {
ParagraphToMarkupDocument(Out, Traits).visit(ReturnParagraph);
}

void SymbolDocCommentVisitor::notesToMarkup(markup::Document &Out) const {
paragraphsToMarkup(Out, NoteParagraphs);
}

void SymbolDocCommentVisitor::warningsToMarkup(markup::Document &Out) const {
paragraphsToMarkup(Out, WarningParagraphs);
}

void SymbolDocCommentVisitor::parameterDocToMarkup(
StringRef ParamName, markup::Paragraph &Out) const {
if (ParamName.empty())
Expand All @@ -354,7 +360,7 @@ void SymbolDocCommentVisitor::parameterDocToString(

void SymbolDocCommentVisitor::docToMarkup(markup::Document &Out) const {
for (unsigned I = 0; I < CommentPartIndex; ++I) {
if (const auto *BC = UnhandledCommands.lookup(I)) {
if (const auto *BC = BlockCommands.lookup(I)) {
BlockCommentToMarkupDocument(Out, Traits).visit(BC);
} else if (const auto *P = FreeParagraphs.lookup(I)) {
ParagraphToMarkupDocument(Out.addParagraph(), Traits).visit(P);
Expand Down Expand Up @@ -382,5 +388,14 @@ void SymbolDocCommentVisitor::templateTypeParmDocToString(
}
}

void SymbolDocCommentVisitor::retvalsToMarkup(markup::Document &Out) const {
if (RetvalCommands.empty())
return;
markup::BulletList &BL = Out.addBulletList();
for (const auto *P : RetvalCommands) {
BlockCommentToMarkupDocument(BL.addItem(), Traits).visit(P);
}
}

} // namespace clangd
} // namespace clang
33 changes: 7 additions & 26 deletions clang-tools-extra/clangd/SymbolDocumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,14 @@ class SymbolDocCommentVisitor

bool hasReturnCommand() const { return ReturnParagraph; }

bool hasRetvalCommands() const { return !RetvalParagraphs.empty(); }

bool hasNoteCommands() const { return !NoteParagraphs.empty(); }

bool hasWarningCommands() const { return !WarningParagraphs.empty(); }

/// Converts all unhandled comment commands to a markup document.
void docToMarkup(markup::Document &Out) const;
/// Converts the "brief" command(s) to a markup document.
void briefToMarkup(markup::Paragraph &Out) const;
/// Converts the "return" command(s) to a markup document.
void returnToMarkup(markup::Paragraph &Out) const;
/// Converts the "note" command(s) to a markup document.
void notesToMarkup(markup::Document &Out) const;
/// Converts the "warning" command(s) to a markup document.
void warningsToMarkup(markup::Document &Out) const;
/// Converts the "retval" command(s) to a markup document.
void retvalsToMarkup(markup::Document &Out) const;

void visitBlockCommandComment(const comments::BlockCommandComment *B);

Expand Down Expand Up @@ -173,19 +165,13 @@ class SymbolDocCommentVisitor
/// Paragraph of the "return" command.
const comments::ParagraphComment *ReturnParagraph = nullptr;

/// Paragraph(s) of the "note" command(s)
llvm::SmallVector<const comments::ParagraphComment *> RetvalParagraphs;
/// All the "retval" command(s)
llvm::SmallVector<const comments::BlockCommandComment *> RetvalCommands;

/// Paragraph(s) of the "note" command(s)
llvm::SmallVector<const comments::ParagraphComment *> NoteParagraphs;

/// Paragraph(s) of the "warning" command(s)
llvm::SmallVector<const comments::ParagraphComment *> WarningParagraphs;

/// All the paragraphs we don't have any special handling for,
/// e.g. "details".
/// All the parsed doxygen block commands.
/// They might have special handling internally like \\note or \\warning
llvm::SmallDenseMap<unsigned, const comments::BlockCommandComment *>
UnhandledCommands;
BlockCommands;

/// Parsed paragaph(s) of the "param" comamnd(s)
llvm::SmallDenseMap<StringRef, const comments::ParamCommandComment *>
Expand All @@ -198,11 +184,6 @@ class SymbolDocCommentVisitor
/// All "free" text paragraphs.
llvm::SmallDenseMap<unsigned, const comments::ParagraphComment *>
FreeParagraphs;

void paragraphsToMarkup(
markup::Document &Out,
const llvm::SmallVectorImpl<const comments::ParagraphComment *>
&Paragraphs) const;
};

} // namespace clangd
Expand Down
43 changes: 39 additions & 4 deletions clang-tools-extra/clangd/unittests/HoverTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4045,9 +4045,19 @@ brief doc
longer doc)"},
{[](HoverInfo &HI) {
HI.Kind = index::SymbolKind::Function;
HI.Documentation = "@brief brief doc\n\n"
"longer doc\n@param a this is a param\n@return it "
"returns something";
HI.Documentation = R"(@brief brief doc

longer doc
@note this is a note

As you see, notes are "inlined".
@warning this is a warning

As well as warnings
@param a this is a param
@return it returns something
@retval 0 if successful
@retval 1 if failed)";
HI.Definition = "int foo(int a)";
HI.ReturnType = "int";
HI.Name = "foo";
Expand All @@ -4068,8 +4078,16 @@ longer doc)"},
@brief brief doc

longer doc
@note this is a note

As you see, notes are "inlined".
@warning this is a warning

As well as warnings
@param a this is a param
@return it returns something
@retval 0 if successful
@retval 1 if failed

---
```cpp
Expand All @@ -4095,8 +4113,25 @@ brief doc

`int` - it returns something

- `0` - if successful
- `1` - if failed

---
longer doc)"},
longer doc

---
**Note:**
this is a note

---
As you see, notes are "inlined".

---
**Warning:**
this is a warning

---
As well as warnings)"},
{[](HoverInfo &HI) {
HI.Kind = index::SymbolKind::Function;
HI.Documentation = "@brief brief doc\n\n"
Expand Down
Loading