chiark / gitweb /
doxygen: slightly more robust way of parsing template arguments.
authorVladimír Vondruš <mosra@centrum.cz>
Mon, 26 Nov 2018 13:40:13 +0000 (14:40 +0100)
committerVladimír Vondruš <mosra@centrum.cz>
Mon, 26 Nov 2018 14:22:35 +0000 (15:22 +0100)
I don't want to parse C++, please don't ask for more.

doxygen/dox2html5.py
doxygen/test/compound_crazy_template_params/Doxyfile [new file with mode: 0644]
doxygen/test/compound_crazy_template_params/File.h [new file with mode: 0644]
doxygen/test/compound_crazy_template_params/File_8h.html [new file with mode: 0644]
doxygen/test/test_compound.py

index ff6dac2b7e23f33d8bc082969c11dee3b7a2f873..6941cd9f3284f89f569ee4deb22e78f25399aabe 100755 (executable)
@@ -1640,11 +1640,21 @@ def parse_template_params(state: State, element: ET.Element, description):
         if declname is not None:
             # declname or decltype?!
             template.name = declname.text
+        # Doxygen sometimes puts both in type, extract that, but only in case
+        # it's not too crazy to do (i.e., no pointer values, no nameless
+        # FooBar<T, U> types). Using rpartition() to split on the last found
+        # space, but in case of nothing found, rpartition() puts the full
+        # string into [2] instead of [0], so we have to account for that.
+        elif template.type[-1].isalnum():
+            parts = template.type.rpartition(' ')
+            if parts[1]:
+                template.type = parts[0]
+                template.name = parts[2]
+            else:
+                template.type = parts[2]
+                template.name = ''
         else:
-            # Doxygen sometimes puts both in type, extract that
-            parts = template.type.partition(' ')
-            template.type = parts[0]
-            template.name = parts[2]
+            template.name = ''
         default = i.find('defval')
         template.default = parse_type(state, default) if default is not None else ''
         if template.name in description:
