It may work reasonably well with older versions, but I can't guarantee
that. Upgrade to the latest version to have the best experience.
+ Some features depend on patches that are not yet integrated in Doxygen, in
+ that case the documentation mentions which revision to use or which patch
+ you need to apply.
+
Everything you need apart from Doxygen itself is a Python script and a bunch of
template files. You can get that by cloning :gh:`the m.css GitHub repository <mosra/m.css$master/doxygen>`
and looking into the ``doxygen/`` directory:
Table of contents for pages is generated only if they specify
``@tableofcontents`` in their documentation block.
+`Namespace members in file scope`_
+----------------------------------
+
+Doxygen by default doesn't render namespace members for file documentation in
+its XML output. To match the behavior of stock HTML output, enable the
+:ini:`XML_NAMESPACE_MEMBERS_IN_FILE_SCOPE` option:
+
+.. code:: ini
+
+ # Requires a patch to Doxygen 1.8.14, see below
+ XML_NAMESPACE_MEMBERS_IN_FILE_SCOPE = YES
+
+.. note-warning:: Doxygen patches
+
+ In order to use the :ini:`XML_NAMESPACE_MEMBERS_IN_FILE_SCOPE` option, you
+ need Doxygen with :gh:`doxygen/doxygen#653` applied.
+
`Code highlighting`_
--------------------
=============================== ===============================================
Property Description
=============================== ===============================================
+:py:`enum.base_url` Base URL of file containing detailed
+ description [3]_
:py:`enum.id` Identifier hash [3]_
:py:`enum.type` Enum type or empty if implicitly typed [6]_
:py:`enum.is_strong` If the enum is strong
=========================== ===================================================
Property Description
=========================== ===================================================
+:py:`value.base_url` Base URL of file containing detailed description
+ [3]_
:py:`value.id` Identifier hash [3]_
:py:`value.name` Value name [4]_
:py:`value.initializer` Value initializer. Can be empty. [1]_
=========================== ===================================================
Property Description
=========================== ===================================================
+:py:`typedef.base_url` Base URL of file containing detailed description
+ [3]_
:py:`typedef.id` Identifier hash [3]_
:py:`typedef.is_using` Whether it is a :cpp:`typedef` or an :cpp:`using`
:py:`typedef.type` Typedef type, or what all goes before the name for
=============================== ===============================================
Property Description
=============================== ===============================================
+:py:`func.base_url` Base URL of file containing detailed
+ description [3]_
:py:`func.id` Identifier hash [3]_
:py:`func.type` Function return type [6]_
:py:`func.name` Function name [4]_
=========================== ===================================================
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]_
.. [2] :py:`i.description` is HTML code with the full description, containing
paragraphs, notes, code blocks, images etc. Can be empty in case just the
brief description is present.
-.. [3] :py:`i.id` is a hash used to link to the member on the page, usually
- appearing after ``#`` in page URL
+.. [3] :py:`i.base_url`, joined using ``#`` with :py:`i.id` form a unique URL
+ for given symbol. If the :py:`i.base_url` is not the same as
+ :py:`compound.url`, it means given symbol is just referenced from given
+ compound and its detailed documentation resides elsewhere.
.. [4] :py:`i.name` is just the member name, not qualified. Prepend
:py:`compound.prefix_wbr` to it to get the fully qualified name.
.. [5] :py:`compound.has_*_details` and :py:`i.has_details` are :py:`True` if
there is detailed description, function/template/macro parameter
documentation or enum value listing that makes it worth to render the full
description block. If :py:`False`, the member should be included only in
- the brief listing on top of the page to avoid unnecessary repetition.
+ the brief listing on top of the page to avoid unnecessary repetition. If
+ :py:`i.base_url` is not the same as :py:`compound.url`, its
+ :py:`i.has_details` is always set to :py:`False`.
.. [6] :py:`i.type` and :py:`param.default` is rendered as HTML and usually
contains links to related documentation
.. [7] :py:`i.is_deprecated` is set to :py:`True` if detailed docs of given
assert element.tag == 'memberdef' and element.attrib['kind'] == 'enum'
enum = Empty()
- enum.id = extract_id_hash(state, element)
+ enum.base_url, enum.id = parse_id(state, element)
enum.type = parse_type(state, element.find('type'))
enum.name = element.find('name').text
if enum.name.startswith('@'): enum.name = '(anonymous)'
enumvalue: ET.Element
for enumvalue in element.findall('enumvalue'):
value = Empty()
- value.id = extract_id_hash(state, enumvalue)
+ # The base_url might be different, but should be the same as enum.base_url
+ value_base_url, value.id = parse_id(state, enumvalue)
+ assert value_base_url == enum.base_url
value.name = enumvalue.find('name').text
# There can be an implicit initializer for enum value
value.initializer = html.escape(enumvalue.findtext('initializer', ''))
value.description, value_search_keywords, value.is_deprecated = parse_enum_value_desc(state, enumvalue)
if value.description:
enum.has_value_details = True
- if not state.doxyfile['M_SEARCH_DISABLED']:
+ if enum.base_url == state.current_url and not state.doxyfile['M_SEARCH_DISABLED']:
result = Empty()
result.flags = ResultFlag.ENUM_VALUE|(ResultFlag.DEPRECATED if value.is_deprecated else ResultFlag(0))
- result.url = state.current_url + '#' + value.id
+ result.url = enum.base_url + '#' + value.id
result.prefix = state.current_prefix + [enum.name]
result.name = value.name
result.keywords = value_search_keywords
state.search += [result]
enum.values += [value]
- enum.has_details = enum.description or enum.has_value_details
+ enum.has_details = enum.base_url == state.current_url and (enum.description or enum.has_value_details)
if enum.brief or enum.has_details or enum.has_value_details:
- if not state.doxyfile['M_SEARCH_DISABLED']:
+ if enum.base_url == state.current_url and not state.doxyfile['M_SEARCH_DISABLED']:
result = Empty()
result.flags = ResultFlag.ENUM|(ResultFlag.DEPRECATED if enum.is_deprecated else ResultFlag(0))
- result.url = state.current_url + '#' + enum.id
+ result.url = enum.base_url + '#' + enum.id
result.prefix = state.current_prefix
result.name = enum.name
result.keywords = search_keywords
assert element.tag == 'memberdef' and element.attrib['kind'] == 'typedef'
typedef = Empty()
- typedef.id = extract_id_hash(state, element)
+ typedef.base_url, typedef.id = parse_id(state, element)
typedef.is_using = element.findtext('definition', '').startswith('using')
typedef.type = parse_type(state, element.find('type'))
typedef.args = parse_type(state, element.find('argsstring'))
typedef.is_protected = element.attrib['prot'] == 'protected'
typedef.has_template_details, typedef.templates = parse_template_params(state, element.find('templateparamlist'), templates)
- typedef.has_details = typedef.description or typedef.has_template_details
+ typedef.has_details = typedef.base_url == state.current_url and (typedef.description or typedef.has_template_details)
if typedef.brief or typedef.has_details:
- if not state.doxyfile['M_SEARCH_DISABLED']:
+ # Avoid duplicates in search
+ if typedef.base_url == state.current_url and not state.doxyfile['M_SEARCH_DISABLED']:
result = Empty()
result.flags = ResultFlag.TYPEDEF|(ResultFlag.DEPRECATED if typedef.is_deprecated else ResultFlag(0))
- result.url = state.current_url + '#' + typedef.id
+ result.url = typedef.base_url + '#' + typedef.id
result.prefix = state.current_prefix
result.name = typedef.name
result.keywords = search_keywords
assert element.tag == 'memberdef' and element.attrib['kind'] == 'function'
func = Empty()
- func.id = extract_id_hash(state, element)
+ func.base_url, func.id = parse_id(state, element)
func.type = parse_type(state, element.find('type'))
func.name = fix_type_spacing(html.escape(element.find('name').text))
func.brief = parse_desc(state, element.find('briefdescription'))
# Some param description got unused
if params: logging.warning("{}: function parameter description doesn't match parameter names: {}".format(state.current, repr(params)))
- func.has_details = func.description or func.has_template_details or func.has_param_details or func.return_value or func.return_values
+ func.has_details = func.base_url == state.current_url and (func.description or func.has_template_details or func.has_param_details or func.return_value or func.return_values)
if func.brief or func.has_details:
- if not state.doxyfile['M_SEARCH_DISABLED']:
+ # Avoid duplicates in search
+ if func.base_url == state.current_url and not state.doxyfile['M_SEARCH_DISABLED']:
result = Empty()
result.flags = ResultFlag.FUNC|(ResultFlag.DEPRECATED if func.is_deprecated else ResultFlag(0))|(ResultFlag.DELETED if func.is_deleted else ResultFlag(0))
- result.url = state.current_url + '#' + func.id
+ result.url = func.base_url + '#' + func.id
result.prefix = state.current_prefix
result.name = func.name
result.keywords = search_keywords
assert element.tag == 'memberdef' and element.attrib['kind'] == 'variable'
var = Empty()
- var.id = extract_id_hash(state, element)
+ var.base_url, var.id = parse_id(state, element)
var.type = parse_type(state, element.find('type'))
if var.type.startswith('constexpr'):
var.type = var.type[10:]
var.brief = parse_desc(state, element.find('briefdescription'))
var.description, search_keywords, var.is_deprecated = parse_var_desc(state, element)
- var.has_details = not not var.description
+ var.has_details = var.base_url == state.current_url and var.description
if var.brief or var.has_details:
- if not state.doxyfile['M_SEARCH_DISABLED']:
+ # Avoid duplicates in search
+ if var.base_url == state.current_url and not state.doxyfile['M_SEARCH_DISABLED']:
result = Empty()
result.flags = ResultFlag.VAR|(ResultFlag.DEPRECATED if var.is_deprecated else ResultFlag(0))
- result.url = state.current_url + '#' + var.id
+ result.url = var.base_url + '#' + var.id
result.prefix = state.current_prefix
result.name = var.name
result.keywords = search_keywords
<dt>
{% set j = joiner(',\n ') %}
- <span class="m-dox-wrap-bumper">enum {% if enum.is_strong %}class {% endif %}<a href="#{{ enum.id }}" {% if enum.has_details %}class="m-dox"{% else %}class="m-dox-self" name="{{ enum.id }}"{% endif %}>{{ enum.name }}</a>{% if enum.type %}: {{ enum.type }}{% endif %} { </span><span class="m-dox-wrap">{% for value in enum.values %}{{ j() }}<a href="#{{ value.id }}" class="m-dox">{{ value.name }}</a>{% if value.initializer %} {{ value.initializer }}{% endif %}{% if value.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% endfor %} }{% if enum.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and enum.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}</span>
+ <span class="m-dox-wrap-bumper">enum {% if enum.is_strong %}class {% endif %}<a href="{% if enum.base_url != compound.url %}{{ enum.base_url }}{% endif %}#{{ enum.id }}" {% if enum.has_details or enum.base_url != compound.url %}class="m-dox"{% else %}class="m-dox-self" name="{{ enum.id }}"{% endif %}>{{ enum.name }}</a>{% if enum.type %}: {{ enum.type }}{% endif %} { </span><span class="m-dox-wrap">{% for value in enum.values %}{{ j() }}<a href="#{{ value.id }}" class="m-dox">{{ value.name }}</a>{% if value.initializer %} {{ value.initializer }}{% endif %}{% if value.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% endfor %} }{% if enum.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and enum.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}</span>
</dt>
<dd>{{ enum.brief }}</dd>
<div class="m-dox-template">template<{% for t in func.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif%}{% endfor %}></div>
{% endif %}
{% set j = joiner(',\n ') %}
- <span class="m-dox-wrap-bumper">{{ func.prefix }}{% if func.type == 'void' %}void {% elif func.type %}auto {% endif %}<a href="#{{ func.id }}" {% if func.has_details %}class="m-dox"{% else %}class="m-dox-self" name="{{ func.id }}"{% endif %}>{{ func.name }}</a>(</span><span class="m-dox-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.type and func.type != 'void' %} -> {{ func.type }}{% endif %}{% if func.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if not func.type or mark_nonpublic %}{% if func.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% elif func.is_private %} <span class="m-label m-flat m-danger">private</span>{% endif %}{% endif %}{% if func.is_defaulted %} <span class="m-label m-flat m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-flat m-danger">deleted</span>{% endif %}{% if func.is_explicit %} <span class="m-label m-flat m-info">explicit</span> {% endif %}{% if func.is_pure_virtual %} <span class="m-label m-flat m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}{% if func.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}{% if func.is_noexcept %} <span class="m-label m-flat m-success">noexcept</span>{% endif %}</span>
+ <span class="m-dox-wrap-bumper">{{ func.prefix }}{% if func.type == 'void' %}void {% elif func.type %}auto {% endif %}<a href="{% if func.base_url != compound.url %}{{ func.base_url }}{% endif %}#{{ func.id }}" {% if func.has_details or func.base_url != compound.url %}class="m-dox"{% else %}class="m-dox-self" name="{{ func.id }}"{% endif %}>{{ func.name }}</a>(</span><span class="m-dox-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.type and func.type != 'void' %} -> {{ func.type }}{% endif %}{% if func.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if not func.type or mark_nonpublic %}{% if func.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% elif func.is_private %} <span class="m-label m-flat m-danger">private</span>{% endif %}{% endif %}{% if func.is_defaulted %} <span class="m-label m-flat m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-flat m-danger">deleted</span>{% endif %}{% if func.is_explicit %} <span class="m-label m-flat m-info">explicit</span> {% endif %}{% if func.is_pure_virtual %} <span class="m-label m-flat m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}{% if func.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}{% if func.is_noexcept %} <span class="m-label m-flat m-success">noexcept</span>{% endif %}</span>
</dt>
<dd>{{ func.brief }}</dd>
{% set j = joiner(', ') %}
<div class="m-dox-template">template<{% for t in typedef.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif%}{% endfor %}></div>
{% endif %}
- using <a href="#{{ typedef.id }}" {% if typedef.has_details %}class="m-dox"{% else %}class="m-dox-self" name="{{ typedef.id }}"{% endif %}>{{ typedef.name }}</a> = {{ typedef.type }}{{ typedef.args }}{% if typedef.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and typedef.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}
+ using <a href="{% if typedef.base_url != compound.url %}{{ typedef.base_url }}{% endif %}#{{ typedef.id }}" {% if typedef.has_details or typedef.base_url != compound.url %}class="m-dox"{% else %}class="m-dox-self" name="{{ typedef.id }}"{% endif %}>{{ typedef.name }}</a> = {{ typedef.type }}{{ typedef.args }}{% if typedef.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and typedef.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}
{# This empty line needs to be there otherwise it's eaten #}
</dt>
- <dt>{% if var.is_static %}static {% endif %}{{ var.type }} <a href="#{{ var.id }}" {% if var.has_details %}class="m-dox"{% else %}class="m-dox-self" name="{{ var.id }}"{% endif %}>{{ var.name }}</a>{% if var.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and var.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if var.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}</dt>
+ <dt>{% if var.is_static %}static {% endif %}{{ var.type }} <a href="{% if var.base_url != compound.url %}{{ var.base_url }}{% endif %}#{{ var.id }}" {% if var.has_details or var.base_url != compound.url %}class="m-dox"{% else %}class="m-dox-self" name="{{ var.id }}"{% endif %}>{{ var.name }}</a>{% if var.is_deprecated %} <span class="m-label m-danger">deprecated</span>{% endif %}{% if mark_nonpublic and var.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if var.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}</dt>
<dd>{{ var.brief }}</dd>
--- /dev/null
+INPUT = File.h
+QUIET = YES
+GENERATE_HTML = NO
+GENERATE_LATEX = NO
+GENERATE_XML = YES
+XML_PROGRAMLISTING = NO
+XML_NAMESPACE_MEMBERS_IN_FILE_SCOPE = YES
+
+M_PAGE_FINE_PRINT =
+M_THEME_COLOR =
+M_LINKS_NAVBAR1 =
+M_LINKS_NAVBAR2 =
+M_SEARCH_DISABLED = YES
--- /dev/null
+/** @file
+ * @brief A file
+ */
+
+/** @brief A namespace */
+namespace Namespace {
+
+/**
+@brief A function
+
+Detailed function docs.
+*/
+void foo();
+
+/** @brief Function with just a brief */
+void fooBrief();
+
+/**
+@brief An enum
+
+Detailed enum docs.
+*/
+enum Enum {
+ Value /**< A value */
+};
+
+/** @brief Enum with just a brief */
+enum EnumBrief {};
+
+/**
+@brief A typedef
+
+Detailed typedef docs.
+*/
+typedef int Typedef;
+
+/** @brief Typedef with just a brief */
+typedef int TypedefBrief;
+
+/**
+@brief A variable
+
+Detailed variable docs.
+*/
+constexpr int Variable = 5;
+
+/** @brief Variable with just a brief */
+constexpr int VariableBrief = 5;
+
+/**
+@brief A macro
+
+This appears only in the file docs and fully expanded.
+*/
+#define A_MACRO
+
+}
+
+/* For the undocumented namespace, everything should appear in file docs */
+namespace UndocumentedNamespace {
+
+/**
+@brief A function
+
+Detailed function docs.
+*/
+void foo();
+
+/** @brief Function with just a brief */
+void fooBrief();
+
+/**
+@brief An enum
+
+Detailed enum docs.
+*/
+enum Enum {
+ Value /**< A value */
+};
+
+/** @brief Enum with just a brief */
+enum EnumBrief {};
+
+/**
+@brief A typedef
+
+Detailed typedef docs.
+*/
+typedef int Typedef;
+
+/** @brief Typedef with just a brief */
+typedef int TypedefBrief;
+
+/**
+@brief A variable
+
+Detailed variable docs.
+*/
+constexpr int Variable = 5;
+
+/** @brief Variable with just a brief */
+constexpr int VariableBrief = 5;
+
+}
--- /dev/null
+<!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="#namespaces">Namespaces</a></li>
+ <li><a href="#enum-members">Enums</a></li>
+ <li><a href="#typedef-members">Typedefs</a></li>
+ <li><a href="#func-members">Functions</a></li>
+ <li><a href="#var-members">Variables</a></li>
+ <li><a href="#defines">Defines</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="namespaces">
+ <h2><a href="#namespaces">Namespaces</a></h3>
+ <dl class="m-dox">
+ <dt>namespace <a href="namespaceNamespace.html" class="m-dox">Namespace</a></dt>
+ <dd>A namespace.</dd>
+ </dl>
+ </section>
+ <section id="enum-members">
+ <h2><a href="#enum-members">Enums</a></h3>
+ <dl class="m-dox">
+ <dt>
+ <span class="m-dox-wrap-bumper">enum <a href="namespaceNamespace.html#add172b93283b1ab7612c3ca6cc5dcfea" class="m-dox">Enum</a> { </span><span class="m-dox-wrap"><a href="#add172b93283b1ab7612c3ca6cc5dcfeaa2ef662d81d3f82682b3f993eba87420e" class="m-dox">Value</a> }</span>
+ </dt>
+ <dd>An enum.</dd>
+ <dt>
+ <span class="m-dox-wrap-bumper">enum <a href="namespaceNamespace.html#abddfdbdba5c5512af93fad488e874a6e" class="m-dox">EnumBrief</a> { </span><span class="m-dox-wrap"> }</span>
+ </dt>
+ <dd>Enum with just a brief.</dd>
+ <dt>
+ <span class="m-dox-wrap-bumper">enum <a href="#aeefb6576381a49c1c6e3b7352fe4472f" class="m-dox">Enum</a> { </span><span class="m-dox-wrap"><a href="#aeefb6576381a49c1c6e3b7352fe4472fafbbe8f667f7bfa0603c82d017bc304da" class="m-dox">Value</a> }</span>
+ </dt>
+ <dd>An enum.</dd>
+ <dt>
+ <span class="m-dox-wrap-bumper">enum <a href="#a2632ae5b1d4434dc63030d1343378099" class="m-dox-self" name="a2632ae5b1d4434dc63030d1343378099">EnumBrief</a> { </span><span class="m-dox-wrap"> }</span>
+ </dt>
+ <dd>Enum with just a brief.</dd>
+ </dl>
+ </section>
+ <section id="typedef-members">
+ <h2><a href="#typedef-members">Typedefs</a></h3>
+ <dl class="m-dox">
+ <dt>
+ using <a href="namespaceNamespace.html#abe2a245304bc2234927ef33175646e08" class="m-dox">Typedef</a> = int
+ </dt>
+ <dd>A typedef.</dd>
+ <dt>
+ using <a href="namespaceNamespace.html#a3528713a2cb2fc8e4b0c8fab2e3142e6" class="m-dox">TypedefBrief</a> = int
+ </dt>
+ <dd>Typedef with just a brief.</dd>
+ <dt>
+ using <a href="#ad339d36696a203dd41ce1b4967eaff0a" class="m-dox">Typedef</a> = int
+ </dt>
+ <dd>A typedef.</dd>
+ <dt>
+ using <a href="#a023e422700677703873bc1e7372e7400" class="m-dox-self" name="a023e422700677703873bc1e7372e7400">TypedefBrief</a> = int
+ </dt>
+ <dd>Typedef with just a brief.</dd>
+ </dl>
+ </section>
+ <section id="func-members">
+ <h2><a href="#func-members">Functions</a></h3>
+ <dl class="m-dox">
+ <dt>
+ <span class="m-dox-wrap-bumper">void <a href="namespaceNamespace.html#a0f1fe1a972c7c4196988a1bdde63ec77" class="m-dox">foo</a>(</span><span class="m-dox-wrap">)</span>
+ </dt>
+ <dd>A function.</dd>
+ <dt>
+ <span class="m-dox-wrap-bumper">void <a href="namespaceNamespace.html#a25c0cb6154508312ca2f28fdab944741" class="m-dox">fooBrief</a>(</span><span class="m-dox-wrap">)</span>
+ </dt>
+ <dd>Function with just a brief.</dd>
+ <dt>
+ <span class="m-dox-wrap-bumper">void <a href="#a3d859e95e6eb8b4da1c10b6417ab8e9b" class="m-dox">foo</a>(</span><span class="m-dox-wrap">)</span>
+ </dt>
+ <dd>A function.</dd>
+ <dt>
+ <span class="m-dox-wrap-bumper">void <a href="#a9ca3f6e800be14b033c364187b444b2f" class="m-dox-self" name="a9ca3f6e800be14b033c364187b444b2f">fooBrief</a>(</span><span class="m-dox-wrap">)</span>
+ </dt>
+ <dd>Function with just a brief.</dd>
+ </dl>
+ </section>
+ <section id="var-members">
+ <h2><a href="#var-members">Variables</a></h3>
+ <dl class="m-dox">
+ <dt>int <a href="namespaceNamespace.html#ad3121960d8665ab045ca1bfa1480a86d" class="m-dox">Variable</a> <span class="m-label m-flat m-primary">constexpr</span></dt>
+ <dd>A variable.</dd>
+ <dt>int <a href="namespaceNamespace.html#aa8b31b63b2a5e71fe1734212a093bdc3" class="m-dox">VariableBrief</a> <span class="m-label m-flat m-primary">constexpr</span></dt>
+ <dd>Variable with just a brief.</dd>
+ <dt>int <a href="#a7dc9e9cdaf8275ac8636d69b90f37045" class="m-dox">Variable</a> <span class="m-label m-flat m-primary">constexpr</span></dt>
+ <dd>A variable.</dd>
+ <dt>int <a href="#a39904e2093f37ccfc2b7ad44ead2420a" class="m-dox-self" name="a39904e2093f37ccfc2b7ad44ead2420a">VariableBrief</a> <span class="m-label m-flat m-primary">constexpr</span></dt>
+ <dd>Variable with just a brief.</dd>
+ </dl>
+ </section>
+ <section id="define-members">
+ <h2><a href="#define-members">Defines</a></h3>
+ <dl class="m-dox">
+ <dt>
+ <span class="m-dox-wrap-bumper">#define <a href="#a1e6e7cc6cc96adc8342c838f55790259" class="m-dox">A_MACRO</a></span>
+ </dt>
+ <dd>A macro.</dd>
+ </dl>
+ </section>
+ <section>
+ <h2>Enum documentation</h2>
+ <section class="m-dox-details" id="aeefb6576381a49c1c6e3b7352fe4472f"><div>
+ <h3>
+ enum <a href="#aeefb6576381a49c1c6e3b7352fe4472f" class="m-dox-self">Enum</a>
+ </h3>
+ <p>An enum.</p>
+<p>Detailed enum docs.</p>
+ <table class="m-table m-fullwidth m-flat m-dox">
+ <thead><tr><th style="width: 1%">Enumerators</th><th></th></tr></thead>
+ <tbody>
+ <tr>
+ <td><a href="#aeefb6576381a49c1c6e3b7352fe4472fafbbe8f667f7bfa0603c82d017bc304da" class="m-dox-self" name="aeefb6576381a49c1c6e3b7352fe4472fafbbe8f667f7bfa0603c82d017bc304da">Value</a></td>
+ <td>
+<p>A value</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div></section>
+ </section>
+ <section>
+ <h2>Typedef documentation</h2>
+ <section class="m-dox-details" id="ad339d36696a203dd41ce1b4967eaff0a"><div>
+ <h3>
+ typedef int <a href="#ad339d36696a203dd41ce1b4967eaff0a" class="m-dox-self">Typedef</a>
+ </h3>
+ <p>A typedef.</p>
+<p>Detailed typedef docs.</p>
+ </div></section>
+ </section>
+ <section>
+ <h2>Function documentation</h2>
+ <section class="m-dox-details" id="a3d859e95e6eb8b4da1c10b6417ab8e9b"><div>
+ <h3>
+ <span class="m-dox-wrap-bumper">void </span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a3d859e95e6eb8b4da1c10b6417ab8e9b" class="m-dox-self">foo</a>(</span><span class="m-dox-wrap">)</span></span>
+ </h3>
+ <p>A function.</p>
+<p>Detailed function docs.</p>
+ </div></section>
+ </section>
+ <section>
+ <h2>Variable documentation</h2>
+ <section class="m-dox-details" id="a7dc9e9cdaf8275ac8636d69b90f37045"><div>
+ <h3>
+ int <a href="#a7dc9e9cdaf8275ac8636d69b90f37045" class="m-dox-self">Variable</a> <span class="m-label m-primary">constexpr</span>
+ </h3>
+ <p>A variable.</p>
+<p>Detailed variable docs.</p>
+ </div></section>
+ </section>
+ <section>
+ <h2>Define documentation</h2>
+ <section class="m-dox-details" id="a1e6e7cc6cc96adc8342c838f55790259"><div>
+ <h3>
+ <span class="m-dox-wrap-bumper">#define <a href="#a1e6e7cc6cc96adc8342c838f55790259" class="m-dox-self">A_MACRO</a></span>
+ </h3>
+ <p>A macro.</p>
+<p>This appears only in the file docs and fully expanded.</p>
+ </div></section>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>Namespace namespace | 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>Namespace <span class="m-thin">namespace</span></h1>
+ <p>A namespace.</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#enum-members">Enums</a></li>
+ <li><a href="#typedef-members">Typedefs</a></li>
+ <li><a href="#func-members">Functions</a></li>
+ <li><a href="#var-members">Variables</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="enum-members">
+ <h2><a href="#enum-members">Enums</a></h3>
+ <dl class="m-dox">
+ <dt>
+ <span class="m-dox-wrap-bumper">enum <a href="#add172b93283b1ab7612c3ca6cc5dcfea" class="m-dox">Enum</a> { </span><span class="m-dox-wrap"><a href="#add172b93283b1ab7612c3ca6cc5dcfeaa2ef662d81d3f82682b3f993eba87420e" class="m-dox">Value</a> }</span>
+ </dt>
+ <dd>An enum.</dd>
+ <dt>
+ <span class="m-dox-wrap-bumper">enum <a href="#abddfdbdba5c5512af93fad488e874a6e" class="m-dox-self" name="abddfdbdba5c5512af93fad488e874a6e">EnumBrief</a> { </span><span class="m-dox-wrap"> }</span>
+ </dt>
+ <dd>Enum with just a brief.</dd>
+ </dl>
+ </section>
+ <section id="typedef-members">
+ <h2><a href="#typedef-members">Typedefs</a></h3>
+ <dl class="m-dox">
+ <dt>
+ using <a href="#abe2a245304bc2234927ef33175646e08" class="m-dox">Typedef</a> = int
+ </dt>
+ <dd>A typedef.</dd>
+ <dt>
+ using <a href="#a3528713a2cb2fc8e4b0c8fab2e3142e6" class="m-dox-self" name="a3528713a2cb2fc8e4b0c8fab2e3142e6">TypedefBrief</a> = int
+ </dt>
+ <dd>Typedef with just a brief.</dd>
+ </dl>
+ </section>
+ <section id="func-members">
+ <h2><a href="#func-members">Functions</a></h3>
+ <dl class="m-dox">
+ <dt>
+ <span class="m-dox-wrap-bumper">void <a href="#a0f1fe1a972c7c4196988a1bdde63ec77" class="m-dox">foo</a>(</span><span class="m-dox-wrap">)</span>
+ </dt>
+ <dd>A function.</dd>
+ <dt>
+ <span class="m-dox-wrap-bumper">void <a href="#a25c0cb6154508312ca2f28fdab944741" class="m-dox-self" name="a25c0cb6154508312ca2f28fdab944741">fooBrief</a>(</span><span class="m-dox-wrap">)</span>
+ </dt>
+ <dd>Function with just a brief.</dd>
+ </dl>
+ </section>
+ <section id="var-members">
+ <h2><a href="#var-members">Variables</a></h3>
+ <dl class="m-dox">
+ <dt>int <a href="#ad3121960d8665ab045ca1bfa1480a86d" class="m-dox">Variable</a> <span class="m-label m-flat m-primary">constexpr</span></dt>
+ <dd>A variable.</dd>
+ <dt>int <a href="#aa8b31b63b2a5e71fe1734212a093bdc3" class="m-dox-self" name="aa8b31b63b2a5e71fe1734212a093bdc3">VariableBrief</a> <span class="m-label m-flat m-primary">constexpr</span></dt>
+ <dd>Variable with just a brief.</dd>
+ </dl>
+ </section>
+ <section>
+ <h2>Enum documentation</h2>
+ <section class="m-dox-details" id="add172b93283b1ab7612c3ca6cc5dcfea"><div>
+ <h3>
+ enum Namespace::<wbr /><a href="#add172b93283b1ab7612c3ca6cc5dcfea" class="m-dox-self">Enum</a>
+ </h3>
+ <p>An enum.</p>
+<p>Detailed enum docs.</p>
+ <table class="m-table m-fullwidth m-flat m-dox">
+ <thead><tr><th style="width: 1%">Enumerators</th><th></th></tr></thead>
+ <tbody>
+ <tr>
+ <td><a href="#add172b93283b1ab7612c3ca6cc5dcfeaa2ef662d81d3f82682b3f993eba87420e" class="m-dox-self" name="add172b93283b1ab7612c3ca6cc5dcfeaa2ef662d81d3f82682b3f993eba87420e">Value</a></td>
+ <td>
+<p>A value</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div></section>
+ </section>
+ <section>
+ <h2>Typedef documentation</h2>
+ <section class="m-dox-details" id="abe2a245304bc2234927ef33175646e08"><div>
+ <h3>
+ typedef int Namespace::<wbr /><a href="#abe2a245304bc2234927ef33175646e08" class="m-dox-self">Typedef</a>
+ </h3>
+ <p>A typedef.</p>
+<p>Detailed typedef docs.</p>
+ </div></section>
+ </section>
+ <section>
+ <h2>Function documentation</h2>
+ <section class="m-dox-details" id="a0f1fe1a972c7c4196988a1bdde63ec77"><div>
+ <h3>
+ <span class="m-dox-wrap-bumper">void Namespace::<wbr /></span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a0f1fe1a972c7c4196988a1bdde63ec77" class="m-dox-self">foo</a>(</span><span class="m-dox-wrap">)</span></span>
+ </h3>
+ <p>A function.</p>
+<p>Detailed function docs.</p>
+ </div></section>
+ </section>
+ <section>
+ <h2>Variable documentation</h2>
+ <section class="m-dox-details" id="ad3121960d8665ab045ca1bfa1480a86d"><div>
+ <h3>
+ int Namespace::<wbr /><a href="#ad3121960d8665ab045ca1bfa1480a86d" class="m-dox-self">Variable</a> <span class="m-label m-primary">constexpr</span>
+ </h3>
+ <p>A variable.</p>
+<p>Detailed variable docs.</p>
+ </div></section>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
GENERATE_LATEX = NO
GENERATE_XML = YES
XML_PROGRAMLISTING = NO
+
+# Verify that this doesn't cause duplicated items
+XML_NAMESPACE_MEMBERS_IN_FILE_SCOPE = YES
+
EXAMPLE_PATH = .
ALIASES = \
"m_keywords{1}=@xmlonly<mcss:search xmlns:mcss=\"http://mcss.mosra.cz/doxygen/\" mcss:keywords=\"\1\" />@endxmlonly" \
import os
import unittest
-from test import IntegrationTestCase
+from distutils.version import LooseVersion
+
+from test import IntegrationTestCase, doxygen_version
class Listing(IntegrationTestCase):
def __init__(self, *args, **kwargs):
# Base and derived class listing
self.assertEqual(*self.actual_expected_contents('structDeprecatedNamespace_1_1BaseDeprecatedClass.html'))
self.assertEqual(*self.actual_expected_contents('structDeprecatedNamespace_1_1DeprecatedClass.html'))
+
+class NamespaceMembersInFileScope(IntegrationTestCase):
+ def __init__(self, *args, **kwargs):
+ super().__init__(__file__, 'namespace_members_in_file_scope', *args, **kwargs)
+
+ def test(self):
+ self.run_dox2html5(wildcard='namespaceNamespace.xml')
+
+ # The namespace should have the detailed docs
+ self.assertEqual(*self.actual_expected_contents('namespaceNamespace.html'))
+
+ @unittest.skipUnless(LooseVersion(doxygen_version()) > LooseVersion("1.8.14"),
+ "https://github.com/doxygen/doxygen/pull/653")
+ def test_file(self):
+ self.run_dox2html5(wildcard='File_8h.xml')
+
+ # The file should have just links to detailed docs
+ self.assertEqual(*self.actual_expected_contents('File_8h.html'))