Skip to content

feat: support @relates #698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 27 additions & 56 deletions include/mrdocs/Metadata/Javadoc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ enum class NodeKind
throws,
details,
see,
related,
precondition,
postcondition
};
Expand Down Expand Up @@ -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<Related const&>(other);
}
};

//------------------------------------------------
//
// Block nodes
Expand Down Expand Up @@ -877,62 +898,6 @@ struct Postcondition : Paragraph

//------------------------------------------------

/** A visitor for node types.
*/
template<class F, class... Args>
constexpr
auto
visit(
NodeKind kind,
F&& f, Args&&... args)
{
switch(kind)
{
case NodeKind::admonition:
return f.template operator()<Admonition>(std::forward<Args>(args)...);
case NodeKind::brief:
return f.template operator()<Brief>(std::forward<Args>(args)...);
case NodeKind::code:
return f.template operator()<Code>(std::forward<Args>(args)...);
case NodeKind::heading:
return f.template operator()<Heading>(std::forward<Args>(args)...);
case NodeKind::link:
return f.template operator()<Link>(std::forward<Args>(args)...);
case NodeKind::reference:
return f.template operator()<Reference>(std::forward<Args>(args)...);
case NodeKind::copied:
return f.template operator()<Copied>(std::forward<Args>(args)...);
case NodeKind::list_item:
return f.template operator()<ListItem>(std::forward<Args>(args)...);
case NodeKind::unordered_list:
return f.template operator()<UnorderedList>(std::forward<Args>(args)...);
case NodeKind::paragraph:
return f.template operator()<Paragraph>(std::forward<Args>(args)...);
case NodeKind::param:
return f.template operator()<Param>(std::forward<Args>(args)...);
case NodeKind::returns:
return f.template operator()<Returns>(std::forward<Args>(args)...);
case NodeKind::styled:
return f.template operator()<Styled>(std::forward<Args>(args)...);
case NodeKind::text:
return f.template operator()<Text>(std::forward<Args>(args)...);
case NodeKind::tparam:
return f.template operator()<TParam>(std::forward<Args>(args)...);
case NodeKind::throws:
return f.template operator()<Throws>(std::forward<Args>(args)...);
case NodeKind::details:
return f.template operator()<Details>(std::forward<Args>(args)...);
case NodeKind::see:
return f.template operator()<See>(std::forward<Args>(args)...);
case NodeKind::precondition:
return f.template operator()<Precondition>(std::forward<Args>(args)...);
case NodeKind::postcondition:
return f.template operator()<Postcondition>(std::forward<Args>(args)...);
default:
return f.template operator()<void>(std::forward<Args>(args)...);
}
}

/** Visit a node.

@param node The node to visit.
Expand Down Expand Up @@ -995,6 +960,8 @@ visit(
return visitor.template visit<Precondition>();
case NodeKind::postcondition:
return visitor.template visit<Postcondition>();
case NodeKind::related:
return visitor.template visit<Related>();
default:
MRDOCS_UNREACHABLE();
}
Expand Down Expand Up @@ -1063,6 +1030,9 @@ struct MRDOCS_DECL
/// The list of "see also" references.
std::vector<doc::See> sees;

/// The list of "related" references.
std::vector<SymbolID> related;

/// The list of preconditions.
std::vector<doc::Precondition> preconditions;

Expand Down Expand Up @@ -1093,6 +1063,7 @@ struct MRDOCS_DECL
tparams.empty() &&
exceptions.empty() &&
sees.empty() &&
related.empty() &&
preconditions.empty() &&
postconditions.empty();
}
Expand Down
3 changes: 2 additions & 1 deletion mrdocs.rnc
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
Expand All @@ -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 |
Expand Down
5 changes: 5 additions & 0 deletions share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
32 changes: 32 additions & 0 deletions src/lib/AST/ParseJavadoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<doc::Related>(
C->hasTrailingNewline() && !hasExtraText,
std::string(ref));
}
// Emplace the rest of the string as doc::Text
if(hasExtraText)
{
emplaceText<doc::Text>(
C->hasTrailingNewline(),
s.substr(ref.size()));
}
return;
}

default:
break;
Expand Down
3 changes: 3 additions & 0 deletions src/lib/Gen/adoc/DocVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<doc::Text const&>(I));
Expand Down
11 changes: 10 additions & 1 deletion src/lib/Gen/hbs/HandlebarsCorpus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ domCreate(
return corpus.toStringFn(corpus, I);
}

dom::Value
domCreate(
SymbolID const& I,
HandlebarsCorpus const& corpus)
{
return corpus.get(I);
}

dom::Value
domCreate(
doc::Precondition const& I,
Expand Down Expand Up @@ -225,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)
{
Expand Down Expand Up @@ -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));
Expand Down
3 changes: 3 additions & 0 deletions src/lib/Gen/html/DocVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<doc::Text const&>(I));
Expand Down
13 changes: 13 additions & 0 deletions src/lib/Gen/xml/XMLWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,9 @@ writeNode(doc::Node const& node)
case doc::NodeKind::copied:
writeCopied(dynamic_cast<doc::Copied const&>(node));
break;
case doc::NodeKind::related:
writeRelated(dynamic_cast<doc::Related const&>(node));
break;
case doc::NodeKind::throws:
writeThrows(dynamic_cast<doc::Throws const&>(node));
break;
Expand Down Expand Up @@ -841,6 +844,16 @@ writeCopied(
});
}

void
XMLWriter::
writeRelated(
doc::Related const& node)
{
tags_.write("relates", node.string, {
{ node.id }
});
}

void
XMLWriter::
writeLink(
Expand Down
1 change: 1 addition & 0 deletions src/lib/Gen/xml/XMLWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "");
Expand Down
15 changes: 13 additions & 2 deletions src/lib/Metadata/Finalizers/JavadocFinalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Info&>(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 &&
Expand Down Expand Up @@ -150,7 +160,8 @@ finalize(doc::Node& node)
finalize(N.children);
}

if constexpr(std::same_as<NodeTy, doc::Reference>)
if constexpr(std::same_as<NodeTy, doc::Reference> ||
std::same_as<NodeTy, doc::Related>)
{
finalize(dynamic_cast<doc::Reference&>(N), true);
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/Metadata/Javadoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading