From 3044b35e325928d1c5c78ea1ec5ca912bfca56f0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 24 Feb 2019 20:06:36 +0100 Subject: [PATCH] doxygen: option to show undocumented symbols. Done simply as a preprocessing step by populating the for each symbol that has neither nor with an empty . That's all. --- doc/doxygen.rst | 30 +- doxygen/dox2html5.py | 41 ++- doxygen/test/test_doxyfile.py | 1 + doxygen/test/test_undocumented.py | 60 ++++ doxygen/test/undocumented/Directory/File.h | 119 +++++++ doxygen/test/undocumented/Doxyfile | 18 + doxygen/test/undocumented/File_8h.html | 267 +++++++++++++++ doxygen/test/undocumented/annotated.html | 122 +++++++ doxygen/test/undocumented/classClass.html | 92 +++++ .../dir_4b0d5f8864bf89936129251a2d32609b.html | 109 ++++++ doxygen/test/undocumented/files.html | 111 ++++++ doxygen/test/undocumented/group__group.html | 209 ++++++++++++ .../test/undocumented/namespaceNamespace.html | 319 ++++++++++++++++++ .../structNamespace_1_1ClassInANamespace.html | 144 ++++++++ 14 files changed, 1637 insertions(+), 5 deletions(-) create mode 100644 doxygen/test/test_undocumented.py create mode 100644 doxygen/test/undocumented/Directory/File.h create mode 100644 doxygen/test/undocumented/Doxyfile create mode 100644 doxygen/test/undocumented/File_8h.html create mode 100644 doxygen/test/undocumented/annotated.html create mode 100644 doxygen/test/undocumented/classClass.html create mode 100644 doxygen/test/undocumented/dir_4b0d5f8864bf89936129251a2d32609b.html create mode 100644 doxygen/test/undocumented/files.html create mode 100644 doxygen/test/undocumented/group__group.html create mode 100644 doxygen/test/undocumented/namespaceNamespace.html create mode 100644 doxygen/test/undocumented/structNamespace_1_1ClassInANamespace.html diff --git a/doc/doxygen.rst b/doc/doxygen.rst index 6c4315fe..3c183ce0 100644 --- a/doc/doxygen.rst +++ b/doc/doxygen.rst @@ -183,7 +183,11 @@ If you see something unexpected or not see something expected, check the - Files, directories and symbols that don't have any documentation are not present in the output at all. This is done in order to encourage good documentation practices --- having the output consist of an actual - human-written documentation instead of just autogenerated lists. + human-written documentation instead of just autogenerated lists. If you + *really* want to have them included in the output, you can enable them + using a default-to-off :ini:`M_SHOW_UNDOCUMENTED` option, but there are + some tradeoffs. See `Showing undocumented symbols and files`_ for + more information. - Table of contents is generated for compound references as well, containing all sections of detailed description together with anchors to member listings @@ -399,6 +403,10 @@ Variable Description search is offered. See `Search options`_ for more information. Has effect only if :ini:`M_SEARCH_DISABLED` is not ``YES``. +:ini:`M_SHOW_UNDOCUMENTED` Include undocumented symbols, files and + directories in the output. If not set, + ``NO`` is used. See `Showing undocumented symbols and files`_ + for more information. =================================== =========================================== Note that namespace, directory and page lists are always fully expanded as @@ -570,6 +578,26 @@ the search to a subdomain: M_SEARCH_EXTERNAL_URL = "https://google.com/search?q=site:doc.magnum.graphics+{query}" +`Showing undocumented symbols and files`_ +----------------------------------------- + +As noted in `Features`_, the main design decision of the m.css Doxygen theme is +to reduce the amount of useless output. A plain list of undocumented APIs also +counts as useless output, so by default everything that's not documented is not +shown. + +In some cases, however, it might be desirable to show undocumented symbols as +well --- for example when converting an existing project from vanilla Doxygen +to m.css, not all APIs might be documented yet and thus the output would be +incomplete. The :ini:`M_SHOW_UNDOCUMENTED` option unconditionally makes all +undocumented symbols, files and directories "appear documented". Note, however, +that Doxygen itself doesn't allow to link to undocumented symbols and so even +though the undocumented symbols are present in the output, nothing is able to +reference them, causing very questionable usability of such approach. A +potential "fix" to this is enabling the :ini:`EXTRACT_ALL` option, but that +exposes all symbols, including private and file-local ones --- which, most +probably, is *not* what you want. + `Content`_ ========== diff --git a/doxygen/dox2html5.py b/doxygen/dox2html5.py index 6b917497..0585fa9e 100755 --- a/doxygen/dox2html5.py +++ b/doxygen/dox2html5.py @@ -1505,9 +1505,16 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET. ' class="{}"'.format(add_inline_css_class) if add_inline_css_class else '', add_wbr(parse_inline_desc(state, i).strip())) - # with custom CSS classes + # with custom CSS classes. This is (ab)used by the + # M_SHOW_UNDOCUMENTED option to make things appear to be documented + # in _document_all_stuff(). In that case the class attribute is not + # present. elif i.tag == '{http://mcss.mosra.cz/doxygen/}span': - out.parsed += '{}'.format(i.attrib['{http://mcss.mosra.cz/doxygen/}class'], parse_inline_desc(state, i).strip()) + content = parse_inline_desc(state, i).strip() + if '{http://mcss.mosra.cz/doxygen/}class' in i.attrib: + out.parsed += '{}'.format(i.attrib['{http://mcss.mosra.cz/doxygen/}class'], content) + else: + out.parsed += '{}'.format(content) # WHAT THE HELL WHY IS THIS NOT AN XML ENTITY elif i.tag in ['mdash', 'ndash', 'laquo', 'raquo']: @@ -2057,6 +2064,20 @@ def parse_define(state: State, element: ET.Element): return define return None +# Used for the M_SHOW_UNDOCUMENTED option +def _document_all_stuff(compounddef: ET.Element): + for i in compounddef.findall('.//briefdescription/..'): + brief = i.find('briefdescription') + if not brief and not i.find('detaileddescription'): + # Add an empty to the paragraph so it doesn't look empty. + # Can't use strong/emphasis, as those are collapsed if empty as + # well; on the other hand it's very unlikely that someone would + # want to use @m_span with empty contents. + dim = ET.Element('{http://mcss.mosra.cz/doxygen/}span') + para = ET.Element('para') + para.append(dim) + brief.append(para) + def extract_metadata(state: State, xml): logging.debug("Extracting metadata from {}".format(os.path.basename(xml))) @@ -2085,6 +2106,11 @@ def extract_metadata(state: State, xml): logging.debug("No useful info in {}, skipping".format(os.path.basename(xml))) return + # In order to show also undocumented members, go through all empty + # s and fill them with a generic text. + if state.doxyfile['M_SHOW_UNDOCUMENTED']: + _document_all_stuff(compounddef) + compound = StateCompound() compound.id = compounddef.attrib['id'] compound.kind = compounddef.attrib['kind'] @@ -2392,6 +2418,11 @@ def parse_xml(state: State, xml: str): logging.debug("{}: only private things, skipping".format(state.current)) return None + # In order to show also undocumented members, go through all empty + # s and fill them with a generic text. + if state.doxyfile['M_SHOW_UNDOCUMENTED']: + _document_all_stuff(compounddef) + # Ignoring compounds w/o any description, except for pages and groups, # which are created explicitly if not compounddef.find('briefdescription') and not compounddef.find('detaileddescription') and not compounddef.attrib['kind'] in ['page', 'group']: @@ -3291,7 +3322,8 @@ copy a link to the result using ⌘ M produces a Markdown link.

"""], 'M_SEARCH_BASE_URL': [''], - 'M_SEARCH_EXTERNAL_URL': [''] + 'M_SEARCH_EXTERNAL_URL': [''], + 'M_SHOW_UNDOCUMENTED': ['NO'] } # Defaults so we don't fail with minimal Doxyfiles and also that the @@ -3409,7 +3441,8 @@ copy a link to the result using ⌘ 'SHOW_INCLUDE_FILES', 'M_EXPAND_INNER_TYPES', 'M_SEARCH_DISABLED', - 'M_SEARCH_DOWNLOAD_BINARY']: + 'M_SEARCH_DOWNLOAD_BINARY', + 'M_SHOW_UNDOCUMENTED']: if i in config: state.doxyfile[i] = ' '.join(config[i]) == 'YES' # List values that we want. Drop empty lines. diff --git a/doxygen/test/test_doxyfile.py b/doxygen/test/test_doxyfile.py index eccf17d6..eeae2b29 100644 --- a/doxygen/test/test_doxyfile.py +++ b/doxygen/test/test_doxyfile.py @@ -73,6 +73,7 @@ copy a link to the result using ⌘ L while ⌘ M produces a Markdown link.

""", + 'M_SHOW_UNDOCUMENTED': False, 'M_THEME_COLOR': '#22272e', 'OUTPUT_DIRECTORY': '', 'PROJECT_BRIEF': 'is cool', diff --git a/doxygen/test/test_undocumented.py b/doxygen/test/test_undocumented.py new file mode 100644 index 00000000..01c6b4fe --- /dev/null +++ b/doxygen/test/test_undocumented.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +# +# This file is part of m.css. +# +# Copyright © 2017, 2018, 2019 Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +import os + +from dox2html5 import search_data_header_struct + +from . import IntegrationTestCase + +class Test(IntegrationTestCase): + def __init__(self, *args, **kwargs): + super().__init__(__file__, '', *args, **kwargs) + + def test(self): + self.run_dox2html5(wildcard='*.xml') + + # The index pages should be full + self.assertEqual(*self.actual_expected_contents('annotated.html')) + self.assertEqual(*self.actual_expected_contents('files.html')) + + # The empty class pages should be present + self.assertEqual(*self.actual_expected_contents('classClass.html')) + + # Namespace, dir, file, group and class member listing + self.assertEqual(*self.actual_expected_contents('namespaceNamespace.html')) + self.assertEqual(*self.actual_expected_contents('dir_4b0d5f8864bf89936129251a2d32609b.html')) + self.assertEqual(*self.actual_expected_contents('File_8h.html')) + self.assertEqual(*self.actual_expected_contents('group__group.html')) + self.assertEqual(*self.actual_expected_contents('structNamespace_1_1ClassInANamespace.html')) + + # Test we have all symbols in search data. It's enough to assert the + # count, it equal to symbol count in the header file + # TODO: reuse the search data deserialization API once done + with open(os.path.join(self.path, 'html', 'searchdata.bin'), 'rb') as f: + serialized = f.read() + magic, version, symbol_count, map_offset = search_data_header_struct.unpack_from(serialized) + self.assertEqual(symbol_count, 38) diff --git a/doxygen/test/undocumented/Directory/File.h b/doxygen/test/undocumented/Directory/File.h new file mode 100644 index 00000000..71622df4 --- /dev/null +++ b/doxygen/test/undocumented/Directory/File.h @@ -0,0 +1,119 @@ +/* An undocumented directory */ + +/* An undocumented file in an undocumented directory */ + +/* An undocumented class in the root namespace */ +class Class {}; + +/* An undocumented structure in the root namespace */ +struct Struct {}; + +/* An undocumented union in the root namespace */ +union Union {}; + +/* An undocumented enum in the root namespace */ +enum Enum {}; + +/* An undocumented typedef in the root namespace */ +typedef int Int; + +/* An undocumented using declaration in the root namespace */ +using Float = float; + +/* An undocumented variable in the root namespace */ +constexpr const int Var = 3; + +/* An undocumented function in the root namespace */ +void foo(); + +/* An undocumented namespace */ +namespace Namespace { + +/* An undocumented class */ +struct ClassInANamespace { + /* An undocumented inner class */ + class ClassInAClass {}; + + /* An undocumented inner enum */ + enum EnumInAClass {}; + + /* An undocumented inner typedef */ + typedef int IntInAClass; + + /* An undocumented inner using declaration */ + using FloatInAClass = float; + + /* An undocumented inner variable */ + constexpr const int VarInAClass = 3; + + /* An undocumented inner function */ + void fooInAClass(); +}; + +/* An undocumented enum */ +enum EnumInANamespace {}; + +/* An undocumented typedef */ +typedef int IntInANamespace; + +/* An undocumented using declaration */ +using FloatInANamespace = float; + +/* An undocumented variable */ +constexpr const int VarInANamespace = 3; + +/* An undocumented function */ +void fooInANamespace(); + +/** @{ @name A group */ /* does *not* contribute to search symbol count */ + +/* An undocumented flag in a group */ +enum FlagInAGroup {}; + +/* An undocumented alias in a group */ +using MainInAGroup = void; + +/* A undocumented function in a group */ +void barInAGroup(); + +/* An undocumented variable in a group */ +constexpr void* variableInAGroup = nullptr; + +/* An undocumented define in a group */ +#define A_DEFINE_IN_A_GROUP + +/*@}*/ + +/** @defgroup group A module +@{ */ + +/* An undocumented class in a module */ +class ClassInModule {}; + +/* An undocumented structure in a module */ +struct StructInModule {}; + +/* An undocumented union in a module */ +union UnionInModule {}; + +/* An undocumented enum in a module */ +enum EnumInModule {}; + +/* An undocumented typedef in a module */ +typedef int IntInModule; + +/* An undocumented using declaration in a module */ +using FloatInModule = float; + +/* An undocumented variable in a module */ +constexpr const int VarInModule = 3; + +/* An undocumented function in a module */ +void fooInModule(); + +/*@}*/ + +}} + +/* An undocumented define */ +#define A_DEFINE diff --git a/doxygen/test/undocumented/Doxyfile b/doxygen/test/undocumented/Doxyfile new file mode 100644 index 00000000..3ef7f712 --- /dev/null +++ b/doxygen/test/undocumented/Doxyfile @@ -0,0 +1,18 @@ +INPUT = Directory +RECURSIVE = YES +QUIET = YES +GENERATE_HTML = NO +GENERATE_LATEX = NO +GENERATE_XML = YES +XML_PROGRAMLISTING = NO + +##! M_PAGE_FINE_PRINT = +##! M_THEME_COLOR = +##! M_FAVICON = + +XML_NS_MEMB_FILE_SCOPE = YES +##! M_LINKS_NAVBAR1 = \ +##! modules \ +##! namespaces +##! M_SEARCH_DOWNLOAD_BINARY = YES +##! M_SHOW_UNDOCUMENTED = YES diff --git a/doxygen/test/undocumented/File_8h.html b/doxygen/test/undocumented/File_8h.html new file mode 100644 index 00000000..c189dc47 --- /dev/null +++ b/doxygen/test/undocumented/File_8h.html @@ -0,0 +1,267 @@ + + + + + Directory/File.h file | My Project + + + + + +
+
+
+
+
+

