From d3425e069fa28e307f96f9350745f70228152019 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 19 Feb 2025 14:33:59 -0500 Subject: [PATCH 01/11] rename HasOverrideAttr to IsOverride --- docs/modules/ROOT/pages/generators.adoc | 4 ++-- include/mrdocs/Metadata/Info/Function.hpp | 4 ++-- .../generator/common/partials/symbol/signature/function.hbs | 2 +- src/lib/AST/ASTVisitor.cpp | 2 +- src/lib/Gen/xml/XMLWriter.cpp | 2 +- src/lib/Metadata/Info/Function.cpp | 2 +- .../filters/symbol-name/excluded-base-class.xml | 6 +++--- test-files/golden-tests/symbols/function/mem-fn.xml | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/modules/ROOT/pages/generators.adoc b/docs/modules/ROOT/pages/generators.adoc index 84bce290a..ca5dcf819 100644 --- a/docs/modules/ROOT/pages/generators.adoc +++ b/docs/modules/ROOT/pages/generators.adoc @@ -330,9 +330,9 @@ When the symbol kind is `function`, the symbol object has the following addition | `bool` | Whether the function is noreturn. -| `hasOverrideAttr` +| `isOverride` | `bool` -| Whether the function has the override attribute. +| Whether the function is override. | `hasTrailingReturn` | `bool` diff --git a/include/mrdocs/Metadata/Info/Function.hpp b/include/mrdocs/Metadata/Info/Function.hpp index 56489b23e..08b2af5c7 100644 --- a/include/mrdocs/Metadata/Info/Function.hpp +++ b/include/mrdocs/Metadata/Info/Function.hpp @@ -166,7 +166,7 @@ struct FunctionInfo final bool IsDeleted = false; bool IsDeletedAsWritten = false; bool IsNoReturn = false; - bool HasOverrideAttr = false; + bool IsOverride = false; bool HasTrailingReturn = false; bool IsNodiscard = false; bool IsExplicitObjectMemberFunction = false; @@ -221,7 +221,7 @@ tag_invoke( io.map("isDeleted", I.IsDeleted); io.map("isDeletedAsWritten", I.IsDeletedAsWritten); io.map("isNoReturn", I.IsNoReturn); - io.map("hasOverrideAttr", I.HasOverrideAttr); + io.map("isOverride", I.IsOverride); io.map("hasTrailingReturn", I.HasTrailingReturn); io.map("isConst", I.IsConst); io.map("isVolatile", I.IsVolatile); diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/function.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/function.hbs index 130a8b58d..dfe4acf8c 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/function.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/function.hbs @@ -28,7 +28,7 @@ {{#if requires}} requires {{requires}}{{/if~}} -{{#if hasOverrideAttr}} override{{/if~}} +{{#if isOverride}} override{{/if~}} {{#if isFinal}} final{{/if~}} {{#if isPure}} = 0{{/if~}} {{#if isDeleted}} = delete{{/if~}} diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index 95ca28786..043b0fa08 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -801,7 +801,6 @@ populate( I.IsDeleted |= D->isDeleted(); I.IsDeletedAsWritten |= D->isDeletedAsWritten(); I.IsNoReturn |= D->isNoReturn(); - I.HasOverrideAttr |= D->hasAttr(); if (ConstexprSpecKind const CSK = D->getConstexprKind(); CSK != ConstexprSpecKind::Unspecified) @@ -927,6 +926,7 @@ populate(FunctionInfo& I, CXXMethodDecl const* D) I.IsVolatile |= D->isVolatile(); I.RefQualifier = toReferenceKind(D->getRefQualifier()); I.IsFinal |= D->hasAttr(); + I.IsOverride |= D->hasAttr(); } void diff --git a/src/lib/Gen/xml/XMLWriter.cpp b/src/lib/Gen/xml/XMLWriter.cpp index df3b7c9e1..bb0161ee0 100644 --- a/src/lib/Gen/xml/XMLWriter.cpp +++ b/src/lib/Gen/xml/XMLWriter.cpp @@ -334,7 +334,7 @@ writeFunction( writeAttr(I.IsDeleted, "is-deleted", tags_); writeAttr(I.IsDeletedAsWritten, "is-deleted-as-written", tags_); writeAttr(I.IsNoReturn, "is-no-return", tags_); - writeAttr(I.HasOverrideAttr, "has-override", tags_); + writeAttr(I.IsOverride, "is-override", tags_); writeAttr(I.HasTrailingReturn, "has-trailing-return", tags_); writeAttr(I.Constexpr, "constexpr-kind", tags_); writeAttr(I.OverloadedOperator, "operator", tags_); diff --git a/src/lib/Metadata/Info/Function.cpp b/src/lib/Metadata/Info/Function.cpp index ecd879832..d760817f6 100644 --- a/src/lib/Metadata/Info/Function.cpp +++ b/src/lib/Metadata/Info/Function.cpp @@ -331,11 +331,11 @@ merge(FunctionInfo& I, FunctionInfo&& Other) I.IsDeleted |= Other.IsDeleted; I.IsDeletedAsWritten |= Other.IsDeletedAsWritten; I.IsNoReturn |= Other.IsNoReturn; - I.HasOverrideAttr |= Other.HasOverrideAttr; I.HasTrailingReturn |= Other.HasTrailingReturn; I.IsConst |= Other.IsConst; I.IsVolatile |= Other.IsVolatile; I.IsFinal |= Other.IsFinal; + I.IsOverride |= Other.IsOverride; I.IsNodiscard |= Other.IsNodiscard; I.IsExplicitObjectMemberFunction |= Other.IsExplicitObjectMemberFunction; if (I.Constexpr == ConstexprKind::None) diff --git a/test-files/golden-tests/filters/symbol-name/excluded-base-class.xml b/test-files/golden-tests/filters/symbol-name/excluded-base-class.xml index e33b54280..3c77edd6a 100644 --- a/test-files/golden-tests/filters/symbol-name/excluded-base-class.xml +++ b/test-files/golden-tests/filters/symbol-name/excluded-base-class.xml @@ -13,11 +13,11 @@ - + - + @@ -37,7 +37,7 @@ - + diff --git a/test-files/golden-tests/symbols/function/mem-fn.xml b/test-files/golden-tests/symbols/function/mem-fn.xml index 45064bb1d..301e9bbe1 100644 --- a/test-files/golden-tests/symbols/function/mem-fn.xml +++ b/test-files/golden-tests/symbols/function/mem-fn.xml @@ -115,7 +115,7 @@ - + @@ -163,7 +163,7 @@ - + From df10dc64c6b001aba472e93d83a743f5f375f73e Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 19 Feb 2025 17:15:53 -0500 Subject: [PATCH 02/11] [WIP] add AttributeKind --- docs/modules/ROOT/pages/generators.adoc | 36 ++-------- include/mrdocs/Metadata/Info.hpp | 7 ++ include/mrdocs/Metadata/Info/Field.hpp | 14 ---- include/mrdocs/Metadata/Info/Function.hpp | 9 +-- include/mrdocs/Metadata/Info/Variable.hpp | 2 - include/mrdocs/Metadata/Specifiers.hpp | 24 +++++++ .../common/partials/symbol/attributes.hbs | 2 + .../partials/symbol/signature/concept.hbs | 2 +- .../common/partials/symbol/signature/enum.hbs | 2 +- .../partials/symbol/signature/field.hbs | 4 +- .../partials/symbol/signature/function.hbs | 2 +- .../partials/symbol/signature/record.hbs | 2 +- .../partials/symbol/signature/typedef.hbs | 4 +- .../partials/symbol/signature/variable.hbs | 2 + src/lib/AST/ASTVisitor.cpp | 70 ++++++++++++++++--- src/lib/AST/ASTVisitor.hpp | 7 +- src/lib/Gen/xml/XMLWriter.cpp | 5 -- src/lib/Metadata/Info.cpp | 16 +++++ src/lib/Metadata/Info/Field.cpp | 3 - src/lib/Metadata/Info/Function.cpp | 2 - src/lib/Metadata/Specifiers.cpp | 14 ++++ 21 files changed, 143 insertions(+), 86 deletions(-) create mode 100644 share/mrdocs/addons/generator/common/partials/symbol/attributes.hbs diff --git a/docs/modules/ROOT/pages/generators.adoc b/docs/modules/ROOT/pages/generators.adoc index ca5dcf819..ec6e78de6 100644 --- a/docs/modules/ROOT/pages/generators.adoc +++ b/docs/modules/ROOT/pages/generators.adoc @@ -189,6 +189,10 @@ The `Symbol` object represents a symbol extracted from the source code.The symbo | `Any` | The documentation for the symbol. +| `attributes` +| `string[]` +| The attributes of the symbol. + |=== Handlebars generators extend each symbol with the following fields: @@ -326,10 +330,6 @@ When the symbol kind is `function`, the symbol object has the following addition | `bool` | Whether the function is deleted as written. -| `isNoReturn` -| `bool` -| Whether the function is noreturn. - | `isOverride` | `bool` | Whether the function is override. @@ -350,10 +350,6 @@ When the symbol kind is `function`, the symbol object has the following addition | `bool` | Whether the function is final. -| `isNodiscard` -| `bool` -| Whether the function is nodiscard. - | `isExplicitObjectMemberFunction` | `bool` | Whether the function is an explicit object member function. @@ -401,10 +397,6 @@ When the symbol kind is `function`, the symbol object has the following addition | `requires` | `string` | The `requires` expression of the function. - -| `attributes` -| `string[]` -| The attributes of the function. |=== When the symbol kind is `typedef`, the symbol object has the following additional properties: @@ -461,10 +453,6 @@ When the symbol kind is `variable`, the symbol object has the following addition | `initializer` | `string` | The initializer of the variable. - -| `attributes` -| `string[]` -| The attributes of the variable. |=== When the symbol kind is `field` (i.e. non-static data members), the symbol object has the following additional properties: @@ -480,14 +468,6 @@ When the symbol kind is `field` (i.e. non-static data members), the symbol objec | `string` | The default value of the field. -| `isMaybeUnused` -| `bool` -| Whether the field is maybe unused. - -| `isDeprecated` -| `bool` -| Whether the field is deprecated. - | `isVariant` | `bool` | Whether the field is a variant. @@ -500,17 +480,9 @@ When the symbol kind is `field` (i.e. non-static data members), the symbol objec | `bool` | Whether the field is a bitfield. -| `hasNoUniqueAddress` -| `string` -| Whether the field has the `[[no_unique_address]]` attribute. - | `bitfieldWidth` | `string` | The width of the bitfield. - -| `attributes` -| `string[]` -| The attributes of the field. |=== When the symbol kind is `friend`, the symbol object has the following additional properties: diff --git a/include/mrdocs/Metadata/Info.hpp b/include/mrdocs/Metadata/Info.hpp index ecf56351b..964fa3ae3 100644 --- a/include/mrdocs/Metadata/Info.hpp +++ b/include/mrdocs/Metadata/Info.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -112,6 +113,10 @@ struct MRDOCS_VISIBLE Info */ std::optional javadoc; + /** The attributes appertaining to this declaration. + */ + std::vector Attributes; + //-------------------------------------------- ~Info() override = default; @@ -298,6 +303,8 @@ tag_invoke( { io.map("doc", *I.javadoc); } + + io.map("attributes", dom::LazyArray(I.Attributes)); io.map("loc", dynamic_cast(I)); } diff --git a/include/mrdocs/Metadata/Info/Field.hpp b/include/mrdocs/Metadata/Info/Field.hpp index 711cab72d..69746ca26 100644 --- a/include/mrdocs/Metadata/Info/Field.hpp +++ b/include/mrdocs/Metadata/Info/Field.hpp @@ -48,16 +48,6 @@ struct FieldInfo final /** The width of the bitfield */ ConstantExprInfo BitfieldWidth; - // KRYSTIAN FIXME: nodiscard cannot be applied to fields; this should - // instead be IsMaybeUnused. we should also store the spelling - bool IsMaybeUnused = false; - - bool IsDeprecated = false; - - bool HasNoUniqueAddress = false; - - std::vector Attributes; - //-------------------------------------------- explicit FieldInfo(SymbolID ID) noexcept @@ -86,17 +76,13 @@ tag_invoke( { io.map("default", I.Default.Written); } - io.map("isMaybeUnused", I.IsMaybeUnused); - io.map("isDeprecated", I.IsDeprecated); io.map("isVariant", I.IsVariant); io.map("isMutable", I.IsMutable); io.map("isBitfield", I.IsBitfield); - io.map("hasNoUniqueAddress", I.HasNoUniqueAddress); if (I.IsBitfield) { io.map("bitfieldWidth", I.BitfieldWidth.Written); } - io.map("attributes", dom::LazyArray(I.Attributes)); } /** Map the FieldInfo to a @ref dom::Value object. diff --git a/include/mrdocs/Metadata/Info/Function.hpp b/include/mrdocs/Metadata/Info/Function.hpp index 08b2af5c7..b655389fa 100644 --- a/include/mrdocs/Metadata/Info/Function.hpp +++ b/include/mrdocs/Metadata/Info/Function.hpp @@ -165,10 +165,7 @@ struct FunctionInfo final bool IsExplicitlyDefaulted = false; bool IsDeleted = false; bool IsDeletedAsWritten = false; - bool IsNoReturn = false; - bool IsOverride = false; bool HasTrailingReturn = false; - bool IsNodiscard = false; bool IsExplicitObjectMemberFunction = false; ConstexprKind Constexpr = ConstexprKind::None; OperatorKind OverloadedOperator = OperatorKind::None; @@ -183,6 +180,7 @@ struct FunctionInfo final bool IsConst = false; bool IsVolatile = false; bool IsFinal = false; + bool IsOverride = false; ReferenceKind RefQualifier = ReferenceKind::None; ExplicitInfo Explicit; @@ -220,13 +218,11 @@ tag_invoke( io.map("isExplicitlyDefaulted", I.IsExplicitlyDefaulted); io.map("isDeleted", I.IsDeleted); io.map("isDeletedAsWritten", I.IsDeletedAsWritten); - io.map("isNoReturn", I.IsNoReturn); - io.map("isOverride", I.IsOverride); io.map("hasTrailingReturn", I.HasTrailingReturn); io.map("isConst", I.IsConst); io.map("isVolatile", I.IsVolatile); io.map("isFinal", I.IsFinal); - io.map("isNodiscard", I.IsNodiscard); + io.map("isOverride", I.IsOverride); io.map("isExplicitObjectMemberFunction", I.IsExplicitObjectMemberFunction); if (I.Constexpr != ConstexprKind::None) { @@ -251,7 +247,6 @@ tag_invoke( { io.map("requires", I.Requires.Written); } - io.map("attributes", dom::LazyArray(I.Attributes)); } /** Map the FunctionInfo to a @ref dom::Value object. diff --git a/include/mrdocs/Metadata/Info/Variable.hpp b/include/mrdocs/Metadata/Info/Variable.hpp index c8d8ece54..c3f7c7528 100644 --- a/include/mrdocs/Metadata/Info/Variable.hpp +++ b/include/mrdocs/Metadata/Info/Variable.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include namespace clang::mrdocs { @@ -89,7 +88,6 @@ tag_invoke( { io.map("initializer", I.Initializer.Written); } - io.map("attributes", dom::LazyArray(I.Attributes)); } /** Map the VariableInfo to a @ref dom::Value object. diff --git a/include/mrdocs/Metadata/Specifiers.hpp b/include/mrdocs/Metadata/Specifiers.hpp index b9d069da4..9296fb1bb 100644 --- a/include/mrdocs/Metadata/Specifiers.hpp +++ b/include/mrdocs/Metadata/Specifiers.hpp @@ -36,6 +36,17 @@ enum class AccessKind Private, }; +/** Attribute kinds. +*/ +enum class AttributeKind +{ + Deprecated, + MaybeUnused, + Nodiscard, + Noreturn, + NoUniqueAddress +}; + /** `constexpr`/`consteval` specifier kinds [dcl.spec.general] p2: At most one of the `constexpr`, `consteval`, @@ -209,6 +220,7 @@ enum class StorageClassKind }; MRDOCS_DECL dom::String toString(AccessKind kind) noexcept; +MRDOCS_DECL dom::String toString(AttributeKind kind) noexcept; MRDOCS_DECL dom::String toString(ConstexprKind kind) noexcept; MRDOCS_DECL dom::String toString(ExplicitKind kind) noexcept; MRDOCS_DECL dom::String toString(NoexceptKind kind) noexcept; @@ -278,6 +290,18 @@ tag_invoke( v = toString(kind); } +/** Return the AttributeKind as a @ref dom::Value string. + */ +inline +void +tag_invoke( + dom::ValueFromTag, + dom::Value& v, + AttributeKind kind) +{ + v = toString(kind); +} + /** Return the ConstexprKind as a @ref dom::Value string. */ inline diff --git a/share/mrdocs/addons/generator/common/partials/symbol/attributes.hbs b/share/mrdocs/addons/generator/common/partials/symbol/attributes.hbs new file mode 100644 index 000000000..b91c1b94c --- /dev/null +++ b/share/mrdocs/addons/generator/common/partials/symbol/attributes.hbs @@ -0,0 +1,2 @@ +{{!-- Renders the symbol attributes. --}} +{{ str "[[" }}{{join ", " attributes}}{{ str "]]" }} \ No newline at end of file diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/concept.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/concept.hbs index ae55eb0c2..cbdca0fa7 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/concept.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/concept.hbs @@ -1,3 +1,3 @@ {{>template/head template}} -concept {{>symbol/name symbol}} = {{constraint}}; \ No newline at end of file +concept {{>symbol/name symbol}}{{#if attributes}} {{>symbol/attributes symbol}}{{/if}} = {{constraint}}; \ No newline at end of file diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs index 202010d35..acc446f11 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs @@ -1,2 +1,2 @@ -enum {{#if isScoped}}class {{/if}}{{>symbol/name .~}} +enum {{#if isScoped}}class {{/if}}{{#if attributes}} {{>symbol/attributes symbol}}{{/if}} {{>symbol/name .~}} {{#if type}} : {{>type/declarator type}}{{/if}}; \ No newline at end of file diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/field.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/field.hbs index e43274dc5..d96783fbe 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/field.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/field.hbs @@ -1,5 +1,5 @@ -{{#if attributes}}{{ str "[[" }}{{join ", " attributes}}{{ str "]]" }} -{{/if}} +{{#if attributes}}{{>symbol/attributes symbol}} +{{/if~}} {{#if isMutable}}mutable {{/if~}} {{>type/declarator-prefix type}} {{>symbol/name symbol~}} diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/function.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/function.hbs index dfe4acf8c..acd79e615 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/function.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/function.hbs @@ -2,7 +2,7 @@ {{/if~}} {{#if isFriend}}friend {{/if~}} -{{#if attributes}}{{#unless isFriend}}{{ str "[[" }}{{join ", " attributes}}{{ str "]]" }} +{{#if attributes}}{{#unless isFriend}}{{>symbol/attributes symbol}} {{/unless}}{{/if~}} {{#if constexprKind}}{{constexprKind}} {{/if~}} diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/record.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/record.hbs index 0afb25ed2..66183f1d2 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/record.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/record.hbs @@ -1,6 +1,6 @@ {{#if template}}{{>template/head template}} {{/if~}} -{{#if isFriend}}friend {{/if}}{{tag}} {{>symbol/name symbol link=(select link link template.primary)~}} +{{#if isFriend}}friend {{/if}}{{tag}}{{#if attributes}} {{>symbol/attributes symbol}}{{/if}} {{>symbol/name symbol link=(select link link template.primary)~}} {{#unless bases~}} {{else if isFriend~}} {{else}} diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/typedef.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/typedef.hbs index 1469df45e..0b08bd4eb 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/typedef.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/typedef.hbs @@ -1,7 +1,9 @@ {{#if isUsing~}} {{#if template}}{{>template/head template}} {{/if~}} - using {{name}} = {{>type/declarator type}} + using {{name}}{{#if attributes}} {{>symbol/attributes symbol}}{{/if}} = {{>type/declarator type}} {{~else~}} + {{#if attributes}}{{>symbol/attributes symbol}} + {{/if~}} typedef {{>type/declarator type decl-name=name}} {{~/if}}; \ No newline at end of file diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/variable.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/variable.hbs index 77caeb6a1..856bcc3df 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/variable.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/variable.hbs @@ -1,5 +1,7 @@ {{#if template}}{{>template/head template}} {{/if~}} +{{#if attributes}}{{>symbol/attributes symbol}} +{{/if~}} {{#if isInline}}inline {{/if~}} {{#if isConstexpr}}constexpr {{/if~}} {{#if storageClass}}{{storageClass}} diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index 043b0fa08..e711116cb 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -525,6 +525,7 @@ populate(Info& I, bool const isNew, DeclTy const* D) { populate(I.javadoc, D); populate(dynamic_cast(I), D); + populateAttributes(I, D); // All other information is redundant if the symbol is not new MRDOCS_CHECK_OR(isNew); @@ -800,7 +801,6 @@ populate( I.IsExplicitlyDefaulted |= D->isExplicitlyDefaulted(); I.IsDeleted |= D->isDeleted(); I.IsDeletedAsWritten |= D->isDeletedAsWritten(); - I.IsNoReturn |= D->isNoReturn(); if (ConstexprSpecKind const CSK = D->getConstexprKind(); CSK != ConstexprSpecKind::Unspecified) @@ -813,7 +813,6 @@ populate( I.StorageClass = toStorageClassKind(SC); } - I.IsNodiscard |= D->hasAttr(); I.IsExplicitObjectMemberFunction |= D->hasCXXExplicitFunctionObjectParameter(); ArrayRef const params = D->parameters(); @@ -899,8 +898,6 @@ populate( } } } - - populateAttributes(I, D); } void @@ -1056,7 +1053,6 @@ populate( QT.removeLocalConst(); } I.Type = toTypeInfo(QT); - populateAttributes(I, D); } void @@ -1100,10 +1096,6 @@ populate( I.IsBitfield = true; populate(I.BitfieldWidth, D->getBitWidth()); } - I.HasNoUniqueAddress = D->hasAttr(); - I.IsDeprecated = D->hasAttr(); - I.IsMaybeUnused = D->hasAttr(); - populateAttributes(I, D); } void @@ -1624,11 +1616,55 @@ populate( })); } -template InfoTy> void ASTVisitor:: -populateAttributes(InfoTy& I, Decl const* D) +populateAttributes(Info& I, Decl const* D) { + if(! D->hasAttrs()) + return; + for(const Attr* AT : D->getAttrs()) + { + switch(AT->getKind()) + { + case attr::Kind::Deprecated: + addAttribute(I, AttributeKind::Deprecated); + break; + case attr::Kind::Unused: + addAttribute(I, AttributeKind::MaybeUnused); + break; + case attr::Kind::WarnUnusedResult: + addAttribute(I, AttributeKind::Nodiscard); + break; + case attr::Kind::NoReturn: + addAttribute(I, AttributeKind::Noreturn); + break; + case attr::Kind::NoUniqueAddress: + addAttribute(I, AttributeKind::NoUniqueAddress); + break; + default: + // KRYSTIAN TODO: handle more attributes types + break; + } + } + +#if 0 + if(D->hasAttr()) + addAttribute(I, AttributeKind::Deprecated); + + if(D->hasAttr()) + addAttribute(I, AttributeKind::MaybeUnused); + + if(D->hasAttr()) + addAttribute(I, AttributeKind::Nodiscard); + + if(D->hasAttr()) + addAttribute(I, AttributeKind::Noreturn); + + if(D->hasAttr()) + addAttribute(I, AttributeKind::NoUniqueAddress); + #endif + + #if 0 if constexpr (requires { I.Attributes; }) { MRDOCS_CHECK_OR(D->hasAttrs()); @@ -1645,6 +1681,18 @@ populateAttributes(InfoTy& I, Decl const* D) } } } + #endif +} + +void +ASTVisitor:: +addAttribute( + Info& I, + AttributeKind kind) +{ + if(std::ranges::find(I.Attributes, kind) != I.Attributes.end()) + return; + I.Attributes.emplace_back(kind); } void diff --git a/src/lib/AST/ASTVisitor.hpp b/src/lib/AST/ASTVisitor.hpp index c6f717143..b39e79021 100644 --- a/src/lib/AST/ASTVisitor.hpp +++ b/src/lib/AST/ASTVisitor.hpp @@ -708,10 +708,11 @@ class ASTVisitor std::vector>& result, ASTTemplateArgumentListInfo const* args); - template InfoTy> - static void - populateAttributes(InfoTy& I, Decl const* D); + populateAttributes(Info& I, Decl const* D); + + void + addAttribute(Info& I, AttributeKind kind); // ================================================= // Populate function helpers diff --git a/src/lib/Gen/xml/XMLWriter.cpp b/src/lib/Gen/xml/XMLWriter.cpp index bb0161ee0..0bae2f9ff 100644 --- a/src/lib/Gen/xml/XMLWriter.cpp +++ b/src/lib/Gen/xml/XMLWriter.cpp @@ -333,7 +333,6 @@ writeFunction( writeAttr(I.IsExplicitlyDefaulted, "is-explicitly-defaulted", tags_); writeAttr(I.IsDeleted, "is-deleted", tags_); writeAttr(I.IsDeletedAsWritten, "is-deleted-as-written", tags_); - writeAttr(I.IsNoReturn, "is-no-return", tags_); writeAttr(I.IsOverride, "is-override", tags_); writeAttr(I.HasTrailingReturn, "has-trailing-return", tags_); writeAttr(I.Constexpr, "constexpr-kind", tags_); @@ -342,7 +341,6 @@ writeFunction( writeAttr(I.IsConst, "is-const", tags_); writeAttr(I.IsVolatile, "is-volatile", tags_); writeAttr(I.RefQualifier, "ref-qualifier", tags_); - writeAttr(I.IsNodiscard, "nodiscard", tags_); writeAttr(I.IsExplicitObjectMemberFunction, "is-explicit-object-member-function", tags_); writeReturnType(*I.ReturnType, tags_); @@ -585,9 +583,6 @@ writeField( }); writeAttr(I.IsVariant, "is-variant", tags_); - writeAttr(I.IsMaybeUnused, "maybe-unused", tags_); - writeAttr(I.IsDeprecated, "deprecated", tags_); - writeAttr(I.HasNoUniqueAddress, "no-unique-address", tags_); writeType(I.Type, tags_); diff --git a/src/lib/Metadata/Info.cpp b/src/lib/Metadata/Info.cpp index db2746b0f..2c03abb3d 100644 --- a/src/lib/Metadata/Info.cpp +++ b/src/lib/Metadata/Info.cpp @@ -64,6 +64,22 @@ merge(Info& I, Info&& Other) { merge(*I.javadoc, std::move(*Other.javadoc)); } + + if(I.Attributes.empty()) + { + I.Attributes = std::move(Other.Attributes); + } + else if(! Other.Attributes.empty()) + { + auto it = std::ranges::remove_if( + Other.Attributes, [&](AttributeKind k) + { + return std::ranges::find( + I.Attributes, k) != I.Attributes.end(); + }).begin(); + I.Attributes.insert(I.Attributes.end(), + Other.Attributes.begin(), it); + } } } // clang::mrdocs diff --git a/src/lib/Metadata/Info/Field.cpp b/src/lib/Metadata/Info/Field.cpp index ae31c6966..55ba56756 100644 --- a/src/lib/Metadata/Info/Field.cpp +++ b/src/lib/Metadata/Info/Field.cpp @@ -32,9 +32,6 @@ merge(FieldInfo& I, FieldInfo&& Other) merge(I.BitfieldWidth, std::move(Other.BitfieldWidth)); I.IsVariant |= Other.IsVariant; I.IsMutable |= Other.IsMutable; - I.IsMaybeUnused |= Other.IsMaybeUnused; - I.IsDeprecated |= Other.IsDeprecated; - I.HasNoUniqueAddress |= Other.HasNoUniqueAddress; } } // clang::mrdocs diff --git a/src/lib/Metadata/Info/Function.cpp b/src/lib/Metadata/Info/Function.cpp index d760817f6..a197b2ebb 100644 --- a/src/lib/Metadata/Info/Function.cpp +++ b/src/lib/Metadata/Info/Function.cpp @@ -330,13 +330,11 @@ merge(FunctionInfo& I, FunctionInfo&& Other) I.IsExplicitlyDefaulted |= Other.IsExplicitlyDefaulted; I.IsDeleted |= Other.IsDeleted; I.IsDeletedAsWritten |= Other.IsDeletedAsWritten; - I.IsNoReturn |= Other.IsNoReturn; I.HasTrailingReturn |= Other.HasTrailingReturn; I.IsConst |= Other.IsConst; I.IsVolatile |= Other.IsVolatile; I.IsFinal |= Other.IsFinal; I.IsOverride |= Other.IsOverride; - I.IsNodiscard |= Other.IsNodiscard; I.IsExplicitObjectMemberFunction |= Other.IsExplicitObjectMemberFunction; if (I.Constexpr == ConstexprKind::None) { diff --git a/src/lib/Metadata/Specifiers.cpp b/src/lib/Metadata/Specifiers.cpp index 2e3390648..8a1c68ba0 100644 --- a/src/lib/Metadata/Specifiers.cpp +++ b/src/lib/Metadata/Specifiers.cpp @@ -26,6 +26,20 @@ dom::String toString(AccessKind kind) noexcept } } +dom::String toString(AttributeKind kind) noexcept +{ + switch(kind) + { + case AttributeKind::Deprecated: return "deprecated"; + case AttributeKind::MaybeUnused: return "maybe_unused"; + case AttributeKind::Nodiscard: return "nodiscard"; + case AttributeKind::Noreturn: return "noreturn"; + case AttributeKind::NoUniqueAddress: return "no_unique_address"; + default: + MRDOCS_UNREACHABLE(); + } +} + dom::String toString(StorageClassKind kind) noexcept { switch(kind) From 5c0d61e7ca9b8b9671944a57f38ed52ad033f252 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 21 Feb 2025 12:48:22 -0500 Subject: [PATCH 03/11] [FOLD] handle noreturn correctly --- src/lib/AST/ASTVisitor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index e711116cb..409cc5f7c 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -1636,6 +1636,7 @@ populateAttributes(Info& I, Decl const* D) addAttribute(I, AttributeKind::Nodiscard); break; case attr::Kind::NoReturn: + case attr::Kind::CXX11NoReturn: addAttribute(I, AttributeKind::Noreturn); break; case attr::Kind::NoUniqueAddress: From 02cb24d7b295290857c9991e79e767d615d511c3 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 21 Feb 2025 13:53:25 -0500 Subject: [PATCH 04/11] [FOLD] remove extra space --- .../addons/generator/common/partials/symbol/signature/enum.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs index acc446f11..30510ecdd 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs @@ -1,2 +1,2 @@ -enum {{#if isScoped}}class {{/if}}{{#if attributes}} {{>symbol/attributes symbol}}{{/if}} {{>symbol/name .~}} +enum {{#if isScoped}}class{{/if}}{{#if attributes}} {{>symbol/attributes symbol}}{{/if}} {{>symbol/name .~}} {{#if type}} : {{>type/declarator type}}{{/if}}; \ No newline at end of file From 4840abe4bdd0d70495fa4fe2a37175353c02a916 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 24 Feb 2025 12:06:41 -0500 Subject: [PATCH 05/11] [FOLD] --- .../addons/generator/common/partials/symbol/signature/enum.hbs | 2 +- test-files/golden-tests/symbols/function/attributes-2.adoc | 1 - test-files/golden-tests/symbols/function/attributes-2.html | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs b/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs index 30510ecdd..41689683f 100644 --- a/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs +++ b/share/mrdocs/addons/generator/common/partials/symbol/signature/enum.hbs @@ -1,2 +1,2 @@ -enum {{#if isScoped}}class{{/if}}{{#if attributes}} {{>symbol/attributes symbol}}{{/if}} {{>symbol/name .~}} +enum{{#if isScoped}} class{{/if}}{{#if attributes}} {{>symbol/attributes symbol}}{{/if}} {{>symbol/name .~}} {{#if type}} : {{>type/declarator type}}{{/if}}; \ No newline at end of file diff --git a/test-files/golden-tests/symbols/function/attributes-2.adoc b/test-files/golden-tests/symbols/function/attributes-2.adoc index 87af947cd..1eb417a05 100644 --- a/test-files/golden-tests/symbols/function/attributes-2.adoc +++ b/test-files/golden-tests/symbols/function/attributes-2.adoc @@ -22,7 +22,6 @@ Declared in `<attributes‐2.cpp>` [source,cpp,subs="verbatim,replacements,macros,-callouts"] ---- template<class T> -[[nodiscard]] int f(); ---- diff --git a/test-files/golden-tests/symbols/function/attributes-2.html b/test-files/golden-tests/symbols/function/attributes-2.html index 8f3f4bf24..e8de79b54 100644 --- a/test-files/golden-tests/symbols/function/attributes-2.html +++ b/test-files/golden-tests/symbols/function/attributes-2.html @@ -34,7 +34,6 @@

Synopsis

 
 template<class T>
-[[nodiscard]]
 int
 f();
 

From f11eb29e111e082d7335b63df6213e56c80d8524 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Thu, 20 Mar 2025 11:30:37 -0400
Subject: [PATCH 06/11] [FOLD] xmlwriter supports attributes

---
 src/lib/Gen/xml/XMLWriter.cpp | 41 +++++++++++++++++++++++------------
 src/lib/Gen/xml/XMLWriter.hpp |  1 +
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/src/lib/Gen/xml/XMLWriter.cpp b/src/lib/Gen/xml/XMLWriter.cpp
index 0bae2f9ff..34f970e8c 100644
--- a/src/lib/Gen/xml/XMLWriter.cpp
+++ b/src/lib/Gen/xml/XMLWriter.cpp
@@ -244,8 +244,8 @@ writeEnum(
     }
 
     writeSourceInfo(I);
-
     writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     corpus_.traverse(I, *this);
 
@@ -269,8 +269,8 @@ writeEnumConstant(
     });
 
     writeSourceInfo(I);
-
     writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     tags_.close(enumConstantTagName);
 }
@@ -286,8 +286,8 @@ writeFriend(
         });
 
     writeSourceInfo(I);
