From bb6a6d36eab028f915240aa56f65c820033e0713 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 19 Jun 2023 14:24:16 -0400 Subject: [PATCH 1/2] fix: invert Value::getBool --- include/mrdox/Support/Dom.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mrdox/Support/Dom.hpp b/include/mrdox/Support/Dom.hpp index 76b977cf7..b42ca6eef 100644 --- a/include/mrdox/Support/Dom.hpp +++ b/include/mrdox/Support/Dom.hpp @@ -245,7 +245,7 @@ class MRDOX_DECL bool getBool() const noexcept { MRDOX_ASSERT(kind_ == Kind::Boolean); - return number_ == 0; + return number_ != 0; } std::int64_t getInteger() const noexcept From feb82415e0a6fad6702c72830bcf161f64943996 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 19 Jun 2023 11:39:08 -0400 Subject: [PATCH 2/2] feat: adoc support for templates --- .../asciidoc/partials/nontype-tparam.adoc.hbs | 4 + .../asciidoc/partials/record.adoc.hbs | 5 + .../asciidoc/partials/template-args.adoc.hbs | 6 + .../asciidoc/partials/template-head.adoc.hbs | 11 + .../partials/template-tparam.adoc.hbs | 5 + .../asciidoc/partials/type-tparam.adoc.hbs | 4 + include/mrdox/Dom/DomTemplate.hpp | 136 +++++++++++ source/-adoc/Builder.cpp | 11 + source/Dom/DomSymbol.cpp | 40 +++- source/Dom/DomTemplate.cpp | 216 ++++++++++++++++++ 10 files changed, 436 insertions(+), 2 deletions(-) create mode 100644 addons/generator/asciidoc/partials/nontype-tparam.adoc.hbs create mode 100644 addons/generator/asciidoc/partials/template-args.adoc.hbs create mode 100644 addons/generator/asciidoc/partials/template-head.adoc.hbs create mode 100644 addons/generator/asciidoc/partials/template-tparam.adoc.hbs create mode 100644 addons/generator/asciidoc/partials/type-tparam.adoc.hbs create mode 100644 include/mrdox/Dom/DomTemplate.hpp create mode 100644 source/Dom/DomTemplate.cpp diff --git a/addons/generator/asciidoc/partials/nontype-tparam.adoc.hbs b/addons/generator/asciidoc/partials/nontype-tparam.adoc.hbs new file mode 100644 index 000000000..cb832bfb7 --- /dev/null +++ b/addons/generator/asciidoc/partials/nontype-tparam.adoc.hbs @@ -0,0 +1,4 @@ +{{>type-name type}} +{{~#if is-pack}}...{{/if}} +{{~#if name}} {{name}}{{/if}} +{{~#if default}} = {{default}}{{/if~}} diff --git a/addons/generator/asciidoc/partials/record.adoc.hbs b/addons/generator/asciidoc/partials/record.adoc.hbs index e1684a7a0..7379db466 100644 --- a/addons/generator/asciidoc/partials/record.adoc.hbs +++ b/addons/generator/asciidoc/partials/record.adoc.hbs @@ -8,7 +8,12 @@ [source,cpp,subs=+macros] ---- +{{#if symbol.template}} +{{>template-head symbol.template}} +{{symbol.tag}} {{symbol.name}}{{>template-args symbol.template}} +{{else}} {{symbol.tag}} {{symbol.name}} +{{/if}} { {{#each symbol.members}} {{>record-member}} diff --git a/addons/generator/asciidoc/partials/template-args.adoc.hbs b/addons/generator/asciidoc/partials/template-args.adoc.hbs new file mode 100644 index 000000000..87a339d4e --- /dev/null +++ b/addons/generator/asciidoc/partials/template-args.adoc.hbs @@ -0,0 +1,6 @@ +{{~#if (neq kind "primary")~}}< +{{~#each args~}} + {{value}} + {{~#if (not @last)}}, {{/if}} +{{~/each~}} +>{{/if}} \ No newline at end of file diff --git a/addons/generator/asciidoc/partials/template-head.adoc.hbs b/addons/generator/asciidoc/partials/template-head.adoc.hbs new file mode 100644 index 000000000..b2bb63f21 --- /dev/null +++ b/addons/generator/asciidoc/partials/template-head.adoc.hbs @@ -0,0 +1,11 @@ +template< +{{~#each params~}} + {{~#if (eq kind "type")}} + {{~>type-tparam~}} + {{~else if (eq kind "non-type")}} + {{~>nontype-tparam~}} + {{~else if (eq kind "template")}} + {{~>template-tparam~}} + {{~/if~}} + {{~#if (not @last)~}}, {{/if}} +{{~/each~}}> diff --git a/addons/generator/asciidoc/partials/template-tparam.adoc.hbs b/addons/generator/asciidoc/partials/template-tparam.adoc.hbs new file mode 100644 index 000000000..5bfca0228 --- /dev/null +++ b/addons/generator/asciidoc/partials/template-tparam.adoc.hbs @@ -0,0 +1,5 @@ +{{~>template-head~}} +typename +{{~#if is-pack}}...{{/if}} +{{~#if name}} {{name}}{{/if}} +{{~#if default}} = {{default}}{{/if~}} diff --git a/addons/generator/asciidoc/partials/type-tparam.adoc.hbs b/addons/generator/asciidoc/partials/type-tparam.adoc.hbs new file mode 100644 index 000000000..c5dac5ae4 --- /dev/null +++ b/addons/generator/asciidoc/partials/type-tparam.adoc.hbs @@ -0,0 +1,4 @@ +typename +{{~#if is-pack}}...{{/if}} +{{~#if name}} {{name}}{{/if}} +{{~#if default}} = {{>type-name default}}{{~/if~}} diff --git a/include/mrdox/Dom/DomTemplate.hpp b/include/mrdox/Dom/DomTemplate.hpp new file mode 100644 index 000000000..a697ad7ce --- /dev/null +++ b/include/mrdox/Dom/DomTemplate.hpp @@ -0,0 +1,136 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdox +// + +#ifndef MRDOX_API_DOM_DOMTEMPLATE_HPP +#define MRDOX_API_DOM_DOMTEMPLATE_HPP + +#include +#include +#include + +namespace clang { +namespace mrdox { + +class MRDOX_DECL + DomTParam : public dom::Object +{ + TParam const* I_; + Corpus const& corpus_; + +public: + DomTParam( + TParam const& I, + Corpus const& corpus) noexcept + : I_(&I) + , corpus_(corpus) + { + } + + dom::Value get(std::string_view key) const override; + std::vector props() const override; +}; + +// ---------------------------------------------------------------- + +class MRDOX_DECL + DomTArg : public dom::Object +{ + TArg const* I_; + Corpus const& corpus_; + +public: + DomTArg( + TArg const& I, + Corpus const& corpus) noexcept + : I_(&I) + , corpus_(corpus) + { + } + + dom::Value get(std::string_view key) const override; + std::vector props() const override; +}; + +// ---------------------------------------------------------------- + +/** An array of template parameters +*/ +class DomTParamArray : public dom::Array +{ + std::vector const& list_; + Corpus const& corpus_; + +public: + DomTParamArray( + std::vector const& list, + Corpus const& corpus) noexcept + : list_(list) + , corpus_(corpus) + { + } + + std::size_t length() const noexcept override + { + return list_.size(); + } + + dom::Value get(std::size_t index) const override; +}; + +// ---------------------------------------------------------------- + +/** An array of template arguments +*/ +class DomTArgArray : public dom::Array +{ + std::vector const& list_; + Corpus const& corpus_; + +public: + DomTArgArray( + std::vector const& list, + Corpus const& corpus) noexcept + : list_(list) + , corpus_(corpus) + { + } + + std::size_t length() const noexcept override + { + return list_.size(); + } + + dom::Value get(std::size_t index) const override; +}; + +// ---------------------------------------------------------------- + +/** Template info +*/ +class MRDOX_DECL + DomTemplate : public dom::Object +{ + TemplateInfo const* I_; + Info const* Primary_; + Corpus const& corpus_; + +public: + DomTemplate( + TemplateInfo const& I, + Corpus const& corpus) noexcept; + + dom::Value get(std::string_view key) const override; + std::vector props() const override; +}; + +} // mrdox +} // clang + +#endif diff --git a/source/-adoc/Builder.cpp b/source/-adoc/Builder.cpp index 8b1e76c04..03b9de338 100644 --- a/source/-adoc/Builder.cpp +++ b/source/-adoc/Builder.cpp @@ -112,6 +112,17 @@ Builder( return a === b; }); + Handlebars.registerHelper( + 'neq', function(a, b) + { + return a !== b; + }); + + Handlebars.registerHelper( + 'not', function(a) + { + return ! a; + }); )"); if(err) throw err; diff --git a/source/Dom/DomSymbol.cpp b/source/Dom/DomSymbol.cpp index 10dcb33af..2cf876c6d 100644 --- a/source/Dom/DomSymbol.cpp +++ b/source/Dom/DomSymbol.cpp @@ -4,6 +4,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) +// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) // // Official repository: https://github.com/cppalliance/mrdox // @@ -18,6 +19,7 @@ #include #include #include +#include #include namespace clang { @@ -87,6 +89,12 @@ get(std::string_view key) const if(key == "specializations") return dom::makePointer( I_->Specializations, corpus_); + if(key == "template") + { + if(! I_->Template) + return nullptr; + return dom::makePointer(*I_->Template, corpus_); + } } if constexpr(T::isFunction()) { @@ -99,15 +107,33 @@ get(std::string_view key) const if(key == "specs") return dom::makePointer( *I_, corpus_); + if(key == "template") + { + if(! I_->Template) + return nullptr; + return dom::makePointer(*I_->Template, corpus_); + } } if constexpr(T::isEnum()) { } if constexpr(T::isTypedef()) { + if(key == "template") + { + if(! I_->Template) + return nullptr; + return dom::makePointer(*I_->Template, corpus_); + } } if constexpr(T::isVariable()) { + if(key == "template") + { + if(! I_->Template) + return nullptr; + return dom::makePointer(*I_->Template, corpus_); + } } if constexpr(T::isField()) { @@ -149,13 +175,23 @@ props() const -> "bases", "friends", "members", - "specializations" + "specializations", + "template" }); if constexpr(T::isFunction()) v.insert(v.end(), { "return", "params", - "specs" + "specs", + "template" + }); + if constexpr(T::isVariable()) + v.insert(v.end(), { + "template" + }); + if constexpr(T::isTypedef()) + v.insert(v.end(), { + "template" }); return v; } diff --git a/source/Dom/DomTemplate.cpp b/source/Dom/DomTemplate.cpp new file mode 100644 index 000000000..62f20876f --- /dev/null +++ b/source/Dom/DomTemplate.cpp @@ -0,0 +1,216 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdox +// + +#include +#include +#include + +namespace clang { +namespace mrdox { + +// ---------------------------------------------------------------- + +dom::Value +DomTParam:: +get(std::string_view key) const +{ + if(key == "kind") + { + switch(I_->Kind) + { + case TParamKind::Type: + return "type"; + case TParamKind::NonType: + return "non-type"; + case TParamKind::Template: + return "template"; + default: + MRDOX_UNREACHABLE(); + } + } + if(key == "name") + return dom::nonEmptyString(I_->Name); + if(key == "is-pack") + return I_->IsParameterPack; + if(key == "type") + { + if(I_->Kind != TParamKind::NonType) + return nullptr; + return dom::makePointer( + I_->get().Type, corpus_); + } + if(key == "params") + { + if(I_->Kind != TParamKind::Template) + return nullptr; + return dom::makePointer( + I_->get().Params, corpus_); + } + if(key == "default") + { + switch(I_->Kind) + { + case TParamKind::Type: + { + const auto& P = I_->get(); + if(! P.Default) + return nullptr; + return dom::makePointer( + *P.Default, corpus_); + } + case TParamKind::NonType: + { + const auto& P = I_->get(); + if(! P.Default) + return nullptr; + return *P.Default; + } + case TParamKind::Template: + { + const auto& P = I_->get(); + if(! P.Default) + return nullptr; + return *P.Default; + } + default: + MRDOX_UNREACHABLE(); + } + } + return nullptr; +} + +auto +DomTParam:: +props() const -> + std::vector +{ + return { + "kind", + "name", + "is-pack", + "default", + // only for NonTypeTParam + "type", + // only for TemplateTParam + "params" + }; +} + +dom::Value +DomTParamArray:: +get(std::size_t index) const +{ + if(index >= list_.size()) + return nullptr; + return dom::makePointer( + list_[index], corpus_); +} + +// ---------------------------------------------------------------- + +dom::Value +DomTArg:: +get(std::string_view key) const +{ + if(key == "value") + return dom::nonEmptyString(I_->Value); + return nullptr; +} + +auto +DomTArg:: +props() const -> + std::vector +{ + return { + "value" + }; +} + +dom::Value +DomTArgArray:: +get(std::size_t index) const +{ + if(index >= list_.size()) + return nullptr; + return dom::makePointer( + list_[index], corpus_); +} + +// ---------------------------------------------------------------- + +DomTemplate:: +DomTemplate( + TemplateInfo const& I, + Corpus const& corpus) noexcept + : I_(&I) + , corpus_(corpus) +{ + if(I_->Primary) + Primary_ = corpus_.find(*I_->Primary); + else + Primary_ = nullptr; +} + +dom::Value +DomTemplate:: +get(std::string_view key) const +{ + if(key == "kind") + { + switch(I_->specializationKind()) + { + case TemplateSpecKind::Primary: + return "primary"; + case TemplateSpecKind::Explicit: + return "explicit"; + case TemplateSpecKind::Partial: + return "partial"; + default: + MRDOX_UNREACHABLE(); + } + } + if(key == "primary") + { + if(! Primary_) + return nullptr; + return visit( + *Primary_, + [&](T const& I) -> + dom::ObjectPtr + { + return dom::makePointer< + DomSymbol>(I, corpus_); + }); + } + if(key == "params") + return dom::makePointer( + I_->Params, corpus_); + if(key == "args") + return dom::makePointer( + I_->Args, corpus_); + return nullptr; +} + +auto +DomTemplate:: +props() const -> + std::vector +{ + return { + "params", + "args", + "kind", + "primary" + }; +} + +} // mrdox +} // clang