| .. _docs-style-doxygen: |
| |
| =================== |
| Doxygen style guide |
| =================== |
| .. _Doxygen: https://www.doxygen.nl/index.html |
| |
| ``pigweed.dev`` uses `Doxygen`_ to auto-generate C and C++ API references |
| from code comments in header files. These specially formatted comments are |
| called **Doxygen comments**. This style guide shows you how to format Doxygen |
| comments and other related documentation. |
| |
| .. _docs-style-doxygen-quickstart: |
| |
| ---------- |
| Quickstart |
| ---------- |
| Auto-generating an API reference on ``pigweed.dev`` requires interacting with |
| a few different tools. This section provides an overview of when you interact |
| with each tool, using ``pw_i2c`` as an example. |
| |
| .. inclusive-language: disable |
| |
| .. _//pw_i2c/public/pw_i2c/device.h: https://cs.opensource.google/pigweed/pigweed/+/4c1a7158b663f114c297d9c0a806f412768e73f8:pw_i2c/public/pw_i2c/device.h |
| .. _Breathe directives: https://breathe.readthedocs.io/en/latest/directives.html |
| .. _Sphinx: https://www.sphinx-doc.org/en/master/ |
| .. _//pw_i2c/reference.rst: https://cs.opensource.google/pigweed/pigweed/+/4c1a7158b663f114c297d9c0a806f412768e73f8:pw_i2c/reference.rst;l=44 |
| .. _//docs/BUILD.gn: https://cs.opensource.google/pigweed/pigweed/+/4c1a7158b663f114c297d9c0a806f412768e73f8:docs/BUILD.gn;l=192 |
| |
| .. inclusive-language: enable |
| |
| #. Annotate your header file using `Doxygen`_ syntax. All of the comments |
| that start with triple slashes (``///``) are Doxygen comments. Doxygen |
| ignores double slash (``//``) comments. |
| |
| Example: `//pw_i2c/public/pw_i2c/device.h`_ |
| |
| #. Include the API reference content into a reStructuredText file using |
| `Breathe directives`_. Breathe is the bridge between Doxygen and `Sphinx`_, |
| the documentation generator that powers ``pigweed.dev``. See |
| :ref:`docs-style-doxygen-breathe-overview` for more explanation. |
| |
| Example: `//pw_i2c/reference.rst`_ |
| |
| #. Add your header file's path to the ``_doxygen_input_files`` list in |
| ``//docs/BUILD.gn``. The docs build system throws a "symbol not found" |
| errors if you forget this step. |
| |
| Example: `//docs/BUILD.gn`_ |
| |
| .. _docs-style-doxygen-writing: |
| |
| --------------------------- |
| API reference writing style |
| --------------------------- |
| .. _API reference code comments: https://developers.google.com/style/api-reference-comments |
| |
| Follow the guidance in `API reference code comments`_. |
| |
| .. _docs-style-doxygen-comment-style: |
| |
| --------------------- |
| Doxygen comment style |
| --------------------- |
| This section explains how you should style the comments within header files |
| that Doxygen converts into API references. |
| |
| .. _docs-style-doxygen-comment-syntax: |
| |
| Comment syntax |
| ============== |
| Use the triple slash (``///``) syntax. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// ... |
| /// ... |
| |
| .. _docs-style-doxygen-special-command-syntax: |
| |
| Special command syntax |
| ====================== |
| .. _Special commands: https://www.doxygen.nl/manual/commands.html |
| |
| `Special commands`_ like ``@code`` and ``@param`` are the core annotation |
| tools of Doxygen. Doxygen recognizes words that begin with either backslashes |
| (``\``) or at symbols (``@``) as special commands. For example, ``\code`` and |
| ``@code`` are synonyms. Always use the at symbol (``@``) format. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @param[out] dest The memory area to copy to. |
| |
| .. admonition:: **No** |
| :class: error |
| |
| .. code-block:: none |
| |
| /// \param dest The memory area to copy to. |
| |
| .. _docs-style-doxygen-structural-commands: |
| |
| Structural commands |
| =================== |
| .. _Doxygen structural commands: https://doxygen.nl/manual/docblocks.html#structuralcommands |
| |
| `Doxygen structural commands`_ like ``@struct``, ``@fn``, ``@class``, and ``@file`` |
| associate a comment to a symbol. Don't use structural commands if they're not |
| needed. In other words, if your Doxygen comment renders correctly without the |
| structural command, don't use it. |
| |
| Code examples |
| ============= |
| Use ``@code{.cpp}`` followed by the code example followed by ``@endcode``. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @code{.cpp} |
| /// #include "pw_kvs/key_value_store.h" |
| /// #include "pw_kvs/flash_test_partition.h" |
| /// |
| /// ... |
| /// @endcode |
| |
| Omit or change ``{.cpp}`` if your code example isn't C++ code. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @code |
| /// START + I2C_ADDRESS + WRITE(0) + TX_BUFFER_BYTES + STOP |
| /// START + I2C_ADDRESS + READ(1) + RX_BUFFER_BYTES + STOP |
| /// @endcode |
| |
| .. _docs-style-doxygen-params: |
| |
| Parameters |
| ========== |
| Use ``@param[<direction>] <name> <description>`` for each parameter. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @param[out] dest The memory area to copy to. |
| /// @param[in] src The memory area to copy from. |
| /// @param[in] n The number of bytes to copy. |
| |
| Put a newline between the parameters if you need multi-line descriptions. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @param[out] dest Lorem ipsum dolor sit amet, consectetur adipiscing |
| /// elit, sed do eiusmod tempor incididunt ut labore et dolore magna... |
| /// |
| /// @param[in] src The memory area to copy from. |
| /// |
| /// @param[in] n The number of bytes to copy. |
| |
| The direction annotation is required. |
| |
| .. admonition:: **No** |
| :class: error |
| |
| .. code-block:: none |
| |
| /// @param dest The memory area to copy to. |
| /// @param src The memory area to copy from. |
| /// @param n The number of bytes to copy. |
| |
| ``<direction>`` must be specified and the value must be either ``in`` or |
| ``out``. |
| |
| .. _docs-style-doxygen-pre: |
| |
| Preconditions |
| ============= |
| Use ``@pre <description>``. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @pre Description of a precondition that must be satisifed before |
| /// invoking this function. |
| |
| Deprecated features |
| =================== |
| Use ``@deprecated <description>``. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @deprecated This function, class, or other entity is deprecated. Use |
| /// the replacement instead. |
| |
| .. _docs-style-doxygen-pw_status: |
| |
| pw_status codes |
| =============== |
| Use the following syntax when referring to ``pw_status`` codes: |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| @pw_status{...} |
| |
| Replace ``...`` with a valid ``pw_status`` code. See |
| :ref:`module-pw_status-quickref`. |
| |
| Doxygen converts this alias into a link to the status code's reference |
| documentation. |
| |
| Don't use this syntax for functions or methods that return a set of |
| status codes. Use ``pw-status-codes``. See :ref:`pw-status-codes`. |
| |
| .. _pw-status-codes: |
| |
| Functions and methods that return pw::Status codes |
| ================================================== |
| Use ``pw-status-codes`` to present the set of codes and descriptions as a |
| two-column table: |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @returns @rst |
| /// |
| /// .. pw-status-codes:: |
| /// |
| /// <code>: <description> |
| /// |
| /// <code>: <description> |
| /// |
| /// @endrst |
| |
| Example: |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @returns @rst |
| /// |
| /// .. pw-status-codes:: |
| /// |
| /// OK: The bulk read was successful. |
| /// |
| /// RESOURCE_EXHAUSTED: The remaining space is too small to hold a |
| /// new block. |
| /// |
| /// @endrst |
| |
| * Each ``<code>`` must be a valid :ref:`status code <module-pw_status-codes>`. |
| The part before the colon must be plaintext. |
| * Each ``<description>`` should explain further what the code means in this |
| particular scenario. The description must be a single paragraph. It can use |
| inline reStructuredText features such as code formatting and cross-references. |
| * ``pw-status-codes`` needs to be wrapped in ``@rst`` and ``@endrst`` |
| because it's a reStructuredText directive and Doxygen doesn't natively |
| support reST. The implementation is at |
| ``//pw_docgen/py/pw_docgen/sphinx/pw_status_codes.py``. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: none |
| |
| /// @returns @rst |
| /// |
| /// .. pw-status-codes:: |
| /// |
| /// OK: Data successfully written to ``buffer``. |
| /// |
| /// RESOURCE_EXHAUSTED: The remaining space is too small to hold a |
| /// new block. See :ref:`module-pw_example-troubleshooting`. |
| /// |
| /// @endrst |
| |
| It's OK to use reStructuredText features like code formatting and |
| cross-references within the descriptions. The status code itself |
| must be plaintext. |
| |
| .. admonition:: **No** |
| :class: error |
| |
| .. code-block:: none |
| |
| /// @returns @rst |
| /// |
| /// .. pw-status-codes:: |
| /// |
| /// RESOURCE_EXHAUSTED: The remaining space is too small to hold a |
| /// new block. |
| /// |
| /// @endrst |
| |
| For items that span multiple lines, don't use whitespace like this. |
| |
| .. _docs-style-doxygen-namespaces: |
| |
| Use fully namespaced names |
| ========================== |
| In general, write out the full namespace to Pigweed classes, methods, and |
| so on. If you're writing a code sample, and that code sample clearly shows |
| where the item comes from via a ``using`` statement, you don't need to use |
| full namespacing. |
| |
| .. admonition:: Discussion |
| |
| Pigweed has over 160 modules. It can be overwhelming for beginners |
| to figure out where an item is coming from. |
| |
| .. _docs-style-doxygen-multisymbol: |
| |
| Single comment block for multiple symbols |
| ========================================= |
| Use ``@def <symbol>`` followed by the comment block. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: cpp |
| |
| /// @def PW_ASSERT_EXCLUSIVE_LOCK |
| /// @def PW_ASSERT_SHARED_LOCK |
| /// |
| /// Documents functions that dynamically check to see if a lock is held, and |
| /// fail if it is not held. |
| |
| .. _docs-style-doxygen-xrefs: |
| |
| Cross-references (x-refs) |
| ========================= |
| |
| .. _docs-style-doxygen-xrefs-comments: |
| |
| X-refs in Doxygen comments |
| -------------------------- |
| For C or C++ x-refs, use one of the following aliases: |
| |
| .. csv-table:: |
| :header: Alias, reStructuredText equivalent |
| |
| ``@c_macro{<identifier>}``, ``:c:macro:`<identifier>``` |
| ``@cpp_func{<identifier>}``, ``:cpp:func:`<identifier>``` |
| ``@cpp_class{<identifier>}``, ``:cpp:class:`<identifier>``` |
| ``@cpp_type{<identifier>}``, ``:cpp:type:`<identifier>``` |
| |
| .. inclusive-language: disable |
| |
| .. _Sphinx Domain: https://www.sphinx-doc.org/en/master/usage/domains/index.html |
| |
| .. inclusive-language: enable |
| |
| For all other x-refs, use Pigweed's custom basic alias, |
| ``@crossref{<domain>,<type>,<identifier>}``. ``<domain>`` must be a valid |
| `Sphinx Domain`_ and ``<type>`` must be a valid type within that domain. |
| ``@crossref`` can be used with any domain. |
| |
| Avoid Doxygen x-refs |
| ^^^^^^^^^^^^^^^^^^^^ |
| Always use Pigweed's custom aliases for x-refs unless you have specific |
| reasons not to do so. Pigweed's x-ref aliases are built on top of Sphinx. |
| Doxygen provides its own features for x-refs but they should be avoided |
| because Sphinx's are better: |
| |
| * Sphinx x-refs work for all identifiers known to Sphinx, including |
| those documented with directives like ``.. cpp:class::`` or extracted from |
| Python. Doxygen references can only refer to identifiers known to Doxygen. |
| * Sphinx x-refs always use consistent formatting. Doxygen |
| x-refs sometimes render as plaintext instead of code-style |
| monospace, or include ``()`` in macros that shouldn’t have them. |
| * Sphinx x-refs can refer to symbols that haven't yet been documented. |
| They will be formatted correctly and become links once the symbols are |
| documented. |
| |
| Using Sphinx x-refs in Doxygen comments makes x-ref syntax more consistent |
| within Doxygen comments and between reStructuredText and Doxygen. |
| |
| .. _docs-style-doxygen-xrefs-rest: |
| |
| Cross-references in reST to Doxygen symbols |
| ------------------------------------------- |
| After you've used Doxygen to generate API references, you can link to those |
| symbols from your reStructuredText with standard Sphinx x-ref |
| syntax. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: rst |
| |
| :cpp:class:`pw::sync::BinarySemaphore::BinarySemaphore` |
| |
| .. inclusive-language: disable |
| |
| .. _domain: https://www.sphinx-doc.org/en/master/usage/domains/index.html |
| .. _C++ Domain: https://www.sphinx-doc.org/en/master/usage/domains/cpp.html |
| .. _C Domain: https://www.sphinx-doc.org/en/master/usage/domains/c.html |
| .. _Python Domain: https://www.sphinx-doc.org/en/master/usage/domains/python.html |
| |
| .. inclusive-language: enable |
| |
| In the Sphinx docs the reference documentation for x-ref syntax is |
| provided in the `domain`_ docs: |
| |
| * `C++ Domain`_ |
| * `C Domain`_ |
| * `Python Domain`_ |
| |
| .. _docs-style-doxygen-embedded-rest: |
| |
| Embedded reStructuredText |
| ========================= |
| To use reStructuredText (reST) within a Doxygen comment, wrap the reST |
| in ``@rst`` and ``@endrst``. |
| |
| .. _docs-style-doxygen-breathe: |
| |
| ------- |
| Breathe |
| ------- |
| .. _Breathe: https://breathe.readthedocs.io |
| |
| This section provides guidance on how `Breathe`_ should and shouldn't be used |
| when authoring ``pigweed.dev`` docs. |
| |
| .. _docs-style-doxygen-breathe-overview: |
| |
| Overview |
| ======== |
| .. inclusive-language: disable |
| |
| .. _Breathe directives: https://breathe.readthedocs.io/en/latest/directives.html |
| .. _Sphinx: https://www.sphinx-doc.org/en/master/ |
| |
| .. inclusive-language: enable |
| |
| After you annotate your header comments as Doxygen comments, you need to |
| specify where to render the API reference within the ``pigweed.dev`` docs. |
| The reStructuredText files distributed across the main Pigweed repo are |
| the source code for ``pigweed.dev``. Updating these ``.rst`` files is how |
| you surface the API reference on ``pigweed.dev``. Doxygen doesn't natively |
| interact with `Sphinx`_, the documentation generator that powers |
| ``pigweed.dev``. `Breathe`_ is the bridge and API that enables ``pigweed.dev`` |
| and Doxygen to work together. |
| |
| .. _docs-style-doxygen-breathe-doxygenclass: |
| |
| doxygenclass |
| ============ |
| .. _doxygenclass: https://breathe.readthedocs.io/en/latest/directives.html#doxygenclass |
| |
| OK to use. `doxygenclass`_ documents a class and its members. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: rst |
| |
| .. doxygenclass:: pw::sync::BinarySemaphore |
| :members: |
| |
| Classes that are a major part of a Pigweed module's API should have their |
| own section so that they're easy to find in the right-side page nav on |
| ``pigweed.dev``. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: rst |
| |
| .. _module-pw_<name>-reference: |
| |
| ========= |
| Reference |
| ========= |
| .. pigweed-module-subpage:: |
| :name: pw_<name> |
| |
| ... |
| |
| .. _module-pw_<name>-reference-<class>: |
| |
| ------------------- |
| pw::<name>::<class> |
| ------------------- |
| .. doxygenclass:: pw::<name>::<class> |
| :members: |
| |
| .. _docs-style-doxygen-breathe-doxygenfunction: |
| |
| doxygenfunction |
| =============== |
| .. _doxygenfunction: https://breathe.readthedocs.io/en/latest/directives.html#doxygenfunction |
| |
| OK to use. `doxygenfunction` documents a single function or method. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: rst |
| |
| .. doxygenfunction:: pw::tokenizer::EncodeArgs |
| |
| .. _docs-style-doxygen-breathe-doxygendefine: |
| |
| doxygendefine |
| ============= |
| .. _doxygendefine: https://breathe.readthedocs.io/en/latest/directives.html#doxygendefine |
| |
| OK to use. `doxygendefine`_ documents a preprocessor macro. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: rst |
| |
| .. doxygendefine:: PW_TOKENIZE_STRING |
| |
| .. _docs-style-doxygen-breathe-doxygengroup: |
| |
| doxygengroup |
| ============ |
| .. _doxygengroup: https://breathe.readthedocs.io/en/latest/directives.html#doxygengroup |
| |
| `doxygengroup`_ lets you manually mark a set of symbols as belonging to the same |
| conceptual group. |
| |
| ``doxygengroup`` is OK to use when a simple |
| :ref:`docs-style-doxygen-breathe-doxygenclass`-based organization |
| doesn't work well for your module. |
| |
| .. _@defgroup: https://www.doxygen.nl/manual/commands.html#cmddefgroup |
| .. _@addtogroup: https://www.doxygen.nl/manual/commands.html#cmdaddtogroup |
| .. _@ingroup: https://www.doxygen.nl/manual/commands.html#cmdingroup |
| |
| To create a group, annotate your Doxygen comments with `@defgroup`_, |
| `@addtogroup`_, and `@ingroup`_. You can wrap a set of contiguous comments |
| in ``@{`` and ``@}`` to indicate that they all belong to a group. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: cpp |
| |
| /// @defgroup <name> <description> |
| /// @{ |
| /// ... |
| /// @} |
| |
| .. _issue #772: https://github.com/breathe-doc/breathe/issues/772 |
| |
| Don't include namespaces in ``doxygengroup`` because Breathe doesn't handle |
| them correctly. See `issue #772`_. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: rst |
| |
| .. cpp:namespace:: my_namespace |
| |
| .. doxygengroup:: my_group |
| :content-only: |
| :members: |
| |
| .. _docs-style-doxygen-breathe-doxygentypedef: |
| |
| doxygentypedef |
| ============== |
| .. _doxygentypedef: https://breathe.readthedocs.io/en/latest/directives.html#doxygentypedef |
| |
| OK to use. `doxygentypedef`_ documents a ``typedef`` or ``using`` statement. |
| |
| .. admonition:: **Yes** |
| :class: checkmark |
| |
| .. code-block:: rst |
| |
| .. doxygentypedef:: pw::Function |
| |
| .. _docs-style-doxygen-breathe-doxygenfile: |
| |
| doxygenfile |
| =========== |
| .. _doxygenfile: https://breathe.readthedocs.io/en/latest/directives.html#doxygenfile |
| |
| Don't use `doxygenfile`_. Use :ref:`docs-style-doxygen-breathe-doxygengroup` |
| instead. |
| |
| .. _docs-style-doxygen-disabled-include: |
| |
| ----------------------------------------------- |
| Disabled auto-generated ``#include`` statements |
| ----------------------------------------------- |
| .. note:: |
| |
| This is an FYI section. There's no prescriptive rule here. |
| |
| Doxygen and Breathe have the ability to auto-generate ``#include`` statements |
| for class references. These have been disabled because: |
| |
| * The auto-generated paths are inaccurate. E.g. the ``#include`` for |
| ``pw::string::RandomGenerator`` was generated as ``#include <random.h>`` |
| when it should be ``#include "pw_random/random.h"``. |
| * The auto-generation is not consistent. They seem to only get generated when |
| using the ``doxygennamespace`` directive but ``pigweed.dev`` frequently |
| uses ``doxygenclass``, ``doxygenfunction``, etc. |
| |
| In the future, if it's decided that these ``#include`` statements are needed, |
| there is a way to manually override each one. The code block below shows how |
| it's done. This approach wouldn't be great because it adds a lot of noise to |
| the header files. |
| |
| .. code-block:: |
| |
| /// @class RandomGenerator random.h "pw_random/random.h"`` |
| |
| See `b/295023422 <https://issues.pigweed.dev/issues/295023422>`_. |