+ Directory/File.h file +

+

+
+

Contents

+ +
+
+

Namespaces

+
+
namespace Namespace
+
+
+
+
+

Classes

+
+
+ class Class +
+
+
+ struct Struct +
+
+
+ union Union +
+
+
+ struct Namespace::ClassInANamespace +
+
+
+ class Namespace::ClassInANamespace::ClassInAClass +
+
+
+ class Namespace::ClassInModule +
+
+
+ struct Namespace::StructInModule +
+
+
+ union Namespace::UnionInModule +
+
+
+
+
+

Enums

+
+
+ enum Enum { } +
+
+
+ enum EnumInANamespace { } +
+
+
+ enum EnumInModule { } +
+
+
+
+
+

Typedefs

+
+
+ using Int = int +
+
+
+ using Float = float +
+
+
+ using IntInANamespace = int +
+
+
+ using FloatInANamespace = float +
+
+
+ using IntInModule = int +
+
+
+ using FloatInModule = float +
+
+
+
+
+

Functions

+
+
+ void foo() +
+
+
+ void fooInANamespace() +
+
+
+ void fooInModule() +
+
+
+
+
+

Variables

+
+
+ const int Var constexpr +
+
+
+ const int VarInANamespace constexpr +
+
+
+ const int VarInModule constexpr +
+
+
+
+
+

