chiark / gitweb /
doxygen: list base and derived classes.
authorVladimír Vondruš <mosra@centrum.cz>
Thu, 18 Jan 2018 13:14:29 +0000 (14:14 +0100)
committerVladimír Vondruš <mosra@centrum.cz>
Thu, 18 Jan 2018 14:02:25 +0000 (15:02 +0100)
doxygen/dox2html5.py
doxygen/templates/base-class-reference.html
doxygen/templates/entry-class.html
doxygen/test/cpp_derived/Doxyfile [new file with mode: 0644]
doxygen/test/cpp_derived/classA.html [new file with mode: 0644]
doxygen/test/cpp_derived/classPrivateBase.html [new file with mode: 0644]
doxygen/test/cpp_derived/classProtectedBase.html [new file with mode: 0644]
doxygen/test/cpp_derived/classVirtualBase.html [new file with mode: 0644]
doxygen/test/cpp_derived/input.h [new file with mode: 0644]
doxygen/test/test_cpp.py

index 7fce3351f099f7305e563cb768e0928acf3d07f7..c65ba3cdc6b22ece4076811b25f2253a199ac376 100755 (executable)
@@ -1298,6 +1298,8 @@ def parse_xml(state: State, xml: str):
     compound.files = []
     compound.namespaces = []
     compound.classes = []
+    compound.base_classes = []
+    compound.derived_classes = []
     compound.enums = []
     compound.typedefs = []
     compound.funcs = []
@@ -1435,6 +1437,48 @@ def parse_xml(state: State, xml: str):
                         assert compound.kind in ['namespace', 'file']
                         compound.classes += [class_]
 
+        # Base class (if it links to anywhere)
+        elif compounddef_child.tag == 'basecompoundref':
+            assert compound.kind in ['class', 'struct', 'union']
+
+            if 'refid' in compounddef_child.attrib:
+                id = compounddef_child.attrib['refid']
+
+                # Add it only if it's not private and we have documentation for it
+                if not compounddef_child.attrib['prot'] == 'private' and id in state.compounds and state.compounds[id].has_details:
+                    symbol = state.compounds[id]
+
+                    class_ = Empty()
+                    class_.kind = symbol.kind
+                    class_.url = symbol.url
+                    class_.name = symbol.leaf_name
+                    class_.brief = symbol.brief
+                    class_.templates = symbol.templates
+                    class_.is_protected = compounddef_child.attrib['prot'] == 'protected'
+                    class_.is_virtual = compounddef_child.attrib['virt'] == 'virtual'
+
+                    compound.base_classes += [class_]
+
+        # Derived class (if it links to anywhere)
+        elif compounddef_child.tag == 'derivedcompoundref':
+            assert compound.kind in ['class', 'struct', 'union']
+
+            if 'refid' in compounddef_child.attrib:
+                id = compounddef_child.attrib['refid']
+
+                # Add it only if it's not private and we have documentation for it
+                if not compounddef_child.attrib['prot'] == 'private' and id in state.compounds and state.compounds[id].has_details:
+                    symbol = state.compounds[id]
+
+                    class_ = Empty()
+                    class_.kind = symbol.kind
+                    class_.url = symbol.url
+                    class_.name = symbol.leaf_name
+                    class_.brief = symbol.brief
+                    class_.templates = symbol.templates
+
+                    compound.derived_classes += [class_]
+
         # Other, grouped in sections
         elif compounddef_child.tag == 'sectiondef':
             if compounddef_child.attrib['kind'] == 'enum':
index 48d592478d86ea7cc6c39da769582d27071ca475..3174bda2ae06419163945f4a9479fca6fcf050e8 100644 (file)
             <li>
               Reference
               <ul>
+                {% if compound.base_classes %}
+                <li><a href="#base-classes">Base classes</a></li>
+                {% endif %}
+                {% if compound.derived_classes %}
+                <li><a href="#derived-classes">Derived classes</a></li>
+                {% endif %}
                 {% if compound.public_types %}
                 <li><a href="#pub-types">Public types</a></li>
                 {% endif %}
         {% endif %}
         {% if compound.description %}
 {{ compound.description }}
+        {% endif %}
+        {% if compound.base_classes %}
+        <section id="base-classes">
+          <h2><a href="#base-classes">Base classes</a></h3>
+          <dl class="m-dox">
+            {% for class in compound.base_classes %}
+{{ entry_class(class) }}
+            {% endfor %}
+          </dl>
+        </section>
+        {% endif %}
+        {% if compound.derived_classes %}
+        <section id="derived-classes">
+          <h2><a href="#derived-classes">Derived classes</a></h3>
+          <dl class="m-dox">
+            {% for class in compound.derived_classes %}
+{{ entry_class(class) }}
+            {% endfor %}
+          </dl>
+        </section>
         {% endif %}
         {% if compound.public_types %}
         <section id="pub-types">
index 5ce0b748884b8904983d549a8e6130aaa1ae3b52..bd7d1c9925a0f9511e1477faacb296eb2bbdc63d 100644 (file)
@@ -3,6 +3,8 @@
               {% set j = joiner(', ') %}
               <div class="m-dox-template">template&lt;{% for t in class.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif %}{% endfor %}&gt;</div>
               {% endif %}
