From 24ef72c2d1ffc9f094a164273827a0e09d446fb9 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 11 Oct 2024 11:14:29 -0400 Subject: [PATCH 1/5] feat: support @relates --- include/mrdocs/Metadata/Javadoc.hpp | 30 +++++++++++++++++ .../generator/adoc/partials/symbol.adoc.hbs | 10 ++++++ src/lib/AST/ParseJavadoc.cpp | 32 +++++++++++++++++++ src/lib/Gen/hbs/HandlebarsCorpus.cpp | 9 ++++++ src/lib/Metadata/Javadoc.cpp | 1 + 5 files changed, 82 insertions(+) diff --git a/include/mrdocs/Metadata/Javadoc.hpp b/include/mrdocs/Metadata/Javadoc.hpp index e8eafde45..ec6fd32ea 100644 --- a/include/mrdocs/Metadata/Javadoc.hpp +++ b/include/mrdocs/Metadata/Javadoc.hpp @@ -120,6 +120,7 @@ enum class NodeKind throws, details, see, + related, precondition, postcondition }; @@ -374,6 +375,26 @@ struct Copied final : Reference } }; +/** A reference to a related symbol. +*/ +struct Related final : Reference +{ + static constexpr auto static_kind = NodeKind::related; + + Related(std::string string_ = std::string()) noexcept + : Reference(std::move(string_), NodeKind::related) + { + } + + auto operator<=>(Related const&) const = default; + bool operator==(Related const&) const noexcept = default; + bool equals(Node const& other) const noexcept override + { + return Kind == other.Kind && + *this == dynamic_cast(other); + } +}; + //------------------------------------------------ // // Block nodes @@ -928,6 +949,8 @@ visit( return f.template operator()(std::forward(args)...); case NodeKind::postcondition: return f.template operator()(std::forward(args)...); + case NodeKind::related: + return f.template operator()(std::forward(args)...); default: return f.template operator()(std::forward(args)...); } @@ -995,6 +1018,8 @@ visit( return visitor.template visit(); case NodeKind::postcondition: return visitor.template visit(); + case NodeKind::related: + return visitor.template visit(); default: MRDOCS_UNREACHABLE(); } @@ -1063,12 +1088,16 @@ struct MRDOCS_DECL /// The list of "see also" references. std::vector sees; + /// The list of "related" references. + std::vector related; + /// The list of preconditions. std::vector preconditions; /// The list of postconditions. std::vector postconditions; + /** Constructor. */ MRDOCS_DECL @@ -1093,6 +1122,7 @@ struct MRDOCS_DECL tparams.empty() && exceptions.empty() && sees.empty() && + related.empty() && preconditions.empty() && postconditions.empty(); } diff --git a/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs index 5f4c4e2e8..271a03e46 100644 --- a/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs +++ b/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs @@ -174,3 +174,13 @@ {{/each}} {{/if}} +{{! Related }} +{{#if symbol.doc.related}} +{{#> markup/dynamic-level-h }}Related{{/markup/dynamic-level-h}} + +{{#each symbol.doc.related}} +{{{.}}} + +{{/each}} + +{{/if}} diff --git a/src/lib/AST/ParseJavadoc.cpp b/src/lib/AST/ParseJavadoc.cpp index 45fe23a44..4297132b8 100644 --- a/src/lib/AST/ParseJavadoc.cpp +++ b/src/lib/AST/ParseJavadoc.cpp @@ -1122,6 +1122,38 @@ visitInlineCommandComment( } return; } + // KRYSTIAN FIXME: these need to be made inline commands in clang + case CommandTraits::KCI_related: + case CommandTraits::KCI_relates: + { + if(! goodArgCount(1, *C)) + return; + // The parsed reference often includes characters + // that are not valid in identifiers, so we need to + // clean it up. + // Find the first character that is not a valid C++ + // identifier character, and truncate the string there. + // This potentially creates two text nodes. + auto const s = C->getArgText(0).str(); + std::string_view ref = parseQualifiedIdentifier(s); + bool const hasExtraText = ref.size() != s.size(); + if (!ref.empty()) + { + // the referenced symbol will be resolved during + // the finalization step once all symbols are extracted + emplaceText( + C->hasTrailingNewline() && !hasExtraText, + std::string(ref)); + } + // Emplace the rest of the string as doc::Text + if(hasExtraText) + { + emplaceText( + C->hasTrailingNewline(), + s.substr(ref.size())); + } + return; + } default: break; diff --git a/src/lib/Gen/hbs/HandlebarsCorpus.cpp b/src/lib/Gen/hbs/HandlebarsCorpus.cpp index 25245d618..e0701091d 100644 --- a/src/lib/Gen/hbs/HandlebarsCorpus.cpp +++ b/src/lib/Gen/hbs/HandlebarsCorpus.cpp @@ -98,6 +98,14 @@ domCreate( return corpus.toStringFn(corpus, I); } +dom::Value +domCreate( + doc::Related const& I, + HandlebarsCorpus const& corpus) +{ + return corpus.toStringFn(corpus, I); +} + dom::Value domCreate( doc::Precondition const& I, @@ -257,6 +265,7 @@ getJavadoc(Javadoc const& jd) const emplaceObjectArray("tparams", jd.tparams); emplaceObjectArray("exceptions", jd.exceptions); emplaceObjectArray("see", jd.sees); + emplaceObjectArray("related", jd.related); emplaceObjectArray("preconditions", jd.preconditions); emplaceObjectArray("postconditions", jd.postconditions); return dom::Object(std::move(objKeyValues)); diff --git a/src/lib/Metadata/Javadoc.cpp b/src/lib/Metadata/Javadoc.cpp index 6be625954..5f4db623c 100644 --- a/src/lib/Metadata/Javadoc.cpp +++ b/src/lib/Metadata/Javadoc.cpp @@ -211,6 +211,7 @@ operator==(Javadoc const& other) const noexcept tparams == other.tparams && exceptions == other.exceptions && sees == other.sees && + related == other.related && preconditions == other.preconditions && postconditions == other.postconditions; } From 10c64fd025132373b42a704c4b23902a48457f53 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 8 Jan 2025 12:55:19 -0500 Subject: [PATCH 2/5] chore: remove unused visit function --- include/mrdocs/Metadata/Javadoc.hpp | 58 ----------------------------- 1 file changed, 58 deletions(-) diff --git a/include/mrdocs/Metadata/Javadoc.hpp b/include/mrdocs/Metadata/Javadoc.hpp index ec6fd32ea..d3208f427 100644 --- a/include/mrdocs/Metadata/Javadoc.hpp +++ b/include/mrdocs/Metadata/Javadoc.hpp @@ -898,64 +898,6 @@ struct Postcondition : Paragraph //------------------------------------------------ -/** A visitor for node types. - */ -template -constexpr -auto -visit( - NodeKind kind, - F&& f, Args&&... args) -{ - switch(kind) - { - case NodeKind::admonition: - return f.template operator()(std::forward(args)...); - case NodeKind::brief: - return f.template operator()(std::forward(args)...); - case NodeKind::code: - return f.template operator()(std::forward(args)...); - case NodeKind::heading: - return f.template operator()(std::forward(args)...); - case NodeKind::link: - return f.template operator()(std::forward(args)...); - case NodeKind::reference: - return f.template operator()(std::forward(args)...); - case NodeKind::copied: - return f.template operator()(std::forward(args)...); - case NodeKind::list_item: - return f.template operator()(std::forward(args)...); - case NodeKind::unordered_list: - return f.template operator()(std::forward(args)...); - case NodeKind::paragraph: - return f.template operator()(std::forward(args)...); - case NodeKind::param: - return f.template operator()(std::forward(args)...); - case NodeKind::returns: - return f.template operator()(std::forward(args)...); - case NodeKind::styled: - return f.template operator()(std::forward(args)...); - case NodeKind::text: - return f.template operator()(std::forward(args)...); - case NodeKind::tparam: - return f.template operator()(std::forward(args)...); - case NodeKind::throws: - return f.template operator()(std::forward(args)...); - case NodeKind::details: - return f.template operator()
(std::forward(args)...); - case NodeKind::see: - return f.template operator()(std::forward(args)...); - case NodeKind::precondition: - return f.template operator()(std::forward(args)...); - case NodeKind::postcondition: - return f.template operator()(std::forward(args)...); - case NodeKind::related: - return f.template operator()(std::forward(args)...); - default: - return f.template operator()(std::forward(args)...); - } -} - /** Visit a node. @param node The node to visit. From 155bf147e1797159f1d0acb80877510c30122507 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 10 Feb 2025 14:02:18 -0500 Subject: [PATCH 3/5] [FOLD] add relates element to named symbol --- include/mrdocs/Metadata/Javadoc.hpp | 2 +- src/lib/Gen/hbs/HandlebarsCorpus.cpp | 6 +++--- src/lib/Metadata/Finalizers/JavadocFinalizer.cpp | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/mrdocs/Metadata/Javadoc.hpp b/include/mrdocs/Metadata/Javadoc.hpp index d3208f427..58b6f4733 100644 --- a/include/mrdocs/Metadata/Javadoc.hpp +++ b/include/mrdocs/Metadata/Javadoc.hpp @@ -1031,7 +1031,7 @@ struct MRDOCS_DECL std::vector sees; /// The list of "related" references. - std::vector related; + std::vector related; /// The list of preconditions. std::vector preconditions; diff --git a/src/lib/Gen/hbs/HandlebarsCorpus.cpp b/src/lib/Gen/hbs/HandlebarsCorpus.cpp index e0701091d..331a58c68 100644 --- a/src/lib/Gen/hbs/HandlebarsCorpus.cpp +++ b/src/lib/Gen/hbs/HandlebarsCorpus.cpp @@ -100,10 +100,10 @@ domCreate( dom::Value domCreate( - doc::Related const& I, + SymbolID const& I, HandlebarsCorpus const& corpus) { - return corpus.toStringFn(corpus, I); + return corpus.get(I); } dom::Value @@ -233,7 +233,7 @@ getJavadoc(Javadoc const& jd) const elements.reserve(nodes.size()); for (value_type const& elem : nodes) { - if constexpr (requires { !elem; }) + if constexpr (requires { *elem; }) { if (!elem) { diff --git a/src/lib/Metadata/Finalizers/JavadocFinalizer.cpp b/src/lib/Metadata/Finalizers/JavadocFinalizer.cpp index ba88143e4..9dc1fcde6 100644 --- a/src/lib/Metadata/Finalizers/JavadocFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/JavadocFinalizer.cpp @@ -114,8 +114,18 @@ finalize(doc::Reference& ref, bool const emitWarning) { if (auto resRef = corpus_.lookup(current_context_->id, ref.string)) { - Info const& res = *resRef; + // KRYSTIAN NOTE: we should provide an overload that + // returns a non-const reference. + auto& res = const_cast(resRef->get()); ref.id = res.id; + if(ref.Kind == doc::NodeKind::related) + { + if(! res.javadoc) + res.javadoc.emplace(); + auto& related = res.javadoc->related; + if(std::ranges::find(related, current_context_->id) == related.end()) + related.emplace_back(current_context_->id); + } } else if ( emitWarning && @@ -150,7 +160,8 @@ finalize(doc::Node& node) finalize(N.children); } - if constexpr(std::same_as) + if constexpr(std::same_as || + std::same_as) { finalize(dynamic_cast(N), true); } From fcb6ce3aaa3a68b31c0de1a0eb9044a014c3c02f Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 14 Feb 2025 11:20:25 -0500 Subject: [PATCH 4/5] [FOLD] add generator support --- .../generator/adoc/partials/symbol.adoc.hbs | 15 +++++---------- src/lib/Gen/adoc/DocVisitor.cpp | 3 +++ src/lib/Gen/html/DocVisitor.cpp | 3 +++ src/lib/Gen/xml/XMLWriter.cpp | 13 +++++++++++++ src/lib/Gen/xml/XMLWriter.hpp | 1 + .../golden-tests/javadoc/relates/relates.cpp | 13 +++++++++++++ 6 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 test-files/golden-tests/javadoc/relates/relates.cpp diff --git a/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs index 271a03e46..7dae77cc9 100644 --- a/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs +++ b/share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs @@ -68,6 +68,11 @@ {{#if symbol.usingDirectives}} {{>symbol/members-table members=symbol.usingDirectives title="Using Directives"}} +{{/if}} +{{! Related symbols }} +{{#if symbol.doc.related}} +{{>symbol/members-table members=symbol.doc.related title="Related functions"}} + {{/if}} {{! Description }} {{#if symbol.doc.description}} @@ -174,13 +179,3 @@ {{/each}} {{/if}} -{{! Related }} -{{#if symbol.doc.related}} -{{#> markup/dynamic-level-h }}Related{{/markup/dynamic-level-h}} - -{{#each symbol.doc.related}} -{{{.}}} - -{{/each}} - -{{/if}} diff --git a/src/lib/Gen/adoc/DocVisitor.cpp b/src/lib/Gen/adoc/DocVisitor.cpp index e2301e3e9..fe2654194 100644 --- a/src/lib/Gen/adoc/DocVisitor.cpp +++ b/src/lib/Gen/adoc/DocVisitor.cpp @@ -287,6 +287,9 @@ void DocVisitor:: operator()(doc::Reference const& I) const { + if (I.Kind == doc::NodeKind::related) + return; + if (I.id == SymbolID::invalid) { return (*this)(static_cast(I)); diff --git a/src/lib/Gen/html/DocVisitor.cpp b/src/lib/Gen/html/DocVisitor.cpp index 0e71039d5..4233a3bec 100644 --- a/src/lib/Gen/html/DocVisitor.cpp +++ b/src/lib/Gen/html/DocVisitor.cpp @@ -285,6 +285,9 @@ void DocVisitor:: operator()(doc::Reference const& I) const { + if (I.Kind == doc::NodeKind::related) + return; + if (I.id == SymbolID::invalid) { return (*this)(static_cast(I)); diff --git a/src/lib/Gen/xml/XMLWriter.cpp b/src/lib/Gen/xml/XMLWriter.cpp index 1cffdddab..7df92957c 100644 --- a/src/lib/Gen/xml/XMLWriter.cpp +++ b/src/lib/Gen/xml/XMLWriter.cpp @@ -785,6 +785,9 @@ writeNode(doc::Node const& node) case doc::NodeKind::copied: writeCopied(dynamic_cast(node)); break; + case doc::NodeKind::related: + writeRelated(dynamic_cast(node)); + break; case doc::NodeKind::throws: writeThrows(dynamic_cast(node)); break; @@ -841,6 +844,16 @@ writeCopied( }); } +void +XMLWriter:: +writeRelated( + doc::Related const& node) +{ + tags_.write("relates", node.string, { + { node.id } + }); +} + void XMLWriter:: writeLink( diff --git a/src/lib/Gen/xml/XMLWriter.hpp b/src/lib/Gen/xml/XMLWriter.hpp index 1f5baea82..3a749e7db 100644 --- a/src/lib/Gen/xml/XMLWriter.hpp +++ b/src/lib/Gen/xml/XMLWriter.hpp @@ -89,6 +89,7 @@ class XMLWriter void writeTParam(doc::TParam const& node); void writeReference(doc::Reference const& node); void writeCopied(doc::Copied const& node); + void writeRelated(doc::Related const& node); void writeThrows(doc::Throws const& node); void writeDetails(doc::Details const& node, llvm::StringRef tag = ""); void writeSee(doc::See const& node, llvm::StringRef tag = ""); diff --git a/test-files/golden-tests/javadoc/relates/relates.cpp b/test-files/golden-tests/javadoc/relates/relates.cpp new file mode 100644 index 000000000..0c3522ba0 --- /dev/null +++ b/test-files/golden-tests/javadoc/relates/relates.cpp @@ -0,0 +1,13 @@ +/** A brief for A. +*/ +struct A { }; + +/** A brief for B +*/ +struct B { }; + +/** A brief for f. + + @relates A +*/ +void f(); From 823038f387b7850b61edca53bb2eb3676933d4ae Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 14 Feb 2025 11:35:17 -0500 Subject: [PATCH 5/5] add tests --- include/mrdocs/Metadata/Javadoc.hpp | 1 - mrdocs.rnc | 3 +- .../golden-tests/javadoc/relates/relates.adoc | 107 ++++++++++++++++ .../golden-tests/javadoc/relates/relates.html | 121 ++++++++++++++++++ .../golden-tests/javadoc/relates/relates.xml | 33 +++++ 5 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 test-files/golden-tests/javadoc/relates/relates.adoc create mode 100644 test-files/golden-tests/javadoc/relates/relates.html create mode 100644 test-files/golden-tests/javadoc/relates/relates.xml diff --git a/include/mrdocs/Metadata/Javadoc.hpp b/include/mrdocs/Metadata/Javadoc.hpp index 58b6f4733..2834cc693 100644 --- a/include/mrdocs/Metadata/Javadoc.hpp +++ b/include/mrdocs/Metadata/Javadoc.hpp @@ -1039,7 +1039,6 @@ struct MRDOCS_DECL /// The list of postconditions. std::vector postconditions; - /** Constructor. */ MRDOCS_DECL diff --git a/mrdocs.rnc b/mrdocs.rnc index bf0aee028..c5f9323ab 100644 --- a/mrdocs.rnc +++ b/mrdocs.rnc @@ -416,7 +416,7 @@ grammar Postcondition = element post { TextNode * } Details = element details { TextNode * } - TextNode = ( Link | Styled | Text | Reference | Copied ) + TextNode = ( Link | Styled | Text | Reference | Related | Copied ) Link = element link { attribute href { text }, text } Styled = ( @@ -426,6 +426,7 @@ grammar element italic { text } ) Text = element text { text } Reference = element reference { ID ?, text } + Related = element relates { ID ?, text } Copied = element ( copydoc | diff --git a/test-files/golden-tests/javadoc/relates/relates.adoc b/test-files/golden-tests/javadoc/relates/relates.adoc new file mode 100644 index 000000000..255ba707d --- /dev/null +++ b/test-files/golden-tests/javadoc/relates/relates.adoc @@ -0,0 +1,107 @@ += Reference +:mrdocs: + +[#index] +== Global namespace + + +=== Types + +[cols=2] +|=== +| Name | Description + +| <> +| A brief for A. + +| <> +| A brief for B + +|=== +=== Functions + +[cols=2] +|=== +| Name | Description + +| <> +| A brief for f. + +|=== + +[#A] +== A + + +A brief for A. + +=== Synopsis + + +Declared in `<relates.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct A; +---- + + + + +=== Related functions + +[cols=2] +|=== +| Name | Description + +| <> +| A brief for f. + +|=== + +[#B] +== B + + +A brief for B + +=== Synopsis + + +Declared in `<relates.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct B; +---- + + + + +[#f] +== f + + +A brief for f. + +=== Synopsis + + +Declared in `<relates.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +void +f(); +---- + +=== Description + + + + + + + + +[.small]#Created with https://www.mrdocs.com[MrDocs]# diff --git a/test-files/golden-tests/javadoc/relates/relates.html b/test-files/golden-tests/javadoc/relates/relates.html new file mode 100644 index 000000000..ad9de8d58 --- /dev/null +++ b/test-files/golden-tests/javadoc/relates/relates.html @@ -0,0 +1,121 @@ + + +Reference + + +
+

