Skip to content

Commit

Permalink
Doc: Add Function Documentation Style Guide (#588)
Browse files Browse the repository at this point in the history
Some recent PRs have included comments about stylistic inconsistencies
in the documentation. This PR adds a style guide for documenting
user-callable and user-supplied functions to hopefully reduce this kind
of traffic in future PRs.

---------

Co-authored-by: Daniel R. Reynolds <[email protected]>
  • Loading branch information
gardner48 and drreynolds authored Oct 8, 2024
1 parent a1bc879 commit 1770cd7
Show file tree
Hide file tree
Showing 2 changed files with 271 additions and 22 deletions.
11 changes: 8 additions & 3 deletions doc/superbuild/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx_rtd_theme', 'sphinx.ext.ifconfig', 'sphinx.ext.mathjax',
'sphinxfortran.fortran_domain', 'sphinxcontrib.bibtex',
'sphinx_copybutton', 'sphinx.ext.graphviz', 'sphinx_sundials',
'sphinx_toolbox.collapse']
'sphinx.ext.intersphinx', 'sphinxfortran.fortran_domain',
'sphinxcontrib.bibtex', 'sphinx_copybutton', 'sphinx.ext.graphviz',
'sphinx_sundials', 'sphinx_toolbox.collapse']

intersphinx_mapping = {"sphinx": ("https://www.sphinx-doc.org/en/master/", None),}

# No non-external references will be resolved by intersphinx
intersphinx_disabled_reftypes = ["*"]

# References
bibtex_bibfiles = ['../../shared/sundials.bib']
Expand Down
282 changes: 263 additions & 19 deletions doc/superbuild/source/developers/style_guide/Documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,28 +127,272 @@ All citations go into `doc/shared/sundials.bib`.
TODO: add citation and reference key style.


Documenting Functions
=====================
User-Callable Functions
=======================

Adding New Functions
--------------------
Document user-callable functions with the :external+sphinx:rst:dir:`c:function`
or :external+sphinx:rst:dir:`cpp:function` directives, as appropriate. The
directive is followed by the C/C++ function signature. Under the signature
(skipping a line and indenting 3 spaces) provide a brief description of the
function followed by any information on its usage. When describing the function
parameters use ``:param <name>:``. If the function returns a specific set of
SUNDIALS error codes, describe the possible return values using ``:retval
<value>:`` for each value. Otherwise, use a single ``:returns:`` item to
describe the result of the function. If the function returns ``void``, a return
entry should not be included. Below we give two examples, the first returns an
error code (int) while the second is a constructor that returns an object
(pointer).

The documentation for new functions should include the ``.. versionadded::``
directive at the end of the documentation text noting the *package version*
number in which the function was added.
.. code-block:: rst
Changes to Existing Functions
-----------------------------
.. c:function:: int SetFoo(param_type p1, param_type p2)
If the signature or behavior of a function changes in any release the
``.. versionchanged::`` directive should be added to the function documentation
noting the *package version* number in which the change happened and describing
the change.
Brief description of what the user-callable function does.
Deprecating Functions
---------------------
Additional information about the function and its usage.
When a function is deprecated the ``.. deprecated::`` directive should be added
to the function documentation noting the *package version* number in which the
function was deprecated and describing what function should be used instead
if appropriate.
:param p1: description of the first parameter.
:param p2: description of the second parameter.
:retval SUCCESS: under some conditions.
:retval FAILURE_1: under some other conditions.
:retval FAILURE_2: under yet some other conditions.
.. code-block:: rst
.. c:function:: FooObject CreateFooObject(param_type p1, param_type p2)
Brief description of what the user-callable function does.
Additional information about the function and its usage.
:param p1: description of the first parameter.
:param p2: description of the second parameter.
:returns: If successful some object, otherwise ``NULL``.
When adding, updating, or deprecating a function, use the
:external+sphinx:rst:dir:`versionadded`,
:external+sphinx:rst:dir:`versionchanged`, or
:external+sphinx:rst:dir:`deprecated` directives with the placeholder version
number ``x.y.z`` after the return description. The release script will find and
replace all instances of ``x.y.z`` in the documentation with the actual release
number. When altering the behavior of a function or deprecating a function
include a description for the change under the directive (skipping a line and
indenting 3 spaces). For example,

.. code-block:: rst
.. versionadded:: x.y.z
.. code-block:: rst
.. versionchanged:: x.y.z
Describe how the function behavior has changed from before.
.. code-block:: rst
.. deprecated:: x.y.z
If a replacement function/procedure is available, describe what users
should do to replace the deprecated function e.g., cross reference the
function superseding this one or list the new steps to follow. Otherwise,
note the feature/capability is no longer supported/provided and, if
possible, state why this function was removed.
If special attention needs to be drawn to some behavior, consideration, or
limitation of a function that could be overlooked in the description, use the
:external+sphinx:rst:dir:`note` or :external+sphinx:rst:dir:`warning` directives
as appropriate. These should be used sparingly to avoid diluting their impact.
For example,

