chiark / gitweb /
doxygen: improve #include information display based on real-world use.
authorVladimír Vondruš <mosra@centrum.cz>
Mon, 31 Dec 2018 23:35:49 +0000 (00:35 +0100)
committerVladimír Vondruš <mosra@centrum.cz>
Mon, 31 Dec 2018 23:35:49 +0000 (00:35 +0100)
 * In cases where Doxygen spots the namespace first in a *.cpp file (and
   later in a header) but the namespace is still contained in a single
   header, the include informations was improperly put locally into
   members, instead of globally. Now the information is propagated
   upwards from the members to ensure correctness. This needs also
   special handling for namespaces that are otherwise empty, where
   there's nothing that could propagate the info upwards.
 * Complex namespaces (namespaces containing other namespaces or
   classes) no longer have the include information global even though
   the non-class/namespace members are in the same file. This would be
   misleading since inner namespaces and classes are often in different
   files.

doxygen/dox2html5.py
doxygen/test/compound_deprecated/namespaceDeprecatedNamespace.html
doxygen/test/compound_includes/First.h
doxygen/test/compound_includes/namespaceContainsNamespace.html [new file with mode: 0644]
doxygen/test/compound_includes/namespaceContainsNamespace_1_1ContainsClass.html [new file with mode: 0644]
doxygen/test/compound_includes/namespaceEmpty.html [new file with mode: 0644]
doxygen/test/compound_listing/namespaceRoot_1_1Directory.html
doxygen/test/test_compound.py

index 45c369a5304871024f2b3e7567eb1f21b496ddeb..59e9a6225cb7c99dcbd6537879b13afac6c02e8d 100755 (executable)
@@ -428,6 +428,11 @@ def parse_ref(state: State, element: ET.Element) -> str:
 
     return '<a href="{}" class="{}">{}</a>'.format(url, class_, add_wbr(parse_inline_desc(state, element).strip()))
 
+def make_include(state: State, file) -> Tuple[str, str]:
+    if file in state.includes and state.compounds[state.includes[file]].has_details:
+        return (html.escape('<{}>'.format(file)), state.compounds[state.includes[file]].url)
+    return None
+
 def parse_id_and_include(state: State, element: ET.Element) -> Tuple[str, str, str, Tuple[str, str]]:
     # Returns URL base (usually saved to state.current_definition_url_base and
     # used by extract_id_hash() later), base URL (with file extension), and the
