}
return IndentedR;
}
+
+class Heading : public Paragraph {
+public:
+ Heading(size_t Level) : Level(Level) {}
+ void renderMarkdown(llvm::raw_ostream &OS) const override {
+ OS << std::string(Level, '#') << ' ';
+ Paragraph::renderMarkdown(OS);
+ }
+
+private:
+ size_t Level;
+};
+
} // namespace
std::string Block::asMarkdown() const {
Children.emplace_back(std::make_unique<BulletList>());
return *static_cast<BulletList *>(Children.back().get());
}
+
+Paragraph &Document::addHeading(size_t Level) {
+ assert(Level > 0);
+ Children.emplace_back(std::make_unique<Heading>(Level));
+ return *static_cast<Paragraph *>(Children.back().get());
+}
} // namespace markup
} // namespace clangd
} // namespace clang
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FORMATTEDSTRING_H
#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
#include <memory>
#include <string>
#include <vector>
/// 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");
+ /// Heading is a special type of paragraph that will be prepended with \p
+ /// Level many '#'s in markdown.
+ Paragraph &addHeading(size_t Level);
BulletList &addBulletList();
// class `X`
//
// function `foo` → `int`
- markup::Paragraph &Header = Output.addParagraph();
+ // 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);
Header.appendText(index::getSymbolKindString(Kind));
assert(!Name.empty() && "hover triggered on a nameless symbol");
Header.appendCode(Name);
EXPECT_EQ(D.asPlainText(), "foo\n\nbar");
}
+TEST(Document, Heading) {
+ Document D;
+ D.addHeading(1).appendText("foo");
+ D.addHeading(2).appendText("bar");
+ D.addParagraph().appendText("baz");
+ EXPECT_EQ(D.asMarkdown(), "# foo \n## bar \nbaz");
+ EXPECT_EQ(D.asPlainText(), "foo\nbar\nbaz");
+}
+
TEST(CodeBlock, Render) {
Document D;
// Code blocks preserves any extra spaces.
}
}
}
+
TEST(Hover, Present) {
struct {
const std::function<void(HoverInfo &)> Builder;
}
}
+// This is a separate test as headings don't create any differences in plaintext
+// mode.
+TEST(Hover, PresentHeadings) {
+ HoverInfo HI;
+ HI.Kind = index::SymbolKind::Variable;
+ HI.Name = "foo";
+ HI.Type = "type";
+
+ EXPECT_EQ(HI.present().asMarkdown(), "### variable `foo` \\: `type`");
+}
+
} // namespace
} // namespace clangd
} // namespace clang