From: Vladimír Vondruš Date: Sat, 12 Jan 2019 16:11:14 +0000 (+0100) Subject: doxygen: properly shown includes for relateds in different files. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~cjwatson/git?a=commitdiff_plain;h=f6f75dbc6d5e55ef9ce37b71a4a9c9e32b9cf28c;p=blog.git doxygen: properly shown includes for relateds in different files. --- diff --git a/doc/doxygen.rst b/doc/doxygen.rst index 68ed0089..08a896e7 100644 --- a/doc/doxygen.rst +++ b/doc/doxygen.rst @@ -211,9 +211,8 @@ If you see something unexpected or not see something expected, check the - Deprecation markers are propagated to member and compound listing pages and search results; :cpp:`delete`\ d functions are marked in search as well - Information about which file to :cpp:`#include` for given symbol is - provided also for free functions, enums, typedefs and variables (or - namespaces, in case all contents of the namespace are in a single file). - See `Include files`_ for more information. + provided also for namespaces, free and related functions, enums, typedefs + and variables. See `Include files`_ for more information. `Intentionally unsupported features`_ ------------------------------------- @@ -721,6 +720,9 @@ typedefs, variables and :cpp:`#define`\ s. The rules are: - Files don't show any include information, as it is known implicitly - In case of modules (grouped using ``@defgroup``), the :cpp:`#include` info is always shown locally for each member. This includes also :cpp:`#define`\ s. +- In case of enums, typedefs, variables, functions and defines ``@related`` + to some class, these also have the :cpp:`#include` shown in case it's + different from the class :cpp:`include`. This feature is enabled by default, disable :ini:`SHOW_INCLUDE_FILES` to hide all :cpp:`#include`-related information: diff --git a/doxygen/dox2html5.py b/doxygen/dox2html5.py index 733c212e..2084b14c 100755 --- a/doxygen/dox2html5.py +++ b/doxygen/dox2html5.py @@ -466,7 +466,7 @@ def make_include(state: State, file) -> Tuple[str, str]: 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]]: +def parse_id_and_include(state: State, element: ET.Element) -> Tuple[str, str, str, Tuple[str, str], bool]: # 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 # actual ID @@ -476,6 +476,7 @@ def parse_id_and_include(state: State, element: ET.Element) -> Tuple[str, str, s # Extract the corresponding include, if the current compound is a namespace # or a module include = None + has_details = False if state.current_kind in ['namespace', 'group']: location_attribs = element.find('location').attrib file = location_attribs['declfile'] if 'declfile' in location_attribs else location_attribs['file'] @@ -498,7 +499,18 @@ def parse_id_and_include(state: State, element: ET.Element) -> Tuple[str, str, s elif state.current_include and state.current_include != file: state.current_include = None - return id[:i], id[:i] + '.html', id[i+2:], include + # Extract corresponding include also for class/struct/union "relateds", if + # it's different from what the class has. This also forcibly enables + # has_details (unlike the case above, where has_details will be enabled + # only if all members don't have the same include) + if state.current_kind in ['class', 'struct', 'union']: + location_attribs = element.find('location').attrib + file = location_attribs['declfile'] if 'declfile' in location_attribs else location_attribs['file'] + if state.current_include != file: + include = make_include(state, file) + has_details = True + + return id[:i], id[:i] + '.html', id[i+2:], include, has_details def extract_id_hash(state: State, element: ET.Element) -> str: # Can't use parse_id() here as sections with _1 in it have it verbatim @@ -1667,7 +1679,7 @@ def parse_enum(state: State, element: ET.Element): assert element.tag == 'memberdef' and element.attrib['kind'] == 'enum' enum = Empty() - state.current_definition_url_base, enum.base_url, enum.id, enum.include = parse_id_and_include(state, element) + state.current_definition_url_base, enum.base_url, enum.id, enum.include, enum.has_details = parse_id_and_include(state, element) enum.type = parse_type(state, element.find('type')) enum.name = element.find('name').text if enum.name.startswith('@'): enum.name = '(anonymous)' @@ -1705,7 +1717,8 @@ def parse_enum(state: State, element: ET.Element): state.search += [result] enum.values += [value] - enum.has_details = enum.base_url == state.current_compound_url and (enum.description or enum.has_value_details) + if enum.base_url == state.current_compound_url and (enum.description or enum.has_value_details): + enum.has_details = True # has_details might already be True from above if enum.brief or enum.has_details or enum.has_value_details: if enum.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']: result = Empty() @@ -1769,7 +1782,7 @@ def parse_typedef(state: State, element: ET.Element): assert element.tag == 'memberdef' and element.attrib['kind'] == 'typedef' typedef = Empty() - state.current_definition_url_base, typedef.base_url, typedef.id, typedef.include = parse_id_and_include(state, element) + state.current_definition_url_base, typedef.base_url, typedef.id, typedef.include, typedef.has_details = parse_id_and_include(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')) @@ -1779,7 +1792,8 @@ def parse_typedef(state: State, element: ET.Element): 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.base_url == state.current_compound_url and (typedef.description or typedef.has_template_details) + if typedef.base_url == state.current_compound_url and (typedef.description or typedef.has_template_details): + typedef.has_details = True # has_details might already be True from above if typedef.brief or typedef.has_details: # Avoid duplicates in search if typedef.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']: @@ -1797,7 +1811,7 @@ def parse_func(state: State, element: ET.Element): assert element.tag == 'memberdef' and element.attrib['kind'] in ['function', 'friend', 'signal', 'slot'] func = Empty() - state.current_definition_url_base, func.base_url, func.id, func.include = parse_id_and_include(state, element) + state.current_definition_url_base, func.base_url, func.id, func.include, func.has_details = parse_id_and_include(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')) @@ -1915,7 +1929,8 @@ def parse_func(state: State, element: ET.Element): # 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.base_url == state.current_compound_url and (func.description or func.has_template_details or func.has_param_details or func.return_value or func.return_values or func.exceptions) + if func.base_url == state.current_compound_url and (func.description or func.has_template_details or func.has_param_details or func.return_value or func.return_values or func.exceptions): + func.has_details = True # has_details might already be True from above if func.brief or func.has_details: # Avoid duplicates in search if func.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']: @@ -1935,7 +1950,7 @@ def parse_var(state: State, element: ET.Element): assert element.tag == 'memberdef' and element.attrib['kind'] == 'variable' var = Empty() - state.current_definition_url_base, var.base_url, var.id, var.include = parse_id_and_include(state, element) + state.current_definition_url_base, var.base_url, var.id, var.include, var.has_details = parse_id_and_include(state, element) var.type = parse_type(state, element.find('type')) if var.type.startswith('constexpr'): var.type = var.type[10:] @@ -1950,7 +1965,8 @@ def parse_var(state: State, element: ET.Element): var.description, templates, search_keywords, var.is_deprecated = parse_var_desc(state, element) var.has_template_details, var.templates = parse_template_params(state, element.find('templateparamlist'), templates) - var.has_details = var.base_url == state.current_compound_url and (var.description or var.has_template_details) + if var.base_url == state.current_compound_url and (var.description or var.has_template_details): + var.has_details = True # has_details might already be True from above if var.brief or var.has_details: # Avoid duplicates in search if var.base_url == state.current_compound_url and not state.doxyfile['M_SEARCH_DISABLED']: @@ -1972,7 +1988,7 @@ def parse_define(state: State, element: ET.Element): # so we don't need to have define.base_url. Can't use extract_id_hash() # here because current_definition_url_base might be stale. See a test in # compound_namespace_members_in_file_scope_define_base_url. - state.current_definition_url_base, _, define.id, define.include = parse_id_and_include(state, element) + state.current_definition_url_base, _, define.id, define.include, define.has_details = parse_id_and_include(state, element) define.name = element.find('name').text define.brief = parse_desc(state, element.find('briefdescription')) define.description, params, define.return_value, search_keywords, define.is_deprecated = parse_define_desc(state, element) @@ -1993,7 +2009,8 @@ def parse_define(state: State, element: ET.Element): # Some param description got unused if params: logging.warning("{}: define parameter description doesn't match parameter names: {}".format(state.current, repr(params))) - define.has_details = define.description or define.return_value + if define.description or define.return_value: + define.has_details = True # has_details might already be True from above if define.brief or define.has_details: if not state.doxyfile['M_SEARCH_DISABLED']: result = Empty() diff --git a/doxygen/test/compound_includes/Second.h b/doxygen/test/compound_includes/Second.h index 5f366406..c833d45f 100644 --- a/doxygen/test/compound_includes/Second.h +++ b/doxygen/test/compound_includes/Second.h @@ -18,4 +18,29 @@ enum Flag {}; /*@}*/ +/** @related Class + * @brief A related enum in a different file. Shouldn't be shown in namespace docs but it is :( + */ +enum RelatedEnum {}; + +/** @related Class + * @brief A related typedef in a different file + */ +typedef int RelatedInt; + +/** @related Class + * @brief A related variable in a different file + */ +constexpr const int RelatedVar = 3; + +/** @related Class + * @brief A related function in a different file + */ +void relatedFunc(); + +/** @related Class + * @brief A related define in a different file + */ +#define RELATED_DEFINE + } diff --git a/doxygen/test/compound_includes/classClass.html b/doxygen/test/compound_includes/classClass.html index 6df71c72..16de8ae1 100644 --- a/doxygen/test/compound_includes/classClass.html +++ b/doxygen/test/compound_includes/classClass.html @@ -31,6 +31,7 @@ Reference @@ -45,6 +46,81 @@
No include information for this one (and thus no details)
+ +
+

