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