[clang-tools-extra] 7c13fe8 - [clangd] Introduce codeblocks

Kadir Cetinkaya via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 13 00:59:05 PST 2019


Author: Kadir Cetinkaya
Date: 2019-12-13T09:58:55+01:00
New Revision: 7c13fe8a6a643497d49036e6ea368e1adb06f57e

URL: https://github.com/llvm/llvm-project/commit/7c13fe8a6a643497d49036e6ea368e1adb06f57e
DIFF: https://github.com/llvm/llvm-project/commit/7c13fe8a6a643497d49036e6ea368e1adb06f57e.diff

LOG: [clangd] Introduce codeblocks

Summary: Follow-up to the patch D71248

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D71414

Added: 
    

Modified: 
    clang-tools-extra/clangd/FormattedString.cpp
    clang-tools-extra/clangd/FormattedString.h
    clang-tools-extra/clangd/Hover.cpp
    clang-tools-extra/clangd/unittests/FormattedStringTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/FormattedString.cpp b/clang-tools-extra/clangd/FormattedString.cpp
index 8bb17f38012b..69d33a45ada1 100644
--- a/clang-tools-extra/clangd/FormattedString.cpp
+++ b/clang-tools-extra/clangd/FormattedString.cpp
@@ -72,10 +72,10 @@ std::string renderInlineBlock(llvm::StringRef Input) {
   return "`" + std::move(R) + "`";
 }
 