Enum documentation

+
+

+ enum RelatedEnum +
#include <Second.h>
+

+

A related enum in a different file. Shouldn't be shown in namespace docs but it is :(.

+
+
+
+

Typedef documentation

+
+

+ typedef int RelatedInt +
#include <Second.h>
+

+

A related typedef in a different file.

+
+
+
+

Function documentation

+
+

+ void relatedFunc() +
#include <Second.h>
+

+

A related function in a different file.

+
+
+
+

Variable documentation

+
+

+ const int RelatedVar constexpr +
#include <Second.h>
+

+

A related variable in a different file.

+
+
+
+

Define documentation

+
+

+ #define RELATED_DEFINE +
#include <Second.h>
+

+

A related define in a different file.

+
+
diff --git a/doxygen/test/compound_includes/namespaceSpread.html b/doxygen/test/compound_includes/namespaceSpread.html index 9952561a..5ff098c5 100644 --- a/doxygen/test/compound_includes/namespaceSpread.html +++ b/doxygen/test/compound_includes/namespaceSpread.html @@ -46,6 +46,10 @@ enum Enum { }
An enum.
+
+ enum RelatedEnum { } +
+
A related enum in a different file. Shouldn't be shown in namespace docs but it is :(.
@@ -105,6 +109,13 @@