-
     writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     Attributes attrs = {};
     if(I.FriendSymbol)
@@ -325,6 +325,8 @@ writeFunction(
         });
 
     writeSourceInfo(I);
+    writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     writeAttr(I.IsVariadic,            "is-variadic", tags_);
     writeAttr(I.IsVirtualAsWritten,    "is-virtual-as-written", tags_);
@@ -348,7 +350,6 @@ writeFunction(
     for(auto const& J : I.Params)
         writeParam(J, tags_);
 
-    writeJavadoc(I.javadoc);
 
     tags_.close(functionTagName);
 
@@ -381,6 +382,8 @@ writeGuide(
         });
 
     writeSourceInfo(I);
+    writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     tags_.open(deducedTagName);
     writeType(I.Deduced, tags_);
@@ -389,8 +392,6 @@ writeGuide(
     for(auto const& J : I.Params)
         writeParam(J, tags_);
 
-    writeJavadoc(I.javadoc);
-
     tags_.close(guideTagName);
 
     closeTemplate(I.Template);
@@ -411,8 +412,8 @@ writeConcept(
         });
 
     writeSourceInfo(I);
-
     writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     tags_.close(conceptTagName);
 
@@ -431,8 +432,8 @@ writeNamespaceAlias(
         });
 
     writeSourceInfo(I);
