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 
&lt;{{#Parameters}}{{Param}}{{^End}}, {{/End}}{{/Parameters}}&gt;</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 &lt;typename... Tys&gt;</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

Reply via email to