.. code-block:: rst
.. note::
Something users should not over look e.g., a feature is only compatible
with a subset of methods.
.. code-block:: rst
.. warning::
Something critical users should be aware of e.g., performance impacts.
Finally, at the end of the function documentation, you may include (a
non-trivial) example usage of the function and/or a list of example programs
that utilize the function. For example,

.. code-block:: rst
**Example usage:**
.. code-block:: C
/* Short code block demonstrating typical usage */
/* Create the object */
FooObject foo_obj = CreateFooObject(p1, p2);
if (foo_obj == NULL) { return 1; }
/* Attach the object to mem */
int retval = SetFoo(mem, foo_obj);
if (retval != 0) { return 1; }
/* Perform some actions */
...
/* Destroy the object */
retval = DestroyFooObject(&foo_obj);
if (retval != 0) { return 1; }
.. code-block:: rst
**Examples codes:**
* ``examples/package/subdir/pkg_some_code.c``
Putting it all together, the rendered documentation should look like the
following.

.. c:function:: int FooSetBar(void* foo_obj, int bar_value)
:nocontentsentry:
:noindexentry:
This function sets the value of Bar in a FooObject.
The default value for Bar is :math:`10`. An input value :math:`< 0` will
reset Bar to the default value.
:param foo_obj: the FooObject.
:param bar_value: the value of Bar.
:retval SUCCESS: if the value was successfully set.
:retval NULL_OBJ: if the ``foo_obj`` was ``NULL``.
.. versionadded:: 1.1.0
.. versionchanged:: 2.0.0
The type of p1 was changed from ``unsigned int`` to ``int``
.. note::
Utilizing this capability requires building with Bar enabled.
.. warning::
Setting values greater than 100 may degrade performance.
**Example usage:**
.. code-block:: C
/* Create the object */
void* foo_obj = CreateFooObject(p1, p2);
if (foo_obj == NULL) { return 1; }
/* Update the value of Bar */
int retval = FooSetBar(foo_obj, 50);
if (retval != 0) { return 1; }
/* Perform some actions */
...
**Examples codes:**

* ``examples/package/subdir/pkg_foo_demo.c``


User-Supplied Functions
=======================

Document user-supplied functions with the :external+sphinx:rst:dir:`c:type`
directive. The directive is followed by the ``typedef`` for the function
pointer. The description of the function type mirrors the style used for
user-callable function with one exception. As :external+sphinx:rst:dir:`c:type`
does not currently support the ``param``, ``retval``, and ``returns`` fields,
these sections must be manually created. The style that follows is chosen to
reflect that of ``param``, ``retval``, and ``returns`` fields as much as
possible. Function parameters should be listed under a boldface "Parameters:"
section with the parameters in boldface and separated from their description by
an en-dash. As user-supplied functions typically return a ``int``, but specific
values are not required, a description of how the return value is interpreted
should be given under a boldface "Returns:" section (skipping a line and
indenting 2 spaces). If specific return values are required, these should be
documented similarly to the function parameters and listed under a boldface
"Return values:" section. If the function returns ``void``, a return section
should not be included. Below we give, two examples describing user-supplied
functions.

.. code-block:: rst
.. c:type:: int (*FooFn)(param_type p1, param_type p2)
Brief description of what the user-provided function should do.
Additional information about the function and its usage.
**Parameters:**
* **p1** -- description of the first parameter.
* **p2** -- description of the second parameter.
**Returns:**
A :c:type:`FooFn` function should return 0 if successful, a positive
value if a recoverable error occurred, or a negative value if an
unrecoverable error occurred.
.. code-block:: rst
.. c:type:: int (*BarFn)(param_type p1, param_type p2)
Brief description of what the user-provided function should do.
Additional information about the function and its usage.
**Parameters:**
* **p1** -- description of the first parameter.
* **p2** -- description of the second parameter.
**Return values:**
* **VALUE_1** -- under some circumstances.
* **VALUE_2** -- under some other circumstances.
Other than the difference in the function parameter and return value sections
the remaining guidelines from the user-callable function documentation are the
same. Putting it all together, the rendered documentation should look like the
following.

.. c:type:: int (*FooFn)(double* p1, double* p2)
:nocontentsentry:
:noindexentry:

Brief description of what the user-provided function should do.

Additional information about the function and its usage.

**Parameters:**

* **p1** -- the input array of values.
* **p2** -- the output array of values.

**Returns:**

A :c:type:`FooFn` function should return 0 if successful, a positive value
if a recoverable error occurred, or a negative value if an unrecoverable
error occurred.

.. versionadded:: 2.2.0

.. note::

This function is required when using the Foo option.

**Examples codes:**

* ``examples/package/subdir/pkg_bar_demo.c``

0 comments on commit 1770cd7

Please sign in to comment.