-
     writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     tags_.write("aliased", {}, {
         {"name", toString(*I.AliasedSymbol)},
@@ -475,8 +476,8 @@ XMLWriter::
     });
 
     writeSourceInfo(I);
-
     writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     for (auto const& id : I.UsingSymbols)
         tags_.write("named", {}, { id });
@@ -500,6 +501,8 @@ writeRecord(
         });
 
     writeSourceInfo(I);
+    writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     writeAttr(I.IsFinal, "is-final", tags_);
     writeAttr(I.IsFinalDestructor, "is-final-dtor", tags_);
@@ -514,7 +517,6 @@ writeRecord(
         tags_.close(baseTagName);
     }
 
-    writeJavadoc(I.javadoc);
 
     corpus_.traverse(I, *this);
 
@@ -542,11 +544,11 @@ writeTypedef(
         });
 
     writeSourceInfo(I);
+    writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     writeType(I.Type, tags_);
 
-    writeJavadoc(I.javadoc);
-
     tags_.close(tag);
 
     closeTemplate(I.Template);
@@ -576,6 +578,8 @@ writeField(
     });
 
     writeSourceInfo(I);
+    writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     if(I.IsMutable)
         tags_.write(attributeTagName, {}, {
@@ -586,7 +590,6 @@ writeField(
 
     writeType(I.Type, tags_);
 
-    writeJavadoc(I.javadoc);
 
     tags_.close(tag_name);
 }
@@ -605,6 +608,8 @@ writeVariable(
         });
 
     writeSourceInfo(I);
+    writeJavadoc(I.javadoc);
+    writeAttributes(I.Attributes);
 
     writeAttr(I.StorageClass, "storage-class", tags_);
     writeAttr(I.IsInline, "is-inline", tags_);
@@ -614,7 +619,6 @@ writeVariable(
 
     writeType(I.Type, tags_);
 
-    writeJavadoc(I.javadoc);
 
     tags_.close(varTagName);
 
@@ -623,6 +627,15 @@ writeVariable(
 
 //------------------------------------------------
 
+void
+XMLWriter::
+writeAttributes(
+    std::span attributes)
+{
+    for(auto attr : attributes)
+        tags.write(attributeTagName, {}, { { "id", toString(attr) } });
+}
+
 void
 XMLWriter::
 writeSourceInfo(
diff --git a/src/lib/Gen/xml/XMLWriter.hpp b/src/lib/Gen/xml/XMLWriter.hpp
index 28bd07feb..8a20610da 100644
--- a/src/lib/Gen/xml/XMLWriter.hpp
+++ b/src/lib/Gen/xml/XMLWriter.hpp
@@ -68,6 +68,7 @@ class XMLWriter
     void writeSourceInfo(SourceInfo const& I);
     void writeLocation(Location const& loc, bool def = false);
     void writeJavadoc(std::optional const& javadoc);
+    void writeAttributes(std::span attributes);
     void openTemplate(const std::optional& I);
     void closeTemplate(const std::optional& I);
 

From dc25c41021b14545928282f92e040633d5bb3ff4 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Thu, 20 Mar 2025 11:44:04 -0400
Subject: [PATCH 07/11] [FOLD]

---
 src/lib/Gen/xml/XMLWriter.cpp | 30 +++++++++++++++---------------
 src/lib/Gen/xml/XMLWriter.hpp |  2 +-
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/lib/Gen/xml/XMLWriter.cpp b/src/lib/Gen/xml/XMLWriter.cpp
index 34f970e8c..680232b24 100644
--- a/src/lib/Gen/xml/XMLWriter.cpp
+++ b/src/lib/Gen/xml/XMLWriter.cpp
@@ -245,7 +245,7 @@ writeEnum(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     corpus_.traverse(I, *this);
 
@@ -270,7 +270,7 @@ writeEnumConstant(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     tags_.close(enumConstantTagName);
 }
@@ -287,7 +287,7 @@ writeFriend(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     Attributes attrs = {};
     if(I.FriendSymbol)
@@ -326,7 +326,7 @@ writeFunction(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     writeAttr(I.IsVariadic,            "is-variadic", tags_);
     writeAttr(I.IsVirtualAsWritten,    "is-virtual-as-written", tags_);
@@ -383,7 +383,7 @@ writeGuide(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     tags_.open(deducedTagName);
     writeType(I.Deduced, tags_);
@@ -413,7 +413,7 @@ writeConcept(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     tags_.close(conceptTagName);
 
@@ -433,7 +433,7 @@ writeNamespaceAlias(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     tags_.write("aliased", {}, {
         {"name", toString(*I.AliasedSymbol)},
@@ -477,7 +477,7 @@ XMLWriter::
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     for (auto const& id : I.UsingSymbols)
         tags_.write("named", {}, { id });
@@ -502,7 +502,7 @@ writeRecord(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     writeAttr(I.IsFinal, "is-final", tags_);
     writeAttr(I.IsFinalDestructor, "is-final-dtor", tags_);
@@ -545,7 +545,7 @@ writeTypedef(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     writeType(I.Type, tags_);
 
@@ -579,7 +579,7 @@ writeField(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     if(I.IsMutable)
         tags_.write(attributeTagName, {}, {
@@ -609,7 +609,7 @@ writeVariable(
 
     writeSourceInfo(I);
     writeJavadoc(I.javadoc);
-    writeAttributes(I.Attributes);
+    writeAttributes(I);
 
     writeAttr(I.StorageClass, "storage-class", tags_);
     writeAttr(I.IsInline, "is-inline", tags_);
@@ -630,10 +630,10 @@ writeVariable(
 void
 XMLWriter::
 writeAttributes(
-    std::span attributes)
+    const Info& I)
 {
-    for(auto attr : attributes)
-        tags.write(attributeTagName, {}, { { "id", toString(attr) } });
+    for(auto attr : I.Attributes)
+        tags_.write(attributeTagName, {}, { { "id", toString(attr) } });
 }
 
 void
diff --git a/src/lib/Gen/xml/XMLWriter.hpp b/src/lib/Gen/xml/XMLWriter.hpp
index 8a20610da..ec516d8ee 100644
--- a/src/lib/Gen/xml/XMLWriter.hpp
+++ b/src/lib/Gen/xml/XMLWriter.hpp
@@ -68,7 +68,7 @@ class XMLWriter
     void writeSourceInfo(SourceInfo const& I);
     void writeLocation(Location const& loc, bool def = false);
     void writeJavadoc(std::optional const& javadoc);
-    void writeAttributes(std::span attributes);
+    void writeAttributes(const Info& I);
     void openTemplate(const std::optional& I);
     void closeTemplate(const std::optional& I);
 

From deeb34981bcc8745e8a27cf6f10e2e91e0d9fa4c Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 21 Mar 2025 10:23:25 -0400
Subject: [PATCH 08/11] [FOLD]

---
 src/lib/Gen/xml/XMLWriter.cpp | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/lib/Gen/xml/XMLWriter.cpp b/src/lib/Gen/xml/XMLWriter.cpp
index 680232b24..c0fb02c56 100644
--- a/src/lib/Gen/xml/XMLWriter.cpp
+++ b/src/lib/Gen/xml/XMLWriter.cpp
@@ -325,7 +325,6 @@ writeFunction(
         });
 
     writeSourceInfo(I);
-    writeJavadoc(I.javadoc);
     writeAttributes(I);
 
     writeAttr(I.IsVariadic,            "is-variadic", tags_);
@@ -350,6 +349,7 @@ writeFunction(
     for(auto const& J : I.Params)
         writeParam(J, tags_);
 
+    writeJavadoc(I.javadoc);
 
     tags_.close(functionTagName);
 
@@ -382,7 +382,6 @@ writeGuide(
         });
 
     writeSourceInfo(I);
-    writeJavadoc(I.javadoc);
     writeAttributes(I);
 
     tags_.open(deducedTagName);
@@ -391,6 +390,8 @@ writeGuide(
 
     for(auto const& J : I.Params)
         writeParam(J, tags_);
+    
+    writeJavadoc(I.javadoc);
 
     tags_.close(guideTagName);
 
@@ -501,7 +502,6 @@ writeRecord(
         });
 
     writeSourceInfo(I);
-    writeJavadoc(I.javadoc);
     writeAttributes(I);
 
     writeAttr(I.IsFinal, "is-final", tags_);
@@ -517,6 +517,7 @@ writeRecord(
         tags_.close(baseTagName);
     }
 
+    writeJavadoc(I.javadoc);
 
     corpus_.traverse(I, *this);
 
@@ -544,10 +545,11 @@ writeTypedef(
         });
 
     writeSourceInfo(I);
-    writeJavadoc(I.javadoc);
     writeAttributes(I);
 
     writeType(I.Type, tags_);
+    
+    writeJavadoc(I.javadoc);
 
     tags_.close(tag);
 
@@ -578,7 +580,6 @@ writeField(
     });
 
     writeSourceInfo(I);
-    writeJavadoc(I.javadoc);
     writeAttributes(I);
 
     if(I.IsMutable)
@@ -590,6 +591,7 @@ writeField(
 
     writeType(I.Type, tags_);
 
+    writeJavadoc(I.javadoc);
 
     tags_.close(tag_name);
 }
@@ -608,7 +610,6 @@ writeVariable(
         });
 
     writeSourceInfo(I);
-    writeJavadoc(I.javadoc);
     writeAttributes(I);
 
     writeAttr(I.StorageClass, "storage-class", tags_);
@@ -619,6 +620,7 @@ writeVariable(
 
     writeType(I.Type, tags_);
 
+    writeJavadoc(I.javadoc);
 
     tags_.close(varTagName);
 

From e43782678176ffe1838834b42f79856d1a65113a Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 21 Mar 2025 10:52:31 -0400
Subject: [PATCH 09/11] [FOLD]

---
 src/lib/AST/ASTVisitor.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp
index 409cc5f7c..cf6f8fbf7 100644
--- a/src/lib/AST/ASTVisitor.cpp
+++ b/src/lib/AST/ASTVisitor.cpp
@@ -1622,6 +1622,10 @@ populateAttributes(Info& I, Decl const* D)
 {
     if(! D->hasAttrs())
         return;
+
+    if(const TemplateDecl* TD = D->getDescribedTemplate())
+        populateAttributes(I, TD);
+        
     for(const Attr* AT : D->getAttrs())
     {
         switch(AT->getKind())

From 1b26d68be076d9db3d20dabfd409f8ffbd1a7fe5 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 21 Mar 2025 11:01:28 -0400
Subject: [PATCH 10/11] [FOLD]

---
 test-files/golden-tests/snippets/terminate.xml        | 2 +-
 test-files/golden-tests/symbols/function/noreturn.xml | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/test-files/golden-tests/snippets/terminate.xml b/test-files/golden-tests/snippets/terminate.xml
index a47f44fa8..aaa40702e 100644
--- a/test-files/golden-tests/snippets/terminate.xml
+++ b/test-files/golden-tests/snippets/terminate.xml
@@ -4,7 +4,7 @@
 
   
     
-    
+    
     
       
         Exit the program.
diff --git a/test-files/golden-tests/symbols/function/noreturn.xml b/test-files/golden-tests/symbols/function/noreturn.xml
index cd7b613bb..2a4c6a2fe 100644
--- a/test-files/golden-tests/symbols/function/noreturn.xml
+++ b/test-files/golden-tests/symbols/function/noreturn.xml
@@ -6,11 +6,11 @@
     
     
       
-      
+      
     
     
       
-      
+      
       
     
     
@@ -20,7 +20,7 @@
   
   
     
-    
+    
   
 
 

From 977fb77b5fd68b045e40aced25a9b4242a78fbc5 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Mon, 24 Mar 2025 12:05:57 -0400
Subject: [PATCH 11/11] [FOLD]

---
 test-files/golden-tests/symbols/variable/no_unique_address.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test-files/golden-tests/symbols/variable/no_unique_address.xml b/test-files/golden-tests/symbols/variable/no_unique_address.xml
index 5172e712c..81d8cf4c4 100644
--- a/test-files/golden-tests/symbols/variable/no_unique_address.xml
+++ b/test-files/golden-tests/symbols/variable/no_unique_address.xml
@@ -9,7 +9,7 @@
     
     
       
-      
+