Doxygen

From FreeCAD Documentation
Revision as of 02:13, 17 July 2019 by Vocx (talk | contribs) (→‎Second style: documentation block before the code: In the following example the documentation blocks start with a double pound sign ##.)
Future home of tutorial how to write doxygen for FreeCAD Source_documentation#How_to_integrate_doxygen_in_to_the_FreeCAD_source_code

Doxygen is a popular tool for generating documentation from annotated C++ sources, but it also supports other popular programming languages such as C#, PHP, Java, and Python. Visit Doxygen website to learn more about the system.

This document gives a brief introduction to Doxygen, in particular how it is used with FreeCAD to document its sources. See the Doxygen Manual for the full information on its usage.

Doxygen with C++ code

The Getting started (Step 3) section of the Doxygen manual mentions the basic ways of documenting the sources.

For members, classes and namespaces there are basically two options:

  1. Place a special "documentation block" in front of the declaration or definition of the function, member, class or namespace. For file, class and namespace members it is also allowed to place the documentation directly after the member. See section Special comment blocks to learn more about these blocks.
  2. Place a special documentation block somewhere else (another file or another location) and put a "structural command" in the documentation block. A structural command links a documentation block to a certain entity that can be documented (e.g. a function, member, class, namespace or file). See section Documentation at other places to learn more about structural commands.

Note:

  • The advantage of the first option is that you do not have to repeat the name of the entity (function, member, class, or namespace), as Doxygen will analyze the code and extract the relevant information.
  • Files can only be documented using the second option, since there is no way to put a documentation block before a file. Of course, file members (functions, variables, typedefs, defines) do not need an explicit structural command; just putting a special documentation block before or after them will work fine.

First style: documentation block before the code

Usually you'd want to document the code in the header file, just before the class declaration or function prototype. This keeps the declaration and documentation close to each other, so it's easy to update the latter one if the first one changes.

The special documentation block starts like a C-style comment /* but has an additional asterisk, so /**. The block ends with a matching */. An alternative is using C++-style comments // with an additional slash, so ///.

/**
 * Returns the name of the workbench object.
 */
std::string name() const;

/**
 * Set the name to the workbench object.
 */
void setName(const std::string&);

/// remove the added TaskWatcher
void removeTaskWatcher(void);

Second style: documentation block elsewhere

Alternatively, the documentation can be placed in another file (or in the same file at the top or bottom, or wherever), away from the class declaration or function prototype. In this case, you will have duplicated information, once in the actual source file, and once in the documentation file.

First file, source.h:

std::string name() const;
void setName(const std::string&);

Second file, source.h.dox:

/** \file source.h
 *  \brief The documentation of source.h
 *   
 *   The details of this file go here.
 */

/** \fn std::string name() const;
 *  \brief Returns the name of the workbench object.
 */
/** \fn void setName(const std::string&);
 *  \brief Set the name to the workbench object.
 */

In this case the structural command \file is used to indicate which source file is being documented; a structural command \fn indicates that the following code is a function, and the command \brief is used to give a small description of this function.

This way of documenting a source file is useful if you just want to add documentation to your project without adding real code. When you place a comment block in a file with one of the following extensions .dox, .txt, or .doc then Doxygen will parse the comments and build the appropriate documentation, but it will hide this auxiliary file from the file list.

The FreeCAD project adds several files ending in .dox in many directories in order to provide a description, or examples, of the code there. It is important that such files are correctly categorized in a group or namespace, for which Doxygen provides some auxiliary commands like \defgroup, \ingroup, and \namespace.

Example src/Base/core-base.dox; this file in FreeCAD's source tree gives a short explanation of the Base namespace.

/** \defgroup BASE Base
 *  \ingroup CORE
    \brief Basic structures used by other FreeCAD components
    
    The Base module includes most of the basic functions of FreeCAD, such as:
    - Console services: printing different kinds of messages to the FreeCAD report view or the terminal
    - Python interpreter: handles the execution of Python code in FreeCAD
    - Parameter handling: Management, saving and restoring of user preferences settings
    - Units: Management and conversion of different units

*/

/*! \namespace Base
    \ingroup BASE
    \brief Basic structures used by other FreeCAD components

    The Base module includes most of the basic functions of FreeCAD, such as:
    - Console services: printing different kinds of messages to the FreeCAD report view or the terminal
    - Python interpreter: handles the execution of Python code in FreeCAD
    - Parameter handling: Management, saving and restoring of user preferences settings
    - Units: Management and conversion of different units
*/

Another example is the file src/Gui/Command.cpp. Before the implementation details of the Gui::Command methods, there is a documentation block that explains some details of the command framework of FreeCAD. It has various \section commands to structure the documentation. It even includes example code enclosed in a pair of \code and \endcode keywords; when the file is processed by Doxygen this code example will be specially formatted to stand out. The \ref keyword is used in several places to create links to named sections, subsections, pages or anchors elsewhere in the documentation. Similarly, the \see or \sa commands print "See also" and provide a link to other classes, functions, methods, variables, files or URLs.

Example src/Gui/Command.cpp

/** \defgroup commands Command Framework
    \ingroup GUI
    \brief Structure for registering commands to the FreeCAD system
 * \section Overview
 * In GUI applications many commands can be invoked via a menu item, a toolbar button or an accelerator key. The answer of Qt to master this
 * challenge is the class \a QAction. A QAction object can be added to a popup menu or a toolbar and keep the state of the menu item and
 * the toolbar button synchronized.
 *
 * For example, if the user clicks the menu item of a toggle action then the toolbar button gets also pressed
 * and vice versa. For more details refer to your Qt documentation.
 *
 * \section Drawbacks
 * Since QAction inherits QObject and emits the \a triggered() signal or \a toggled() signal for toggle actions it is very convenient to connect
 * these signals e.g. with slots of your MainWindow class. But this means that for every action an appropriate slot of MainWindow is necessary
 * and leads to an inflated MainWindow class. Furthermore, it's simply impossible to provide plugins that may also need special slots -- without
 * changing the MainWindow class.
 *
 * \section wayout Way out
 * To solve these problems we have introduced the command framework to decouple QAction and MainWindow. The base classes of the framework are
 * \a Gui::CommandBase and \a Gui::Action that represent the link between Qt's QAction world and the FreeCAD's command world. 
 *
 * The Action class holds a pointer to QAction and CommandBase and acts as a mediator and -- to save memory -- that gets created 
 * (@ref Gui::CommandBase::createAction()) not before it is added (@ref Gui::Command::addTo()) to a menu or toolbar.
 *
 * Now, the implementation of the slots of MainWindow can be done in the method \a activated() of subclasses of Command instead.
 *
 * For example, the implementation of the "Open file" command can be done as follows.
 * \code
 * class OpenCommand : public Command
 * {
 * public:
 *   OpenCommand() : Command("Std_Open")
 *   {
 *     // set up menu text, status tip, ...
 *     sMenuText     = "&Open";
 *     sToolTipText  = "Open a file";
 *     sWhatsThis    = "Open a file";
 *     sStatusTip    = "Open a file";
 *     sPixmap       = "Open"; // name of a registered pixmap
 *     sAccel        = "Shift+P"; // or "P" or "P, L" or "Ctrl+X, Ctrl+C" for a sequence
 *   }
 * protected:
 *   void activated(int)
 *   {
 *     QString filter ... // make a filter of all supported file formats
 *     QStringList FileList = QFileDialog::getOpenFileNames( filter,QString::null, getMainWindow() );
 *     for ( QStringList::Iterator it = FileList.begin(); it != FileList.end(); ++it ) {
 *       getGuiApplication()->open((*it).latin1());
 *     }
 *   }
 * };
 * \endcode
 * An instance of \a OpenCommand must be created and added to the \ref Gui::CommandManager to make the class known to FreeCAD.
 * To see how menus and toolbars can be built go to the @ref workbench.
 *
 * @see Gui::Command, Gui::CommandManager
 */

Doxygen markup

All Doxygen documentation commands start with a backslash \ or an at-sign @, at your preference. Normally the backslash \ is used, but occasionally the @-sign is used to improve readability.

The commands can have one or more arguments. In the Doxygen manual the arguments are described as follows.

  • If <sharp> braces are used the argument is a single word.
  • If (round) braces are used the argument extends until the end of the line on which the command was found.
  • If {curly} braces are used the argument extends until the next paragraph. Paragraphs are delimited by a blank line or by a section indicator.
  • If [square] brackets are used the argument is optional.

Some of the most common keywords used in the FreeCAD documentation are

  • \defgroup <name> (group title) , see \defgroup, and Grouping.
  • \ingroup (<groupname> [<groupname> <groupname>]), see \ingroup, and Grouping.
  • \addtogroup <name> [(title)], see \addtogroup, and Grouping.
  • \author { list of authors }, see \author; indicates the author of this piece of code.
  • \brief { brief description }, see \brief; briefly describes the function.
  • \file [<name>], see \file; documents a source or header file.
  • \page <name> (title), see \page; puts the information in a separate page, not directly related to one specific class, file or member.
  • \package <name>, see \package; indicates documentation for a Java package (but also used with Python).
  • \fn (function declaration), see \fn; documents a function.
  • \section <section-name> (section title), see \section; starts a section.
  • \subsection <subsection-name> (subsection title), see \subsection; starts a subsection.
  • \namespace <name>, see \namespace; indicates information for a namespace.
  • \cond [(section-label)], and \endcond, see \cond; defines a block to conditionally document or omit.
  • \a <word>, see \a; displays the argument in italics for emphasis.
  • \param [(dir)] <parameter-name> { parameter description }, see \param; indicates the parameter of a function.
  • \return { description of the return value }, see \return; specifies the return value.
  • \sa { references }, see \sa; prints "See also".
  • \note { text }, see \note; adds a paragraph to be used as a note.

Doxygen with Python code

Doxygen works best for statically typed languages like C++. However, it can also create documentation for Python files.

There are two ways to comment Python:

  1. The Pythonic way, using "docstrings", that is, a pair of triple quotes ''' immediately after the class or function definition.
  2. The Doxygen way, putting comments before the class or function definition; in this case double pound signs ## should start the comment, and then single pound signs can be used in subsequent lines.

Note:

  • The first option is preferred to comply with PEP8, PEP257 and most style guidelines for writing Python (see 1, 2). However, in this way Doxygen special commands don't work.
  • The second option isn't the traditional Python style, but it allows you to use Doxygen's special commands like \param and \var.

First style: Pythonic documentation

In the following example one docstring is at the beginning to explain the general contents of this module (file). Then docstrings appear inside the function, class, and class method definitions. In this way, Doxygen will extract the comments and present them as is, without modification.

'''@package docstring
Documentation for this module.
More details.
'''
def func():
    '''Documentation for a function.
    More details.
    '''
    pass
class PyClass:
    '''Documentation for a class.
    More details.
    '''
   
    def __init__(self):
        '''The constructor.'''
        self._memVar = 0
   
    def PyMethod(self):
        '''Documentation for a method.'''
        pass

Second style: documentation block before the code

In the following example the documentation blocks start with a double pound sign ##. One appears at the beginning to explain the general content of this module (file). Then there are blocks before the function, class, and class method definitions, and there is one block after a variable. In this way, Doxygen will extract the documentation, recognize the special commands @package, @param, and @var, and format the text accordingly.

## @package pyexample
#  Documentation for this module.
#
#  More details.
## Documentation for a function.
#
#  More details.
def func():
    pass
## Documentation for a class.
#
#  More details.
class PyClass:
   
    ## The constructor.
    def __init__(self):
        self._memVar = 0
   
    ## Documentation for a method.
    #  @param self The object pointer.
    def PyMethod(self):
        pass
     
    ## A class variable.
    classVar = 0;
    ## @var _memVar
    #  a member variable

Markdown support

Since Doxygen 1.8, Markdown syntax is recognized in documentation blocks. Markdown is a minimalistic formatting language inspired by plain text email which, similar to wiki syntax, intends to be simple and readable without requiring complicated code like that found in HTML, LaTeX or Doxygen's own commands. Markdown has gained popularity with free software, especially in online platforms like Github, as it allows creating documentation without using complicated code. See the Markdown support section in the Doxygen manual to learn more. Visit the Markdown website to learn more about the origin and philosophy of Markdown.

Doxygen supports a standard set of Markdown instructions, as well as some extensions such as Github Markdown. Just like other Doxygen special commands, Markdown formatted text must be inside a documentation block.

Some basic Markdown formatting is presented next.

Here is text for one paragraph.

We continue with more text in another paragraph.

This is a level 1 header
========================

This is a level 2 header
------------------------

# This is a level 1 header

### This is level 3 header #######

> This is a block quote
> spanning multiple lines

- Item 1

  More text for this item.

- Item 2
  * nested list item.
  * another nested item.
- Item 3

1. First item.
2. Second item.

*single asterisks: emphasis*

 _single underscores_

 **double asterisks: strong emphasis**

 __double underscores__

This a normal paragraph

    This is a code block

We continue with a normal paragraph again.

Use the `printf()` function. Inline `code`.

[The link text](http://example.net/)

![Caption text](/path/to/img.jpg)

<http://www.example.com>

First Header  | Second Header
------------- | -------------
Content Cell  | Content Cell 
Content Cell  | Content Cell 

~~~~~~~~~~~~~{.py}
# A class
class Dummy:
    pass
~~~~~~~~~~~~~

~~~~~~~~~~~~~{.c}
int func(int a,int b) { return a*b; }
~~~~~~~~~~~~~

```
int func(int a,int b) { return a*b; }
```

Parsing of documentation blocks

The text inside a special documentation block is parsed before it is written to the HTML and LaTeX output files. During parsing the following steps take place:

  • Markdown formatting is replaced by corresponding HTML or special commands.
  • The special commands inside the documentation are executed. See the section Special Commands in the manual for an explanation of each command.
  • If a line starts with some whitespace followed by one or more asterisks (*) and then optionally more whitespace, then all whitespace and asterisks are removed.
  • All resulting blank lines are treated as paragraph separators.
  • Links are automatically created for words corresponding to documented classes or functions. If the word is preceded by a percentage symbol %, then this symbol is removed, and no link is created for the word.
  • Links are created when certain patterns are found in the text. See the section Automatic link generation in the manual for more information.
  • HTML tags that are in the documentation are interpreted and converted to LaTeX equivalents for the LaTeX output. See the section HTML Commands in the manual for an explanation of each supported HTML tag.

FreeCAD doxygen

FC doxygen formatting

The FC project has chosen the following method for it's doxygen comment blocks: As it's special char of choice

  • \note ex. \note added in FreeCAD 0.17

Note: Please also read: https://github.com/FreeCAD/FreeCAD/blob/master/src/Doc/doctips.dox