-/// Render \p Input as markdown code block with a specified \p Language. The
-/// result is surrounded by >= 3 backticks. Although markdown also allows to use
-/// '~' for code blocks, they are never used.
-std::string renderCodeBlock(llvm::StringRef Input, llvm::StringRef Language) {
+/// Get marker required for \p Input to represent a markdown codeblock. It
+/// consists of at least 3 backticks(`). Although markdown also allows to use
+/// tilde(~) for code blocks, they are never used.
+std::string getMarkerForCodeBlock(llvm::StringRef Input) {
   // Count the maximum number of consecutive backticks in \p Input. We need to
   // start and end the code block with more.
   unsigned MaxBackticks = 0;
@@ -90,8 +90,7 @@ std::string renderCodeBlock(llvm::StringRef Input, llvm::StringRef Language) {
   }
   MaxBackticks = std::max(Backticks, MaxBackticks);
   // Use the corresponding number of backticks to start and end a code block.
-  std::string BlockMarker(/*Repeat=*/std::max(3u, MaxBackticks + 1), '`');
-  return BlockMarker + Language.str() + "\n" + Input.str() + "\n" + BlockMarker;
+  return std::string(/*Repeat=*/std::max(3u, MaxBackticks + 1), '`');
 }
 
 // Trims the input and concatanates whitespace blocks into a single ` `.
@@ -131,6 +130,26 @@ class Spacer : public Block {
   void renderPlainText(llvm::raw_ostream &OS) const override { OS << '\n'; }
 };
 
+class CodeBlock : public Block {
+public:
+  void renderMarkdown(llvm::raw_ostream &OS) const override {
+    std::string Marker = getMarkerForCodeBlock(Contents);
+    // No need to pad from previous blocks, as they should end with a new line.
+    OS << Marker << Language << '\n' << Contents << '\n' << Marker << '\n';
+  }
+
+  void renderPlainText(llvm::raw_ostream &OS) const override {
+    // In plaintext we want one empty line before and after codeblocks.
+    OS << '\n' << Contents << "\n\n";
+  }
+
+  CodeBlock(std::string Contents, std::string Language)
+      : Contents(std::move(Contents)), Language(std::move(Language)) {}
+
+private:
+  std::string Contents;
+  std::string Language;
+};
 } // namespace
 
 std::string Block::asMarkdown() const {
@@ -204,6 +223,11 @@ Paragraph &Document::addParagraph() {
 
 void Document::addSpacer() { Children.push_back(std::make_unique<Spacer>()); }
 
+void Document::addCodeBlock(std::string Code, std::string Language) {
+  Children.emplace_back(
+      std::make_unique<CodeBlock>(std::move(Code), std::move(Language)));
+}
+
 std::string Document::asMarkdown() const {
   return renderBlocks(Children, &Block::renderMarkdown);
 }

diff  --git a/clang-tools-extra/clangd/FormattedString.h b/clang-tools-extra/clangd/FormattedString.h
index 02753950f0cf..4ded2fdee315 100644
--- a/clang-tools-extra/clangd/FormattedString.h
+++ b/clang-tools-extra/clangd/FormattedString.h
@@ -70,6 +70,9 @@ class Document {
   Paragraph &addParagraph();
   /// Inserts a vertical space into the document.
   void addSpacer();
+  /// Adds a block of code. This translates to a ``` block in markdown. In plain
+  /// text representation, the code block will be surrounded by newlines.
+  void addCodeBlock(std::string Code, std::string Language = "cpp");
 
   std::string asMarkdown() const;
   std::string asPlainText() const;

diff  --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index d6b270c826d9..f55a9c3d1f67 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -95,7 +95,7 @@ std::string printDefinition(const Decl *D) {
 }
 
 void printParams(llvm::raw_ostream &OS,
-                        const std::vector<HoverInfo::Param> &Params) {
+                 const std::vector<HoverInfo::Param> &Params) {
   for (size_t I = 0, E = Params.size(); I != E; ++I) {
     if (I)
       OS << ", ";
@@ -456,12 +456,11 @@ markup::Document HoverInfo::present() const {
       P.appendCode(llvm::StringRef(*NamespaceScope).drop_back(2));
   }
 
-  Output.addSpacer();
   if (!Definition.empty()) {
-    Output.addParagraph().appendCode(Definition);
+    Output.addCodeBlock(Definition);
   } else {
     // Builtin types
-    Output.addParagraph().appendCode(Name);
+    Output.addCodeBlock(Name);
   }
 
   if (!Documentation.empty())

diff  --git a/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp b/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp
index 39f5c64a3817..7d57be61f0b2 100644
--- a/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp
@@ -54,6 +54,28 @@ TEST(Render, Escaping) {
   P = Paragraph();
   P.appendCode("`foo`");
   EXPECT_EQ(P.asMarkdown(), "` ``foo`` `");
+
+  // Code blocks might need more than 3 backticks.
+  Document D;
+  D.addCodeBlock("foobarbaz `\nqux");
+  EXPECT_EQ(D.asMarkdown(), "```cpp\n"
+                            "foobarbaz `\nqux\n"
+                            "```");
+  D = Document();
+  D.addCodeBlock("foobarbaz ``\nqux");
+  EXPECT_THAT(D.asMarkdown(), "```cpp\n"
+                              "foobarbaz ``\nqux\n"
+                              "```");
+  D = Document();
+  D.addCodeBlock("foobarbaz ```\nqux");
+  EXPECT_EQ(D.asMarkdown(), "````cpp\n"
+                            "foobarbaz ```\nqux\n"
+                            "````");
+  D = Document();
+  D.addCodeBlock("foobarbaz ` `` ``` ```` `\nqux");
+  EXPECT_EQ(D.asMarkdown(), "`````cpp\n"
+                            "foobarbaz ` `` ``` ```` `\nqux\n"
+                            "`````");
 }
 
 TEST(Paragraph, SeparationOfChunks) {
@@ -96,9 +118,18 @@ TEST(Paragraph, NewLines) {
 TEST(Document, Separators) {
   Document D;
   D.addParagraph().appendText("foo");
+  D.addCodeBlock("test");
   D.addParagraph().appendText("bar");
-  EXPECT_EQ(D.asMarkdown(), "foo\nbar");
-  EXPECT_EQ(D.asPlainText(), "foo\nbar");
+  EXPECT_EQ(D.asMarkdown(), R"md(foo
+```cpp
+test
+```
+bar)md");
+  EXPECT_EQ(D.asPlainText(), R"pt(foo
+
+test
+
+bar)pt");
 }
 
 TEST(Document, Spacer) {
@@ -110,6 +141,38 @@ TEST(Document, Spacer) {
   EXPECT_EQ(D.asPlainText(), "foo\n\nbar");
 }
 
+TEST(CodeBlock, Render) {
+  Document D;
+  // Code blocks preserves any extra spaces.
+  D.addCodeBlock("foo\n  bar\n  baz");
+  EXPECT_EQ(D.asMarkdown(), R"md(```cpp
+foo
+  bar
+  baz
+```)md");
+  EXPECT_EQ(D.asPlainText(), R"pt(foo
+  bar
+  baz)pt");
+  D.addCodeBlock("foo");
+  EXPECT_EQ(D.asMarkdown(), R"md(```cpp
+foo
+  bar
+  baz
+```
+```cpp
+foo
+```)md");
+  // FIXME: we shouldn't have 2 empty lines in between. A solution might be
+  // having a `verticalMargin` method for blocks, and let container insert new
+  // lines according to that before/after blocks.
+  EXPECT_EQ(D.asPlainText(), R"pt(foo
+  bar
+  baz
+
+
+foo)pt");
+}
+
 } // namespace
 } // namespace markup
 } // namespace clangd


        


More information about the cfe-commits mailing list