Merge branch 'doxy/commands'

* doxy/commands:
  Update documentation for doxygen tags
  Fix doxygen translation of \p command for python
  Fix doxygen handling of \em tag for python
  Minor formatting updates to doxygen docs
  Reformat tag lists in doxygen documentation
  Add doxygen_code_blocks_runme.java
  Special handling for python doctest code blocks
  Add new doxygen test doxygen_code_blocks
  Handle doxygen code command with language option
  Improve doxygen parser handling of \code content
  Flag optional arguments in doxygen pydoc output
  Add parameter direction to doxygen pydoc output
  Support doxygen \param[] commands
This commit is contained in:
William S Fulton 2020-01-14 18:36:50 +00:00
commit 00b47d4d1d
19 changed files with 699 additions and 437 deletions

View file

@ -117,14 +117,15 @@ Documenting the code</a>). Here they are:
</pre></div>
<p>
Also any of the above with '&lt;' added after comment-starting symbol,
like <i>/**&lt;, /*!&lt;, ///&lt;, </i> or <i> //!&lt;</i> will be
Also any of the above with '<tt>&lt;</tt>' added after comment-starting symbol,
like <tt>/**&lt;, /*!&lt;, ///&lt;, </tt> or <tt> //!&lt;</tt> will be
treated as a post-comment and will be assigned to the code before the
comment.
Any number of '*' or '/' within a Doxygen comment is considered to be a
separator and is not included in the final comment, so you may safely use
comments like <i>/*********/</i> or <i>//////////</i>.
Any number of '<tt>*</tt>' or '<tt>/</tt>' within a Doxygen comment is
considered to be a separator and is not included in the final comment,
so you may safely use comments like <tt>/*********/</tt>
or <tt>//////////</tt>.
</p>
<p>
@ -606,6 +607,10 @@ Here is the list of all Doxygen tags and the description of how they are transla
<td>translated to {@code ...}</td>
</tr>
<tr>
<td>\code{&lt;ext&gt;}</td>
<td>translated to {@code ...}; code language extension is ignored</td>
</tr>
<tr>
<td>\cond</td>
<td>translated to 'Conditional comment: &lt;condition&gt;'</td>
</tr>
@ -683,7 +688,7 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\n</td>
<td>replaced with new line char</td>
<td>replaced with newline char</td>
</tr>
<tr>
<td>\note</td>
@ -706,6 +711,10 @@ Here is the list of all Doxygen tags and the description of how they are transla
<td>translated to @param</td>
</tr>
<tr>
<td>\param[&lt;dir&gt;]</td>
<td>translated to @param; parameter direction ('in'; 'out'; or 'in,out') is ignored</td>
</tr>
<tr>
<td>\remark</td>
<td>replaced with 'Remarks:'</td>
</tr>
@ -829,155 +838,107 @@ These are suppressed with their content just printed out (if the tag has any
sense, typically text content).
Here is the list of these tags:
</p>
<div class="diagram">
<table border="0" summary="Unsupported Java Doxygen Tags">
<tr>
<th align="left">Unsupported Doxygen tags</th>
</tr>
<tr>
<td>\addindex</td>
<td>\addtogroup</td>
<td>\anchor</td>
<td>\attention</td>
</tr>
<tr>
<td>\brief</td>
<td>\bug</td>
<td>\callgraph</td>
<td>\callergraph</td>
</tr>
<tr>
<td>\class</td>
<td>\copybrief</td>
<td>\copydetails</td>
<td>\copydoc</td>
</tr>
<tr>
<td>\date</td>
<td>\def</td>
<td>\defgroup</td>
<td>\details</td>
</tr>
<tr>
<td>\dir</td>
<td>\dontinclude</td>
<td>\dot</td>
<td>\dotfile</td>
</tr>
<tr>
<td>\enddot</td>
<td>\endhtmlonly</td>
<td>\endinternal</td>
<td>\endlatexonly</td>
</tr>
<tr>
<td>\endmanonly</td>
<td>\endmsc</td>
<td>\endrtfonly</td>
<td>\endxmlonly</td>
</tr>
<tr>
<td>\enum</td>
<td>\example</td>
<td>\extends</td>
</tr>
<tr>
<td>\file</td>
<td>\fn</td>
<td>\headerfile</td>
<td>\hideinitializer</td>
</tr>
<tr>
<td>\htmlinclude</td>
<td>\htmlonly</td>
<td>\implements</td>
<td>\include</td>
</tr>
<tr>
<td>\includelineno</td>
<td>\ingroup</td>
<td>\internal</td>
<td>\invariant</td>
</tr>
<tr>
<td>\interface</td>
<td>\latexonly</td>
<td>\line</td>
<td>\mainpage</td>
</tr>
<tr>
<td>\manonly</td>
<td>\memberof</td>
<td>\msc</td>
<td>\mscfile</td>
</tr>
<tr>
<td>\name</td>
<td>\namespace</td>
<td>\nosubgrouping</td>
<td>\package</td>
</tr>
<tr>
<td>\page</td>
<td>\paragraph</td>
<td>\post</td>
<td>\pre</td>
</tr>
<tr>
<td>\private</td>
<td>\privatesection</td>
<td>\property</td>
<td>\protected</td>
</tr>
<tr>
<td>\protectedsection</td>
<td>\protocol</td>
<td>\public</td>
<td>\publicsection</td>
</tr>
<tr>
<td>\ref</td>
<td>\related</td>
<td>\relates</td>
<td>\relatedalso</td>
</tr>
<tr>
<td>\relatesalso</td>
<td>\retval</td>
<td>\rtfonly</td>
<td>\section</td>
</tr>
<tr>
<td>\short</td>
<td>\showinitializer</td>
<td>\skip</td>
<td>\skipline</td>
</tr>
<tr>
<td>\snippet</td>
<td>\struct</td>
<td>\subpage</td>
<td>\subsection</td>
</tr>
<tr>
<td>\subsubsection</td>
<td>\tableofcontents</td>
<td>\test</td>
<td>\typedef</td>
</tr>
<tr>
<td>\union</td>
<td>\until</td>
<td>\var</td>
<td>\verbinclude</td>
</tr>
<tr>
<td>\weakgroup</td>
<td>\xmlonly</td>
<td>\xrefitem</td>
<td>\category</td>
</tr>
</table>
<b>Unsupported Doxygen tags</b>
<ul style="list-style-type:none;column-count:4;">
<li>\addindex</li>
<li>\addtogroup</li>
<li>\anchor</li>
<li>\attention</li>
<li>\brief</li>
<li>\bug</li>
<li>\callergraph</li>
<li>\callgraph</li>
<li>\category</li>
<li>\class</li>
<li>\copybrief</li>
<li>\copydetails</li>
<li>\copydoc</li>
<li>\date</li>
<li>\def</li>
<li>\defgroup</li>
<li>\details</li>
<li>\dir</li>
<li>\dontinclude</li>
<li>\dot</li>
<li>\dotfile</li>
<li>\enddot</li>
<li>\endhtmlonly</li>
<li>\endinternal</li>
<li>\endlatexonly</li>
<li>\endmanonly</li>
<li>\endmsc</li>
<li>\endrtfonly</li>
<li>\endxmlonly</li>
<li>\enum</li>
<li>\example</li>
<li>\extends</li>
<li>\file</li>
<li>\fn</li>
<li>\headerfile</li>
<li>\hideinitializer</li>
<li>\htmlinclude</li>
<li>\htmlonly</li>
<li>\implements</li>
<li>\include</li>
<li>\includelineno</li>
<li>\ingroup</li>
<li>\interface</li>
<li>\internal</li>
<li>\invariant</li>
<li>\latexonly</li>
<li>\line</li>
<li>\mainpage</li>
<li>\manonly</li>
<li>\memberof</li>
<li>\msc</li>
<li>\mscfile</li>
<li>\name</li>
<li>\namespace</li>
<li>\nosubgrouping</li>
<li>\package</li>
<li>\page</li>
<li>\paragraph</li>
<li>\post</li>
<li>\pre</li>
<li>\private</li>
<li>\privatesection</li>
<li>\property</li>
<li>\protected</li>
<li>\protectedsection</li>
<li>\protocol</li>
<li>\public</li>
<li>\publicsection</li>
<li>\ref</li>
<li>\related</li>
<li>\relatedalso</li>
<li>\relates</li>
<li>\relatesalso</li>
<li>\retval</li>
<li>\rtfonly</li>
<li>\section</li>
<li>\short</li>
<li>\showinitializer</li>
<li>\skip</li>
<li>\skipline</li>
<li>\snippet</li>
<li>\struct</li>
<li>\subpage</li>
<li>\subsection</li>
<li>\subsubsection</li>
<li>\tableofcontents</li>
<li>\test</li>
<li>\typedef</li>
<li>\union</li>
<li>\until</li>
<li>\var</li>
<li>\verbinclude</li>
<li>\weakgroup</li>
<li>\xmlonly</li>
<li>\xrefitem</li>
</ul>
</div>
<p>
@ -987,68 +948,47 @@ comment, the whole comment block is ignored:
<!-- see parser.y, function isStructuralDoxygen() -->
</p>
<div class="diagram">
<table border="0" summary="Ignored Java Doxygen Tags">
<tr>
<th align="left">Ignored Doxygen tags</th>
</tr>
<tr>
<td>\addtogroup</td>
<td>\callgraph</td>
<td>\callergraph</td>
<td>\category</td>
</tr>
<tr>
<td>\class</td>
<td>\def</td>
<td>\defgroup</td>
<td>\dir</td>
</tr>
<tr>
<td>\enum</td>
<td>\example</td>
<td>\file</td>
<td>\fn</td>
</tr>
<tr>
<td>\headerfile</td>
<td>\hideinitializer</td>
<td>\interface</td>
<td>\internal</td>
</tr>
<tr>
<td>\mainpage</td>
<td>\name</td>
<td>\namespace</td>
<td>\nosubgrouping</td>
</tr>
<tr>
<td>\overload</td>
<td>\package</td>
<td>\page</td>
<td>\property</td>
</tr>
<tr>
<td>\protocol</td>
<td>\relates</td>
<td>\relatesalso</td>
<td>\showinitializer</td>
</tr>
<tr>
<td>\struct</td>
<td>\name</td>
<td>\namespace</td>
<td>\nosubgrouping</td>
</tr>
<tr>
<td>\typedef</td>
<td>\union</td>
<td>\var</td>
<td>\weakgroup</td>
</tr>
</table>
<div class="diagram">
<b>Ignored Doxygen tags</b>
<ul style="list-style-type:none;column-count:4;">
<li>\addtogroup</li>
<li>\callergraph</li>
<li>\callgraph</li>
<li>\category</li>
<li>\class</li>
<li>\def</li>
<li>\defgroup</li>
<li>\dir</li>
<li>\enum</li>
<li>\example</li>
<li>\file</li>
<li>\fn</li>
<li>\headerfile</li>
<li>\hideinitializer</li>
<li>\interface</li>
<li>\internal</li>
<li>\mainpage</li>
<li>\name</li>
<li>\namespace</li>
<li>\nosubgrouping</li>
<li>\overload</li>
<li>\package</li>
<li>\page</li>
<li>\property</li>
<li>\protocol</li>
<li>\relates</li>
<li>\relatesalso</li>
<li>\showinitializer</li>
<li>\struct</li>
<li>\typedef</li>
<li>\union</li>
<li>\var</li>
<li>\weakgroup</li>
</ul>
</div>
@ -1246,11 +1186,11 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\a</td>
<td>wrapped with '_'</td>
<td>wrapped with '*'</td>
</tr>
<tr>
<td>\arg</td>
<td>prepended with ' --'</td>
<td>prepended with '* '</td>
</tr>
<tr>
<td>\author</td>
@ -1258,17 +1198,28 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\authors</td>
<td>prints 'Author:'</td>
<td>prints 'Authors:'</td>
</tr>
<tr>
<td>\b</td>
<td>wrapped with '__'</td>
<td>wrapped with '**'</td>
</tr>
<td>\c</td>
<td>wrapped with '``'</td>
</tr>
<tr>
<td>\cite</td>
<td>wrapped with single quotes</td>
</tr>
<tr>
<td>\code</td>
<td>replaced with '.. code-block:: c++'</td>
</tr>
<tr>
<td>\code{&lt;ext&gt;}</td>
<td>replaced with '.. code-block:: &lt;lang&gt;', where the following doxygen code languages are recognized: .c -&gt; C, .py -&gt; python, .java &gt; java</td>
</tr>
<tr>
<td>\cond</td>
<td>translated to 'Conditional comment: &lt;condition&gt;'</td>
</tr>
@ -1282,7 +1233,7 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\e</td>
<td>wrapped with '_'</td>
<td>wrapped with '*'</td>
</tr>
<tr>
<td>\else</td>
@ -1294,7 +1245,7 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\em</td>
<td>wrapped with '_'</td>
<td>wrapped with '*'</td>
</tr>
<tr>
<td>\endcond</td>
@ -1305,8 +1256,24 @@ Here is the list of all Doxygen tags and the description of how they are transla
<td>replaced with '}'</td>
</tr>
<tr>
<td>\example</td>
<td>replaced with 'Example:'</td>
</tr>
<tr>
<td>\exception</td>
<td>replaced with 'Throws:'</td>
<td>replaced with ':raises:'</td>
</tr>
<tr>
<td>\f$</td>
<td>rendered using ':math:``'</td>
</tr>
<tr>
<td>\f[</td>
<td>rendered using '.. math::'</td>
</tr>
<tr>
<td>\f{</td>
<td>rendered using '.. math::'</td>
</tr>
<tr>
<td>\if</td>
@ -1318,11 +1285,11 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\li</td>
<td>prepended with ' --'</td>
<td>prepended with '* '</td>
</tr>
<tr>
<td>\n</td>
<td>replaced with new line char</td>
<td>replaced with newline char</td>
</tr>
<tr>
<td>\note</td>
@ -1332,13 +1299,21 @@ Here is the list of all Doxygen tags and the description of how they are transla
<td>\overload</td>
<td>prints 'This is an overloaded ...' according to Doxygen docs</td>
</tr>
</tr>
<td>\p</td>
<td>wrapped with '``'</td>
</tr>
<tr>
<td>\par</td>
<td>replaced with 'Title: ...'</td>
</tr>
<tr>
<td>\param</td>
<td>translated to 'Arguments:\n param(type) --description'</td>
<td>add ':type:' and ':param:' directives</td>
</tr>
<tr>
<td>\param[&lt;dir&gt;]</td>
<td>same as \param, but direction ('in'; 'out'; 'in,out') is included in ':type:' directive</td>
</tr>
<tr>
<td>\remark</td>
@ -1350,15 +1325,15 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\result</td>
<td>replaced with 'Result:'</td>
<td>add ':rtype:' and ':return:' directives</td>
</tr>
<tr>
<td>\return</td>
<td>replaced with 'Result:'</td>
<td>add ':rtype:' and ':return:' directives</td>
</tr>
<tr>
<td>\returns</td>
<td>replaced with 'Result:'</td>
<td>add ':rtype:' and ':return:' directives</td>
</tr>
<tr>
<td>\sa</td>
@ -1374,11 +1349,11 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\throw</td>
<td>replaced with 'Throws:'</td>
<td>replaced with ':raises:'</td>
</tr>
<tr>
<td>\throws</td>
<td>replaced wih 'Throws:'</td>
<td>replaced wih ':raises:'</td>
</tr>
<tr>
<td>\todo</td>
@ -1386,7 +1361,11 @@ Here is the list of all Doxygen tags and the description of how they are transla
</tr>
<tr>
<td>\tparam</td>
<td>translated to 'Arguments:\n param(type) --description'</td>
<td>add ':type:' and ':param:' directives</td>
</tr>
<tr>
<td>\verbatim</td>
<td>content copied verbatim</td>
</tr>
<tr>
<td>\version</td>
@ -1458,177 +1437,109 @@ are suppressed with their content just printed out (if it has any
sense, typically text content).
Here is the list of these tags:
</p>
<div class="diagram">
<table border="0" summary="Unsupported Python Doxygen Tags">
<tr>
<th align="left">Unsupported Doxygen tags</th>
</tr>
<tr>
<td>\addindex</td>
<td>\addtogroup</td>
<td>\anchor</td>
<td>\attention</td>
</tr>
<tr>
<td>\brief</td>
<td>\bug</td>
<td>\callgraph</td>
<td>\callergraph</td>
</tr>
<tr>
<td>\class</td>
<td>\copybrief</td>
<td>\copydetails</td>
<td>\copydoc</td>
</tr>
<tr>
<td>\date</td>
<td>\def</td>
<td>\defgroup</td>
<td>\details</td>
</tr>
<tr>
<td>\dir</td>
<td>\dontinclude</td>
<td>\dot</td>
<td>\dotfile</td>
</tr>
<tr>
<td>\code</td>
<td>\endcode</td>
<td>\endverbatim</td>
<td>\endlink</td>
</tr>
<tr>
<td>\enddot</td>
<td>\endhtmlonly</td>
<td>\endinternal</td>
<td>\endlatexonly</td>
</tr>
<tr>
<td>\endmanonly</td>
<td>\endmsc</td>
<td>\endrtfonly</td>
<td>\endxmlonly</td>
</tr>
<tr>
<td>\enum</td>
<td>\example</td>
<td>\extends</td>
<td>\f$</td>
</tr>
<tr>
<td>\f[</td>
<td>\f]</td>
<td>\f{</td>
<td>\f}</td>
</tr>
<tr>
<td>\file</td>
<td>\fn</td>
<td>\headerfile</td>
<td>\hideinitializer</td>
</tr>
<tr>
<td>\htmlinclude</td>
<td>\htmlonly</td>
<td>\implements</td>
<td>\include</td>
</tr>
<tr>
<td>\image</td>
<td>\link</td>
<td>\verbatim</td>
<td>\p</td>
</tr>
<tr>
<td>\includelineno</td>
<td>\ingroup</td>
<td>\internal</td>
<td>\invariant</td>
</tr>
<tr>
<td>\interface</td>
<td>\latexonly</td>
<td>\line</td>
<td>\mainpage</td>
</tr>
<tr>
<td>\manonly</td>
<td>\memberof</td>
<td>\msc</td>
<td>\mscfile</td>
</tr>
<tr>
<td>\name</td>
<td>\namespace</td>
<td>\nosubgrouping</td>
<td>\package</td>
</tr>
<tr>
<td>\page</td>
<td>\paragraph</td>
<td>\post</td>
<td>\pre</td>
</tr>
<tr>
<td>\private</td>
<td>\privatesection</td>
<td>\property</td>
<td>\protected</td>
</tr>
<tr>
<td>\protectedsection</td>
<td>\protocol</td>
<td>\public</td>
<td>\publicsection</td>
</tr>
<tr>
<td>\ref</td>
<td>\related</td>
<td>\relates</td>
<td>\relatedalso</td>
</tr>
<tr>
<td>\relatesalso</td>
<td>\retval</td>
<td>\rtfonly</td>
<td>\section</td>
</tr>
<tr>
<td>\short</td>
<td>\showinitializer</td>
<td>\skip</td>
<td>\skipline</td>
</tr>
<tr>
<td>\snippet</td>
<td>\struct</td>
<td>\subpage</td>
<td>\subsection</td>
</tr>
<tr>
<td>\subsubsection</td>
<td>\tableofcontents</td>
<td>\test</td>
<td>\typedef</td>
</tr>
<tr>
<td>\union</td>
<td>\until</td>
<td>\var</td>
<td>\verbinclude</td>
</tr>
<tr>
<td>\weakgroup</td>
<td>\xmlonly</td>
<td>\xrefitem</td>
<td>\category</td>
</tr>
<tr>
<td>\c</td>
</tr>
</table>
<b>Unsupported Python Doxygen tags</b>
<ul style="list-style-type:none;column-count:4;">
<li>\addindex</li>
<li>\addtogroup</li>
<li>\anchor</li>
<li>\attention</li>
<li>\brief</li>
<li>\bug</li>
<li>\callergraph</li>
<li>\callgraph</li>
<li>\category</li>
<li>\class</li>
<li>\copybrief</li>
<li>\copydetails</li>
<li>\copydoc</li>
<li>\date</li>
<li>\def</li>
<li>\defgroup</li>
<li>\details</li>
<li>\dir</li>
<li>\dontinclude</li>
<li>\dot</li>
<li>\dotfile</li>
<li>\enddot</li>
<li>\endhtmlonly</li>
<li>\endinternal</li>
<li>\endlatexonly</li>
<li>\endlink</li>
<li>\endmanonly</li>
<li>\endmsc</li>
<li>\endrtfonly</li>
<li>\endxmlonly</li>
<li>\enum</li>
<li>\extends</li>
<li>\file</li>
<li>\fn</li>
<li>\headerfile</li>
<li>\hideinitializer</li>
<li>\htmlinclude</li>
<li>\htmlonly</li>
<li>\image</li>
<li>\implements</li>
<li>\include</li>
<li>\includelineno</li>
<li>\ingroup</li>
<li>\interface</li>
<li>\internal</li>
<li>\invariant</li>
<li>\latexonly</li>
<li>\line</li>
<li>\link</li>
<li>\mainpage</li>
<li>\manonly</li>
<li>\memberof</li>
<li>\msc</li>
<li>\mscfile</li>
<li>\name</li>
<li>\namespace</li>
<li>\nosubgrouping</li>
<li>\package</li>
<li>\page</li>
<li>\paragraph</li>
<li>\post</li>
<li>\pre</li>
<li>\private</li>
<li>\privatesection</li>
<li>\property</li>
<li>\protected</li>
<li>\protectedsection</li>
<li>\protocol</li>
<li>\public</li>
<li>\publicsection</li>
<li>\ref</li>
<li>\related</li>
<li>\relatedalso</li>
<li>\relates</li>
<li>\relatesalso</li>
<li>\retval</li>
<li>\rtfonly</li>
<li>\section</li>
<li>\short</li>
<li>\showinitializer</li>
<li>\skip</li>
<li>\skipline</li>
<li>\snippet</li>
<li>\struct</li>
<li>\subpage</li>
<li>\subsection</li>
<li>\subsubsection</li>
<li>\tableofcontents</li>
<li>\test</li>
<li>\typedef</li>
<li>\union</li>
<li>\until</li>
<li>\var</li>
<li>\verbinclude</li>
<li>\weakgroup</li>
<li>\xmlonly</li>
<li>\xrefitem</li>
</ul>
</div>
<H3><a name="Doxygen_python_further_details">17.4.4 Further details</a></H3>

View file

@ -65,6 +65,10 @@ div.diagram {
font-family: "Courier New", Courier, "Courier 10 Pitch", monospace;
}
div.diagram li {
margin-left: 0;
}
ul li p {
margin-left: 0;
margin-right: 0;

View file

@ -635,6 +635,7 @@ DOXYGEN_TEST_CASES += \
doxygen_translate \
doxygen_translate_all_tags \
doxygen_translate_links \
doxygen_code_blocks \
$(DOXYGEN_TEST_CASES:=.cpptest): SWIGOPT += -doxygen

View file

@ -0,0 +1,62 @@
%module doxygen_code_blocks
// This test is only used with Python
%inline %{
/**
* \brief Test for code blocks
*
* \code
* simple code block
* \endcode
*
* More advanced usage with C++ characters:
* \code
* std::vector<int> first; // empty vector of ints
* std::vector<int> second (4,100); // four ints with value 100
* std::vector<int> third (second.begin(),second.end()); // iterating through second
* std::vector<int> fourth (third); // a copy of third
* // the iterator constructor can also be used to construct from arrays:
* int myints[] = {16,2,77,29};
* std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
*
* std::cout << "The contents of fifth are:";
* for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
* std::cout << ' ' << *it;
* std::cout << '\n';
* \endcode
*
* A code block for C:
* \code{.c}
* printf("hello world");
* \endcode
*
* A code block for Java:
* \code{.java}
* public class HelloWorld {
* public static void main(String[] args) {
* // Prints "Hello, World" to the terminal window.
* System.out.println("Hello, World");
* }
* }
* \endcode
*
* A code block for python:
* \code{.py}
* print('hello world')
* \endcode
*
* A python doctest example:
* \code{.py}
* >>> 1 + 1
* 2
* \endcode
*/
int function()
{
return 0;
}
%}

View file

@ -262,6 +262,9 @@ void func06(int a)
* \paragraph someParagraph Paragraph title
*
* \param a the first param
* \param[in] b parameter with intent(in)
* \param[out] c parameter with intent(out)
* \param[in,out] d parameter with intent(in,out)
*
* \post Some description
*
@ -273,7 +276,7 @@ void func06(int a)
*
* \property someVar
*/
void func07(int a)
void func07(int a, int b, int c, int d)
{
}

View file

@ -0,0 +1,83 @@
import doxygen_code_blocks.*;
import com.sun.javadoc.*;
import java.util.HashMap;
public class doxygen_code_blocks_runme {
static {
try {
System.loadLibrary("doxygen_code_blocks");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[])
{
/*
Here we are using internal javadoc tool, it accepts the name of the class as paramterer,
and calls the start() method of that class with parsed information.
*/
CommentParser parser = new CommentParser();
com.sun.tools.javadoc.Main.execute("doxygen_code_blocks runtime test",
"CommentParser",
new String[]{"-quiet", "doxygen_code_blocks"});
HashMap<String, String> wantedComments = new HashMap<String, String>();
wantedComments.put("doxygen_code_blocks.doxygen_code_blocks.function()",
" Test for code blocks\n \n" +
" \n \n" +
" {@code \n" +
" simple code block \n" +
" }\n \n" +
" \n \n" +
" More advanced usage with C++ characters:\n \n" +
" {@code \n" +
" std::vector<int> first; // empty vector of ints \n" +
" std::vector<int> second (4,100); // four ints with value 100 \n" +
" std::vector<int> third (second.begin(),second.end()); // iterating through second \n" +
" std::vector<int> fourth (third); // a copy of third \n" +
" // the iterator constructor can also be used to construct from arrays: \n" +
" int myints[] = {16,2,77,29}; \n" +
" std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) ); \n" +
" \n" +
" std::cout << \"The contents of fifth are:\"; \n" +
" for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it) \n" +
" std::cout << \' \' << *it; \n" +
" std::cout << \'\\n\'; \n" +
" }\n \n" +
" \n \n" +
" A code block for C:\n \n" +
" {@code \n" +
" printf(\"hello world\"); \n" +
" }\n \n" +
" \n \n" +
" A code block for Java:\n \n" +
" {@code \n" +
" public class HelloWorld { \n" +
" public static void main(String[] args) { \n" +
" // Prints \"Hello, World\" to the terminal window. \n" +
" System.out.println(\"Hello, World\"); \n" +
" } \n" +
" } \n" +
" }\n \n" +
" \n \n" +
" A code block for python:\n \n" +
" {@code \n" +
" print(\'hello world\') \n" +
" }\n \n" +
" \n \n" +
" A python doctest example:\n \n" +
" {@code \n" +
" >>> 1 + 1 \n" +
" 2 \n" +
" } \n" +
" \n" +
"");
// and ask the parser to check comments for us
System.exit(parser.check(wantedComments));
}
}

View file

@ -96,7 +96,7 @@ public class doxygen_translate_all_tags_runme {
" {@link someMember Some description follows }\n" +
" This will only appear in man\n");
wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func07(int)",
wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func07(int, int, int, int)",
" Comment for <b>func07()</b>.\n" +
" Note: Here \n" +
" is the note! \n" +
@ -107,7 +107,10 @@ public class doxygen_translate_all_tags_runme {
" The paragraph text. \n" +
" Maybe even multiline \n" +
" </p>\n" +
" @param a the first param\n");
" @param a the first param\n" +
" @param b parameter with intent(in)\n" +
" @param c parameter with intent(out)\n" +
" @param d parameter with intent(in,out)\n");
wantedComments.put("doxygen_translate_all_tags.doxygen_translate_all_tags.func08(int)",
"<a id=\"someAnchor\"></a>\n" +

View file

@ -60,7 +60,7 @@ comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function5),
comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function6),
"""\
Test for default args
:type a: int
:type a: int, optional
:param a: Some parameter, default is 42"""
)
comment_verifier.check(inspect.getdoc(doxygen_basic_translate.function7),

View file

@ -58,7 +58,7 @@ comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function5),
comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function6),
"""\
Test for default args
:type a: int
:type a: int, optional
:param a: Some parameter, default is 42"""
)
comment_verifier.check(inspect.getdoc(doxygen_basic_translate_style2.function7),

View file

@ -0,0 +1,58 @@
import doxygen_code_blocks
import inspect
import string
import sys
import comment_verifier
comment_verifier.check(inspect.getdoc(doxygen_code_blocks.function),
"""\
Test for code blocks
.. code-block:: c++
simple code block
More advanced usage with C++ characters:
.. code-block:: c++
std::vector<int> first; // empty vector of ints
std::vector<int> second (4,100); // four ints with value 100
std::vector<int> third (second.begin(),second.end()); // iterating through second
std::vector<int> fourth (third); // a copy of third
// the iterator constructor can also be used to construct from arrays:
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
std::cout << "The contents of fifth are:";
for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\\n';
A code block for C:
.. code-block:: c
printf("hello world");
A code block for Java:
.. code-block:: java
public class HelloWorld {
public static void main(String[] args) {
// Prints "Hello, World" to the terminal window.
System.out.println("Hello, World");
}
}
A code block for python:
.. code-block:: python
print('hello world')
A python doctest example:
>>> 1 + 1
2""")

View file

@ -12,7 +12,7 @@ comment_verifier.check(inspect.getdoc(doxygen_misc_constructs.getAddress),
:param fileName: name of the file, where the source line is located
:type line: int
:param line: line number
:type isGetSize: boolean
:type isGetSize: boolean, optional
:param isGetSize: if set, for every object location both address and size are returned
Connection::getId() """)

View file

@ -82,7 +82,7 @@ r"""Comment for **func03()**.
*italicword*
emphazedWord
*emphazedWord*
@ -196,7 +196,7 @@ is the note!
This is an overloaded member function, provided for convenience.
It differs from the above function only in what argument(s) it accepts.
someword
``someword``
@ -209,7 +209,13 @@ Maybe even multiline
:type a: int
:param a: the first param""")
:param a: the first param
:type b: int, in
:param b: parameter with intent(in)
:type c: int, out
:param c: parameter with intent(out)
:type d: int, in/out
:param d: parameter with intent(in,out)""")
comment_verifier.check(inspect.getdoc(doxygen_translate_all_tags.func08),
r"""Text after anchor.

View file

@ -80,7 +80,7 @@ is the note!
This is an overloaded member function, provided for convenience.
It differs from the above function only in what argument(s) it accepts.
someword
``someword``

View file

@ -18,11 +18,13 @@
const char *CMD_HTML_ONLY = "htmlonly";
// doxy commands are not processed inside this block
const char *CMD_VERBATIM = "verbatim";
const char *CMD_CODE = "code";
const char *CMD_LATEX_1 = "f$";
const char *CMD_LATEX_2 = "f{";
const char *CMD_LATEX_3 = "f[";
const char *CMD_END_HTML_ONLY = "endhtmlonly";
const char *CMD_END_VERBATIM = "endverbatim";
const char *CMD_END_CODE = "endcode";
const char *CMD_END_LATEX_1 = "f$";
const char *CMD_END_LATEX_2 = "f}";
const char *CMD_END_LATEX_3 = "f]";

View file

@ -34,6 +34,30 @@ std::set<std::string> DoxygenParser::doxygenSectionIndicators;
const int TOKENSPERLINE = 8; //change this to change the printing behaviour of the token list
const std::string END_HTML_TAG_MARK("/");
std::string getBaseCommand(const std::string &cmd) {
if (cmd.substr(0,5) == "param")
return "param";
else if (cmd.substr(0,4) == "code")
return "code";
else
return cmd;
}
// Find the first position beyond the word command. Extra logic is
// used to avoid putting the characters "," and "." in
// DOXYGEN_WORD_CHARS.
static size_t getEndOfWordCommand(const std::string &line, size_t pos) {
size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos);
if (line.substr(pos, 6) == "param[")
// include ",", which can appear in param[in,out]
endOfWordPos = line.find_first_not_of(string(DOXYGEN_WORD_CHARS)+ ",", pos);
else if (line.substr(pos, 5) == "code{")
// include ".", which can appear in e.g. code{.py}
endOfWordPos = line.find_first_not_of(string(DOXYGEN_WORD_CHARS)+ ".", pos);
return endOfWordPos;
}
DoxygenParser::DoxygenParser(bool noisy) : noisy(noisy) {
fillTables();
}
@ -118,7 +142,7 @@ void DoxygenParser::printTree(const DoxygenEntityList &rootList) {
}
DoxygenParser::DoxyCommandEnum DoxygenParser::commandBelongs(const std::string &theCommand) {
DoxyCommandsMapIt it = doxygenCommands.find(stringToLower(theCommand));
DoxyCommandsMapIt it = doxygenCommands.find(stringToLower(getBaseCommand(theCommand)));
if (it != doxygenCommands.end()) {
return it->second;
@ -312,7 +336,7 @@ DoxygenParser::TokenListCIt DoxygenParser::getEndOfParagraph(const TokenList &to
} else if (endOfParagraph->m_tokenType == COMMAND) {
if (isSectionIndicator(endOfParagraph->m_tokenString)) {
if (isSectionIndicator(getBaseCommand(endOfParagraph->m_tokenString))) {
return endOfParagraph;
} else {
endOfParagraph++;
@ -666,7 +690,7 @@ void DoxygenParser::addCommandUnique(const std::string &theCommand, const TokenL
// \f{ ... \f}
// \f{env}{ ... \f}
// \f$ ... \f$
else if (theCommand == "code" || theCommand == "verbatim"
else if (getBaseCommand(theCommand) == "code" || theCommand == "verbatim"
|| theCommand == "dot" || theCommand == "msc" || theCommand == "f[" || theCommand == "f{" || theCommand == "f$") {
if (!endCommands.size()) {
// fill in static table of end commands
@ -683,7 +707,7 @@ void DoxygenParser::addCommandUnique(const std::string &theCommand, const TokenL
if (it != endCommands.end())
endCommand = it->second;
else
endCommand = "end" + theCommand;
endCommand = "end" + getBaseCommand(theCommand);
std::string content = getStringTilEndCommand(endCommand, tokList);
aNewList.push_back(DoxygenEntity("plainstd::string", content));
@ -1090,7 +1114,7 @@ size_t DoxygenParser::processVerbatimText(size_t pos, const std::string &line) {
size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos);
string cmd = line.substr(pos, endOfWordPos - pos);
if (cmd == CMD_END_HTML_ONLY || cmd == CMD_END_VERBATIM || cmd == CMD_END_LATEX_1 || cmd == CMD_END_LATEX_2 || cmd == CMD_END_LATEX_3) {
if (cmd == CMD_END_HTML_ONLY || cmd == CMD_END_VERBATIM || cmd == CMD_END_LATEX_1 || cmd == CMD_END_LATEX_2 || cmd == CMD_END_LATEX_3 || cmd == CMD_END_CODE) {
m_isVerbatimText = false;
addDoxyCommand(m_tokenList, cmd);
@ -1154,22 +1178,34 @@ bool DoxygenParser::processEscapedChars(size_t &pos, const std::string &line) {
*/
void DoxygenParser::processWordCommands(size_t &pos, const std::string &line) {
pos++;
size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos);
size_t endOfWordPos = getEndOfWordCommand(line, pos);
string cmd = line.substr(pos, endOfWordPos - pos);
addDoxyCommand(m_tokenList, cmd);
if (cmd == CMD_HTML_ONLY || cmd == CMD_VERBATIM || cmd == CMD_LATEX_1 || cmd == CMD_LATEX_2 || cmd == CMD_LATEX_3) {
// A flag for whether we want to skip leading spaces after the command
bool skipLeadingSpace = true;
if (cmd == CMD_HTML_ONLY || cmd == CMD_VERBATIM || cmd == CMD_LATEX_1 || cmd == CMD_LATEX_2 || cmd == CMD_LATEX_3 || getBaseCommand(cmd) == CMD_CODE) {
m_isVerbatimText = true;
} else {
// Skipping leading space is necessary with inline \code command,
// and it won't hurt anything for block \code (TODO: are the other
// commands also compatible with skip leading space? If so, just
// do it every time.)
if (getBaseCommand(cmd) == CMD_CODE) skipLeadingSpace = true;
else skipLeadingSpace = false;
}
if (skipLeadingSpace) {
// skip any possible spaces after command, because some commands have parameters,
// and spaces between command and parameter must be ignored.
if (endOfWordPos != string::npos) {
endOfWordPos = line.find_first_not_of(" \t", endOfWordPos);
}
}
pos = endOfWordPos;
}

View file

@ -21,6 +21,11 @@
#include "doxyentity.h"
// Utility function to return the base part of a command that may
// include options, e.g. param[in] -> param
std::string getBaseCommand(const std::string &cmd);
class DoxygenParser {
private:

View file

@ -334,7 +334,7 @@ std::string JavaDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
void JavaDocConverter::translateEntity(DoxygenEntity &tag, std::string &translatedComment) {
std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
it = tagHandlers.find(tag.typeOfEntity);
it = tagHandlers.find(getBaseCommand(tag.typeOfEntity));
if (it != tagHandlers.end()) {
(this->*(it->second.first))(tag, translatedComment, it->second.second);

View file

@ -174,7 +174,8 @@ static string padCodeAndVerbatimBlocks(const string &docString) {
} else {
if (lastLineWasNonBlank &&
(line.compare(pos, 13, ".. code-block") == 0 ||
line.compare(pos, 7, ".. math") == 0)) {
line.compare(pos, 7, ".. math") == 0 ||
line.compare(pos, 3, ">>>") == 0)) {
// Must separate code or math blocks from the previous line
result += '\n';
}
@ -184,6 +185,21 @@ static string padCodeAndVerbatimBlocks(const string &docString) {
return result;
}
// Helper function to extract the option value from a command,
// e.g. param[in] -> in
static std::string getCommandOption(const std::string &command, char openChar, char closeChar) {
string option;
size_t opt_begin, opt_end;
opt_begin = command.find(openChar);
opt_end = command.find(closeChar);
if (opt_begin != string::npos && opt_end != string::npos)
option = command.substr(opt_begin+1, opt_end-opt_begin-1);
return option;
}
/* static */
PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler) {
return make_pair(handler, std::string());
@ -245,7 +261,7 @@ void PyDocConverter::fillStaticTables() {
tagHandlers["date"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["deprecated"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["details"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["em"] = make_handler(&PyDocConverter::handleParagraph, " ");
tagHandlers["em"] = make_handler(&PyDocConverter::handleTagWrap, "*");
tagHandlers["example"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["exception"] = tagHandlers["throw"] = tagHandlers["throws"] = make_handler(&PyDocConverter::handleTagException);
tagHandlers["htmlonly"] = make_handler(&PyDocConverter::handleParagraph);
@ -254,7 +270,7 @@ void PyDocConverter::fillStaticTables() {
tagHandlers["link"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["manonly"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["note"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["p"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["p"] = make_handler(&PyDocConverter::handleTagWrap, "``");
tagHandlers["partofdescription"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["rtfonly"] = make_handler(&PyDocConverter::handleParagraph);
tagHandlers["remark"] = make_handler(&PyDocConverter::handleParagraph);
@ -428,6 +444,23 @@ std::string PyDocConverter::getParamType(std::string param) {
return type;
}
std::string PyDocConverter::getParamValue(std::string param) {
std::string value;
ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
for (Parm *p = plist; p; p = nextSibling(p)) {
String *pname = Getattr(p, "name");
if (Char(pname) != param)
continue;
String *pval = Getattr(p, "value");
if (pval) value = Char(pval);
break;
}
Delete(plist);
return value;
}
std::string PyDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
std::string translatedComment;
@ -456,7 +489,7 @@ std::string PyDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
void PyDocConverter::translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment) {
// check if we have needed handler and call it
std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
it = tagHandlers.find(doxyEntity.typeOfEntity);
it = tagHandlers.find(getBaseCommand(doxyEntity.typeOfEntity));
if (it != tagHandlers.end())
(this->*(it->second.first)) (doxyEntity, translatedComment, it->second.second);
}
@ -531,19 +564,29 @@ void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComme
trimWhitespace(translatedComment);
// Use the current indent for the code-block line itself.
translatedComment += indent.getFirstLineIndent();
// Go out on a limb and assume that examples in the C or C++ sources use C++.
// In the worst case, we'll highlight C code using C++ syntax which is not a
// big deal (TODO: handle Doxygen code command language argument).
translatedComment += ".. code-block:: c++\n\n";
// Specify the level of extra indentation that will be used for
// subsequent lines within the code block. Note that the correct
// "starting indentation" is already present in the input, so we
// only need to add the desired code block indentation.
string codeIndent = m_indent;
// Check for an option given to the code command (e.g. code{.py}),
// and try to set the code-block language accordingly.
string option = getCommandOption(tag.typeOfEntity, '{', '}');
// Set up the language option to the code-block command, which can
// be any language supported by pygments:
string codeLanguage;
if (option == ".py")
// Other possibilities here are "default" or "python3". In Sphinx
// 2.1.2, basic syntax doesn't render quite the same in these as
// with "python", which for basic keywords seems to provide
// slightly richer formatting. Another option would be to leave
// the language empty, but testing with Sphinx 1.8.5 has produced
// an error "1 argument required".
codeLanguage = "python";
else if (option == ".java")
codeLanguage = "java";
else if (option == ".c")
codeLanguage = "c";
else
// If there is not a match, or if no option was given, go out on a
// limb and assume that the examples in the C or C++ sources use
// C++.
codeLanguage = "c++";
std::string code;
handleTagVerbatim(tag, code, arg);
@ -552,6 +595,27 @@ void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComme
// command:
eraseLeadingNewLine(code);
// Check for python doctest blocks, and treat them specially:
bool isDocTestBlock = false;
size_t startPos;
// ">>>" would normally appear at the beginning, but doxygen comment
// style may have space in front, so skip leading whitespace
if ((startPos=code.find_first_not_of(" \t")) != string::npos && code.substr(startPos,3) == ">>>")
isDocTestBlock = true;
string codeIndent;
if (! isDocTestBlock) {
// Use the current indent for the code-block line itself.
translatedComment += indent.getFirstLineIndent();
translatedComment += ".. code-block:: " + codeLanguage + "\n\n";
// Specify the level of extra indentation that will be used for
// subsequent lines within the code block. Note that the correct
// "starting indentation" is already present in the input, so we
// only need to add the desired code block indentation.
codeIndent = m_indent;
}
translatedComment += codeIndent;
for (size_t n = 0; n < code.length(); n++) {
if (code[n] == '\n') {
@ -636,8 +700,26 @@ void PyDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedC
const std::string &paramName = paramNameEntity.data;
const std::string paramType = getParamType(paramName);
const std::string paramValue = getParamValue(paramName);
// Get command option, e.g. "in", "out", or "in,out"
string commandOpt = getCommandOption(tag.typeOfEntity, '[', ']');
if (commandOpt == "in,out") commandOpt = "in/out";
// If provided, append the parameter direction to the type
// information via a suffix:
std::string suffix;
if (commandOpt.size() > 0)
suffix = ", " + commandOpt;
// If the parameter has a default value, flag it as optional in the
// generated type definition. Particularly helpful when the python
// call is generated with *args, **kwargs.
if (paramValue.size() > 0)
suffix += ", optional";
if (!paramType.empty()) {
translatedComment += ":type " + paramName + ": " + paramType + "\n";
translatedComment += ":type " + paramName + ": " + paramType + suffix + "\n";
translatedComment += indent.getFirstLineIndent();
}
@ -909,3 +991,4 @@ String *PyDocConverter::makeDocumentation(Node *n) {
return NewString(pyDocString.c_str());
}

View file

@ -178,6 +178,11 @@ protected:
*/
std::string getParamType(std::string name);
/*
* Simple helper function to retrieve the parameter value
*/
std::string getParamValue(std::string name);
private:
// temporary thing, should be refactored somehow
Node *currentNode;