@@ -440,14 +445,23 @@ def parse_id_and_include(state: State, element: ET.Element) -> Tuple[str, str, s
     include = None
     if state.current_kind in ['namespace', 'group']:
         file = element.find('location').attrib['file']
-        if file in state.includes and state.compounds[state.includes[file]].has_details:
-            include = (html.escape('<{}>'.format(file)), state.compounds[state.includes[file]].url)
-
-        # If the include differs from current compound include, reset it to signal
-        # that the compound doesn't have one unique include file. This will get
-        # later picked up by parse_xml() which either adds has_details to all
-        # compounds or wipes the compound-specific includes.
-        if state.current_include and state.current_include != file:
+        include = make_include(state, file)
+
+        # If the include for current namespace is not yet set (empty string)
+        # but also not already signalled to be non-unique using None, set it to
+        # this value. Need to do it this way instead of using the location
+        # information from the compound, because namespace location is
+        # sometimes pointed to a *.cpp file, which Doxygen sees before *.h.
+        if not state.current_include and state.current_include is not None:
+            assert state.current_kind == 'namespace'
+            state.current_include = file
+            # parse_xml() fills compound.include from this later
+
+        # If the include differs from current compound include, reset it to
+        # None to signal that the compound doesn't have one unique include
+        # file. This will get later picked up by parse_xml() which either adds
+        # has_details to all compounds or wipes the compound-specific includes.
+        elif state.current_include and state.current_include != file:
             state.current_include = None
 
     return id[:i], id[:i] + '.html', id[i+2:], include
@@ -2347,21 +2361,36 @@ def parse_xml(state: State, xml: str):
         state.current_prefix = []
 
     # Decide about the include file for this compound. Classes get it always,
-    # namespaces only if it we later don't discover that it's spread over
-    # multiple files; files and dirs don't need it (it's implicit) and it makes
-    # no sense for pages or modules.
+    # namespaces without any members too.
     state.current_kind = compound.kind
-    if compound.kind in ['struct', 'class', 'union', 'namespace']:
-        include = compounddef.find('location').attrib['file']
-        if include in state.includes and state.compounds[state.includes[include]].has_details:
-            compound.include = (html.escape('<{}>'.format(include)), state.compounds[state.includes[include]].url)
+    if compound.kind in ['struct', 'class', 'union'] or (compound.kind == 'namespace' and compounddef.find('innerclass') is None and compounddef.find('innernamespace') is None and compounddef.find('sectiondef') is None):
+        file = compounddef.find('location').attrib['file']
+        compound.include = make_include(state, file)
 
         # Save include for current compound. Every enum/var/function/... parser
         # checks against it and resets to None in case the include differs for
         # given entry, meaning all entries need to have their own include
         # definition instead. That's then finally reflected in has_details of
         # each entry.
-        state.current_include = include
+        state.current_include = file
+
+    # Namespaces with members get a placeholder that gets filled from the
+    # contents; but only if the namespace doesn't contain subnamespaces or
+    # classes, in which case it would be misleading. It's done this way because
+    # Doxygen sets namespace location to the first file it sees, which can be
+    # a *.cpp file. In case the namespace doesn't have any members, it's set
+    # above like with classes.
+    #
+    # Once current_include is filled for the first time in
+    # parse_id_and_include(), every enum/var/function/... parser checks against
+    # it and resets to None in case the include differs for given entry,
+    # meaning all entries need to have their own include definition instead.
+    # That's then finally reflected in has_details of each entry.
+    elif compound.kind == 'namespace' and compounddef.find('innerclass') is None and compounddef.find('innernamespace') is None:
+        state.current_include = ''
+
+    # Files and dirs don't need it (it's implicit); and it makes no sense for
+    # pages or modules.
     else:
         state.current_include = None
 
@@ -2887,6 +2916,10 @@ def parse_xml(state: State, xml: str):
     # #include (for all others the include info is either on a compound itself
     # or nowhere at all)
     if state.doxyfile['SHOW_INCLUDE_FILES'] and compound.kind in ['namespace', 'group']:
+        # If we're in a namespace, its include info comes from inside
+        if compound.kind == 'namespace' and state.current_include:
+            compound.include = make_include(state, state.current_include)
+
         # If we discovered that entries of this compound don't have a common
         # #include, flip on has_details of all entries and wipe the compound
         # include. Otherwise wipe the include information from everywhere but
index ede92b56b7c78279d93d1007cf9672f5b932dea4..b2bd4f1a9b7395b67116b8e1a35c57116efb4697 100644 (file)
@@ -21,7 +21,6 @@
       <div class="m-col-l-10 m-push-l-1">
         <h1>
           DeprecatedNamespace <span class="m-thin">namespace</span>
-          <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedFile_8h.html">&lt;Dir/DeprecatedFile.h&gt;</a></div>
         </h1>
         <p>A namespace.</p>
         <div class="m-block m-default">
           <section class="m-dox-details" id="ab1e37ddc1d65765f2a48485df4af7b47"><div>
             <h3>
               enum DeprecatedNamespace::<wbr /><a href="#ab1e37ddc1d65765f2a48485df4af7b47" class="m-dox-self">DeprecatedEnum</a>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedFile_8h.html">&lt;Dir/DeprecatedFile.h&gt;</a></div>
             </h3>
             <p>An enum.</p>
 <aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000010" class="m-dox">Deprecated</a></h4><p>This enum is deprecated.</p></aside>
           <section class="m-dox-details" id="ac59010e983270c330b8625b5433961b9"><div>
             <h3>
               enum DeprecatedNamespace::<wbr /><a href="#ac59010e983270c330b8625b5433961b9" class="m-dox-self">Enum</a>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedFile_8h.html">&lt;Dir/DeprecatedFile.h&gt;</a></div>
             </h3>
             <p>An enum.</p>
             <table class="m-table m-fullwidth m-flat m-dox">
           <section class="m-dox-details" id="af503ad3ff194a4c2512aff16df771164"><div>
             <h3>
               typedef int DeprecatedNamespace::<wbr /><a href="#af503ad3ff194a4c2512aff16df771164" class="m-dox-self">DeprecatedTypedef</a>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedFile_8h.html">&lt;Dir/DeprecatedFile.h&gt;</a></div>
             </h3>
             <p>A typedef.</p>
 <aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000009" class="m-dox">Deprecated</a></h4><p>This typedef is deprecated.</p></aside>
               <span class="m-dox-wrap-bumper">void DeprecatedNamespace::<wbr /></span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a9a1b3fc71d294b548095985acc0d5092" class="m-dox-self">deprecatedFoo</a>(</span><span class="m-dox-wrap">int a,
               bool b,
               double c)</span></span>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedFile_8h.html">&lt;Dir/DeprecatedFile.h&gt;</a></div>
             </h3>
             <p>A function.</p>
 <aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000007" class="m-dox">Deprecated</a></h4><p>This function is deprecated.</p></aside>
           <section class="m-dox-details" id="ae934297fc39624409333eefbfeabf5e5"><div>
             <h3>
               int DeprecatedNamespace::<wbr /><a href="#ae934297fc39624409333eefbfeabf5e5" class="m-dox-self">DeprecatedVariable</a> <span class="m-label m-primary">constexpr</span>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="DeprecatedFile_8h.html">&lt;Dir/DeprecatedFile.h&gt;</a></div>
             </h3>
             <p>A variable.</p>
 <aside class="m-note m-danger"><h4><a href="deprecated.html#_deprecated000008" class="m-dox">Deprecated</a></h4><p>This variable is deprecated.</p></aside>
index e43deb106a2779d6c565f8684043620c0a2cdd46..59945264eb3ca4b7784fd8dfb584c2f748381cbe 100644 (file)
@@ -111,3 +111,34 @@ void foo();
 #define A_DEFINE
 
 /*@}*/
+
+/**
+@brief This namespace should not have a global include
+
+Even though it's in a single file --- the contained namespace might or might
+not be in the same file and that could be misleading.
+*/
+namespace ContainsNamespace {
+    /**
+     * @brief This namespace should not have a global include either
+     *
+     * Because it has a class inside.
+     */
+    namespace ContainsClass {
+        /** @brief Union */
+        union Union {};
+
+        /** @brief This function should also have a local include */
+        void foo();
+    }
+
+    /** @brief This function should have a local include */
+    void foo();
+}
+
+/**
+@brief This namespace should have a global include
+
+Even though it has no members that could set the global include for it.
+*/
+namespace Empty {}
diff --git a/doxygen/test/compound_includes/namespaceContainsNamespace.html b/doxygen/test/compound_includes/namespaceContainsNamespace.html
new file mode 100644 (file)
index 0000000..bb0bf41
--- /dev/null
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>ContainsNamespace 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>
+          ContainsNamespace <span class="m-thin">namespace</span>
+        </h1>
+        <p>This namespace should not have a global include.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#namespaces">Namespaces</a></li>
+                <li><a href="#func-members">Functions</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+<p>Even though it&#x27;s in a single file &mdash; the contained namespace might or might not be in the same file and that could be misleading.</p>
+        <section id="namespaces">
+          <h2><a href="#namespaces">Namespaces</a></h2>
+          <dl class="m-dox">
+            <dt>namespace <a href="namespaceContainsNamespace_1_1ContainsClass.html" class="m-dox">ContainsClass</a></dt>
+            <dd>This namespace should not have a global include either.</dd>
+          </dl>
+        </section>
+        <section id="func-members">
+          <h2><a href="#func-members">Functions</a></h2>
+          <dl class="m-dox">
+            <dt>
+              <span class="m-dox-wrap-bumper">void <a href="#a557222af70bdf83d775dc885ef2c5331" class="m-dox">foo</a>(</span><span class="m-dox-wrap">)</span>
+            </dt>
+            <dd>This function should have a local include.</dd>
+          </dl>
+        </section>
+        <section>
+          <h2>Function documentation</h2>
+          <section class="m-dox-details" id="a557222af70bdf83d775dc885ef2c5331"><div>
+            <h3>
+              <span class="m-dox-wrap-bumper">void ContainsNamespace::<wbr /></span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a557222af70bdf83d775dc885ef2c5331" class="m-dox-self">foo</a>(</span><span class="m-dox-wrap">)</span></span>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="First_8h.html">&lt;First.h&gt;</a></div>
+            </h3>
+            <p>This function should have a local include.</p>
+          </div></section>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/doxygen/test/compound_includes/namespaceContainsNamespace_1_1ContainsClass.html b/doxygen/test/compound_includes/namespaceContainsNamespace_1_1ContainsClass.html
new file mode 100644 (file)
index 0000000..4653643
--- /dev/null
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>ContainsNamespace::ContainsClass 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>
+          <span class="m-breadcrumb"><a href="namespaceContainsNamespace.html">ContainsNamespace</a>::<wbr/></span>ContainsClass <span class="m-thin">namespace</span>
+        </h1>
+        <p>This namespace should not have a global include either.</p>
+        <div class="m-block m-default">
+          <h3>Contents</h3>
+          <ul>
+            <li>
+              Reference
+              <ul>
+                <li><a href="#nested-classes">Classes</a></li>
+                <li><a href="#func-members">Functions</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+<p>Because it has a class inside.</p>
+        <section id="nested-classes">
+          <h2><a href="#nested-classes">Classes</a></h2>
+          <dl class="m-dox">
+            <dt>
+              union <a href="unionContainsNamespace_1_1ContainsClass_1_1Union.html" class="m-dox">Union</a>
+            </dt>
+            <dd><a href="unionContainsNamespace_1_1ContainsClass_1_1Union.html" class="m-dox">Union</a>.</dd>
+          </dl>
+        </section>
+        <section id="func-members">
+          <h2><a href="#func-members">Functions</a></h2>
+          <dl class="m-dox">
+            <dt>
+              <span class="m-dox-wrap-bumper">void <a href="#a35d45ad407b8ce350d3e93d78ddb165b" class="m-dox">foo</a>(</span><span class="m-dox-wrap">)</span>
+            </dt>
+            <dd>This function should also have a local include.</dd>
+          </dl>
+        </section>
+        <section>
+          <h2>Function documentation</h2>
+          <section class="m-dox-details" id="a35d45ad407b8ce350d3e93d78ddb165b"><div>
+            <h3>
+              <span class="m-dox-wrap-bumper">void ContainsNamespace::<wbr />ContainsClass::<wbr /></span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a35d45ad407b8ce350d3e93d78ddb165b" class="m-dox-self">foo</a>(</span><span class="m-dox-wrap">)</span></span>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="First_8h.html">&lt;First.h&gt;</a></div>
+            </h3>
+            <p>This function should also have a local include.</p>
+          </div></section>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/doxygen/test/compound_includes/namespaceEmpty.html b/doxygen/test/compound_includes/namespaceEmpty.html
new file mode 100644 (file)
index 0000000..9fca57e
--- /dev/null
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>Empty 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>
+          Empty <span class="m-thin">namespace</span>
+          <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="First_8h.html">&lt;First.h&gt;</a></div>
+        </h1>
+        <p>This namespace should have a global include.</p>
+<p>Even though it has no members that could set the global include for it.</p>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
index 7a3c42c7e875f7e7c5354f5620f5bf26bb93c899..1cb98471d275684b6a7297a47d3cf300b8ee0bee 100644 (file)
@@ -37,7 +37,6 @@
       <div class="m-col-l-10 m-push-l-1">
         <h1>
           <span class="m-breadcrumb"><a href="namespaceRoot.html">Root</a>::<wbr/></span>Directory <span class="m-thin">namespace</span>