diff --git a/doxygen/test/compound_crazy_template_params/Doxyfile b/doxygen/test/compound_crazy_template_params/Doxyfile
new file mode 100644 (file)
index 0000000..49e476e
--- /dev/null
@@ -0,0 +1,13 @@
+INPUT                   = File.h
+QUIET                   = YES
+GENERATE_HTML           = NO
+GENERATE_LATEX          = NO
+GENERATE_XML            = YES
+XML_PROGRAMLISTING      = NO
+
+##! M_PAGE_FINE_PRINT   =
+##! M_THEME_COLOR       =
+##! M_FAVICON           =
+##! M_LINKS_NAVBAR1     =
+##! M_LINKS_NAVBAR2     =
+##! M_SEARCH_DISABLED   = YES
diff --git a/doxygen/test/compound_crazy_template_params/File.h b/doxygen/test/compound_crazy_template_params/File.h
new file mode 100644 (file)
index 0000000..22658b6
--- /dev/null
@@ -0,0 +1,22 @@
+#include <type_traits>
+
+/** @file
+ * @brief A file
+ */
+
+/**
+@brief Templates can get quite crazy
+@tparam T yes they
+@param value can
+*/
+template<class T, std::enable_if<!std::is_function_v<T> && std::is_class_v<T>>* = nullptr> void foo(T* value);
+
+/**
+@brief Templates can get quite crazy
+@tparam T yes they
+@tparam ptr absolutely
+@param value can
+*/
+template<class T, std::enable_if<!std::is_function_v<T> && std::is_class_v<T>>* ptr = nullptr> void bar(T* value);
+
+}
diff --git a/doxygen/test/compound_crazy_template_params/File_8h.html b/doxygen/test/compound_crazy_template_params/File_8h.html
new file mode 100644 (file)
index 0000000..e064c8f
--- /dev/null
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>File.h file | My Project</title>
+  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+  <link rel="stylesheet" href="m-dark+doxygen.compiled.css" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+  <div class="m-container">
+    <div class="m-row">
+      <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Project</a>
+    </div>
+  </div>
+</nav></header>
+<main><article>
+  <div class="m-container m-container-inflatable">
+    <div class="m-row">
+      <div class="m-col-l-10 m-push-l-1">
+        <h1>
+          File.h <span class="m-thin">file</span>
+        </h1>
+        <p>A file.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#func-members">Functions</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+        <section id="func-members">
+          <h2><a href="#func-members">Functions</a></h2>
+          <dl class="m-dox">
+            <dt>
+              <div class="m-dox-template">template&lt;class T, std::enable_if&lt;!std::is_function_v&lt;T&gt; &amp;&amp; std::is_class_v&lt;T&gt;&gt;* = nullptr&gt;</div>
+              <span class="m-dox-wrap-bumper">void <a href="#a3fcc4b26608bf4ff7db5fa240177dd8c" class="m-dox">foo</a>(</span><span class="m-dox-wrap">T* value)</span>
+            </dt>
+            <dd>Templates can get quite crazy.</dd>
+            <dt>
+              <div class="m-dox-template">template&lt;class T, std::enable_if&lt;!std::is_function_v&lt;T&gt; &amp;&amp; std::is_class_v&lt;T&gt;&gt;* ptr = nullptr&gt;</div>
+              <span class="m-dox-wrap-bumper">void <a href="#ac4a8db0384a78f2a419a4693296c0fce" class="m-dox">bar</a>(</span><span class="m-dox-wrap">T* value)</span>
+            </dt>
+            <dd>Templates can get quite crazy.</dd>
+          </dl>
+        </section>
+        <section>
+          <h2>Function documentation</h2>
+          <section class="m-dox-details" id="a3fcc4b26608bf4ff7db5fa240177dd8c"><div>
+            <h3>
+              <div class="m-dox-template">
+                template&lt;class T, std::enable_if&lt;!std::is_function_v&lt;T&gt; &amp;&amp; std::is_class_v&lt;T&gt;&gt;* = nullptr&gt;
+              </div>
+              <span class="m-dox-wrap-bumper">void </span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a3fcc4b26608bf4ff7db5fa240177dd8c" class="m-dox-self">foo</a>(</span><span class="m-dox-wrap">T* value)</span></span>
+            </h3>
+            <p>Templates can get quite crazy.</p>
+            <table class="m-table m-fullwidth m-flat">
+              <thead>
+                <tr><th colspan="2">Template parameters</th></tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td style="width: 1%">T</td>
+                  <td>yes they</td>
+                </tr>
+              </tbody>
+              <thead>
+                <tr><th colspan="2">Parameters</th></tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td>value</td>
+                  <td>can</td>
+                </tr>
+              </tbody>
+            </table>
+          </div></section>
+          <section class="m-dox-details" id="ac4a8db0384a78f2a419a4693296c0fce"><div>
+            <h3>
+              <div class="m-dox-template">
+                template&lt;class T, std::enable_if&lt;!std::is_function_v&lt;T&gt; &amp;&amp; std::is_class_v&lt;T&gt;&gt;* ptr = nullptr&gt;
+              </div>
+              <span class="m-dox-wrap-bumper">void </span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#ac4a8db0384a78f2a419a4693296c0fce" class="m-dox-self">bar</a>(</span><span class="m-dox-wrap">T* value)</span></span>
+            </h3>
+            <p>Templates can get quite crazy.</p>
+            <table class="m-table m-fullwidth m-flat">
+              <thead>
+                <tr><th colspan="2">Template parameters</th></tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td style="width: 1%">T</td>
+                  <td>yes they</td>
+                </tr>
+                <tr>
+                  <td>ptr</td>
+                  <td>absolutely</td>
+                </tr>
+              </tbody>
+              <thead>
+                <tr><th colspan="2">Parameters</th></tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td>value</td>
+                  <td>can</td>
+                </tr>
+              </tbody>
+            </table>
+          </div></section>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
index 69221b8c4d5f8975c8a56ccfcbed675a7012308b..a2478f5f057905a6d257f1804cc105270a5549fc 100644 (file)
@@ -235,3 +235,13 @@ class FilenameCase(IntegrationTestCase):
         self.assertEqual(*self.actual_expected_contents('pages.html'))
         self.assertEqual(*self.actual_expected_contents('_u_p_p_e_r_c_a_s_e.html'))
         self.assertEqual(*self.actual_expected_contents('class_u_p_p_e_r_c_l_a_s_s.html'))
+
+class CrazyTemplateParams(IntegrationTestCase):
+    def __init__(self, *args, **kwargs):
+        super().__init__(__file__, 'crazy_template_params', *args, **kwargs)
+
+    def test(self):
+        self.run_dox2html5(wildcard='*.xml')
+
+        # The file should have the whole template argument as a type
+        self.assertEqual(*self.actual_expected_contents('File_8h.html'))