Reference

+
+
+

Global namespace

+
+

Types

+ + + + + + + + + + + +
NameDescription
A A brief for A. + +
B A brief for B + +
+

Functions

+ + + + + + + + + + +
NameDescription
f A brief for f. + +
+
+
+
+

A

+
+A brief for A. + + +
+
+
+

Synopsis

+
+Declared in <relates.cpp>
+
+
+struct A;
+
+
+
+ + +
+
+
+

B

+
+A brief for B + + +
+
+
+

Synopsis

+
+Declared in <relates.cpp>
+
+
+struct B;
+
+
+
+ + +
+
+
+

f

+
+A brief for f. + + +
+
+
+

Synopsis

+
+Declared in <relates.cpp>
+
+
+void
+f();
+
+
+
+
+

Description

+

+ + +
+
+ +
+
+

Created with MrDocs

+
+ + \ No newline at end of file diff --git a/test-files/golden-tests/javadoc/relates/relates.xml b/test-files/golden-tests/javadoc/relates/relates.xml new file mode 100644 index 000000000..23446ff4a --- /dev/null +++ b/test-files/golden-tests/javadoc/relates/relates.xml @@ -0,0 +1,33 @@ + + + + + + + + A brief for A. + + + + + + + + A brief for B + + + + + + + + A brief for f. + + + A + + + + +