-          <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
         </h1>
         <p>Namespace in directory.</p>
         <div class="m-block m-default">
@@ -85,7 +84,7 @@
           <h2><a href="#enum-members">Enums</a></h2>
           <dl class="m-dox">
             <dt>
-              <span class="m-dox-wrap-bumper">enum <a href="#afdcca564079156feb9314ad46e0ec20d" class="m-dox-self" name="afdcca564079156feb9314ad46e0ec20d">Enum</a> { </span><span class="m-dox-wrap"> }</span>
+              <span class="m-dox-wrap-bumper">enum <a href="#afdcca564079156feb9314ad46e0ec20d" class="m-dox">Enum</a> { </span><span class="m-dox-wrap"> }</span>
             </dt>
             <dd>An enum.</dd>
           </dl>
           <h2><a href="#typedef-members">Typedefs</a></h2>
           <dl class="m-dox">
             <dt>
-              using <a href="#ac5f7e56298e7c5f4744da826f519b41c" class="m-dox-self" name="ac5f7e56298e7c5f4744da826f519b41c">Int</a> = int
+              using <a href="#ac5f7e56298e7c5f4744da826f519b41c" class="m-dox">Int</a> = int
             </dt>
             <dd>A typedef.</dd>
             <dt>
-              using <a href="#a61d6355f361b4a422e0dc65fc6ab9703" class="m-dox-self" name="a61d6355f361b4a422e0dc65fc6ab9703">Float</a> = float
+              using <a href="#a61d6355f361b4a422e0dc65fc6ab9703" class="m-dox">Float</a> = float
             </dt>
             <dd>An using declaration.</dd>
           </dl>
           <h2><a href="#func-members">Functions</a></h2>
           <dl class="m-dox">
             <dt>
