================
@@ -0,0 +1,291 @@
+//===--- SymbolDocumentation.cpp ==-------------------------------*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolDocumentation.h"
+
+#include "support/Markup.h"
+#include "clang/AST/Comment.h"
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/CommentVisitor.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace clangd {
+
+void commandToMarkup(markup::Paragraph &Out, StringRef Command,
+                     comments::CommandMarkerKind CommandMarker,
+                     StringRef Args) {
+  Out.appendBoldText(
+      (CommandMarker == (comments::CommandMarkerKind::CMK_At) ? "@" : "\\") +
+      Command.str());
+  if (!Args.empty()) {
+    Out.appendSpace();
+    Out.appendEmphasizedText(Args.str());
+  }
+}
+
+class ParagraphToMarkupDocument
+    : public comments::ConstCommentVisitor<ParagraphToMarkupDocument> {
+public:
+  ParagraphToMarkupDocument(markup::Paragraph &Out,
+                            const comments::CommandTraits &Traits)
+      : Out(Out), Traits(Traits) {}
+
+  void visitParagraphComment(const comments::ParagraphComment *C) {
+    if (!C)
+      return;
+
+    for (const auto *Child = C->child_begin(); Child != C->child_end();
+         ++Child) {
+      visit(*Child);
+    }
+  }
+
+  void visitTextComment(const comments::TextComment *C) {
+    // Always trim leading space after a newline.
+    StringRef Text = C->getText();
+    if (LastChunkEndsWithNewline && C->getText().starts_with(' '))
+      Text = Text.drop_front();
+
+    LastChunkEndsWithNewline = C->hasTrailingNewline();
+    Out.appendText(Text.str() + (LastChunkEndsWithNewline ? "\n" : ""));
+  }
+
+  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);
+      }
+
+      switch (C->getRenderKind()) {
+      case comments::InlineCommandRenderKind::Monospaced:
+        Out.appendCode(ArgText);
+        break;
+      case comments::InlineCommandRenderKind::Bold:
+        Out.appendBoldText(ArgText);
+        break;
+      case comments::InlineCommandRenderKind::Emphasized:
+        Out.appendEmphasizedText(ArgText);
+        break;
+      default:
+        commandToMarkup(Out, C->getCommandName(Traits), C->getCommandMarker(),
+                        ArgText);
+        break;
+      }
+    } else {
+      if (C->getCommandName(Traits) == "n") {
+        // \n is a special case, it is used to create a new line.
+        Out.appendText("  \n");
+        LastChunkEndsWithNewline = true;
+        return;
+      }
+
+      commandToMarkup(Out, C->getCommandName(Traits), C->getCommandMarker(),
+                      "");
+    }
+  }
+
+  void visitHTMLStartTagComment(const comments::HTMLStartTagComment *STC) {
+    std::string TagText = "<" + STC->getTagName().str();
+
+    for (unsigned I = 0; I < STC->getNumAttrs(); ++I) {
+      const comments::HTMLStartTagComment::Attribute &Attr = STC->getAttr(I);
+      TagText += " " + Attr.Name.str() + "=\"" + Attr.Value.str() + "\"";
+    }
+
+    if (STC->isSelfClosing())
+      TagText += " /";
+    TagText += ">";
+
+    LastChunkEndsWithNewline = STC->hasTrailingNewline();
+    Out.appendText(TagText + (LastChunkEndsWithNewline ? "\n" : ""));
+  }
+
+  void visitHTMLEndTagComment(const comments::HTMLEndTagComment *ETC) {
+    LastChunkEndsWithNewline = ETC->hasTrailingNewline();
+    Out.appendText("</" + ETC->getTagName().str() + ">" +
+                   (LastChunkEndsWithNewline ? "\n" : ""));
+  }
+
+private:
+  markup::Paragraph &Out;
+  const comments::CommandTraits &Traits;
+
+  /// If true, the next leading space after a new line is trimmed.
+  bool LastChunkEndsWithNewline = false;
+};
+
+class ParagraphToString
+    : public comments::ConstCommentVisitor<ParagraphToString> {
+public:
+  ParagraphToString(llvm::raw_string_ostream &Out,
+                    const comments::CommandTraits &Traits)
+      : Out(Out), Traits(Traits) {}
+
+  void visitParagraphComment(const comments::ParagraphComment *C) {
+    if (!C)
+      return;
+
+    for (const auto *Child = C->child_begin(); Child != C->child_end();
+         ++Child) {
+      visit(*Child);
+    }
+  }
+
+  void visitTextComment(const comments::TextComment *C) { Out << C->getText(); 
}
+
+  void visitInlineCommandComment(const comments::InlineCommandComment *C) {
+    Out << (C->getCommandMarker() == comments::CommandMarkerKind::CMK_At
+                ? "@"
+                : "\\");
+    Out << C->getCommandName(Traits);
+    if (C->getNumArgs() > 0) {
+      Out << " ";
+      for (unsigned I = 0; I < C->getNumArgs(); ++I) {
+        if (I > 0)
----------------
emaxx-google wrote:

nit: We can skip this check and add the preceding space unconditionally. Then 
we don't need to add it before the `for` loop or check for `getNumArgs`.

https://github.com/llvm/llvm-project/pull/150790
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to