From: Vladimír Vondruš Date: Sun, 30 Dec 2018 23:58:40 +0000 (+0100) Subject: doxygen: support C++14 variable templates. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~cjwatson/git?a=commitdiff_plain;h=088e8ef567c2b997a95cb9709cbc38122b4bad47;p=blog.git doxygen: support C++14 variable templates. Interestingly enough, Doxygen already has the support and I just need some basic template bureaucracy to get it running. --- diff --git a/doc/doxygen.rst b/doc/doxygen.rst index b46ecc19..ae7e266a 100644 --- a/doc/doxygen.rst +++ b/doc/doxygen.rst @@ -1760,25 +1760,29 @@ every item has the following properties: .. class:: m-table m-fullwidth -=========================== =================================================== -Property Description -=========================== =================================================== -:py:`var.base_url` Base URL of file containing detailed description - [3]_ -:py:`var.id` Identifier hash [3]_ -:py:`var.type` Variable type [6]_ -:py:`var.name` Variable name [4]_ -:py:`var.brief` Brief description. Can be empty. [1]_ -:py:`var.description` Detailed description. Can be empty. [2]_ -:py:`var.has_details` If there is enough content for the full description - block [5]_ -:py:`var.is_deprecated` Whether the variable is deprecated. [7]_ -:py:`var.is_static` If the variable is :cpp:`static`. Set only for - member variables. -:py:`var.is_protected` If the variable is :cpp:`protected`. Set only for - member variables. -:py:`var.is_constexpr` If the variable is :cpp:`constexpr` -=========================== =================================================== +=============================== =============================================== +Property Description +=============================== =============================================== +:py:`var.base_url` Base URL of file containing detailed + description [3]_ +:py:`var.id` Identifier hash [3]_ +:py:`var.type` Variable type [6]_ +:py:`var.name` Variable name [4]_ +:py:`var.templates` Template specification for C++14 variable + templates. See `Template properties`_ for + details. +:py:`var.has_template_details` If template parameters have description +:py:`var.brief` Brief description. Can be empty. [1]_ +:py:`var.description` Detailed description. Can be empty. [2]_ +:py:`var.has_details` If there is enough content for the full + description block [5]_ +:py:`var.is_deprecated` Whether the variable is deprecated. [7]_ +:py:`var.is_static` If the variable is :cpp:`static`. Set only for + member variables. +:py:`var.is_protected` If the variable is :cpp:`protected`. Set only + for member variables. +:py:`var.is_constexpr` If the variable is :cpp:`constexpr` +=============================== =============================================== `Define properties`_ ```````````````````` diff --git a/doxygen/dox2html5.py b/doxygen/dox2html5.py index 4a7d863f..bcc27b68 100755 --- a/doxygen/dox2html5.py +++ b/doxygen/dox2html5.py @@ -1545,10 +1545,10 @@ def parse_enum_value_desc(state: State, element: ET.Element) -> str: def parse_var_desc(state: State, element: ET.Element) -> str: parsed = parse_desc_internal(state, element.find('detaileddescription')) parsed.parsed += parse_desc(state, element.find('inbodydescription')) - if parsed.templates or parsed.params or parsed.return_value or parsed.return_values or parsed.exceptions: - logging.warning("{}: unexpected @tparam / @param / @return / @retval / @exception found in variable description, ignoring".format(state.current)) + if parsed.params or parsed.return_value or parsed.return_values or parsed.exceptions: + logging.warning("{}: unexpected @param / @return / @retval / @exception found in variable description, ignoring".format(state.current)) assert not parsed.section # might be problematic - return (parsed.parsed, parsed.search_keywords, parsed.is_deprecated) + return (parsed.parsed, parsed.templates, parsed.search_keywords, parsed.is_deprecated) def parse_toplevel_desc(state: State, element: ET.Element): state.parsing_toplevel_desc = True @@ -1850,9 +1850,10 @@ def parse_var(state: State, element: ET.Element): var.is_private = element.attrib['prot'] == 'private' var.name = element.find('name').text var.brief = parse_desc(state, element.find('briefdescription')) - var.description, search_keywords, var.is_deprecated = parse_var_desc(state, element) + var.description, templates, search_keywords, var.is_deprecated = parse_var_desc(state, element) + var.has_template_details, var.templates = parse_template_params(state, element.find('templateparamlist'), templates) - var.has_details = var.base_url == state.current_compound_url and var.description + var.has_details = var.base_url == state.current_compound_url and (var.description or var.has_template_details) if var.brief or var.has_details: # Avoid duplicates in search if var.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']: diff --git a/doxygen/templates/details-var.html b/doxygen/templates/details-var.html index 0eabc81a..2dbea7a4 100644 --- a/doxygen/templates/details-var.html +++ b/doxygen/templates/details-var.html @@ -1,9 +1,15 @@