-              <span class="m-dox-wrap-bumper">void <a href="#a1e483a02e625a420e6b3541677ab4fbd" class="m-dox-self" name="a1e483a02e625a420e6b3541677ab4fbd">foo</a>(</span><span class="m-dox-wrap">)</span>
+              <span class="m-dox-wrap-bumper">void <a href="#a1e483a02e625a420e6b3541677ab4fbd" class="m-dox">foo</a>(</span><span class="m-dox-wrap">)</span>
             </dt>
             <dd>A function.</dd>
           </dl>
           <h2><a href="#var-members">Variables</a></h2>
           <dl class="m-dox">
             <dt>
-              const int <a href="#acdc29819d61c01eed9c74242010a7601" class="m-dox-self" name="acdc29819d61c01eed9c74242010a7601">Var</a> <span class="m-label m-flat m-primary">constexpr</span>
+              const int <a href="#acdc29819d61c01eed9c74242010a7601" class="m-dox">Var</a> <span class="m-label m-flat m-primary">constexpr</span>
             </dt>
             <dd>A variable.</dd>
           </dl>
           <h2><a href="#a-group">A group</a></h2>
           <dl class="m-dox">
             <dt>
-              <span class="m-dox-wrap-bumper">enum <a href="#ad48cec404dd0ac98a7cb35cde9b80ef7" class="m-dox-self" name="ad48cec404dd0ac98a7cb35cde9b80ef7">Flag</a> { </span><span class="m-dox-wrap"> }</span>
+              <span class="m-dox-wrap-bumper">enum <a href="#ad48cec404dd0ac98a7cb35cde9b80ef7" class="m-dox">Flag</a> { </span><span class="m-dox-wrap"> }</span>
             </dt>
             <dd>Flag in a group.</dd>
             <dt>
-              using <a href="#ad647ff34e255fa1b8adea19bfc55d631" class="m-dox-self" name="ad647ff34e255fa1b8adea19bfc55d631">Main</a> = void
+              using <a href="#ad647ff34e255fa1b8adea19bfc55d631" class="m-dox">Main</a> = void
             </dt>
             <dd>Alias in a group.</dd>
             <dt>
-              void* <a href="#ac4c2505beb086a985a4154d00d41de70" class="m-dox-self" name="ac4c2505beb086a985a4154d00d41de70">variable</a> <span class="m-label m-flat m-primary">constexpr</span>
+              void* <a href="#ac4c2505beb086a985a4154d00d41de70" class="m-dox">variable</a> <span class="m-label m-flat m-primary">constexpr</span>
             </dt>
             <dd>Variable in a group.</dd>
             <dt>
-              <span class="m-dox-wrap-bumper">void <a href="#a0daa434b0cb806e7613bcc06ed6baaf6" class="m-dox-self" name="a0daa434b0cb806e7613bcc06ed6baaf6">bar</a>(</span><span class="m-dox-wrap">)</span>
+              <span class="m-dox-wrap-bumper">void <a href="#a0daa434b0cb806e7613bcc06ed6baaf6" class="m-dox">bar</a>(</span><span class="m-dox-wrap">)</span>
             </dt>
             <dd>Function in a group.</dd>
           </dl>
         </section>