Defines

+
+
+ #define A_DEFINE +
+
+
+
+
+

A group

+
+
+ #define A_DEFINE_IN_A_GROUP +
+
+
+ enum FlagInAGroup { } +
+
+
+ using MainInAGroup = void +
+
+
+ void* variableInAGroup constexpr +
+
+
+ void barInAGroup() +
+
+
+
+
+
+
+
+ + + + + diff --git a/doxygen/test/undocumented/annotated.html b/doxygen/test/undocumented/annotated.html new file mode 100644 index 00000000..2ed7c582 --- /dev/null +++ b/doxygen/test/undocumented/annotated.html @@ -0,0 +1,122 @@ + + + + + My Project + + + + + +
+
+
+
+
+

Classes

+ + +
+
+
+
+ + + + + diff --git a/doxygen/test/undocumented/classClass.html b/doxygen/test/undocumented/classClass.html new file mode 100644 index 00000000..e2ce0751 --- /dev/null +++ b/doxygen/test/undocumented/classClass.html @@ -0,0 +1,92 @@ + + + + + Class class | My Project + + + + + +
+
+ + + + + diff --git a/doxygen/test/undocumented/dir_4b0d5f8864bf89936129251a2d32609b.html b/doxygen/test/undocumented/dir_4b0d5f8864bf89936129251a2d32609b.html new file mode 100644 index 00000000..efdd6122 --- /dev/null +++ b/doxygen/test/undocumented/dir_4b0d5f8864bf89936129251a2d32609b.html @@ -0,0 +1,109 @@ + + + + + Directory/ directory | My Project + + + + + +
+
+
+
+
+

+ Directory/ directory +

+

+
+

Contents

+
    +
  • + Reference + +
  • +
+
+
+

Files

+
+
file File.h
+
+
+
+
+
+
+
+ + + + + diff --git a/doxygen/test/undocumented/files.html b/doxygen/test/undocumented/files.html new file mode 100644 index 00000000..9ed47f35 --- /dev/null +++ b/doxygen/test/undocumented/files.html @@ -0,0 +1,111 @@ + + + + + My Project + + + + + +
+
+
+
+
+

