From: Vladimír Vondruš Date: Thu, 12 Apr 2018 16:14:53 +0000 (+0200) Subject: doxygen: implement support for the \exception keyword. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~cjwatson/git?a=commitdiff_plain;h=188b8a40fb577710166b1d416b540ec7cfc3eff6;p=blog.git doxygen: implement support for the \exception keyword. --- diff --git a/doc/doxygen.rst b/doc/doxygen.rst index 5f3962bc..267dc5be 100644 --- a/doc/doxygen.rst +++ b/doc/doxygen.rst @@ -1311,7 +1311,9 @@ Property Description details. :py:`func.has_param_details` If function parameters have description :py:`func.return_value` Return value description. Can be empty. -:py:`func.return_values` Description of particular empty values. See +:py:`func.return_values` Description of particular return values. See + below for details. +:py:`func.exceptions` Description of particular exception types. See below for details. :py:`func.brief` Brief description. Can be empty. [1]_ :py:`func.description` Detailed description. Can be empty. [2]_ @@ -1365,11 +1367,12 @@ Property Description :py:`'inout'` or :py:`''` if unspecified. =========================== =================================================== -The :py:`func.return_values` is a list of return values and their description -(in contract to :py:`func.return_value`, which is just a single description). -Each item is a tuple of :py:`(value, description)`. Can be empty, it can also -happen that both :py:`func.return_value` and :py:`func.return_values` are -present. +The :py:`func.return_values` property is a list of return values and their +description (in contract to :py:`func.return_value`, which is just a single +description). Each item is a tuple of :py:`(value, description)`. Can be empty, +it can also happen that both :py:`func.return_value` and :py:`func.return_values` +are resent. Similarly, the :py:`func.exceptions` property is a list of +:py:`(type, description)` tuples. `Variable properties`_ `````````````````````` diff --git a/doxygen/dox2html5.py b/doxygen/dox2html5.py index 39aec712..f8edab6f 100755 --- a/doxygen/dox2html5.py +++ b/doxygen/dox2html5.py @@ -450,6 +450,7 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET. out.params = {} out.return_value = None out.return_values = [] + out.exceptions = [] out.add_css_class = None out.footer_navigation = False out.example_navigation = None @@ -508,6 +509,8 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET. out.return_value = parsed.return_value if parsed.return_values: out.return_values += parsed.return_values + if parsed.exceptions: + out.exceptions += parsed.exceptions i: ET.Element for index, i in enumerate(element): @@ -930,6 +933,8 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET. out.params[name.text] = (description, name.attrib['direction'] if 'direction' in name.attrib else '') elif i.attrib['kind'] == 'retval': out.return_values += [(name.text, description)] + elif i.attrib['kind'] == 'exception': + out.exceptions += [(name.text, description)] else: assert i.attrib['kind'] == 'templateparam' out.templates[name.text] = description @@ -1279,7 +1284,7 @@ def parse_desc_keywords(state: State, element: ET.Element) -> str: # Verify that we didn't ignore any important info by accident parsed = parse_desc_internal(state, element) - assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values + assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values and not parsed.exceptions assert not parsed.section # might be problematic return parsed.parsed, parsed.search_keywords, parsed.search_enum_values_as_keywords @@ -1287,14 +1292,14 @@ def parse_enum_desc(state: State, element: ET.Element) -> str: # Verify that we didn't ignore any important info by accident parsed = parse_desc_internal(state, element.find('detaileddescription')) parsed.parsed += parse_desc(state, element.find('inbodydescription')) - assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values + assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values and not parsed.exceptions assert not parsed.section # might be problematic return (parsed.parsed, parsed.search_keywords, parsed.search_enum_values_as_keywords, parsed.is_deprecated) def parse_enum_value_desc(state: State, element: ET.Element) -> str: # Verify that we didn't ignore any important info by accident parsed = parse_desc_internal(state, element.find('detaileddescription')) - assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values + assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values and not parsed.exceptions assert not parsed.section # might be problematic return (parsed.parsed, parsed.search_keywords, parsed.is_deprecated) @@ -1302,14 +1307,14 @@ def parse_var_desc(state: State, element: ET.Element) -> str: # Verify that we didn't ignore any important info by accident parsed = parse_desc_internal(state, element.find('detaileddescription')) parsed.parsed += parse_desc(state, element.find('inbodydescription')) - assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values + assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values and not parsed.exceptions assert not parsed.section # might be problematic return (parsed.parsed, parsed.search_keywords, parsed.is_deprecated) def parse_toplevel_desc(state: State, element: ET.Element): # Verify that we didn't ignore any important info by accident parsed = parse_desc_internal(state, element) - assert not parsed.return_value and not parsed.return_values + assert not parsed.return_value and not parsed.return_values and not parsed.exceptions if parsed.params: logging.warning("{}: use @tparam instead of @param for documenting class templates, @param is ignored".format(state.current)) return (parsed.parsed, parsed.templates, parsed.section[2] if parsed.section else '', parsed.footer_navigation, parsed.example_navigation, parsed.search_keywords, parsed.is_deprecated) @@ -1318,7 +1323,7 @@ def parse_typedef_desc(state: State, element: ET.Element): # Verify that we didn't ignore any important info by accident parsed = parse_desc_internal(state, element.find('detaileddescription')) parsed.parsed += parse_desc(state, element.find('inbodydescription')) - assert not parsed.params and not parsed.return_value and not parsed.return_values + assert not parsed.params and not parsed.return_value and not parsed.return_values and not parsed.exceptions assert not parsed.section # might be problematic return (parsed.parsed, parsed.templates, parsed.search_keywords, parsed.is_deprecated) @@ -1327,13 +1332,13 @@ def parse_func_desc(state: State, element: ET.Element): parsed = parse_desc_internal(state, element.find('detaileddescription')) parsed.parsed += parse_desc(state, element.find('inbodydescription')) assert not parsed.section # might be problematic - return (parsed.parsed, parsed.templates, parsed.params, parsed.return_value, parsed.return_values, parsed.search_keywords, parsed.is_deprecated) + return (parsed.parsed, parsed.templates, parsed.params, parsed.return_value, parsed.return_values, parsed.exceptions, parsed.search_keywords, parsed.is_deprecated) def parse_define_desc(state: State, element: ET.Element): # Verify that we didn't ignore any important info by accident parsed = parse_desc_internal(state, element.find('detaileddescription')) parsed.parsed += parse_desc(state, element.find('inbodydescription')) - assert not parsed.templates + assert not parsed.templates and not parsed.exceptions assert not parsed.return_values # might be problematic? assert not parsed.section # might be problematic return (parsed.parsed, parsed.params, parsed.return_value, parsed.search_keywords, parsed.is_deprecated) @@ -1343,7 +1348,7 @@ def parse_inline_desc(state: State, element: ET.Element) -> str: # Verify that we didn't ignore any important info by accident parsed = parse_desc_internal(state, element, trim=False) - assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values + assert not parsed.templates and not parsed.params and not parsed.return_value and not parsed.return_values and not parsed.exceptions assert not parsed.section return parsed.parsed @@ -1477,7 +1482,7 @@ def parse_func(state: State, element: ET.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')) - func.description, templates, params, func.return_value, func.return_values, search_keywords, func.is_deprecated = parse_func_desc(state, element) + func.description, templates, params, func.return_value, func.return_values, func.exceptions, search_keywords, func.is_deprecated = parse_func_desc(state, element) # Extract function signature to prefix, suffix and various flags. Important # things affecting caller such as static or const (and rvalue overloads) @@ -1560,7 +1565,7 @@ 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_url and (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 or func.exceptions) if func.brief or func.has_details: # Avoid duplicates in search if func.base_url == state.current_url and not state.doxyfile['M_SEARCH_DISABLED']: diff --git a/doxygen/templates/details-func.html b/doxygen/templates/details-func.html index 0b38eefc..14666c79 100644 --- a/doxygen/templates/details-func.html +++ b/doxygen/templates/details-func.html @@ -18,7 +18,7 @@ {% if func.brief %}