+        <section>
+          <h2>Enum documentation</h2>
+          <section class="m-dox-details" id="afdcca564079156feb9314ad46e0ec20d"><div>
+            <h3>
+              enum Root::<wbr />Directory::<wbr /><a href="#afdcca564079156feb9314ad46e0ec20d" class="m-dox-self">Enum</a>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>An enum.</p>
+          </div></section>
+          <section class="m-dox-details" id="ad48cec404dd0ac98a7cb35cde9b80ef7"><div>
+            <h3>
+              enum Root::<wbr />Directory::<wbr /><a href="#ad48cec404dd0ac98a7cb35cde9b80ef7" class="m-dox-self">Flag</a>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>Flag in a group.</p>
+          </div></section>
+        </section>
+        <section>
+          <h2>Typedef documentation</h2>
+          <section class="m-dox-details" id="ac5f7e56298e7c5f4744da826f519b41c"><div>
+            <h3>
+              typedef int Root::<wbr />Directory::<wbr /><a href="#ac5f7e56298e7c5f4744da826f519b41c" class="m-dox-self">Int</a>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>A typedef.</p>
+          </div></section>
+          <section class="m-dox-details" id="a61d6355f361b4a422e0dc65fc6ab9703"><div>
+            <h3>
+              using Root::<wbr />Directory::<wbr /><a href="#a61d6355f361b4a422e0dc65fc6ab9703" class="m-dox-self">Float</a> = float
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>An using declaration.</p>
+          </div></section>
+          <section class="m-dox-details" id="ad647ff34e255fa1b8adea19bfc55d631"><div>
+            <h3>
+              using Root::<wbr />Directory::<wbr /><a href="#ad647ff34e255fa1b8adea19bfc55d631" class="m-dox-self">Main</a> = void
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>Alias in a group.</p>
+          </div></section>
+        </section>
+        <section>
+          <h2>Function documentation</h2>
+          <section class="m-dox-details" id="a1e483a02e625a420e6b3541677ab4fbd"><div>
+            <h3>
+              <span class="m-dox-wrap-bumper">void Root::<wbr />Directory::<wbr /></span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a1e483a02e625a420e6b3541677ab4fbd" class="m-dox-self">foo</a>(</span><span class="m-dox-wrap">)</span></span>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>A function.</p>
+          </div></section>
+          <section class="m-dox-details" id="a0daa434b0cb806e7613bcc06ed6baaf6"><div>
+            <h3>
+              <span class="m-dox-wrap-bumper">void Root::<wbr />Directory::<wbr /></span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a0daa434b0cb806e7613bcc06ed6baaf6" class="m-dox-self">bar</a>(</span><span class="m-dox-wrap">)</span></span>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>Function in a group.</p>
+          </div></section>
+        </section>
+        <section>
+          <h2>Variable documentation</h2>
+          <section class="m-dox-details" id="acdc29819d61c01eed9c74242010a7601"><div>
+            <h3>
+              const int Root::<wbr />Directory::<wbr /><a href="#acdc29819d61c01eed9c74242010a7601" class="m-dox-self">Var</a> <span class="m-label m-primary">constexpr</span>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>A variable.</p>
+          </div></section>
+          <section class="m-dox-details" id="ac4c2505beb086a985a4154d00d41de70"><div>
+            <h3>
+              void* Root::<wbr />Directory::<wbr /><a href="#ac4c2505beb086a985a4154d00d41de70" class="m-dox-self">variable</a> <span class="m-label m-primary">constexpr</span>
+              <div class="m-dox-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="File_8h.html">&lt;Directory/File.h&gt;</a></div>
+            </h3>
+            <p>Variable in a group.</p>
+          </div></section>
+        </section>
       </div>
     </div>
   </div>
index 6597ee3801599a62f1cec5eb619511c70fbe90a1..334ec2d707f213a41f2f0cd571da862df00cdb98 100644 (file)
@@ -261,6 +261,12 @@ class Includes(IntegrationTestCase):
         self.assertEqual(*self.actual_expected_contents('classClass.html'))
         self.assertEqual(*self.actual_expected_contents('group__group.html'))
 
+        # These two should all have local includes because otherwise it gets
+        # misleading; the Empty namespace a global one
+        self.assertEqual(*self.actual_expected_contents('namespaceContainsNamespace.html'))
+        self.assertEqual(*self.actual_expected_contents('namespaceContainsNamespace_1_1ContainsClass.html'))
+        self.assertEqual(*self.actual_expected_contents('namespaceEmpty.html'))
+
 class IncludesDisabled(IntegrationTestCase):
     def __init__(self, *args, **kwargs):
         super().__init__(__file__, 'includes_disabled', *args, **kwargs)