Skip to content
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

feat: support @relates #698

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
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
84 changes: 28 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 @@ -364,6 +365,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 @@ -867,62 +888,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 @@ -985,6 +950,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 @@ -1053,12 +1020,16 @@ 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;

/// The list of postconditions.
std::vector<doc::Postcondition> postconditions;


/** Constructor.
*/
MRDOCS_DECL
Expand All @@ -1083,6 +1054,7 @@ struct MRDOCS_DECL
tparams.empty() &&
exceptions.empty() &&
sees.empty() &&
related.empty() &&
preconditions.empty() &&
postconditions.empty();
}
Expand Down
10 changes: 10 additions & 0 deletions share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,13 @@
{{/each}}

{{/if}}
{{! Related }}
{{#if symbol.doc.related}}
{{#> markup/dynamic-level-h }}Related{{/markup/dynamic-level-h}}

{{#each symbol.doc.related}}
{{{.}}}

{{/each}}

{{/if}}
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
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
4 changes: 2 additions & 2 deletions src/lib/Lib/CorpusImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,11 @@ lookup(SymbolID const& context, std::string_view name) const
return lookupImpl(*this, context, name);
}

Info const*
Info*
CorpusImpl::
lookup(SymbolID const& context, std::string_view name)
{
return lookupImpl(*this, context, name);
return const_cast<Info*>(lookupImpl(*this, context, name));
}

template <class Self>
Expand Down
6 changes: 3 additions & 3 deletions src/lib/Lib/CorpusImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ class CorpusImpl final : public Corpus
Info const*
find(SymbolID const& id) const noexcept override;

Info const*
lookup(SymbolID const& context, std::string_view name) const override;
Info*
lookup(SymbolID const& context, std::string_view name);

Info const*
lookup(SymbolID const& context, std::string_view name);
lookup(SymbolID const& context, std::string_view name) const override;

/** Build metadata for a set of translation units.

Expand Down
13 changes: 11 additions & 2 deletions src/lib/Metadata/Finalizers/JavadocFinalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,18 @@ void
JavadocFinalizer::
finalize(doc::Reference& ref)
{
Info const* res = corpus_.lookup(current_context_->id, ref.string);
Info* res = corpus_.lookup(current_context_->id, ref.string);
if (res)
{
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);
}
}
if (res == nullptr &&
// Only warn once per reference
Expand Down Expand Up @@ -150,7 +158,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));
}
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 @@ -192,6 +192,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