https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/171937
>From 3fa22eb125c56c4354d6007b2c7af86b44ab72f0 Mon Sep 17 00:00:00 2001 From: Erick Velez <[email protected]> Date: Thu, 11 Dec 2025 09:38:13 -0800 Subject: [PATCH 1/2] [clang-doc] Add JSON output to existing template tests clang-doc has some useful, preexisting tests for templates, so we'll reuse them to cover more cases. --- .../test/clang-doc/templates.cpp | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/clang-tools-extra/test/clang-doc/templates.cpp b/clang-tools-extra/test/clang-doc/templates.cpp index abe03a7d2d0ea..171ff496ab8ef 100644 --- a/clang-tools-extra/test/clang-doc/templates.cpp +++ b/clang-tools-extra/test/clang-doc/templates.cpp @@ -7,6 +7,9 @@ // RUN: clang-doc --doxygen --executor=standalone %s -output=%t/docs --format=md // RUN: cat %t/docs/GlobalNamespace/index.md | FileCheck %s --check-prefix=MD +// RUN: clang-doc --doxygen --executor=standalone %s -output=%t/docs --format=json +// RUN: cat %t/docs/json/GlobalNamespace/index.json | FileCheck %s --check-prefix=JSON + // YAML: --- // YAML-NEXT: USR: '{{([0-9A-F]{40})}}' // YAML-NEXT: ChildRecords: @@ -44,6 +47,27 @@ void ParamPackFunction(T... args); // MD: ### ParamPackFunction // MD: *void ParamPackFunction(T... args)* +// JSON: "Name": "ParamPackFunction", +// JSON-NEXT: "Params": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Name": "args", +// JSON-NEXT: "Type": "T..." +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "ReturnType": { +// JSON-NEXT: "IsBuiltIn": true, +// JSON-NEXT: "IsTemplate": false, +// JSON-NEXT: "Name": "void", +// JSON-NEXT: "QualName": "void", +// JSON-NEXT: "USR": "0000000000000000000000000000000000000000" +// JSON-NEXT: }, +// JSON-NEXT: "Template": { +// JSON-NEXT: "Parameters": [ +// JSON-NEXT: "class... T" +// JSON-NEXT: ] +// JSON-NEXT: }, + template <typename T, int U = 1> void function(T x) {} @@ -70,6 +94,28 @@ void function(T x) {} // MD: *void function(T x)* // MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 23]]* +// JSON: "Name": "function", +// JSON-NEXT: "Params": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Name": "x", +// JSON-NEXT: "Type": "T" +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "ReturnType": { +// JSON-NEXT: "IsBuiltIn": true, +// JSON-NEXT: "IsTemplate": false, +// JSON-NEXT: "Name": "void", +// JSON-NEXT: "QualName": "void", +// JSON-NEXT: "USR": "0000000000000000000000000000000000000000" +// JSON-NEXT: }, +// JSON-NEXT: "Template": { +// JSON-NEXT: "Parameters": [ +// JSON-NEXT: "typename T", +// JSON-NEXT: "int U = 1" +// JSON-NEXT: ] +// JSON-NEXT: }, + template <> void function<bool, 0>(bool x) {} @@ -98,6 +144,31 @@ void function<bool, 0>(bool x) {} // MD: *void function(bool x)* // MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 26]]* +// JSON: "Name": "function", +// JSON-NEXT: "Params": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Name": "x", +// JSON-NEXT: "Type": "bool" +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "ReturnType": { +// JSON-NEXT: "IsBuiltIn": true, +// JSON-NEXT: "IsTemplate": false, +// JSON-NEXT: "Name": "void", +// JSON-NEXT: "QualName": "void", +// JSON-NEXT: "USR": "0000000000000000000000000000000000000000" +// JSON-NEXT: }, +// JSON-NEXT: "Template": { +// JSON-NEXT: "Specialization": { +// JSON-NEXT: "Parameters": [ +// JSON-NEXT: "bool", +// JSON-NEXT: "0" +// JSON-NEXT: ], +// JSON-NEXT: "SpecializationOf": "{{([0-9A-F]{40})}}" +// JSON-NEXT: } +// JSON-NEXT: }, + /// A Tuple type /// /// Does Tuple things. @@ -154,3 +225,20 @@ tuple<int, int, bool> func_with_tuple_param(tuple<int, int, bool> t) { return t; // MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 44]]* // MD: A function with a tuple parameter // MD: **t** The input to func_with_tuple_param + +// JSON: "Name": "func_with_tuple_param", +// COM: FIXME: Add type info to parameters +// JSON-NEXT: "Params": [ +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Name": "t", +// JSON-NEXT: "Type": "tuple" +// JSON-NEXT: } +// JSON-NEXT: ], +// JSON-NEXT: "ReturnType": { +// JSON-NEXT: "IsBuiltIn": false, +// JSON-NEXT: "IsTemplate": false, +// JSON-NEXT: "Name": "tuple", +// JSON-NEXT: "QualName": "tuple<int, int, bool>", +// JSON-NEXT: "USR": "{{([0-9A-F]{40})}}" +// JSON-NEXT: }, >From 58a5f5b96cb213d79d2f65fe4b8ebf5e8e4543b8 Mon Sep 17 00:00:00 2001 From: Erick Velez <[email protected]> Date: Thu, 11 Dec 2025 09:54:03 -0800 Subject: [PATCH 2/2] [clang-doc] Add class template to HTML --- clang-tools-extra/clang-doc/JSONGenerator.cpp | 11 ++++- .../clang-doc/assets/class-template.mustache | 3 ++ .../test/clang-doc/json/class-requires.cpp | 5 ++- .../clang-doc/json/class-specialization.cpp | 10 ++++- .../test/clang-doc/json/class-template.cpp | 5 ++- .../test/clang-doc/json/class.cpp | 5 ++- .../test/clang-doc/json/concept.cpp | 5 ++- .../test/clang-doc/json/function-requires.cpp | 10 ++++- .../test/clang-doc/json/method-template.cpp | 5 ++- .../test/clang-doc/templates.cpp | 44 ++++++++++++++++--- .../unittests/clang-doc/JSONGeneratorTest.cpp | 5 ++- 11 files changed, 89 insertions(+), 19 deletions(-) diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index 83fa556782793..327184afd7dc1 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -378,8 +378,15 @@ static void serializeInfo(const ArrayRef<TemplateParamInfo> &Params, json::Value ParamsArray = Array(); auto &ParamsArrayRef = *ParamsArray.getAsArray(); ParamsArrayRef.reserve(Params.size()); - for (const auto &Param : Params) - ParamsArrayRef.push_back(Param.Contents); + for (size_t Idx = 0; Idx < Params.size(); ++Idx) { + json::Value ParamObjVal = Object(); + Object &ParamObj = *ParamObjVal.getAsObject(); + + ParamObj["Param"] = Params[Idx].Contents; + if (Idx == Params.size() - 1) + ParamObj["End"] = true; + ParamsArrayRef.push_back(ParamObjVal); + } Obj["Parameters"] = ParamsArray; } diff --git a/clang-tools-extra/clang-doc/assets/class-template.mustache b/clang-tools-extra/clang-doc/assets/class-template.mustache index 52caebb503e2d..ee1220071e24a 100644 --- a/clang-tools-extra/clang-doc/assets/class-template.mustache +++ b/clang-tools-extra/clang-doc/assets/class-template.mustache @@ -107,6 +107,9 @@ <div class="resizer" id="resizer"></div> <div class="content"> <section class="hero section-container"> + {{#Template}} + <pre><code class="language-cpp code-clang-doc">template <{{#Parameters}}{{Param}}{{^End}}, {{/End}}{{/Parameters}}></code></pre> + {{/Template}} <div class="hero__title"> <h1 class="hero__title-large">{{TagType}} {{Name}}</h1> <p>Defined at line {{Location.LineNumber}} of file {{Location.Filename}}</p> diff --git a/clang-tools-extra/test/clang-doc/json/class-requires.cpp b/clang-tools-extra/test/clang-doc/json/class-requires.cpp index 4e5ec3a5729cd..e10c5e89f6e17 100644 --- a/clang-tools-extra/test/clang-doc/json/class-requires.cpp +++ b/clang-tools-extra/test/clang-doc/json/class-requires.cpp @@ -29,7 +29,10 @@ struct MyClass; // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "Parameters": [ -// CHECK-NEXT: "typename T" +// CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "typename T" +// CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: }, // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" diff --git a/clang-tools-extra/test/clang-doc/json/class-specialization.cpp b/clang-tools-extra/test/clang-doc/json/class-specialization.cpp index 60f3b44eb69b0..6fd2f81e49b46 100644 --- a/clang-tools-extra/test/clang-doc/json/class-specialization.cpp +++ b/clang-tools-extra/test/clang-doc/json/class-specialization.cpp @@ -16,7 +16,10 @@ template<> struct MyClass<int> {}; // BASE-NEXT: "TagType": "struct", // BASE-NEXT: "Template": { // BASE-NEXT: "Parameters": [ -// BASE-NEXT: "typename T" +// BASE-NEXT: { +// BASE-NEXT: "End": true, +// BASE-NEXT: "Param": "typename T" +// BASE-NEXT: } // BASE-NEXT: ] // BASE-NEXT: }, @@ -30,7 +33,10 @@ template<> struct MyClass<int> {}; // SPECIALIZATION-NEXT: "Template": { // SPECIALIZATION-NEXT: "Specialization": { // SPECIALIZATION-NEXT: "Parameters": [ -// SPECIALIZATION-NEXT: "int" +// SPECIALIZATION-NEXT: { +// SPECIALIZATION-NEXT: "End": true, +// SPECIALIZATION-NEXT: "Param": "int" +// SPECIALIZATION-NEXT: } // SPECIALIZATION-NEXT: ], // SPECIALIZATION-NEXT: "SpecializationOf": "{{[0-9A-F]*}}" // SPECIALIZATION-NEXT: } diff --git a/clang-tools-extra/test/clang-doc/json/class-template.cpp b/clang-tools-extra/test/clang-doc/json/class-template.cpp index de52064466140..9b0d4c4a9ba23 100644 --- a/clang-tools-extra/test/clang-doc/json/class-template.cpp +++ b/clang-tools-extra/test/clang-doc/json/class-template.cpp @@ -26,5 +26,8 @@ template<typename T> struct MyClass { // CHECK: "Type": "T" // CHECK: "Template": { // CHECK-NEXT: "Parameters": [ -// CHECK-NEXT: "typename T" +// CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "Param": "typename T" +// CHECK-NEXT: } // CHECK-NEXT: ] diff --git a/clang-tools-extra/test/clang-doc/json/class.cpp b/clang-tools-extra/test/clang-doc/json/class.cpp index d57e8a990c3fe..1c0d5d5ab567a 100644 --- a/clang-tools-extra/test/clang-doc/json/class.cpp +++ b/clang-tools-extra/test/clang-doc/json/class.cpp @@ -108,7 +108,10 @@ struct MyClass { // CHECK-NEXT: }, // CHECK-NEXT: "Template": { // CHECK-NEXT: "Parameters": [ -// CHECK-NEXT: "typename T" +// CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "Param": "typename T" +// CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: }, diff --git a/clang-tools-extra/test/clang-doc/json/concept.cpp b/clang-tools-extra/test/clang-doc/json/concept.cpp index f4c4ad3946d47..fc440d095fc4c 100644 --- a/clang-tools-extra/test/clang-doc/json/concept.cpp +++ b/clang-tools-extra/test/clang-doc/json/concept.cpp @@ -25,7 +25,10 @@ concept Incrementable = requires(T x) { // CHECK-NEXT: "Name": "Incrementable", // CHECK-NEXT: "Template": { // CHECK-NEXT: "Parameters": [ -// CHECK-NEXT: "typename T" +// CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "Param": "typename T" +// CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: }, // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" diff --git a/clang-tools-extra/test/clang-doc/json/function-requires.cpp b/clang-tools-extra/test/clang-doc/json/function-requires.cpp index 8ba6adc66a54b..931bb07edb836 100644 --- a/clang-tools-extra/test/clang-doc/json/function-requires.cpp +++ b/clang-tools-extra/test/clang-doc/json/function-requires.cpp @@ -43,7 +43,10 @@ template<Incrementable T> Incrementable auto incrementTwo(T t); // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "Parameters": [ -// CHECK-NEXT: "typename T" +// CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "Param": "typename T" +// CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: }, // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" @@ -79,7 +82,10 @@ template<Incrementable T> Incrementable auto incrementTwo(T t); // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "Parameters": [ -// CHECK-NEXT: "Incrementable T" +// CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "Param": "Incrementable T" +// CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: }, // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" diff --git a/clang-tools-extra/test/clang-doc/json/method-template.cpp b/clang-tools-extra/test/clang-doc/json/method-template.cpp index f4885d956ad9b..a617f983d1269 100644 --- a/clang-tools-extra/test/clang-doc/json/method-template.cpp +++ b/clang-tools-extra/test/clang-doc/json/method-template.cpp @@ -36,7 +36,10 @@ struct MyClass { // CHECK-NEXT: }, // CHECK-NEXT: "Template": { // CHECK-NEXT: "Parameters": [ -// CHECK-NEXT: "class T" +// CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "Param": "class T" +// CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: }, // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" diff --git a/clang-tools-extra/test/clang-doc/templates.cpp b/clang-tools-extra/test/clang-doc/templates.cpp index 171ff496ab8ef..addf7cbc63519 100644 --- a/clang-tools-extra/test/clang-doc/templates.cpp +++ b/clang-tools-extra/test/clang-doc/templates.cpp @@ -7,8 +7,9 @@ // RUN: clang-doc --doxygen --executor=standalone %s -output=%t/docs --format=md // RUN: cat %t/docs/GlobalNamespace/index.md | FileCheck %s --check-prefix=MD -// RUN: clang-doc --doxygen --executor=standalone %s -output=%t/docs --format=json +// RUN: clang-doc --doxygen --executor=standalone %s -output=%t/docs --format=html // RUN: cat %t/docs/json/GlobalNamespace/index.json | FileCheck %s --check-prefix=JSON +// RUN: cat %t/docs/html/GlobalNamespace/_ZTV5tuple.html | FileCheck %s --check-prefix=HTML-STRUCT // YAML: --- // YAML-NEXT: USR: '{{([0-9A-F]{40})}}' @@ -64,7 +65,10 @@ void ParamPackFunction(T... args); // JSON-NEXT: }, // JSON-NEXT: "Template": { // JSON-NEXT: "Parameters": [ -// JSON-NEXT: "class... T" +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Param": "class... T" +// JSON-NEXT: } // JSON-NEXT: ] // JSON-NEXT: }, @@ -111,10 +115,15 @@ void function(T x) {} // JSON-NEXT: }, // JSON-NEXT: "Template": { // JSON-NEXT: "Parameters": [ -// JSON-NEXT: "typename T", -// JSON-NEXT: "int U = 1" +// JSON-NEXT: { +// JSON-NEXT: "Param": "typename T" +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Param": "int U = 1" +// JSON-NEXT: } // JSON-NEXT: ] -// JSON-NEXT: }, +// JSON-NEXT: } template <> void function<bool, 0>(bool x) {} @@ -162,8 +171,13 @@ void function<bool, 0>(bool x) {} // JSON-NEXT: "Template": { // JSON-NEXT: "Specialization": { // JSON-NEXT: "Parameters": [ -// JSON-NEXT: "bool", -// JSON-NEXT: "0" +// JSON-NEXT: { +// JSON-NEXT: "Param": "bool" +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "End": true, +// JSON-NEXT: "Param": "0" +// JSON-NEXT: } // JSON-NEXT: ], // JSON-NEXT: "SpecializationOf": "{{([0-9A-F]{40})}}" // JSON-NEXT: } @@ -175,6 +189,22 @@ void function<bool, 0>(bool x) {} template <typename... Tys> struct tuple {}; +// HTML-STRUCT: <section class="hero section-container"> +// HTML-STRUCT-NEXT: <pre><code class="language-cpp code-clang-doc">template <typename... Tys></code></pre> +// HTML-STRUCT-NEXT: <div class="hero__title"> +// HTML-STRUCT-NEXT: <h1 class="hero__title-large">struct tuple</h1> +// HTML-STRUCT-NEXT: <p>Defined at line [[# @LINE - 6]] of file {{.*}}templates.cpp</p> +// HTML-STRUCT-NEXT: <div class="hero__subtitle"> +// HTML-STRUCT-NEXT: <div> +// HTML-STRUCT-NEXT: <p> A Tuple type</p> +// HTML-STRUCT-NEXT: </div> +// HTML-STRUCT-NEXT: <div> +// HTML-STRUCT-NEXT: <p> Does Tuple things.</p> +// HTML-STRUCT-NEXT: </div> +// HTML-STRUCT-NEXT: </div> +// HTML-STRUCT-NEXT: </div> +// HTML-STRUCT-NEXT: </section> + /// A function with a tuple parameter /// /// \param t The input to func_with_tuple_param diff --git a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp index b468964630d45..11ab969aa6b90 100644 --- a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp @@ -175,7 +175,10 @@ TEST_F(JSONGeneratorTest, emitRecordJSON) { "TagType": "class", "Template": { "Parameters": [ - "class T" + { + "End": true, + "Param": "class T" + } ] }, "USR": "0000000000000000000000000000000000000000", _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