Files

+ + +
+
+
+
+ + + + + diff --git a/doxygen/test/undocumented/group__group.html b/doxygen/test/undocumented/group__group.html new file mode 100644 index 00000000..4fe2c1b8 --- /dev/null +++ b/doxygen/test/undocumented/group__group.html @@ -0,0 +1,209 @@ + + + + + A module module | My Project + + + + + +
+
+
+
+
+

+ A module module

+

+
+

Contents

+ +
+
+

Classes

+
+
+ class Namespace::ClassInModule +
+
+
+ struct Namespace::StructInModule +
+
+
+ union Namespace::UnionInModule +
+
+
+
+
+

Enums

+
+
+ enum EnumInModule { } +
+
+
+
+
+

Typedefs

+
+
+ using IntInModule = int +
+
+
+ using FloatInModule = float +
+
+
+
+
+

Functions

+
+
+ void fooInModule() +
+
+
+
+
+

Variables

+
+
+ const int VarInModule constexpr +
+
+
+
+
+

Enum documentation

+
+

+ enum EnumInModule + +

+

+
+
+
+

Typedef documentation

+
+

+ typedef int IntInModule + +

+

+
+
+

+ using FloatInModule = float + +

+

+
+
+
+

Function documentation

+
+

+ void fooInModule() + +

+

+
+
+
+

Variable documentation

+
+

+ const int VarInModule constexpr + +

+

+
+
+
+
+
+
+ + + + + diff --git a/doxygen/test/undocumented/namespaceNamespace.html b/doxygen/test/undocumented/namespaceNamespace.html new file mode 100644 index 00000000..7d9b828b --- /dev/null +++ b/doxygen/test/undocumented/namespaceNamespace.html @@ -0,0 +1,319 @@ + + + + + Namespace namespace | My Project + + + + + +
+
+
+
+
+

+ Namespace namespace +

+

+
+

Contents

+ +
+
+

Classes

+
+
+ struct ClassInANamespace +
+
+
+ class ClassInModule +
+
+
+ struct StructInModule +
+
+
+ union UnionInModule +
+
+
+
+
+

Enums

+
+
+ enum EnumInANamespace { } +
+
+
+ enum EnumInModule { } +
+
+
+
+
+

Typedefs

+
+
+ using IntInANamespace = int +
+
+
+ using FloatInANamespace = float +
+
+
+ using IntInModule = int +
+
+
+ using FloatInModule = float +
+
+
+
+
+

Functions

+
+
+ void fooInANamespace() +
+
+
+ void fooInModule() +
+
+
+
+
+

Variables

+
+
+ const int VarInANamespace constexpr +
+
+
+ const int VarInModule constexpr +
+
+
+
+
+

A group

+
+
+ enum FlagInAGroup { } +
+
+
+ using MainInAGroup = void +
+
+
+ void* variableInAGroup constexpr +
+
+
+ void barInAGroup() +
+
+
+
+
+

Enum documentation

+
+

+ enum Namespace::EnumInANamespace + +

+

+
+
+

+ enum Namespace::EnumInModule + +

+

+
+
+

+ enum Namespace::FlagInAGroup + +

+

+
+
+
+

Typedef documentation

+
+

+ typedef int Namespace::IntInANamespace + +

+

+
+
+

+ using Namespace::FloatInANamespace = float + +

+

+
+
+

+ typedef int Namespace::IntInModule + +

+

+
+
+

+ using Namespace::FloatInModule = float + +

+

+
+
+

+ using Namespace::MainInAGroup = void + +

+

+
+
+
+

Function documentation

+
+

+ void Namespace::fooInANamespace() + +

+

+
+
+

+ void Namespace::fooInModule() + +

+

+
+
+

+ void Namespace::barInAGroup() + +

+

+
+
+
+

Variable documentation

+
+

+ const int Namespace::VarInANamespace constexpr + +

+

+
+
+

+ const int Namespace::VarInModule constexpr + +

+

+
+
+

+ void* Namespace::variableInAGroup constexpr + +

+

+
+
+
+
+
+
+ + + + + diff --git a/doxygen/test/undocumented/structNamespace_1_1ClassInANamespace.html b/doxygen/test/undocumented/structNamespace_1_1ClassInANamespace.html new file mode 100644 index 00000000..1a71c906 --- /dev/null +++ b/doxygen/test/undocumented/structNamespace_1_1ClassInANamespace.html @@ -0,0 +1,144 @@ + + + + + Namespace::ClassInANamespace struct | My Project + + + + + +
+
+ + + + + -- 2.30.2