https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/173957
>From b1d985864ff25e66b1382bc13248cc188c39efd3 Mon Sep 17 00:00:00 2001 From: Erick Velez <[email protected]> Date: Mon, 22 Dec 2025 18:25:05 -0800 Subject: [PATCH] [clang-doc] Add typedefs and aliases to templates This patch also adds optional template information to the typedef info struct. --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 3 + clang-tools-extra/clang-doc/BitcodeWriter.cpp | 2 + clang-tools-extra/clang-doc/HTMLGenerator.cpp | 10 +-- clang-tools-extra/clang-doc/JSONGenerator.cpp | 6 +- .../clang-doc/Representation.cpp | 2 + clang-tools-extra/clang-doc/Representation.h | 6 +- clang-tools-extra/clang-doc/Serialize.cpp | 6 ++ .../clang-doc/assets/alias-template.mustache | 12 +++ .../clang-doc/assets/class-template.mustache | 28 ++++-- .../assets/namespace-template.mustache | 22 +++++ clang-tools-extra/clang-doc/support/Utils.cpp | 3 + .../clang-doc/tool/CMakeLists.txt | 1 + .../test/clang-doc/json/class.cpp | 1 + .../test/clang-doc/json/namespace.cpp | 1 + .../test/clang-doc/typedef-alias.cpp | 87 +++++++++++++++++++ 15 files changed, 174 insertions(+), 16 deletions(-) create mode 100644 clang-tools-extra/clang-doc/assets/alias-template.mustache create mode 100644 clang-tools-extra/test/clang-doc/typedef-alias.cpp diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 731b6990cb697..cf2d5dedafb14 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -800,6 +800,9 @@ template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) { template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) { I->Template.emplace(std::move(P)); } +template <> void addTemplate(TypedefInfo *I, TemplateInfo &&P) { + I->Template.emplace(std::move(P)); +} // Template specializations go only into template records. template <typename T> diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index b7f60d88d96ff..e7537458d6e44 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -512,6 +512,8 @@ void ClangDocBitcodeWriter::emitBlock(const TypedefInfo &T) { emitBlock(CI); if (T.DefLoc) emitRecord(*T.DefLoc, TYPEDEF_DEFLOCATION); + if (T.Template) + emitBlock(*T.Template); emitRecord(T.IsUsing, TYPEDEF_IS_USING); emitBlock(T.Underlying); } diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp index 1af555a5b772b..51b2d1f6a92f4 100644 --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -74,12 +74,12 @@ Error HTMLGenerator::setupTemplateFiles(const ClangDocContext &CDCtx) { ConvertToNative(CDCtx.MustacheTemplates.lookup("head-template")); std::string NavbarFilePath = ConvertToNative(CDCtx.MustacheTemplates.lookup("navbar-template")); + std::string AliasFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("alias-template")); std::vector<std::pair<StringRef, StringRef>> Partials = { - {"Comments", CommentFilePath}, - {"FunctionPartial", FunctionFilePath}, - {"EnumPartial", EnumFilePath}, - {"HeadPartial", HeadFilePath}, - {"NavbarPartial", NavbarFilePath}}; + {"Comments", CommentFilePath}, {"FunctionPartial", FunctionFilePath}, + {"EnumPartial", EnumFilePath}, {"HeadPartial", HeadFilePath}, + {"NavbarPartial", NavbarFilePath}, {"AliasPartial", AliasFilePath}}; if (Error Err = setupTemplate(NamespaceTemplate, NamespaceFilePath, Partials)) return Err; diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index 2887c5e7bc187..f4938b3460f53 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -349,8 +349,10 @@ serializeCommonChildren(const ScopeChildren &Children, json::Object &Obj, Obj["HasEnums"] = true; } - if (!Children.Typedefs.empty()) + if (!Children.Typedefs.empty()) { serializeArray(Children.Typedefs, Obj, "Typedefs", SerializeInfo); + Obj["HasTypedefs"] = true; + } if (!Children.Records.empty()) { serializeArray(Children.Records, Obj, "Records", SerializeReferenceLambda); @@ -494,6 +496,8 @@ static void serializeInfo(const TypedefInfo &I, json::Object &Obj, auto &TypeObj = *TypeVal.getAsObject(); serializeInfo(I.Underlying, TypeObj); Obj["Underlying"] = TypeVal; + if (I.Template) + serializeInfo(I.Template.value(), Obj); } static void serializeInfo(const BaseRecordInfo &I, Object &Obj, diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index 8eab5fb992ebc..d840350ba8426 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -368,6 +368,8 @@ void TypedefInfo::merge(TypedefInfo &&Other) { IsUsing = Other.IsUsing; if (Underlying.Type.Name == "") Underlying = Other.Underlying; + if (!Template) + Template = Other.Template; SymbolInfo::merge(std::move(Other)); } diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index a3e779aa39bc4..7685d17bb033d 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -498,12 +498,12 @@ struct TypedefInfo : public SymbolInfo { TypeInfo Underlying; + // Only type aliases can be templates. + std::optional<TemplateInfo> Template; + // Underlying type declaration SmallString<16> TypeDeclaration; - /// Comment description for the typedef. - std::vector<CommentInfo> Description; - // Indicates if this is a new C++ "using"-style typedef: // using MyVector = std::vector<int> // False means it's a C-style typedef: diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 29f8faf94713d..c52106b11f84b 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -1114,6 +1114,9 @@ emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc, Info.DefLoc = Loc; auto &LO = D->getLangOpts(); Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO); + populateTemplateParameters(Info.Template, D); + if (Info.Template) + populateConstraints(Info.Template.value(), D->getDescribedTemplate()); if (Info.Underlying.Type.Name.empty()) { // Typedef for an unnamed type. This is like "typedef struct { } Foo;" @@ -1144,6 +1147,9 @@ emitInfo(const TypeAliasDecl *D, const FullComment *FC, Location Loc, Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO); Info.TypeDeclaration = getTypeAlias(D); Info.IsUsing = true; + populateTemplateParameters(Info.Template, D); + if (Info.Template) + populateConstraints(Info.Template.value(), D->getDescribedAliasTemplate()); extractCommentFromDecl(D, Info); diff --git a/clang-tools-extra/clang-doc/assets/alias-template.mustache b/clang-tools-extra/clang-doc/assets/alias-template.mustache new file mode 100644 index 0000000000000..9b32f132e9ef3 --- /dev/null +++ b/clang-tools-extra/clang-doc/assets/alias-template.mustache @@ -0,0 +1,12 @@ +<div id="{{USR}}" class="delimiter-container"> + {{#Template}} + <pre><code class="language-cpp code-clang-doc">template <{{#Parameters}}{{Param}}{{^End}}, {{/End}}{{/Parameters}}></code></pre> + {{/Template}} + <pre><code class="language-cpp code-clang-doc">{{#IsUsing}}using{{/IsUsing}}{{^IsUsing}}typedef{{/IsUsing}} {{Name}}{{#IsUsing}} ={{/Isusing}} {{#Underlying}}{{Name}}{{/Underlying}}</code></pre> + {{#Description}} + {{>Comments}} + {{/Description}} + {{#Location}} + <p>Defined at line {{LineNumber}} of file {{Filename}}</p> + {{/Location}} +</div> diff --git a/clang-tools-extra/clang-doc/assets/class-template.mustache b/clang-tools-extra/clang-doc/assets/class-template.mustache index ee1220071e24a..9c7b06d7e7117 100644 --- a/clang-tools-extra/clang-doc/assets/class-template.mustache +++ b/clang-tools-extra/clang-doc/assets/class-template.mustache @@ -85,9 +85,20 @@ </ul> </li> {{/Enums}} - {{#Typedef}} - <li class="sidebar-section">Typedef</li> - {{/Typedef}} + {{#HasTypedefs}} + <li class="sidebar-section"> + <a class="sidebar-item" href="#Typedefs">Typedefs</a> + </li> + <li> + <ul> + {{#Typedefs}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> + </li> + {{/Typedefs}} + </ul> + </li> + {{/HasTypedefs}} {{#Record}} <li class="sidebar-section"> <a class="sidebar-item" href="#Classes">Inner Classes</a> @@ -200,11 +211,14 @@ </ul> </section> {{/Record}} - {{#Typedef}} - <section class="section-container"> - <h2 id="Enums">Enums</h2> + {{#HasTypedefs}} + <section id="Typedefs" class="section-container"> + <h2>Typedefs</h2> + {{#Typedefs}} + {{>AliasPartial}} + {{/Typedefs}} </section> - {{/Typedef}} + {{/HasTypedefs}} </div> </div> </main> diff --git a/clang-tools-extra/clang-doc/assets/namespace-template.mustache b/clang-tools-extra/clang-doc/assets/namespace-template.mustache index 3588ecf30b3f9..2d8381a9ea6e3 100644 --- a/clang-tools-extra/clang-doc/assets/namespace-template.mustache +++ b/clang-tools-extra/clang-doc/assets/namespace-template.mustache @@ -85,6 +85,20 @@ </ul> </li> {{/HasConcepts}} + {{#HasTypedefs}} + <li class="sidebar-section"> + <a class="sidebar-item" href="#Typedefs">Typedefs</a> + </li> + <li> + <ul> + {{#Typedefs}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> + </li> + {{/Typedefs}} + </ul> + </li> + {{/HasTypedefs}} </ul> </div> <div class="resizer" id="resizer"></div> @@ -155,6 +169,14 @@ {{/Concepts}} </section> {{/HasConcepts}} + {{#HasTypedefs}} + <section id="Typedefs" class="section-container"> + <h2>Typedefs</h2> + {{#Typedefs}} + {{>AliasPartial}} + {{/Typedefs}} + </section> + {{/HasTypedefs}} </div> </div> </main> diff --git a/clang-tools-extra/clang-doc/support/Utils.cpp b/clang-tools-extra/clang-doc/support/Utils.cpp index e0d92d23b045e..1dce98f06d144 100644 --- a/clang-tools-extra/clang-doc/support/Utils.cpp +++ b/clang-tools-extra/clang-doc/support/Utils.cpp @@ -62,6 +62,8 @@ void getHtmlFiles(StringRef AssetsPath, clang::doc::ClangDocContext &CDCtx) { appendPathPosix(AssetsPath, "navbar-template.mustache"); SmallString<128> IndexTemplate = appendPathPosix(AssetsPath, "index-template.mustache"); + SmallString<128> AliasTemplate = + appendPathPosix(AssetsPath, "alias-template.mustache"); CDCtx.MustacheTemplates.insert( {"namespace-template", NamespaceTemplate.c_str()}); @@ -73,4 +75,5 @@ void getHtmlFiles(StringRef AssetsPath, clang::doc::ClangDocContext &CDCtx) { CDCtx.MustacheTemplates.insert({"head-template", HeadTemplate.c_str()}); CDCtx.MustacheTemplates.insert({"navbar-template", NavbarTemplate.c_str()}); CDCtx.MustacheTemplates.insert({"index-template", IndexTemplate.c_str()}); + CDCtx.MustacheTemplates.insert({"alias-template", AliasTemplate.c_str()}); } diff --git a/clang-tools-extra/clang-doc/tool/CMakeLists.txt b/clang-tools-extra/clang-doc/tool/CMakeLists.txt index 6d8665379e750..aef2acfde0ca3 100644 --- a/clang-tools-extra/clang-doc/tool/CMakeLists.txt +++ b/clang-tools-extra/clang-doc/tool/CMakeLists.txt @@ -34,6 +34,7 @@ set(assets head-template.mustache navbar-template.mustache index-template.mustache + alias-template.mustache ) set(asset_dir "${CMAKE_CURRENT_SOURCE_DIR}/../assets") diff --git a/clang-tools-extra/test/clang-doc/json/class.cpp b/clang-tools-extra/test/clang-doc/json/class.cpp index 79ac20f954f7a..6ec86ff1efeed 100644 --- a/clang-tools-extra/test/clang-doc/json/class.cpp +++ b/clang-tools-extra/test/clang-doc/json/class.cpp @@ -130,6 +130,7 @@ struct MyClass { // CHECK-NEXT: "HasPublicFunctions": true, // CHECK-NEXT: "HasPublicMembers": true, // CHECK-NEXT: "HasRecords": true, +// CHECK-NEXT: "HasTypedefs": true, // CHECK-NEXT: "InfoType": "record", // CHECK-NEXT: "IsTypedef": false, // CHECK-NEXT: "Location": { diff --git a/clang-tools-extra/test/clang-doc/json/namespace.cpp b/clang-tools-extra/test/clang-doc/json/namespace.cpp index 2f79cfa404f07..1337efe3f268d 100644 --- a/clang-tools-extra/test/clang-doc/json/namespace.cpp +++ b/clang-tools-extra/test/clang-doc/json/namespace.cpp @@ -76,6 +76,7 @@ typedef int MyTypedef; // CHECK-NEXT: "HasFunctions": true, // CHECK-NEXT: "HasNamespaces": true, // CHECK-NEXT: "HasRecords": true, +// CHECK-NEXT: "HasTypedefs": true, // CHECK-NEXT: "InfoType": "namespace", // CHECK-NEXT: "Name": "Global Namespace", // CHECK-NEXT: "Namespaces": [ diff --git a/clang-tools-extra/test/clang-doc/typedef-alias.cpp b/clang-tools-extra/test/clang-doc/typedef-alias.cpp new file mode 100644 index 0000000000000..dec2bc5883a09 --- /dev/null +++ b/clang-tools-extra/test/clang-doc/typedef-alias.cpp @@ -0,0 +1,87 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: clang-doc --format=html --output=%t --executor=standalone %s +// RUN: FileCheck %s < %t/html/GlobalNamespace/index.html -check-prefix=HTML-GLOBAL +// RUN: FileCheck %s < %t/html/GlobalNamespace/index.html -check-prefix=HTML-GLOBAL +// RUN: FileCheck %s < %t/html/GlobalNamespace/_ZTV6Vector.html -check-prefix=HTML-VECTOR + +/// \brief This is u_long +using u_long = unsigned long; + +/// \brief This is IntPtr +typedef int* IntPtr; + +template<typename T> +class Vector { + /// \brief This is a Ptr + using Ptr = IntPtr; +}; + +template<typename T> using Vec = Vector<T>; + +using IntVec = Vector<int>; + +// HTML-GLOBAL: <a class="sidebar-item" href="#Typedefs">Typedefs</a> +// HTML-GLOBAL-NEXT: </li> +// HTML-GLOBAL-NEXT: <li> +// HTML-GLOBAL-NEXT: <ul> +// HTML-GLOBAL-NEXT: <li class="sidebar-item-container"> +// HTML-GLOBAL-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">u_long</a> +// HTML-GLOBAL-NEXT: </li> +// HTML-GLOBAL-NEXT: <li class="sidebar-item-container"> +// HTML-GLOBAL-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">IntPtr</a> +// HTML-GLOBAL-NEXT: </li> +// HTML-GLOBAL-NEXT: <li class="sidebar-item-container"> +// HTML-GLOBAL-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">Vec</a> +// HTML-GLOBAL-NEXT: </li> +// HTML-GLOBAL-NEXT: <li class="sidebar-item-container"> +// HTML-GLOBAL-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">IntVec</a> +// HTML-GLOBAL-NEXT: </li> +// HTML-GLOBAL-NEXT: </ul> +// HTML-GLOBAL-NEXT: </li> +// HTML-GLOBAL: <section id="Typedefs" class="section-container"> +// HTML-GLOBAL-NEXT: <h2>Typedefs</h2> +// HTML-GLOBAL-NEXT: <div id="{{([0-9A-F]{40})}}" class="delimiter-container"> +// HTML-GLOBAL-NEXT: <pre><code class="language-cpp code-clang-doc">using u_long = unsigned long</code></pre> +// HTML-GLOBAL-NEXT: <div> +// HTML-GLOBAL-NEXT: <p> This is u_long</p> +// HTML-GLOBAL-NEXT: </div> +// HTML-GLOBAL-NEXT: <p>Defined at line 8 of file {{.*}}typedef-alias.cpp</p> +// HTML-GLOBAL-NEXT: </div> +// HTML-GLOBAL-NEXT: <div id="{{([0-9A-F]{40})}}" class="delimiter-container"> +// HTML-GLOBAL-NEXT: <pre><code class="language-cpp code-clang-doc">typedef IntPtr int *</code></pre> +// HTML-GLOBAL-NEXT: <div> +// HTML-GLOBAL-NEXT: <p> This is IntPtr</p> +// HTML-GLOBAL-NEXT: </div> +// HTML-GLOBAL-NEXT: <p>Defined at line 11 of file {{.*}}typedef-alias.cpp</p> +// HTML-GLOBAL-NEXT: </div> +// HTML-GLOBAL-NEXT: <div id="{{([0-9A-F]{40})}}" class="delimiter-container"> +// HTML-GLOBAL-NEXT: <pre><code class="language-cpp code-clang-doc">template <typename T></code></pre> +// HTML-GLOBAL-NEXT: <pre><code class="language-cpp code-clang-doc">using Vec = Vector<T></code></pre> +// HTML-GLOBAL-NEXT: <p>Defined at line 19 of file {{.*}}typedef-alias.cpp</p> +// HTML-GLOBAL-NEXT: </div> +// HTML-GLOBAL-NEXT: <div id="{{([0-9A-F]{40})}}" class="delimiter-container"> +// HTML-GLOBAL-NEXT: <pre><code class="language-cpp code-clang-doc">using IntVec = Vector<int></code></pre> +// HTML-GLOBAL-NEXT: <p>Defined at line 21 of file {{.*}}typedef-alias.cpp</p> +// HTML-GLOBAL-NEXT: </div> +// HTML-GLOBAL-NEXT: </section> + +// HTML-VECTOR: <a class="sidebar-item" href="#Typedefs">Typedefs</a> +// HTML-VECTOR-NEXT: </li> +// HTML-VECTOR-NEXT: <li> +// HTML-VECTOR-NEXT: <ul> +// HTML-VECTOR-NEXT: <li class="sidebar-item-container"> +// HTML-VECTOR-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">Ptr</a> +// HTML-VECTOR-NEXT: </li> +// HTML-VECTOR-NEXT: </ul> +// HTML-VECTOR-NEXT: </li> +// HTML-VECTOR-NEXT: </ul> +// HTML-VECTOR: <section id="Typedefs" class="section-container"> +// HTML-VECTOR-NEXT: <h2>Typedefs</h2> +// HTML-VECTOR-NEXT: <div id="{{([0-9A-F]{40})}}" class="delimiter-container"> +// HTML-VECTOR-NEXT: <pre><code class="language-cpp code-clang-doc">using Ptr = IntPtr</code></pre> +// HTML-VECTOR-NEXT: <div> +// HTML-VECTOR-NEXT: <p> This is a Ptr</p> +// HTML-VECTOR-NEXT: </div> +// HTML-VECTOR-NEXT: <p>Defined at line 16 of file {{.*}}typedef-alias.cpp</p> +// HTML-VECTOR-NEXT: </div> +// HTML-VECTOR-NEXT: </section> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
