chiark / gitweb /
doxygen: implement support for the \exception keyword.
authorVladimír Vondruš <mosra@centrum.cz>
Thu, 12 Apr 2018 16:14:53 +0000 (18:14 +0200)
committerVladimír Vondruš <mosra@centrum.cz>
Thu, 12 Apr 2018 20:15:39 +0000 (22:15 +0200)
doc/doxygen.rst
doxygen/dox2html5.py
doxygen/templates/details-func.html
doxygen/test/compound_detailed/File.h
doxygen/test/compound_detailed/namespaceFoo.html

index 5f3962bcd81a88ae63210be1d8c77645c50ef8cf..267dc5bec7c8d6d438dc309d8dd80118b7348717 100644 (file)
@@ -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`_
 ``````````````````````
index 39aec712cc9f192c1311ec30675cba982a828c5a..f8edab6fedadebe7ccd6489ac65ecd6cd9da8357 100755 (executable)
@@ -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']:
index 0b38eefc2b2e54600fd28932bed6ecc577d82c7b..14666c79ea1f89d15215f6b1f60cda285945e0df 100644 (file)
@@ -18,7 +18,7 @@
             {% if func.brief %}
             <p>{{ func.brief }}</p>
             {% 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 %}
             <table class="m-table m-fullwidth m-flat">
               {% if func.has_template_details %}
               <thead>
               </tbody>
               {% endif %}
               {% if func.return_value %}
-              {{ '<thead>' if func.return_values else '<tfoot>' }}
+              {{ '<thead>' if func.return_values or func.exceptions else '<tfoot>' }}
                 <tr>
                   <th{% if not func.has_template_details and not func.has_param_details %} style="width: 1%"{% endif %}>Returns</th>
                   <td>{{ func.return_value }}</td>
                 </tr>
-              {{ '</thead>' if func.return_values else '</tfoot>' }}
+              {{ '</thead>' if func.return_values or func.exceptions else '</tfoot>' }}
               {% elif func.return_values %}
               <thead>
                 <tr><th colspan="2">Returns</th></tr>
                 {% endfor %}
               </tbody>
               {% endif %}
+              {% if func.exceptions %}
+              <thead>
+                <tr><th colspan="2">Exceptions</th></tr>
+              </thead>
+              <tbody>
+                {% for exception, description in func.exceptions %}
+                <tr>
+                  <td{% if loop.index == 1 and not func.has_template_details and not func.has_param_details and not func.return_value and not func.return_values %} style="width: 1%"{% endif %}>{{ exception }}</td>
+                  <td>{{ description }}</td>
+                </tr>
+                {% endfor %}
+              </tbody>
+              {% endif %}
             </table>
             {% endif %}
             {% if func.description %}
index 65537eba89ae31caf5a4b902adc72203db2b6141..83df9f306d8778c299521045a4dcb2e5248c0ba3 100644 (file)
@@ -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<class A, class B> int bar(int a, int b);
 
index cd95dd0685f0f969361593e93a8fecb4ff89c7cc..aef055cb87f929fa0c6c6a808ec2165037a1ee5c 100644 (file)
               <span class="m-dox-wrap-bumper">auto <a href="#a2aed7a8280e0ed79f5f9ceb0d54f4a30" class="m-dox">justReturnValues</a>(</span><span class="m-dox-wrap">) -&gt; int</span>
             </dt>
             <dd>Function.</dd>
+            <dt>
+              <span class="m-dox-wrap-bumper">auto <a href="#a7241bb505b7eda882e8508c47062fc3b" class="m-dox">justExceptions</a>(</span><span class="m-dox-wrap">) -&gt; int</span>
+            </dt>
+            <dd>Function.</dd>
             <dt>
               <div class="m-dox-template">template&lt;class A, class B&gt;</div>
               <span class="m-dox-wrap-bumper">auto <a href="#aea7a925ccf30c967a965b2549cec4154" class="m-dox">bar</a>(</span><span class="m-dox-wrap">int a,
               </tbody>
             </table>
           </div></section>
+          <section class="m-dox-details" id="a7241bb505b7eda882e8508c47062fc3b"><div>
+            <h3>
+              <span class="m-dox-wrap-bumper">int Foo::<wbr /></span><span class="m-dox-wrap"><span class="m-dox-wrap-bumper"><a href="#a7241bb505b7eda882e8508c47062fc3b" class="m-dox-self">justExceptions</a>(</span><span class="m-dox-wrap">)</span></span>
+            </h3>
+            <p>Function.</p>
+            <table class="m-table m-fullwidth m-flat">
+              <thead>
+                <tr><th colspan="2">Exceptions</th></tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td style="width: 1%">std::bad_exception</td>
+                  <td>With just exception docs should still have detailed section</td>
+                </tr>
+              </tbody>
+            </table>
+          </div></section>
           <section class="m-dox-details" id="aea7a925ccf30c967a965b2549cec4154"><div>
             <h3>
               <div class="m-dox-template">
                   <td>The answer. To everything</td>
                 </tr>
               </tbody>
+              <thead>
+                <tr><th colspan="2">Exceptions</th></tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td>std::bad_function_call</td>
+                  <td>if you call the function bad</td>
+                </tr>
+                <tr>
+                  <td>std::future_error</td>
+                  <td>if you are from the future</td>
+                </tr>
+              </tbody>
             </table>
 <p>This is a function that has the docs all scattered around. They should get merged and reordered.</p><p>That goes also for the return values.</p><p>Yes?</p><ul><li>We also need to</li><li>extract them out of a list</li></ul>
           </div></section>