An enum.

+
+

+ enum Spread::RelatedEnum +
#include <Second.h>
+

+

A related enum in a different file. Shouldn't be shown in namespace docs but it is :(.

+

enum Spread::Flag diff --git a/doxygen/test/compound_includes_disabled/classClass.html b/doxygen/test/compound_includes_disabled/classClass.html index ff36bbb6..9c1c9374 100644 --- a/doxygen/test/compound_includes_disabled/classClass.html +++ b/doxygen/test/compound_includes_disabled/classClass.html @@ -30,6 +30,7 @@ Reference @@ -44,6 +45,76 @@
No include information for this one (and thus no details)

+ +
+

Enum documentation

+
+

+ enum RelatedEnum +

+

A related enum in a different file. Shouldn't be shown in namespace docs but it is :(.

+
+
+
+

Typedef documentation

+
+

+ typedef int RelatedInt +

+

A related typedef in a different file.

+
+
+
+

Function documentation

+
+

+ void relatedFunc() +

+

A related function in a different file.

+
+
+
+

Variable documentation

+
+

+ const int RelatedVar constexpr +

+

A related variable in a different file.

+
+
+
+

Define documentation

+
+

+ #define RELATED_DEFINE +

+

A related define in a different file.

+
+
diff --git a/doxygen/test/compound_includes_disabled/namespaceSpread.html b/doxygen/test/compound_includes_disabled/namespaceSpread.html index 52016621..4099b5fa 100644 --- a/doxygen/test/compound_includes_disabled/namespaceSpread.html +++ b/doxygen/test/compound_includes_disabled/namespaceSpread.html @@ -46,6 +46,10 @@ enum Enum { }
An enum.
+
+ enum RelatedEnum { } +
+
A related enum in a different file. Shouldn't be shown in namespace docs but it is :(.
diff --git a/doxygen/test/compound_includes_undocumented_files/Second.h b/doxygen/test/compound_includes_undocumented_files/Second.h index 58738cdb..3b541538 100644 --- a/doxygen/test/compound_includes_undocumented_files/Second.h +++ b/doxygen/test/compound_includes_undocumented_files/Second.h @@ -17,4 +17,29 @@ enum Flag {}; /*@}*/ +/** @related Class + * @brief A related enum in a different file. Shouldn't be shown in namespace docs but it is :( + */ +enum RelatedEnum {}; + +/** @related Class + * @brief A related typedef in a different file + */ +typedef int RelatedInt; + +/** @related Class + * @brief A related variable in a different file + */ +constexpr const int RelatedVar = 3; + +/** @related Class + * @brief A related function in a different file + */ +void relatedFunc(); + +/** @related Class + * @brief A related define in a different file + */ +#define RELATED_DEFINE + }