[llvm-branch-commits] [clang-tools-extra] [clang-doc] Add functions to namespace template (PR #171938)
Erick Velez via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Dec 12 10:39:24 PST 2025
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/171938
>From 103242be294fb1bfe326db89fc66fe0843486219 Mon Sep 17 00:00:00 2001
From: Erick Velez <erickvelez7 at gmail.com>
Date: Thu, 11 Dec 2025 14:07:40 -0800
Subject: [PATCH] [clang-doc] Serialize namespace-level functions
---
clang-tools-extra/clang-doc/JSONGenerator.cpp | 4 +-
.../assets/function-template.mustache | 6 +-
.../assets/namespace-template.mustache | 26 +++++++
.../test/clang-doc/json/namespace.cpp | 1 +
.../test/clang-doc/namespace.cpp | 70 ++++++++++++-------
.../test/clang-doc/templates.cpp | 43 ++++++++++++
.../unittests/clang-doc/JSONGeneratorTest.cpp | 1 +
7 files changed, 124 insertions(+), 27 deletions(-)
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index 327184afd7dc1..8828414cb3925 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -629,8 +629,10 @@ static void serializeInfo(const NamespaceInfo &I, json::Object &Obj,
serializeInfo(Info, Object, RepositoryUrl);
};
- if (!I.Children.Functions.empty())
+ if (!I.Children.Functions.empty()) {
serializeArray(I.Children.Functions, Obj, "Functions", SerializeInfo);
+ Obj["HasFunctions"] = true;
+ }
if (!I.Children.Concepts.empty())
serializeArray(I.Children.Concepts, Obj, "Concepts", SerializeInfo);
diff --git a/clang-tools-extra/clang-doc/assets/function-template.mustache b/clang-tools-extra/clang-doc/assets/function-template.mustache
index dc787bf0c8694..5e02257f86de8 100644
--- a/clang-tools-extra/clang-doc/assets/function-template.mustache
+++ b/clang-tools-extra/clang-doc/assets/function-template.mustache
@@ -7,13 +7,17 @@
}}
<div class="delimiter-container">
<div id="{{USR}}">
+ {{#Template}}
+ <pre><code class="language-cpp code-clang-doc">template <{{#Parameters}}{{Param}}{{^End}}, {{/End}}{{/Parameters}}></code></pre>
+ {{/Template}}
{{! Function Prototype }}
- <pre><code class="language-cpp code-clang-doc">{{ReturnType.Name}} {{Name}} ({{#Params}}{{^End}}{{Type}} {{Name}}, {{/End}}{{#End}}{{Type}} {{Name}}{{/End}}{{/Params}})</code></pre>
+ <pre><code class="language-cpp code-clang-doc">{{ReturnType.Name}} {{Name}}{{#Template}}{{#Specialization}}<{{#Parameters}}{{Param}}{{^End}}, {{/End}}{{/Parameters}}>{{/Specialization}}{{/Template}} ({{#Params}}{{^End}}{{Type}} {{Name}}, {{/End}}{{#End}}{{Type}} {{Name}}{{/End}}{{/Params}})</code></pre>
{{! Function Comments }}
{{#Description}}
<div>
{{>Comments}}
</div>
{{/Description}}
+ <p>Defined at line {{Location.LineNumber}} of file {{Location.Filename}}</p>
</div>
</div>
diff --git a/clang-tools-extra/clang-doc/assets/namespace-template.mustache b/clang-tools-extra/clang-doc/assets/namespace-template.mustache
index 7e00821c4914f..5edce48cee6d8 100644
--- a/clang-tools-extra/clang-doc/assets/namespace-template.mustache
+++ b/clang-tools-extra/clang-doc/assets/namespace-template.mustache
@@ -43,6 +43,20 @@
</ul>
</li>
{{/HasRecords}}
+ {{#HasFunctions}}
+ <li class="sidebar-section">
+ <a class="sidebar-item" href="#Functions">Functions</a>
+ </li>
+ <li>
+ <ul>
+ {{#Functions}}
+ <li class="sidebar-item-container">
+ <a class="sidebar-item" href="#{{USR}}">{{Name}}{{#Template}}{{#Specialization}}<{{#Parameters}}{{Param}}{{^End}}, {{/End}}{{/Parameters}}>{{/Specialization}}{{/Template}}</a>
+ </li>
+ {{/Functions}}
+ </ul>
+ </li>
+ {{/HasFunctions}}
</ul>
</div>
<div class="resizer" id="resizer"></div>
@@ -71,6 +85,18 @@
</ul>
</section>
{{/HasRecords}}
+ {{#HasFunctions}}
+ <section id="Functions" class="section-container">
+ <h2>Functions</h2>
+ <ul class="class-container">
+ {{#Functions}}
+ <li>
+ {{>FunctionPartial}}
+ </li>
+ {{/Functions}}
+ </ul>
+ </section>
+ {{/HasFunctions}}
</div>
</div>
</main>
diff --git a/clang-tools-extra/test/clang-doc/json/namespace.cpp b/clang-tools-extra/test/clang-doc/json/namespace.cpp
index c1370d9fe379f..3beb6b91010d6 100644
--- a/clang-tools-extra/test/clang-doc/json/namespace.cpp
+++ b/clang-tools-extra/test/clang-doc/json/namespace.cpp
@@ -73,6 +73,7 @@ typedef int MyTypedef;
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "HasEnums": true,
+// CHECK-NEXT: "HasFunctions": true,
// CHECK-NEXT: "HasRecords": true,
// CHECK-NEXT: "InfoType": "namespace",
// CHECK-NEXT: "Name": "Global Namespace",
diff --git a/clang-tools-extra/test/clang-doc/namespace.cpp b/clang-tools-extra/test/clang-doc/namespace.cpp
index 8580ea6739a21..a8267d34efd59 100644
--- a/clang-tools-extra/test/clang-doc/namespace.cpp
+++ b/clang-tools-extra/test/clang-doc/namespace.cpp
@@ -45,7 +45,7 @@
namespace {
void anonFunction() {}
// MD-ANON-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]*
-// HTML-ANON-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
+// HTML-ANON-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
class AnonClass {};
// MD-ANON-CLASS-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]*
@@ -80,7 +80,7 @@ namespace PrimaryNamespace {
// Function in PrimaryNamespace
void functionInPrimaryNamespace() {}
// MD-PRIMARY-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]*
-// HTML-PRIMARY-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
+// HTML-PRIMARY-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
// Class in PrimaryNamespace
class ClassInPrimaryNamespace {};
@@ -97,7 +97,7 @@ namespace NestedNamespace {
// Function in NestedNamespace
void functionInNestedNamespace() {}
// MD-NESTED-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]*
-// HTML-NESTED-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
+// HTML-NESTED-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
// Class in NestedNamespace
class ClassInNestedNamespace {};
@@ -128,10 +128,17 @@ class ClassInNestedNamespace {};
// HTML-NESTED-INDEX: </a>
// HTML-NESTED-INDEX: </li>
// HTML-NESTED-INDEX: </ul>
-// HTML-NESTED-INDEX-NOT: <h2 id="Functions">Functions</h2>
-// HTML-NESTED-INDEX-NOT: <h3 id="{{([0-9A-F]{40})}}">functionInNestedNamespace</h3>
-// HTML-NESTED-INDEX-NOT: <p>void functionInNestedNamespace()</p>
-// HTML-NESTED-INDEX-NOT: <p> Function in NestedNamespace</p>
+// HTML-NESTED-INDEX: <div class="delimiter-container">
+// HTML-NESTED-INDEX: <div id="{{([0-9A-F]{40})}}">
+// HTML-NESTED-INDEX: <pre><code class="language-cpp code-clang-doc">void functionInNestedNamespace ()</code></pre>
+// HTML-NESTED-INDEX: <div>
+// HTML-NESTED-INDEX: <div>
+// HTML-NESTED-INDEX: <p> Function in NestedNamespace</p>
+// HTML-NESTED-INDEX: </div>
+// HTML-NESTED-INDEX: </div>
+// HTML-NESTED-INDEX: <p>Defined at line 98 of file {{.*}}namespace.cpp</p>
+// HTML-NESTED-INDEX: </div>
+// HTML-NESTED-INDEX: </div>
} // namespace PrimaryNamespace
// MD-PRIMARY-INDEX: # namespace PrimaryNamespace
@@ -148,25 +155,31 @@ class ClassInNestedNamespace {};
// HTML-PRIMARY-INDEX: <h2>PrimaryNamespace</h2>
// HTML-PRIMARY-INDEX-NOT: <h2 id="Namespaces">Namespaces</h2>
// HTML-PRIMARY-INDEX-NOT: <a href="NestedNamespace{{[\/]}}index.html">NestedNamespace</a>
-// HTML-PRIMARY-INDEX <h2>Inner Classes</h2>
-// HTML-PRIMARY-INDEX <ul class="class-container">
-// HTML-PRIMARY-INDEX <li id="{{([0-9A-F]{40})}}" style="max-height: 40px;">
-// HTML-PRIMARY-INDEX <a href="_ZTVN16PrimaryNamespace23ClassInPrimaryNamespaceE.html">
-// HTML-PRIMARY-INDEX <pre><code class="language-cpp code-clang-doc">class ClassInPrimaryNamespace</code></pre>
-// HTML-PRIMARY-INDEX </a>
-// HTML-PRIMARY-INDEX </li>
-// HTML-PRIMARY-INDEX </ul>
-// HTML-PRIMARY-INDEX-NOT: <h2 id="Functions">Functions</h2>
-// HTML-PRIMARY-INDEX-NOT: <h3 id="{{([0-9A-F]{40})}}">functionInPrimaryNamespace</h3>
-// HTML-PRIMARY-INDEX-NOT: <p>void functionInPrimaryNamespace()</p>
-// HTML-PRIMARY-INDEX-NOT: <p> Function in PrimaryNamespace</p>
-
+// HTML-PRIMARY-INDEX: <h2>Inner Classes</h2>
+// HTML-PRIMARY-INDEX: <ul class="class-container">
+// HTML-PRIMARY-INDEX: <li id="{{([0-9A-F]{40})}}" style="max-height: 40px;">
+// HTML-PRIMARY-INDEX: <a href="_ZTVN16PrimaryNamespace23ClassInPrimaryNamespaceE.html">
+// HTML-PRIMARY-INDEX: <pre><code class="language-cpp code-clang-doc">class ClassInPrimaryNamespace</code></pre>
+// HTML-PRIMARY-INDEX: </a>
+// HTML-PRIMARY-INDEX: </li>
+// HTML-PRIMARY-INDEX: </ul>
+// HTML-PRIMARY-INDEX: <div class="delimiter-container">
+// HTML-PRIMARY-INDEX: <div id="{{([0-9A-F]{40})}}">
+// HTML-PRIMARY-INDEX: <pre><code class="language-cpp code-clang-doc">void functionInPrimaryNamespace ()</code></pre>
+// HTML-PRIMARY-INDEX: <div>
+// HTML-PRIMARY-INDEX: <div>
+// HTML-PRIMARY-INDEX: <p> Function in PrimaryNamespace</p>
+// HTML-PRIMARY-INDEX: </div>
+// HTML-PRIMARY-INDEX: </div>
+// HTML-PRIMARY-INDEX: <p>Defined at line 81 of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
+// HTML-PRIMARY-INDEX: </div>
+// HTML-PRIMARY-INDEX: </div>
// AnotherNamespace
namespace AnotherNamespace {
// Function in AnotherNamespace
void functionInAnotherNamespace() {}
// MD-ANOTHER-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]*
-// HTML-ANOTHER-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
+// HTML-ANOTHER-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
// Class in AnotherNamespace
class ClassInAnotherNamespace {};
@@ -198,10 +211,17 @@ class ClassInAnotherNamespace {};
// HTML-ANOTHER-INDEX: </a>
// HTML-ANOTHER-INDEX: </li>
// HTML-ANOTHER-INDEX: </ul>
-// HTML-ANOTHER-INDEX-NOT: <h2 id="Functions">Functions</h2>
-// HTML-ANOTHER-INDEX-NOT: <h3 id="{{([0-9A-F]{40})}}">functionInAnotherNamespace</h3>
-// HTML-ANOTHER-INDEX-NOT: <p>void functionInAnotherNamespace()</p>
-// HTML-ANOTHER-INDEX-NOT: <p> Function in AnotherNamespace</p>
+// HTML-ANOTHER-INDEX: <div class="delimiter-container">
+// HTML-ANOTHER-INDEX: <div id="{{([0-9A-F]{40})}}">
+// HTML-ANOTHER-INDEX: <pre><code class="language-cpp code-clang-doc">void functionInAnotherNamespace ()</code></pre>
+// HTML-ANOTHER-INDEX: <div>
+// HTML-ANOTHER-INDEX: <div>
+// HTML-ANOTHER-INDEX: <p> Function in AnotherNamespace</p>
+// HTML-ANOTHER-INDEX: </div>
+// HTML-ANOTHER-INDEX: </div>
+// HTML-ANOTHER-INDEX: <p>Defined at line 180 of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p>
+// HTML-ANOTHER-INDEX: </div>
+// HTML-ANOTHER-INDEX: </div>
// COM: FIXME: Add namespaces to namespace template
// HTML-GLOBAL-INDEX-NOT: <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
diff --git a/clang-tools-extra/test/clang-doc/templates.cpp b/clang-tools-extra/test/clang-doc/templates.cpp
index addf7cbc63519..e76ccb240dcfc 100644
--- a/clang-tools-extra/test/clang-doc/templates.cpp
+++ b/clang-tools-extra/test/clang-doc/templates.cpp
@@ -10,6 +10,7 @@
// 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
+// RUN: cat %t/docs/html/GlobalNamespace/index.html | FileCheck %s --check-prefix=HTML
// YAML: ---
// YAML-NEXT: USR: '{{([0-9A-F]{40})}}'
@@ -72,6 +73,15 @@ void ParamPackFunction(T... args);
// JSON-NEXT: ]
// JSON-NEXT: },
+// HTML: <div class="delimiter-container">
+// HTML-NEXT: <div id="{{([0-9A-F]{40})}}">
+// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">template <class... T></code></pre>
+// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">void ParamPackFunction (T... args)</code></pre>
+// COM: FIXME: Omit defined line if not defined, or emit declaration line.
+// HTML-NEXT: <p>Defined at line of file </p>
+// HTML-NEXT: </div>
+// HTML-NEXT: </div>
+
template <typename T, int U = 1>
void function(T x) {}
@@ -125,6 +135,15 @@ void function(T x) {}
// JSON-NEXT: ]
// JSON-NEXT: }
+// HTML: <div class="delimiter-container">
+// HTML-NEXT: <div id="{{([0-9A-F]{40})}}">
+// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">template <typename T, int U = 1></code></pre>
+// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">void function (T x)</code></pre>
+// HTML-NEXT: <p>Defined at line [[# @LINE - 56]] of file {{.*}}templates.cpp</p>
+// HTML-NEXT: </div>
+// HTML-NEXT: </div>
+
+
template <>
void function<bool, 0>(bool x) {}
@@ -183,6 +202,14 @@ void function<bool, 0>(bool x) {}
// JSON-NEXT: }
// JSON-NEXT: },
+// HTML: <div class="delimiter-container">
+// HTML-NEXT: <div id="{{([0-9A-F]{40})}}">
+// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">template <></code></pre>
+// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">void function<bool, 0> (bool x)</code></pre>
+// HTML-NEXT: <p>Defined at line [[# @LINE - 62]] of file {{.*}}templates.cpp</p>
+// HTML-NEXT: </div>
+// HTML-NEXT: </div>
+
/// A Tuple type
///
/// Does Tuple things.
@@ -272,3 +299,19 @@ tuple<int, int, bool> func_with_tuple_param(tuple<int, int, bool> t) { return t;
// JSON-NEXT: "QualName": "tuple<int, int, bool>",
// JSON-NEXT: "USR": "{{([0-9A-F]{40})}}"
// JSON-NEXT: },
+
+// HTML: <div class="delimiter-container">
+// HTML-NEXT: <div id="{{([0-9A-F]{40})}}">
+// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">tuple func_with_tuple_param (tuple t)</code></pre>
+// HTML-NEXT: <div>
+// HTML-NEXT: <div>
+// HTML-NEXT: <p> A function with a tuple parameter</p>
+// HTML-NEXT: </div>
+// HTML-NEXT: <h3>Parameters</h3>
+// HTML-NEXT: <div>
+// HTML-NEXT: <b>t</b> The input to func_with_tuple_param
+// HTML-NEXT: </div>
+// HTML-NEXT: </div>
+// HTML-NEXT: <p>Defined at line [[# @LINE - 77]] of file {{.*}}templates.cpp</p>
+// HTML-NEXT: </div>
+// HTML-NEXT: </div>
diff --git a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp
index 11ab969aa6b90..e6eaabcb8127c 100644
--- a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp
@@ -246,6 +246,7 @@ TEST_F(JSONGeneratorTest, emitNamespaceJSON) {
}
],
"HasEnums": true,
+ "HasFunctions": true,
"HasRecords": true,
"InfoType": "namespace",
"Name": "Global Namespace",
More information about the llvm-branch-commits
mailing list