330 lines
12 KiB
C++
330 lines
12 KiB
C++
#include <set>
|
|
#include <string>
|
|
#include "Test/Test.h"
|
|
#include "Support/Doxygen.h"
|
|
#include "Support/Format.h"
|
|
|
|
namespace clice::testing {
|
|
|
|
namespace {
|
|
|
|
suite<"Doxygen"> doxygen = [] {
|
|
test("DoxygenInfo") = [&] {
|
|
DoxygenInfo di;
|
|
di.add_param_command_comment("foo",
|
|
"Doc for foo",
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::In);
|
|
di.add_param_command_comment(
|
|
"bar",
|
|
"Doc for bar",
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::InOut);
|
|
di.add_param_command_comment("baz",
|
|
"Doc for baz",
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::Out);
|
|
auto param_foo = di.find_param_info("foo");
|
|
expect(param_foo.has_value() && param_foo.value()->content.compare("Doc for foo") == 0);
|
|
auto param_bar = di.find_param_info("bar");
|
|
expect(param_bar.has_value() && param_bar.value()->content.compare("Doc for bar") == 0);
|
|
auto param_non_exists = di.find_param_info("xxx");
|
|
expect(!param_non_exists.has_value());
|
|
|
|
for(int i = 0; i < 3; ++i) {
|
|
di.add_block_command_comment("detail", std::format("Detail{}", i));
|
|
di.add_block_command_comment("warning", std::format("Warning{}", i));
|
|
di.add_block_command_comment("note", std::format("Note{}", i));
|
|
}
|
|
|
|
std::set<std::string> expected_detail = {"Detail0", "Detail1", "Detail2"};
|
|
std::set<std::string> expected_warning = {"Warning0", "Warning1", "Warning2"};
|
|
std::set<std::string> expected_note = {"Note0", "Note1", "Note2"};
|
|
|
|
std::map<std::string, std::set<std::string>> expected{
|
|
{"detail", std::move(expected_detail) },
|
|
{"warning", std::move(expected_warning)},
|
|
{"note", std::move(expected_note) },
|
|
};
|
|
|
|
auto bcc_list = di.get_block_command_comments();
|
|
|
|
for(auto& [tag, content]: bcc_list) {
|
|
std::set<std::string> actual;
|
|
for(auto& block: content) {
|
|
actual.insert(block.content);
|
|
}
|
|
expect(expected.contains(tag.str()));
|
|
expect(actual == expected[tag.str()]);
|
|
expected.erase(tag.str());
|
|
}
|
|
|
|
expect(expected.empty());
|
|
};
|
|
|
|
test("DoxygenParserSimple") = [&] {
|
|
// Inline commands
|
|
{
|
|
constexpr auto raw_comment = R"(
|
|
This is a @b Bold word
|
|
This is an \e Italic word
|
|
This is @c InlineCode
|
|
)";
|
|
auto [di, md] = strip_doxygen_info(raw_comment);
|
|
expect(di.get_block_command_comments().size() == 0);
|
|
std::println("Rest:\n```{}```", md);
|
|
}
|
|
|
|
// ParamCommandComment
|
|
{
|
|
constexpr auto raw_comment = R"( @)";
|
|
std::println("Processing raw comment: `{}`", raw_comment);
|
|
auto [di, md] = strip_doxygen_info(raw_comment);
|
|
std::println("Rest:\n```\n{}\n```\n", md);
|
|
}
|
|
|
|
{
|
|
constexpr auto raw_comment = R"( @param)";
|
|
std::println("Processing raw comment: `{}`", raw_comment);
|
|
auto [di, md] = strip_doxygen_info(raw_comment);
|
|
std::println("Rest:\n```\n{}\n```\n", md);
|
|
}
|
|
|
|
{
|
|
constexpr auto raw_comment = R"( @param[in,out] foo doc for foo)";
|
|
std::println("Processing raw comment: `{}`", raw_comment);
|
|
auto [di, md] = strip_doxygen_info(raw_comment);
|
|
expect(md.size() == 0);
|
|
auto info_foo = di.find_param_info("foo");
|
|
expect(info_foo.has_value());
|
|
if(info_foo.has_value()) {
|
|
llvm::StringRef doc = info_foo.value()->content;
|
|
expect(info_foo.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::InOut);
|
|
std::println("Doc:\n```\n{}\n```\n", doc);
|
|
}
|
|
}
|
|
|
|
{
|
|
constexpr auto raw_comment = R"(
|
|
@param[out] foo doc for foo
|
|
doc for foo line2
|
|
\param[in] bar
|
|
doc for bar
|
|
|
|
@param baz
|
|
)";
|
|
auto [di, md] = strip_doxygen_info(raw_comment);
|
|
llvm::StringRef rest = md;
|
|
expect(rest.trim().size() == 0);
|
|
|
|
auto info_foo = di.find_param_info("foo");
|
|
expect(info_foo.has_value());
|
|
if(info_foo.has_value()) {
|
|
llvm::StringRef doc = info_foo.value()->content;
|
|
expect(info_foo.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::Out);
|
|
std::println("Doc:\n```\n{}\n```", doc);
|
|
}
|
|
|
|
auto info_bar = di.find_param_info("bar");
|
|
expect(info_bar.has_value());
|
|
if(info_bar.has_value()) {
|
|
llvm::StringRef doc = info_bar.value()->content;
|
|
expect(info_bar.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::In);
|
|
std::println("Doc:\n```\n{}\n```", doc);
|
|
}
|
|
|
|
auto info_baz = di.find_param_info("baz");
|
|
expect(info_baz.has_value());
|
|
if(info_baz.has_value()) {
|
|
llvm::StringRef doc = info_baz.value()->content;
|
|
expect(info_baz.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::Unspecified);
|
|
expect(doc.trim().size() == 0);
|
|
}
|
|
}
|
|
};
|
|
|
|
test("DoxygenParserIntegrated") = [&] {
|
|
{
|
|
std::println("##################################################################");
|
|
constexpr auto raw_comment = R"(
|
|
@brief Calculates the area of a rectangle.
|
|
|
|
This function computes the area using the formula \c width * height.
|
|
It is considered \b fast and \e reliable.
|
|
|
|
@param[in] width The width of the rectangle (must be > 0)
|
|
@param[in] height The height of the rectangle (must be > 0)
|
|
@return The area as an integer.
|
|
|
|
@note If either width or height is zero, the function returns zero.
|
|
|
|
@details
|
|
details 1 blah blah... line1
|
|
details 1 blah blah... line2
|
|
aabbcssss
|
|
~~~~~~^
|
|
|
|
A line not in a block
|
|
@details
|
|
details 2 blah blah... line1
|
|
details 2 blah blah... line2
|
|
)";
|
|
auto [di, md] = strip_doxygen_info(raw_comment);
|
|
std::println("Markdown After Stripping:\n```\n{}\n```", md);
|
|
auto info_width = di.find_param_info("width");
|
|
expect(info_width.has_value());
|
|
if(info_width.has_value()) {
|
|
expect(info_width.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::In);
|
|
std::println("Doc for `width`:\n```\n{}\n```", info_width.value()->content);
|
|
}
|
|
|
|
auto info_height = di.find_param_info("height");
|
|
expect(info_height.has_value());
|
|
if(info_height.has_value()) {
|
|
expect(info_height.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::In);
|
|
std::println("Doc for `height`:\n```\n{}\n```", info_height.value()->content);
|
|
}
|
|
|
|
auto bcc_list = di.get_block_command_comments();
|
|
expect(bcc_list.size() == 3);
|
|
|
|
std::println("RegularTags:");
|
|
for(auto& [tag_name, content]: bcc_list) {
|
|
std::println("=================================");
|
|
std::println("Tag name: `{}`", tag_name);
|
|
for(auto& item: content) {
|
|
std::println("Item:\n```\n{}\n```", item.content);
|
|
}
|
|
std::println("=================================");
|
|
}
|
|
|
|
auto ret_info = di.get_return_info();
|
|
expect(ret_info.has_value());
|
|
if(ret_info.has_value()) {
|
|
std::println("Doc for return value:\n```\n{}\n```", ret_info.value());
|
|
}
|
|
std::println("##################################################################");
|
|
}
|
|
|
|
// Full test
|
|
{
|
|
constexpr auto raw_comment = R"( @brief brief block
|
|
brief line2
|
|
|
|
normal line...
|
|
normal line...
|
|
a b c d e f
|
|
~~~~^
|
|
normal line...
|
|
|
|
@param[in] foo doc for foo
|
|
@param[out] bar doc for bar
|
|
doc for bar line2
|
|
@param[in,out] baz doc for baz
|
|
@param awa not exist. deprecated
|
|
@param foo doc for foo extra line
|
|
|
|
@details here are some details
|
|
details line2
|
|
details line3 unproper indent but also detail block
|
|
|
|
normal comment line
|
|
@warning watch out
|
|
warn line2
|
|
|
|
+------[foo]------+
|
|
| |
|
|
| I'm a box |
|
|
| |
|
|
+-----------------+
|
|
|
|
desc line outside
|
|
a b c d e f
|
|
~~~~^
|
|
This is inline display: @b Bold \e Italic @c InlineCode
|
|
|
|
@warning watch out *2
|
|
|
|
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
|
|
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
|
|
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
|
|
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
|
|
|
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
|
|
|
@note here's note1
|
|
note1 line2
|
|
|
|
@note here's note2
|
|
note2 line2
|
|
not note2 line3, normal comment
|
|
|
|
@return doc for return value
|
|
)";
|
|
auto [di, md] = strip_doxygen_info(raw_comment);
|
|
std::println("Markdown After Stripping:\n```\n{}\n```", md);
|
|
auto info_foo = di.find_param_info("foo");
|
|
expect(info_foo.has_value());
|
|
if(info_foo.has_value()) {
|
|
expect(info_foo.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::In);
|
|
std::println("Doc for `foo`:\n```\n{}\n```", info_foo.value()->content);
|
|
}
|
|
|
|
auto info_bar = di.find_param_info("bar");
|
|
expect(info_bar.has_value());
|
|
if(info_bar.has_value()) {
|
|
expect(info_bar.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::Out);
|
|
std::println("Doc for `bar`:\n```\n{}\n```", info_bar.value()->content);
|
|
}
|
|
|
|
auto info_baz = di.find_param_info("baz");
|
|
expect(info_baz.has_value());
|
|
if(info_baz.has_value()) {
|
|
expect(info_baz.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::InOut);
|
|
std::println("Doc for `baz`:\n```\n{}\n```", info_baz.value()->content);
|
|
}
|
|
|
|
auto info_awa = di.find_param_info("awa");
|
|
expect(info_awa.has_value());
|
|
if(info_awa.has_value()) {
|
|
expect(info_awa.value()->direction ==
|
|
DoxygenInfo::ParamCommandCommentContent::ParamDirection::Unspecified);
|
|
std::println("Doc for `awa`:\n```\n{}\n```", info_awa.value()->content);
|
|
}
|
|
|
|
auto bcc_list = di.get_block_command_comments();
|
|
expect(bcc_list.size() == 4);
|
|
|
|
std::println("RegularTags:");
|
|
for(auto& [tag_name, content]: bcc_list) {
|
|
std::println("=================================");
|
|
std::println("Tag name: `{}`", tag_name);
|
|
for(auto& item: content) {
|
|
std::println("Item:\n```\n{}\n```", item.content);
|
|
}
|
|
std::println("=================================");
|
|
}
|
|
|
|
auto ret_info = di.get_return_info();
|
|
expect(ret_info.has_value());
|
|
if(ret_info.has_value()) {
|
|
std::println("Doc for return value:\n```\n{}\n```", ret_info.value());
|
|
}
|
|
std::println("##################################################################");
|
|
}
|
|
};
|
|
};
|
|
|
|
} // namespace
|
|
|
|
} // namespace clice::testing
|