-              {{ class.kind }} <a href="{{ class.url }}" class="m-dox">{{ class.name }}</a>
+              {{ class.kind }} <a href="{{ class.url }}" class="m-dox">{{ class.name }}</a>{% if class.is_protected %} <span class="m-label m-flat m-warning">protected</span>{% endif %}{% if class.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}
+
+              {# the empty line is above to fix spacing #}
             </dt>
             <dd>{{ class.brief }}</dd>
diff --git a/doxygen/test/cpp_derived/Doxyfile b/doxygen/test/cpp_derived/Doxyfile
new file mode 100644 (file)
index 0000000..03f063f
--- /dev/null
@@ -0,0 +1,11 @@
+INPUT                   = input.h
+AUTOLINK_SUPPORT        = NO
+QUIET                   = YES
+GENERATE_HTML           = NO
+GENERATE_LATEX          = NO
+GENERATE_XML            = YES
+
+M_PAGE_FINE_PRINT       =
+M_THEME_COLOR           =
+M_LINKS_NAVBAR1         =
+M_LINKS_NAVBAR2         =
diff --git a/doxygen/test/cpp_derived/classA.html b/doxygen/test/cpp_derived/classA.html
new file mode 100644 (file)
index 0000000..f76c70e
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>A class | 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-9 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>
+          A <span class="m-thin">class</span>
+        </h1>
+        <p>A class.</p>
+<p>Should list one protected base and one virtual base, one derived class.</p>
+        <section id="base-classes">
+          <h2><a href="#base-classes">Base classes</a></h3>
+          <dl class="m-dox">
+            <dt>
+              class <a href="classProtectedBase.html" class="m-dox">ProtectedBase</a> <span class="m-label m-flat m-warning">protected</span>
+            </dt>
+            <dd>Protected base, should list a derived, but w/o any label.</dd>
+            <dt>
+              class <a href="classVirtualBase.html" class="m-dox">VirtualBase</a> <span class="m-label m-flat m-warning">virtual</span>
+            </dt>
+            <dd>Virtual base, should list a derived, but w/o any label.</dd>
+          </dl>
+        </section>
+        <section id="derived-classes">
+          <h2><a href="#derived-classes">Derived classes</a></h3>
+          <dl class="m-dox">
+            <dt>
+              class <a href="classDerived.html" class="m-dox">Derived</a>
+            </dt>
+            <dd>A derived class.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/doxygen/test/cpp_derived/classPrivateBase.html b/doxygen/test/cpp_derived/classPrivateBase.html
new file mode 100644 (file)
index 0000000..9047a52
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>PrivateBase class | 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-9 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>
+          PrivateBase <span class="m-thin">class</span>
+        </h1>
+        <p>Private base class, should not list any derived.</p>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/doxygen/test/cpp_derived/classProtectedBase.html b/doxygen/test/cpp_derived/classProtectedBase.html
new file mode 100644 (file)
index 0000000..9f835be
--- /dev/null
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>ProtectedBase class | 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-9 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>
+          ProtectedBase <span class="m-thin">class</span>
+        </h1>
+        <p>Protected base, should list a derived, but w/o any label.</p>
+        <section id="derived-classes">
+          <h2><a href="#derived-classes">Derived classes</a></h3>
+          <dl class="m-dox">
+            <dt>
+              class <a href="classA.html" class="m-dox">A</a>
+            </dt>
+            <dd>A class.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/doxygen/test/cpp_derived/classVirtualBase.html b/doxygen/test/cpp_derived/classVirtualBase.html
new file mode 100644 (file)
index 0000000..4ee7467
--- /dev/null
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <title>VirtualBase class | 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-9 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>
+          VirtualBase <span class="m-thin">class</span>
+        </h1>
+        <p>Virtual base, should list a derived, but w/o any label.</p>
+        <section id="derived-classes">
+          <h2><a href="#derived-classes">Derived classes</a></h3>
+          <dl class="m-dox">
+            <dt>
+              class <a href="classA.html" class="m-dox">A</a>
+            </dt>
+            <dd>A class.</dd>
+          </dl>
+        </section>
+      </div>
+    </div>
+  </div>
+</article></main>
+</body>
+</html>
diff --git a/doxygen/test/cpp_derived/input.h b/doxygen/test/cpp_derived/input.h
new file mode 100644 (file)
index 0000000..c944839
--- /dev/null
@@ -0,0 +1,22 @@
+/** @brief Private base class, should not list any derived */
+class PrivateBase {};
+
+/** @brief Protected base, should list a derived, but w/o any label */
+class ProtectedBase {};
+
+class UndocumentedBase {};
+
+/** @brief Virtual base, should list a derived, but w/o any label */
+class VirtualBase {};
+
+/**
+@brief A class
+
+Should list one protected base and one virtual base, one derived class.
+*/
+class A: PrivateBase, protected ProtectedBase, public UndocumentedBase, public virtual VirtualBase {};
+
+/** @brief A derived class */
+class Derived: public A {};
+
+struct UndocumentedDerived: A {};
index 92f4e686db9020da1d4377b68303e9b7be2fb392..006a0830cd6884c2618b8071d0d30a3f6826055c 100644 (file)
@@ -48,3 +48,14 @@ class TemplateAlias(IntegrationTestCase):
         self.run_dox2html5(wildcard='*.xml')
         self.assertEqual(*self.actual_expected_contents('File_8h.html'))
         self.assertEqual(*self.actual_expected_contents('structTemplate.html'))
+
+class Derived(IntegrationTestCase):
+    def __init__(self, *args, **kwargs):
+        super().__init__(__file__, 'derived', *args, **kwargs)
+
+    def test(self):
+        self.run_dox2html5(wildcard='*.xml')
+        self.assertEqual(*self.actual_expected_contents('classA.html'))
+        self.assertEqual(*self.actual_expected_contents('classPrivateBase.html'))
+        self.assertEqual(*self.actual_expected_contents('classProtectedBase.html'))
+        self.assertEqual(*self.actual_expected_contents('classVirtualBase.html'))