- {% if compound.templates != None %} + {% if compound.templates != None or var.templates != None %}
+ {% if compound.templates != None %} {% set j = joiner(', ') %} template<{% for t in compound.templates %}{{ j() }}{{ t.type }} {% if t.name %}{{ t.name }}{% else %}_{{ loop.index }}{% endif %}{% endfor %}> + {% endif %} + {% if var.templates != None %} + {% set j = joiner(', ') %} + template<{% for t in var.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif %}{% endfor %}> + {% endif %}
{% endif %} {%+ if var.is_static %}static {% endif %}{{ var.type }} {{ prefix }}{{ var.name }}{% if var.is_protected %} protected{% endif %}{% if var.is_constexpr %} constexpr{% endif %} @@ -13,5 +19,22 @@ {% if var.brief %}

{{ var.brief }}

{% endif %} + {% if var.has_template_details %} + + + + + + {% for template in var.templates|selectattr('name') %} + + {{ template.name }} + + + {% endfor %} + +
Template parameters
{{ template.description }}
+ {% endif %} + {% if var.description %} {{ var.description }} + {% endif %}

diff --git a/doxygen/templates/entry-var.html b/doxygen/templates/entry-var.html index 820cab85..7dbe4780 100644 --- a/doxygen/templates/entry-var.html +++ b/doxygen/templates/entry-var.html @@ -1,2 +1,10 @@ -
{% if var.is_static %}static {% endif %}{{ var.type }} {{ var.name }}{% if var.is_deprecated %} deprecated{% endif %}{% if mark_nonpublic and var.is_protected %} protected{% endif %}{% if var.is_constexpr %} constexpr{% endif %}
+
+ {% if var.templates != None %} + {% set j = joiner(', ') %} +
template<{% for t in var.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif%}{% endfor %}>
+ {% endif %} + {%+ if var.is_static %}static {% endif %}{{ var.type }} {{ var.name }}{% if var.is_deprecated %} deprecated{% endif %}{% if mark_nonpublic and var.is_protected %} protected{% endif %}{% if var.is_constexpr %} constexpr{% endif %} + {# This empty line needs to be there otherwise it's eaten #} + +
{{ var.brief }}
diff --git a/doxygen/test/compound_deprecated/namespaceDeprecatedNamespace.html b/doxygen/test/compound_deprecated/namespaceDeprecatedNamespace.html index c27d1916..96369bb9 100644 --- a/doxygen/test/compound_deprecated/namespaceDeprecatedNamespace.html +++ b/doxygen/test/compound_deprecated/namespaceDeprecatedNamespace.html @@ -96,7 +96,9 @@

Variables

-
int DeprecatedVariable deprecated constexpr
+
+ int DeprecatedVariable deprecated constexpr +
A variable.
diff --git a/doxygen/test/compound_detailed/namespaceVar.html b/doxygen/test/compound_detailed/namespaceVar.html index 769d423f..44b53fbf 100644 --- a/doxygen/test/compound_detailed/namespaceVar.html +++ b/doxygen/test/compound_detailed/namespaceVar.html @@ -37,7 +37,9 @@

Variables

-
const int a constexpr
+
+ const int a constexpr +
A value.
diff --git a/doxygen/test/compound_detailed/structTemplate.html b/doxygen/test/compound_detailed/structTemplate.html index 895115d3..0dd5cb71 100644 --- a/doxygen/test/compound_detailed/structTemplate.html +++ b/doxygen/test/compound_detailed/structTemplate.html @@ -93,7 +93,9 @@

Protected variables

-
int a
+
+ int a +
Variable.
diff --git a/doxygen/test/compound_listing/classRoot_1_1Directory_1_1Sub_1_1Class.html b/doxygen/test/compound_listing/classRoot_1_1Directory_1_1Sub_1_1Class.html index 2718105f..3a48bde0 100644 --- a/doxygen/test/compound_listing/classRoot_1_1Directory_1_1Sub_1_1Class.html +++ b/doxygen/test/compound_listing/classRoot_1_1Directory_1_1Sub_1_1Class.html @@ -97,7 +97,9 @@

Public static variables

-
static int Size constexpr
+
+ static int Size constexpr +
A public static var.
@@ -144,7 +146,9 @@

Public variables

-
std::string debug
+
+ std::string debug +
A public variable.
@@ -189,14 +193,18 @@

Protected static variables

-
static bool False
+
+ static bool False +
A protected static var.

Protected variables

-
std::string logger
+
+ std::string logger +
A protected variable.
@@ -220,7 +228,9 @@ using Main = void protected
Protected alias in a group.
-
void* variable protected
+
+ void* variable protected +
Protected variable in a group.
void foo() const & protected @@ -247,7 +257,9 @@ using Float = float
An using declaration.
-
const int Var constexpr
+
+ const int Var constexpr +
A variable.
void foo() diff --git a/doxygen/test/compound_listing/namespaceRoot_1_1Directory.html b/doxygen/test/compound_listing/namespaceRoot_1_1Directory.html index 4b44a073..9ec430f6 100644 --- a/doxygen/test/compound_listing/namespaceRoot_1_1Directory.html +++ b/doxygen/test/compound_listing/namespaceRoot_1_1Directory.html @@ -114,7 +114,9 @@

Variables

-
const int Var constexpr
+
+ const int Var constexpr +
A variable.
@@ -129,7 +131,9 @@ using Main = void
Alias in a group.
-
void* variable constexpr
+
+ void* variable constexpr +
Variable in a group.
void bar() diff --git a/doxygen/test/compound_namespace_members_in_file_scope/File_8h.html b/doxygen/test/compound_namespace_members_in_file_scope/File_8h.html index e2537145..9376e930 100644 --- a/doxygen/test/compound_namespace_members_in_file_scope/File_8h.html +++ b/doxygen/test/compound_namespace_members_in_file_scope/File_8h.html @@ -112,13 +112,21 @@

Variables

-
int Variable constexpr
+
+ int Variable constexpr +
A variable.
-
int VariableBrief constexpr
+
+ int VariableBrief constexpr +
Variable with just a brief.
-
int Variable constexpr
+
+ int Variable constexpr +
A variable.
-
int VariableBrief constexpr
+
+ int VariableBrief constexpr +
Variable with just a brief.
diff --git a/doxygen/test/compound_namespace_members_in_file_scope/namespaceNamespace.html b/doxygen/test/compound_namespace_members_in_file_scope/namespaceNamespace.html index 2ee55d2f..39253918 100644 --- a/doxygen/test/compound_namespace_members_in_file_scope/namespaceNamespace.html +++ b/doxygen/test/compound_namespace_members_in_file_scope/namespaceNamespace.html @@ -79,9 +79,13 @@

Variables

-
int Variable constexpr
+
+ int Variable constexpr +
A variable.
-
int VariableBrief constexpr
+
+ int VariableBrief constexpr +
Variable with just a brief.
diff --git a/doxygen/test/compound_namespace_members_in_file_scope_define_base_url/File_8h.html b/doxygen/test/compound_namespace_members_in_file_scope_define_base_url/File_8h.html index f266c11b..251d11d8 100644 --- a/doxygen/test/compound_namespace_members_in_file_scope_define_base_url/File_8h.html +++ b/doxygen/test/compound_namespace_members_in_file_scope_define_base_url/File_8h.html @@ -55,7 +55,9 @@

Variables

-
int var
+
+ int var +
A variable.
diff --git a/doxygen/test/contents_unexpected_sections/File_8h.html b/doxygen/test/contents_unexpected_sections/File_8h.html index 9b1fcf68..aceba6d0 100644 --- a/doxygen/test/contents_unexpected_sections/File_8h.html +++ b/doxygen/test/contents_unexpected_sections/File_8h.html @@ -60,7 +60,9 @@

Variables

-
int variable
+
+ int variable +
A variable.
diff --git a/doxygen/test/cpp_variable_template/Doxyfile b/doxygen/test/cpp_variable_template/Doxyfile new file mode 100644 index 00000000..ee1cb763 --- /dev/null +++ b/doxygen/test/cpp_variable_template/Doxyfile @@ -0,0 +1,14 @@ +INPUT = input.h +AUTOLINK_SUPPORT = NO +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/cpp_variable_template/input.h b/doxygen/test/cpp_variable_template/input.h new file mode 100644 index 00000000..ad12d6a2 --- /dev/null +++ b/doxygen/test/cpp_variable_template/input.h @@ -0,0 +1,23 @@ +/** @brief A non-template class */ +struct Foo { + /** @brief Template variable without template docs */ + template static T* variable; + + /** + * @brief Template variable with template docs + * @tparam T Well, the type + */ + template static T& another; +}; + +/** @brief Template class */ +template struct Bar { + /** @brief Template variable inside a template class without template docs */ + template static Foo* instance; + + /** + * @brief Template variable inside a template class with template docs + * @tparam U Well, the type + */ + template static Foo& another; +}; diff --git a/doxygen/test/cpp_variable_template/structBar.html b/doxygen/test/cpp_variable_template/structBar.html new file mode 100644 index 00000000..83533d88 --- /dev/null +++ b/doxygen/test/cpp_variable_template/structBar.html @@ -0,0 +1,82 @@ + + + + + Bar struct | My Project + + + + + +
+
+
+
+
+

+
template<class T>
+ Bar struct +

+

Template class.

+
+

Contents

+ +
+
+

Public static variables

+
+
+
template<class U>
+ static Foo<U>* instance +
+
Template variable inside a template class without template docs.
+
+
template<class U>
+ static Foo<U>& another +
+
Template variable inside a template class with template docs.
+
+
+
+

Variable documentation

+
+

+
+ template<class T> + template<class U> +
+ static Foo<U>& Bar<T>::another +

+

Template variable inside a template class with template docs.

+ + + + + + + + + + +
Template parameters
UWell, the type
+
+
+
+
+
+
+ + diff --git a/doxygen/test/cpp_variable_template/structFoo.html b/doxygen/test/cpp_variable_template/structFoo.html new file mode 100644 index 00000000..d123ffc3 --- /dev/null +++ b/doxygen/test/cpp_variable_template/structFoo.html @@ -0,0 +1,80 @@ + + + + + Foo struct | My Project + + + + + +
+
+
+
+
+

+ Foo struct +

+

A non-template class.

+
+

Contents

+ +
+
+

Public static variables

+
+
+
template<class T>
+ static T* variable +
+
Template variable without template docs.
+
+
template<class T>
+ static T& another +
+
Template variable with template docs.
+
+
+
+

Variable documentation

+
+

+
+ template<class T> +
+ static T& Foo::another +

+

Template variable with template docs.

+ + + + + + + + + + +
Template parameters
TWell, the type
+
+
+
+
+
+
+ + diff --git a/doxygen/test/test_cpp.py b/doxygen/test/test_cpp.py index 5bab4020..6e6504b1 100644 --- a/doxygen/test/test_cpp.py +++ b/doxygen/test/test_cpp.py @@ -80,3 +80,12 @@ class SignalsSlots(IntegrationTestCase): def test(self): self.run_dox2html5(wildcard='classClass.xml') self.assertEqual(*self.actual_expected_contents('classClass.html')) + +class VariableTemplate(IntegrationTestCase): + def __init__(self, *args, **kwargs): + super().__init__(__file__, 'variable_template', *args, **kwargs) + + def test(self): + self.run_dox2html5(wildcard='*.xml') + self.assertEqual(*self.actual_expected_contents('structFoo.html')) + self.assertEqual(*self.actual_expected_contents('structBar.html'))