Skip to content
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
21 changes: 15 additions & 6 deletions src/lib/Gen/adoc/DocVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,15 +244,24 @@ operator()(doc::Reference const& I) const
{
return (*this)(static_cast<doc::Text const&>(I));
}
auto url = corpus_.getURL(corpus_->get(I.id));
if (url.starts_with('/'))
dom::Object symbolObj = corpus_.construct(corpus_->get(I.id));
if (symbolObj.exists("url"))
{
url.erase(0, 1);
std::string url = symbolObj.get("url").getString().str();
if (url.starts_with('/'))
{
url.erase(0, 1);
}
fmt::format_to(
std::back_inserter(dest_),
"xref:{}[{}]",
url, AdocEscape(I.string));
return;
}
fmt::format_to(
std::back_inserter(dest_),
"xref:{}[{}]",
url, AdocEscape(I.string));
std::back_inserter(dest_),
"`{}`",
AdocEscape(I.string));
}

void
Expand Down
145 changes: 1 addition & 144 deletions src/lib/Gen/hbs/HandlebarsCorpus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,149 +115,6 @@ domCreate(
return corpus.toStringFn(corpus, I);
}

Info const*
resolveTypedef(Corpus const& c, Info const& I)
{
if (I.Kind == InfoKind::Typedef)
{
TypedefInfo const& TI = dynamic_cast<TypedefInfo const&>(I);
std::unique_ptr<TypeInfo> const& T = TI.Type;
MRDOCS_CHECK_OR(T && T->Kind == TypeKind::Named, &I);
NamedTypeInfo const& NT = dynamic_cast<NamedTypeInfo const&>(*T);
MRDOCS_CHECK_OR(NT.Name, &I);
Info const* resolved = c.find(NT.Name->id);
MRDOCS_CHECK_OR(resolved, &I);
if (resolved->Kind == InfoKind::Typedef)
{
return resolveTypedef(c, *resolved);
}
return resolved;
}
return &I;
}

Info const*
findPrimarySiblingWithUrl(Corpus const& c, Info const& I, Info const& parent)
{
// Look for the primary sibling in the parent scope
auto const* parentScope = dynamic_cast<ScopeInfo const*>(&parent);
MRDOCS_CHECK_OR(parentScope, nullptr);
for (auto& siblingIDs = parentScope->Lookups.at(I.Name);
SymbolID const& siblingID: siblingIDs)
{
Info const* sibling = c.find(siblingID);
if (!sibling ||
!shouldGenerate(*sibling) ||
sibling->Name != I.Name)
{
continue;
}
bool const isPrimarySibling = visit(*sibling, [&](auto const& U)
{
if constexpr (requires { U.Template; })
{
std::optional<TemplateInfo> const& Template = U.Template;
MRDOCS_CHECK_OR(Template, false);
return !Template->Params.empty() && Template->Args.empty();
}
return false;
});
if (!isPrimarySibling)
{
continue;
}
return sibling;
}
return nullptr;
}

Info const*
findPrimarySiblingWithUrl(Corpus const& c, Info const& I);

Info const*
findDirectPrimarySiblingWithUrl(Corpus const& c, Info const& I)
{
// If the parent is a scope, look for a primary sibling
// in the parent scope for which we want to generate the URL
Info const* parent = c.find(I.Parent);
MRDOCS_CHECK_OR(parent, nullptr);
if (!shouldGenerate(*parent))
{
parent = findPrimarySiblingWithUrl(c, *parent);
MRDOCS_CHECK_OR(parent, nullptr);
}
return findPrimarySiblingWithUrl(c, I, *parent);
}

Info const*
findResolvedPrimarySiblingWithUrl(Corpus const& c, Info const& I)
{
// Check if this info is a specialization or a typedef to
// a specialization, otherwise there's nothing to resolve
bool const isSpecialization = visit(I, [&]<typename InfoTy>(InfoTy const& U)
{
// The symbol is a specialization
if constexpr (requires { U.Template; })
{
std::optional<TemplateInfo> const& Template = U.Template;
if (Template &&
!Template->Args.empty())
{
return true;
}
}
// The symbol is a typedef to a specialization
if constexpr (std::same_as<InfoTy, TypedefInfo>)
{
std::unique_ptr<TypeInfo> const& T = U.Type;
MRDOCS_CHECK_OR(T && T->Kind == TypeKind::Named, false);
auto const& NT = dynamic_cast<NamedTypeInfo const&>(*T);
MRDOCS_CHECK_OR(NT.Name, false);
MRDOCS_CHECK_OR(NT.Name->Kind == NameKind::Specialization, false);
return true;
}
return false;
});
MRDOCS_CHECK_OR(isSpecialization, nullptr);

// Find the parent scope containing the primary sibling
// for which we want to generate the URL
Info const* parent = c.find(I.Parent);
MRDOCS_CHECK_OR(parent, nullptr);

// If the parent is a typedef, resolve it
// so we can iterate the members of this scope.
// We can't find siblings in a typedef because
// it's not a scope.
if (parent->Kind == InfoKind::Typedef)
{
parent = resolveTypedef(c, *parent);
MRDOCS_CHECK_OR(parent, nullptr);
}

// If the resolved parent is also a specialization or
// a dependency for which there's no URL, we attempt to
// find the primary sibling for the parent so we take
// the URL from it.
if (!shouldGenerate(*parent))
{
parent = findPrimarySiblingWithUrl(c, *parent);
MRDOCS_CHECK_OR(parent, nullptr);
}

return findPrimarySiblingWithUrl(c, I, *parent);
}

Info const*
findPrimarySiblingWithUrl(Corpus const& c, Info const& I)
{
if (Info const* primary = findDirectPrimarySiblingWithUrl(c, I))
{
return primary;
}
return findResolvedPrimarySiblingWithUrl(c, I);
}

} // (anon)

dom::Object
Expand All @@ -275,7 +132,7 @@ construct(Info const& I) const
// If the URL is not available because it's a specialization
// or dependency, we still want to generate the URL and anchor
// for the primary template if it's part of the corpus.
if (Info const* primaryInfo = findPrimarySiblingWithUrl(getCorpus(), I))
if (Info const* primaryInfo = findAlternativeURLInfo(getCorpus(), I))
{
obj.set("url", getURL(*primaryInfo));
obj.set("anchor", names_.getQualified(primaryInfo->id, '-'));
Expand Down
Loading
Loading