{{ func.brief }}

{% endif %} - {% if func.has_template_details or func.has_param_details or func.return_value or func.return_values %} + {% if func.has_template_details or func.has_param_details or func.return_value or func.return_values or func.exceptions %} {% if func.has_template_details %} @@ -47,12 +47,12 @@ {% endif %} {% if func.return_value %} - {{ '' if func.return_values else '' }} + {{ '' if func.return_values or func.exceptions else '' }} Returns - {{ '' if func.return_values else '' }} + {{ '' if func.return_values or func.exceptions else '' }} {% elif func.return_values %} @@ -68,6 +68,19 @@ {% endfor %} {% endif %} + {% if func.exceptions %} + + + + + {% for exception, description in func.exceptions %} + + {{ exception }} + + + {% endfor %} + + {% endif %}
{{ func.return_value }}
Returns
Exceptions
{{ description }}
{% endif %} {% if func.description %} diff --git a/doxygen/test/compound_detailed/File.h b/doxygen/test/compound_detailed/File.h index 65537eba..83df9f30 100644 --- a/doxygen/test/compound_detailed/File.h +++ b/doxygen/test/compound_detailed/File.h @@ -129,6 +129,12 @@ int justReturn(); */ int justReturnValues(); +/** +@brief Function +@exception std::bad_exception With just exception docs should still have detailed section +*/ +int justExceptions(); + /** @brief A function with scattered docs @@ -153,6 +159,9 @@ Yes? - extract them out of a list @retval 1337 1337 h4xx0r?! @retval 42 The answer. To everything + +@exception std::bad_function_call if you call the function bad +@exception std::future_error if you are from the future */ template int bar(int a, int b); diff --git a/doxygen/test/compound_detailed/namespaceFoo.html b/doxygen/test/compound_detailed/namespaceFoo.html index cd95dd06..aef055cb 100644 --- a/doxygen/test/compound_detailed/namespaceFoo.html +++ b/doxygen/test/compound_detailed/namespaceFoo.html @@ -60,6 +60,10 @@ auto justReturnValues() -> int
Function.
+
+ auto justExceptions() -> int +
+
Function.
template<class A, class B>
auto bar(int a, @@ -198,6 +202,23 @@ +
+

+ int Foo::justExceptions() +

+

Function.

+ + + + + + + + + + +
Exceptions
std::bad_exceptionWith just exception docs should still have detailed section
+

@@ -251,6 +272,19 @@ The answer. To everything + + Exceptions + + + + std::bad_function_call + if you call the function bad + + + std::future_error + if you are from the future + +

This is a function that has the docs all scattered around. They should get merged and reordered.

That goes also for the return values.

Yes?

  • We also need to
  • extract them out of a list