xref: /aosp_15_r20/external/pigweed/docs/style/doxygen.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1.. _docs-style-doxygen:
2
3===================
4Doxygen style guide
5===================
6.. _Doxygen: https://www.doxygen.nl/index.html
7
8``pigweed.dev`` uses `Doxygen`_ to auto-generate C and C++ API references
9from code comments in header files. These specially formatted comments are
10called **Doxygen comments**. This style guide shows you how to format Doxygen
11comments and other related documentation.
12
13.. _docs-style-doxygen-quickstart:
14
15----------
16Quickstart
17----------
18Auto-generating an API reference on ``pigweed.dev`` requires interacting with
19a few different tools. This section provides an overview of when you interact
20with each tool, using ``pw_i2c`` as an example.
21
22.. inclusive-language: disable
23
24.. _//pw_i2c/public/pw_i2c/device.h: https://cs.opensource.google/pigweed/pigweed/+/4c1a7158b663f114c297d9c0a806f412768e73f8:pw_i2c/public/pw_i2c/device.h
25.. _Breathe directives: https://breathe.readthedocs.io/en/latest/directives.html
26.. _Sphinx: https://www.sphinx-doc.org/en/master/
27.. _//pw_i2c/reference.rst: https://cs.opensource.google/pigweed/pigweed/+/4c1a7158b663f114c297d9c0a806f412768e73f8:pw_i2c/reference.rst;l=44
28.. _//docs/BUILD.gn: https://cs.opensource.google/pigweed/pigweed/+/4c1a7158b663f114c297d9c0a806f412768e73f8:docs/BUILD.gn;l=192
29
30.. inclusive-language: enable
31
32#. Annotate your header file using `Doxygen`_ syntax. All of the comments
33   that start with triple slashes (``///``) are Doxygen comments. Doxygen
34   ignores double slash (``//``) comments.
35
36   Example: `//pw_i2c/public/pw_i2c/device.h`_
37
38#. Include the API reference content into a reStructuredText file using
39   `Breathe directives`_. Breathe is the bridge between Doxygen and `Sphinx`_,
40   the documentation generator that powers ``pigweed.dev``. See
41   :ref:`docs-style-doxygen-breathe-overview` for more explanation.
42
43   Example: `//pw_i2c/reference.rst`_
44
45#. Add your header file's path to the ``_doxygen_input_files`` list in
46   ``//docs/BUILD.gn``. The docs build system throws a "symbol not found"
47   errors if you forget this step.
48
49   Example: `//docs/BUILD.gn`_
50
51.. _docs-style-doxygen-writing:
52
53---------------------------
54API reference writing style
55---------------------------
56.. _API reference code comments: https://developers.google.com/style/api-reference-comments
57
58Follow the guidance in `API reference code comments`_.
59
60.. _docs-style-doxygen-comment-style:
61
62---------------------
63Doxygen comment style
64---------------------
65This section explains how you should style the comments within header files
66that Doxygen converts into API references.
67
68.. _docs-style-doxygen-comment-syntax:
69
70Comment syntax
71==============
72Use the triple slash (``///``) syntax.
73
74.. admonition:: **Yes**
75   :class: checkmark
76
77   .. code-block:: none
78
79      /// ...
80      /// ...
81
82.. _docs-style-doxygen-special-command-syntax:
83
84Special command syntax
85======================
86.. _Special commands: https://www.doxygen.nl/manual/commands.html
87
88`Special commands`_ like ``@code`` and ``@param`` are the core annotation
89tools of Doxygen. Doxygen recognizes words that begin with either backslashes
90(``\``) or at symbols (``@``) as special commands. For example, ``\code`` and
91``@code`` are synonyms. Always use the at symbol (``@``) format.
92
93.. admonition:: **Yes**
94   :class: checkmark
95
96   .. code-block:: none
97
98      /// @param[out] dest The memory area to copy to.
99
100.. admonition:: **No**
101   :class: error
102
103   .. code-block:: none
104
105      /// \param dest The memory area to copy to.
106
107.. _docs-style-doxygen-structural-commands:
108
109Structural commands
110===================
111.. _Doxygen structural commands: https://doxygen.nl/manual/docblocks.html#structuralcommands
112
113`Doxygen structural commands`_ like ``@struct``, ``@fn``, ``@class``, and ``@file``
114associate a comment to a symbol. Don't use structural commands if they're not
115needed. In other words, if your Doxygen comment renders correctly without the
116structural command, don't use it.
117
118Code examples
119=============
120Use ``@code{.cpp}`` followed by the code example followed by ``@endcode``.
121
122.. admonition:: **Yes**
123   :class: checkmark
124
125   .. code-block:: none
126
127      /// @code{.cpp}
128      ///   #include "pw_kvs/key_value_store.h"
129      ///   #include "pw_kvs/flash_test_partition.h"
130      ///
131      ///   ...
132      /// @endcode
133
134Omit or change ``{.cpp}`` if your code example isn't C++ code.
135
136.. admonition:: **Yes**
137   :class: checkmark
138
139   .. code-block:: none
140
141      /// @code
142      ///   START + I2C_ADDRESS + WRITE(0) + TX_BUFFER_BYTES + STOP
143      ///   START + I2C_ADDRESS + READ(1) + RX_BUFFER_BYTES + STOP
144      /// @endcode
145
146.. _docs-style-doxygen-params:
147
148Parameters
149==========
150Use ``@param[<direction>] <name> <description>`` for each parameter.
151
152.. admonition:: **Yes**
153   :class: checkmark
154
155   .. code-block:: none
156
157      /// @param[out] dest The memory area to copy to.
158      /// @param[in] src The memory area to copy from.
159      /// @param[in] n The number of bytes to copy.
160
161Put a newline between the parameters if you need multi-line descriptions.
162
163.. admonition:: **Yes**
164   :class: checkmark
165
166   .. code-block:: none
167
168      /// @param[out] dest Lorem ipsum dolor sit amet, consectetur adipiscing
169      /// elit, sed do eiusmod tempor incididunt ut labore et dolore magna...
170      ///
171      /// @param[in] src The memory area to copy from.
172      ///
173      /// @param[in] n The number of bytes to copy.
174
175The direction annotation is required.
176
177.. admonition:: **No**
178   :class: error
179
180   .. code-block:: none
181
182      /// @param dest The memory area to copy to.
183      /// @param src The memory area to copy from.
184      /// @param n The number of bytes to copy.
185
186   ``<direction>`` must be specified and the value must be either ``in`` or
187   ``out``.
188
189.. _docs-style-doxygen-pre:
190
191Preconditions
192=============
193Use ``@pre <description>``.
194
195.. admonition:: **Yes**
196   :class: checkmark
197
198   .. code-block:: none
199
200      /// @pre Description of a precondition that must be satisifed before
201      /// invoking this function.
202
203Deprecated features
204===================
205Use ``@deprecated <description>``.
206
207.. admonition:: **Yes**
208   :class: checkmark
209
210   .. code-block:: none
211
212      /// @deprecated This function, class, or other entity is deprecated. Use
213      /// the replacement instead.
214
215.. _docs-style-doxygen-pw_status:
216
217pw_status codes
218===============
219Use the following syntax when referring to ``pw_status`` codes:
220
221.. admonition:: **Yes**
222   :class: checkmark
223
224   .. code-block:: none
225
226      @pw_status{...}
227
228Replace ``...`` with a valid ``pw_status`` code. See
229:ref:`module-pw_status-quickref`.
230
231Doxygen converts this alias into a link to the status code's reference
232documentation.
233
234Don't use this syntax for functions or methods that return a set of
235status codes. Use ``pw-status-codes``. See :ref:`pw-status-codes`.
236
237.. _pw-status-codes:
238
239Functions and methods that return pw::Status codes
240==================================================
241Use ``pw-status-codes`` to present the set of codes and descriptions as a
242two-column table:
243
244.. admonition:: **Yes**
245   :class: checkmark
246
247   .. code-block:: none
248
249      /// @returns @rst
250      ///
251      /// .. pw-status-codes::
252      ///
253      ///    <code>: <description>
254      ///
255      ///    <code>: <description>
256      ///
257      /// @endrst
258
259Example:
260
261.. admonition:: **Yes**
262   :class: checkmark
263
264   .. code-block:: none
265
266      /// @returns @rst
267      ///
268      /// .. pw-status-codes::
269      ///
270      ///    OK: The bulk read was successful.
271      ///
272      ///    RESOURCE_EXHAUSTED: The remaining space is too small to hold a
273      ///    new block.
274      ///
275      /// @endrst
276
277* Each ``<code>`` must be a valid :ref:`status code <module-pw_status-codes>`.
278  The part before the colon must be plaintext.
279* Each ``<description>`` should explain further what the code means in this
280  particular scenario. The description must be a single paragraph. It can use
281  inline reStructuredText features such as code formatting and cross-references.
282* ``pw-status-codes`` needs to be wrapped in ``@rst`` and ``@endrst``
283  because it's a reStructuredText directive and Doxygen doesn't natively
284  support reST. The implementation is at
285  ``//pw_docgen/py/pw_docgen/sphinx/pw_status_codes.py``.
286
287.. admonition:: **Yes**
288   :class: checkmark
289
290   .. code-block:: none
291
292      /// @returns @rst
293      ///
294      /// .. pw-status-codes::
295      ///
296      ///    OK: Data successfully written to ``buffer``.
297      ///
298      ///    RESOURCE_EXHAUSTED: The remaining space is too small to hold a
299      ///    new block. See :ref:`module-pw_example-troubleshooting`.
300      ///
301      /// @endrst
302
303   It's OK to use reStructuredText features like code formatting and
304   cross-references within the descriptions. The status code itself
305   must be plaintext.
306
307.. admonition:: **No**
308   :class: error
309
310   .. code-block:: none
311
312      /// @returns @rst
313      ///
314      /// .. pw-status-codes::
315      ///
316      ///    RESOURCE_EXHAUSTED: The remaining space is too small to hold a
317      ///                        new block.
318      ///
319      /// @endrst
320
321   For items that span multiple lines, don't use whitespace like this.
322
323.. _docs-style-doxygen-namespaces:
324
325Use fully namespaced names
326==========================
327In general, write out the full namespace to Pigweed classes, methods, and
328so on. If you're writing a code sample, and that code sample clearly shows
329where the item comes from via a ``using`` statement, you don't need to use
330full namespacing.
331
332.. admonition:: Discussion
333
334   Pigweed has over 160 modules. It can be overwhelming for beginners
335   to figure out where an item is coming from.
336
337.. _docs-style-doxygen-multisymbol:
338
339Single comment block for multiple symbols
340=========================================
341Use ``@def <symbol>`` followed by the comment block.
342
343.. admonition:: **Yes**
344   :class: checkmark
345
346   .. code-block:: cpp
347
348      /// @def PW_ASSERT_EXCLUSIVE_LOCK
349      /// @def PW_ASSERT_SHARED_LOCK
350      ///
351      /// Documents functions that dynamically check to see if a lock is held, and
352      /// fail if it is not held.
353
354.. _docs-style-doxygen-xrefs:
355
356Cross-references (x-refs)
357=========================
358
359.. _docs-style-doxygen-xrefs-comments:
360
361X-refs in Doxygen comments
362--------------------------
363For C or C++ x-refs, use one of the following aliases:
364
365.. csv-table::
366   :header: Alias, reStructuredText equivalent
367
368   ``@c_macro{<identifier>}``, ``:c:macro:`<identifier>```
369   ``@cpp_func{<identifier>}``, ``:cpp:func:`<identifier>```
370   ``@cpp_class{<identifier>}``, ``:cpp:class:`<identifier>```
371   ``@cpp_type{<identifier>}``, ``:cpp:type:`<identifier>```
372
373.. inclusive-language: disable
374
375.. _Sphinx Domain: https://www.sphinx-doc.org/en/master/usage/domains/index.html
376
377.. inclusive-language: enable
378
379For all other x-refs, use Pigweed's custom basic alias,
380``@crossref{<domain>,<type>,<identifier>}``. ``<domain>`` must be a valid
381`Sphinx Domain`_ and ``<type>`` must be a valid type within that domain.
382``@crossref`` can be used with any domain.
383
384Avoid Doxygen x-refs
385^^^^^^^^^^^^^^^^^^^^
386Always use Pigweed's custom aliases for x-refs unless you have specific
387reasons not to do so. Pigweed's x-ref aliases are built on top of Sphinx.
388Doxygen provides its own features for x-refs but they should be avoided
389because Sphinx's are better:
390
391* Sphinx x-refs work for all identifiers known to Sphinx, including
392  those documented with directives like ``.. cpp:class::`` or extracted from
393  Python. Doxygen references can only refer to identifiers known to Doxygen.
394* Sphinx x-refs always use consistent formatting. Doxygen
395  x-refs sometimes render as plaintext instead of code-style
396  monospace, or include ``()`` in macros that shouldn’t have them.
397* Sphinx x-refs can refer to symbols that haven't yet been documented.
398  They will be formatted correctly and become links once the symbols are
399  documented.
400
401Using Sphinx x-refs in Doxygen comments makes x-ref syntax more consistent
402within Doxygen comments and between reStructuredText and Doxygen.
403
404.. _docs-style-doxygen-xrefs-rest:
405
406Cross-references in reST to Doxygen symbols
407-------------------------------------------
408After you've used Doxygen to generate API references, you can link to those
409symbols from your reStructuredText with standard Sphinx x-ref
410syntax.
411
412.. admonition:: **Yes**
413   :class: checkmark
414
415   .. code-block:: rst
416
417      :cpp:class:`pw::sync::BinarySemaphore::BinarySemaphore`
418
419.. inclusive-language: disable
420
421.. _domain: https://www.sphinx-doc.org/en/master/usage/domains/index.html
422.. _C++ Domain: https://www.sphinx-doc.org/en/master/usage/domains/cpp.html
423.. _C Domain: https://www.sphinx-doc.org/en/master/usage/domains/c.html
424.. _Python Domain: https://www.sphinx-doc.org/en/master/usage/domains/python.html
425
426.. inclusive-language: enable
427
428In the Sphinx docs the reference documentation for x-ref syntax is
429provided in the `domain`_ docs:
430
431* `C++ Domain`_
432* `C Domain`_
433* `Python Domain`_
434
435.. _docs-style-doxygen-embedded-rest:
436
437Embedded reStructuredText
438=========================
439To use reStructuredText (reST) within a Doxygen comment, wrap the reST
440in ``@rst`` and ``@endrst``.
441
442.. _docs-style-doxygen-breathe:
443
444-------
445Breathe
446-------
447.. _Breathe: https://breathe.readthedocs.io
448
449This section provides guidance on how `Breathe`_ should and shouldn't be used
450when authoring ``pigweed.dev`` docs.
451
452.. _docs-style-doxygen-breathe-overview:
453
454Overview
455========
456.. inclusive-language: disable
457
458.. _Breathe directives: https://breathe.readthedocs.io/en/latest/directives.html
459.. _Sphinx: https://www.sphinx-doc.org/en/master/
460
461.. inclusive-language: enable
462
463After you annotate your header comments as Doxygen comments, you need to
464specify where to render the API reference within the ``pigweed.dev`` docs.
465The reStructuredText files distributed across the main Pigweed repo are
466the source code for ``pigweed.dev``. Updating these ``.rst`` files is how
467you surface the API reference on ``pigweed.dev``. Doxygen doesn't natively
468interact with `Sphinx`_, the documentation generator that powers
469``pigweed.dev``. `Breathe`_ is the bridge and API that enables ``pigweed.dev``
470and Doxygen to work together.
471
472.. _docs-style-doxygen-breathe-doxygenclass:
473
474doxygenclass
475============
476.. _doxygenclass: https://breathe.readthedocs.io/en/latest/directives.html#doxygenclass
477
478OK to use. `doxygenclass`_ documents a class and its members.
479
480.. admonition:: **Yes**
481   :class: checkmark
482
483   .. code-block:: rst
484
485      .. doxygenclass:: pw::sync::BinarySemaphore
486         :members:
487
488Classes that are a major part of a Pigweed module's API should have their
489own section so that they're easy to find in the right-side page nav on
490``pigweed.dev``.
491
492.. admonition:: **Yes**
493   :class: checkmark
494
495   .. code-block:: rst
496
497      .. _module-pw_<name>-reference:
498
499      =========
500      Reference
501      =========
502      .. pigweed-module-subpage::
503         :name: pw_<name>
504
505      ...
506
507      .. _module-pw_<name>-reference-<class>:
508
509      -------------------
510      pw::<name>::<class>
511      -------------------
512      .. doxygenclass:: pw::<name>::<class>
513         :members:
514
515.. _docs-style-doxygen-breathe-doxygenfunction:
516
517doxygenfunction
518===============
519.. _doxygenfunction: https://breathe.readthedocs.io/en/latest/directives.html#doxygenfunction
520
521OK to use. `doxygenfunction` documents a single function or method.
522
523.. admonition:: **Yes**
524   :class: checkmark
525
526   .. code-block:: rst
527
528      .. doxygenfunction:: pw::tokenizer::EncodeArgs
529
530.. _docs-style-doxygen-breathe-doxygendefine:
531
532doxygendefine
533=============
534.. _doxygendefine: https://breathe.readthedocs.io/en/latest/directives.html#doxygendefine
535
536OK to use. `doxygendefine`_ documents a preprocessor macro.
537
538.. admonition:: **Yes**
539   :class: checkmark
540
541   .. code-block:: rst
542
543      .. doxygendefine:: PW_TOKENIZE_STRING
544
545.. _docs-style-doxygen-breathe-doxygengroup:
546
547doxygengroup
548============
549.. _doxygengroup: https://breathe.readthedocs.io/en/latest/directives.html#doxygengroup
550
551`doxygengroup`_ lets you manually mark a set of symbols as belonging to the same
552conceptual group.
553
554``doxygengroup`` is OK to use when a simple
555:ref:`docs-style-doxygen-breathe-doxygenclass`-based organization
556doesn't work well for your module.
557
558.. _@defgroup: https://www.doxygen.nl/manual/commands.html#cmddefgroup
559.. _@addtogroup: https://www.doxygen.nl/manual/commands.html#cmdaddtogroup
560.. _@ingroup: https://www.doxygen.nl/manual/commands.html#cmdingroup
561
562To create a group, annotate your Doxygen comments with `@defgroup`_,
563`@addtogroup`_, and `@ingroup`_. You can wrap a set of contiguous comments
564in ``@{`` and ``@}`` to indicate that they all belong to a group.
565
566.. admonition:: **Yes**
567   :class: checkmark
568
569   .. code-block:: cpp
570
571      /// @defgroup <name> <description>
572      /// @{
573      /// ...
574      /// @}
575
576.. _issue #772: https://github.com/breathe-doc/breathe/issues/772
577
578Don't include namespaces in ``doxygengroup`` because Breathe doesn't handle
579them correctly. See `issue #772`_.
580
581.. admonition:: **Yes**
582   :class: checkmark
583
584   .. code-block:: rst
585
586      .. cpp:namespace:: my_namespace
587
588      .. doxygengroup:: my_group
589         :content-only:
590         :members:
591
592.. _docs-style-doxygen-breathe-doxygentypedef:
593
594doxygentypedef
595==============
596.. _doxygentypedef: https://breathe.readthedocs.io/en/latest/directives.html#doxygentypedef
597
598OK to use. `doxygentypedef`_ documents a ``typedef`` or ``using`` statement.
599
600.. admonition:: **Yes**
601   :class: checkmark
602
603   .. code-block:: rst
604
605      .. doxygentypedef:: pw::Function
606
607.. _docs-style-doxygen-breathe-doxygenfile:
608
609doxygenfile
610===========
611.. _doxygenfile: https://breathe.readthedocs.io/en/latest/directives.html#doxygenfile
612
613Don't use `doxygenfile`_. Use :ref:`docs-style-doxygen-breathe-doxygengroup`
614instead.
615
616.. _docs-style-doxygen-disabled-include:
617
618-----------------------------------------------
619Disabled auto-generated ``#include`` statements
620-----------------------------------------------
621.. note::
622
623   This is an FYI section. There's no prescriptive rule here.
624
625Doxygen and Breathe have the ability to auto-generate ``#include`` statements
626for class references. These have been disabled because:
627
628* The auto-generated paths are inaccurate. E.g. the ``#include`` for
629  ``pw::string::RandomGenerator`` was generated as ``#include <random.h>``
630  when it should be ``#include "pw_random/random.h"``.
631* The auto-generation is not consistent. They seem to only get generated when
632  using the ``doxygennamespace`` directive but ``pigweed.dev`` frequently
633  uses ``doxygenclass``, ``doxygenfunction``, etc.
634
635In the future, if it's decided that these ``#include`` statements are needed,
636there is a way to manually override each one. The code block below shows how
637it's done. This approach wouldn't be great because it adds a lot of noise to
638the header files.
639
640.. code-block::
641
642   /// @class RandomGenerator random.h "pw_random/random.h"``
643
644See `b/295023422 <https://issues.pigweed.dev/issues/295023422>`_.
645