/** @page libsbml-coding Documentation conventions for libSBML
@tableofcontents
@section coding-intro 1. Introduction
This document is a collection of guidelines for libSBML authors to follow
when writing documentation for libSBML code.
LibSBML's application programming interface (API) is documented using a
combination of tools. For almost all languages (C++, C#, C, Python, and
others), the cornerstone of the approach is the open-source software tool Doxygen; for Java, we use Javadoc instead.
We write the documentation in source code and auxiliary files in a way that
both Javadoc and Doxygen can process more or less equally, which requires
that programmers and documentation authors follow various conventions
described in the rest of this document. In addition, we use various
home-grown scripts and programs to massage the output of SWIG to produce
something that can be fed to the Doxygen and Javadoc-based processs.
@section coding-basic 2. Basic guidelines for libSBML
The guidelines presented in this section are oriented towards explaining how
to organize code comments such that Doxygen and Javadoc can produce good
output, yet simultaneously make the comments in the libSBML code files be
readable on their own.
@li Although Doxygen keywords/tags can be prefixed with either @c \@ or @c
@\\, Javadoc only understands keywords prefixed with @c \@. Consequently,
always use the @c \@ prefix for keywords so that they will be understood by
both Doxygen and Javadoc.
@li The main types of Doxygen comments consist of a C-style comment block
beginning with two asterisks (@c *) characters, as in the following example:
@verbatim
/**
* Comments that start with two asterisks within which commands
* understood by Doxygen will begin with the character @.
*/
@endverbatim
Another type of Doxygen comment, used to document enumeration members, begins
with @htmlonly /*!< @endhtmlonly. If your code documentation
does @em not appear inside a comment block that begins with
@htmlonly /** @endhtmlonly or the more
rarely-needed @htmlonly /*!< @endhtmlonly, then it will be
ignored by Doxygen. This may or may not be what you want, depending on the
intention behind the comment.
@li Comments that begin with one asterisk (i.e.,
@htmlonly /* ... @endhtmlonly, or two
forward slashes (i.e., // ...) are @em not processed by Doxygen
and not entered in the formatted user guide. You can use such comments
normally to comment the code for other developers.
@li Doxygen comment blocks can appear at the beginning of a file, in front of
a class declaration, in front of method declarations, in front of function
declarations, and in front of data structure definitions.
@li Doxygen reads both .h and .cpp files. If a
class member (i.e., a method or data member) has
@htmlonly /** @endhtmlonly comment blocks in both the
.h and .cpp files, the text is @em combined in the
final output for that class member. This frequently leads to accidentally
duplicated text in the final output, and generally is a maintenance headache.
To avoid this, and to simplify maintenance of documentation, only put
documentation comments in the .h files.
@li Please write in complete sentences, with correct English grammar and
punctuation. @em Do @em not treat new lines as new sentences or beginnings
of different comments. Here is an example of what should be @em avoided:
@verbatim
/**
* creates a foo object
* given arg is the template
*/
@endverbatim
The text above doesn't end sentences with periods, doesn't begin sentences
with capitals, doesn't form complete sentences, etc. When Doxygen is used
to generate HTML documentation from this, it turns into one long run-on
paragraph, and it's unreadable.
@li We use a feature of Doxygen that makes it use the first sentence
of a documentation comment as the "brief" description of the entity being
described (which may be a class, a method, a class data member, a function,
a typedef, etc.). This means that the first sentence up to a period or a
blank line will be pulled out separately and used as a one-line summary in
certain contexts by Doxygen. The following is an example:
@verbatim
/**
* This is the brief description. After the first sentence, even if
* you continue writing in the same paragraph, the output nevertheless
* is split after the first sentence such that everything else is part of
* the detailed description and not the brief one-sentence description.
* This example would produce two paragraphs in the formatted output:
* one paragraph containing the first sentence, and the rest of the
* text in the second paragraph.
*
* If you also have a third paragraph separated by a blank line in the
* comment, like this, then this third paragraph becomes a third paragraph
* in the output. This part is what most people would expect would happen.
*/
@endverbatim
Consequently, to emphasize this and remind people that this is going to
happen when the API documentation is generated, it is better to format the
comment such that there is a paragraph break after the first sentence,
as follows:
@verbatim
/**
* This is the brief description.
*
* This is the beginning of the detailed description....
*/
@endverbatim
The visual split in the source makes it more obvious what's going to happen.
@li Doxygen automatically turns entity names it recognizes in text into links
to the definition of that entity. This is usually what you want to have
happen; for example, when describing the Model class, you may mention classes
such as Species and Compartment, and those should be turned into convenient
links to their definitions in the API documentation. However, sometimes you
don't want that to happen. To prevent Doxygen from linking a word,
put a percentage sign (\%) in front of it, as in @c \%%Model. Doxygen will
remove the percentage sign and leave the rest of the word unlinked, resulting
in the plain word %Model appearing in the finished document.
@li Sometimes methods are meant to be part of the internal implementation and
not advertised to users of the library. To make Doxygen ignore methods,
wrap their declarations in the .h files with the comment
@verbatim
/** @cond doxygenLibsbmlInternal */
@endverbatim
at the beginning and
@verbatim
/** @endcond */
@endverbatim
at the end of the block. This is merely a convention used in libSBML and not
something that Doxygen defines; we simply use the normal Doxygen conditional
test operator @@cond and give it a symbol we never define:
"doxygenLibsbmlInternal". The symbol name is chosen to suggest the
purpose. Note: if there are multiple methods to be marked in this way,
wrap them individually, placing the @@cond
and @@endcond pairs immediately before and after each method.
This makes it much more likely that a reader will notice what is happening in
the source files. The alternative approach (putting single
@@cond and @@endcond pairs around a group of
methods) makes it much harder to determine which methods are marked as
internal in a file.
@li If an entire file should be omitted from the user documentation, use the
same @@cond doxygenLibsbmlInternal method but put the conditional
near the top of the file and the @@endcond at the very end of the
file. In other words, the top of your file should look like this example:
@verbatim
/**
* @cond doxygenLibsbmlInternal
*
* @file ExpatAttributes.cpp
* @brief Creates new XMLAttributes from "raw" Expat attributes.
* ...
@endverbatim
@li Always put a @c @@class declaration in every file for every class, even
if they are marked as internal using the
@@cond doxygenLibsbmlInternal method described above. Due to
the way our documentation toolchain works, in order for Doxygen and Javadoc
to see the markers we insert to indicate internal classes and methods, it is
necessary for classes to have an @c @@class declaration even if a
file has the @@cond doxygenLibsbmlInternal guards around it.
In other words, the file still needs to have the @c @@class definition for
things to work. The easiest convention to adopt is simply to always put the
@c @@class and @c @@sbmlbrief pairs in every class, no matter what. If the
file is for internal code, then also put the
@@cond doxygenLibsbmlInternal around the entire contents inside.
The use of @c @@sbmlbrief and @c @@class is discussed further in Section @ref
coding-doc-h below.
@li Do not use @@retval for describing return
values; instead, use @@return because (1) it is what Javadoc uses
and (2) the narrative form of @@return lets you provide more
contextual information and other details in describing the return value(s) of
a method or function.
@li Please try to limit the lengths of lines in all files to 79 characters
long or less. This makes code and documentation generally easier to read and
edit in different software tools. Sometimes it's too difficult to avoid a
long line, and then it's okay, but generally it's possible to reformat code
in such away as to keep things to 79 characters.
@li Please write sentences with @em two (2) spaces after the terminating
period, not one. This makes the resulting text easier to read during
editing, compared to when sentence-ending periods are followed by only one
space. (Note that this concerns the readability and editability of source
code, not the appearance of rendered output. The finished typeset output will
@em not have two spaces after every sentence-ending period; it will have one
or slightly more than one, depending on the output format produced. The
reason two-spacing is important for the source is that most people use
monospaced fonts in their text editors and IDEs, and when using monospaced
fonts, the ends of sentences are much easier for human eyes to pick out when
two-spacing is used. Further, text editing programs such as Emacs and vi
have special features to recognize sentences based on this pattern, and
proficient users of those editors can make use of sentence-oriented editing
commands. This is a convention that some people disagree with. Please use
this convention for libSBML anyway.)
@section coding-docs 3. Guidelines for different file types
Below are explanations of how to write documentation for the most common
types of files encountered in libSBML.
@subsection coding-doc-h 3.1 Guidelines for .h files
It is important to note that the documentation of global functions,
variables, typedefs, and enums will only be included in the output of
Doxygen if the file they are in is also documented.
@li Here is a template header file suitable for use when creating a new
.h file for libSBML (and in fact, it's the same for
.cpp files, too). Of course, you should substitute appropriate
content for the text in square brackets (@c [ and @c ]) below. Note also that
the Doxygen keywords @@file, @@brief and
@@author are @em not followed by colon (':')
characters.
@verbatim
/**
* @file [filename]
* @brief [succinct description of what's in this file]
* @author [author's name]
*
**/
@endverbatim
@li When more than one author should be acknowledged for a given file, use
multiple @@author entries, one per line.
@li A .h file will typically have a class declaration in it.
The @em normal, plain Doxygen way that one would document a class (but we do
not do it this way) is to put a comment block immediately in front of the
class declaration in the file. However, we have to do it differently because
of how our files are used to generate output for multiple language bindings.
Thus, for the documentation of classes, please put the documentation
in the file header rather that ahead of the class itself in the
file. The following example illustrates this procedure (and note how more
than one class can be described in the header):
@verbatim
/**
* @file Compartment.h
* [...]
*
* @class Compartment
* @sbmlbrief{core} Implementation of SBML's %Compartment construct.
*
* A compartment in SBML represents a bounded space in which species
* are located. Compartments do not necessarily have to correspond to
* ....
*
*
* @class ListOfCompartments
* @sbmlbrief{core} Implementation of SBML's %ListOfCompartments
* construct.
*
* The various ListOf___ classes in SBML are merely containers used for
* ....
*/
#ifndef Compartment_h
#define Compartment_h
...
@endverbatim
@li Use the special keyword @@sbmlbrief to indicate the SBML
Level 3 package to which a class belongs. This keyword takes one
argument, a label for the package; for SBML Level 3 Core code, use the
label "core". Place the keyword immediately on the line after each
@@class declaration in the .h file, and then write
a brief one-sentence description of the class after the keyword. The example
file fragment above demonstrates this. (As you might guess from its name,
the keyword @@sbmlbrief is something defined by libSBML's
documentation-production system and not a standard Doxygen command.)
@li For each method or data member in the class definition, include a
comment block ahead of it, making sure to provide at least a brief
description. If it takes parameters, use @c @@param to describe the
parameters. If it's a method and the method returns a value, also use @c
@@return to describe the returned value. If you also need to refer to the
parameters in the textual description of the method, use the @c @@p command.
The following example illustrates this:
@verbatim
/**
* Creates a new CompartmentType, optionally with the given @p id and
* @p name attribute values.
*
* In SBML, identifiers are required for CompartmentType objects;
* however, the identifier does not have to be set at the time of
* creation of the object, and instead can be set using the setId()
* method on the SBase parent class.
*
* @param id a string, the identifier of this CompartmentType instance
* @param name a string, the optional name of this
*/
CompartmentType (const std::string& id = "", const std::string& name = "");
@endverbatim
@li Please try to leave 2 blank lines between method declarations and other
items in the definitions of classes. This makes it easier for the eye to
spot transitions between method definitions. Here is an example taken
from a class definition in a .h file:
@verbatim
class LIBSBML_EXTERN CompartmentType : public SBase
{
public:
/**
* Creates a new CompartmentType, optionally with the given @p id and @p
* name attribute values.
*
* In SBML, identifiers are required for CompartmentType objects;
* however, the identifier does not have to be set at the time of
* creation of the object, and instead can be set using the setId()
* method on the SBase parent class.
*
* @param id a string, the identifier of this CompartmentType instance
* @param name a string, the optional name of this
*/
CompartmentType (const std::string& id = "", const std::string& name = "");
/**
* Destroys this CompartmentType.
*/
virtual ~CompartmentType ();
/**
* Copy constructor; creates a copy of this CompartmentType.
*/
CompartmentType(const CompartmentType& orig);
@endverbatim
@subsection coding-doc-cpp 3.2 Guidelines for .cpp files
The .cpp files can be handled very similarly to the
.h files described above. You may use the same header template
shown in the previous section about .h files, and all the same
guidelines apply.
As noted above, when the API manual is generated by Doxygen, it will use the
comments from the .h file as the source of the documentation for
the class and methods. It is therefore unnecessary to repeat the class or
other descriptions placed in the .h file. However, do provide
normal comments (using either the single-asterisk form or the double-slash
form of C++ comments) about the code so that in the future, you and others
would read the file can better understand what the code is doing.
@section coding-other-situations 4. Some important common situations
The descriptions above cover the basics of using Doxygen and Javadoc for
libSBML documentation. What follows is a discussion of other, more involved
topics.
@subsection coding-refs 4.1 Pure functions and constants
This section discusses the special needs of libSBML functions defined outside
of any classes, and symbolic constants (both enumerations and
@#define constants).
@subsubsection coding-constant-refs 4.1.1 Referring to libSBML constants
It's often important to refer to constants such as enumeration values and
@#define'd symbolic constants. It's very useful to have the
names of the constants in the formatted documentation be linked to their
definitions, rather than being merely set in a typewriter-style font.
However, not only does Doxygen fail to do this automatically, but the link
targets need to be different for the different programming languages such as
Python, C# and Java. Handling this using plain Doxygen commands leads to a
complex and unmaintainable combination of repeated @@if clike
... @@endif @@if java ... @@endif @@if python ... @@endif.
To make it easier to name and link constants consistently, we developed a
simple-to-use Doxygen macro that is recognized and treated specially by
src/bindings/swig/swigdoc.py. This macro is named
@@sbmlconstant and takes two required arguments:
@@sbmlconstant{symbol,type}
The type is the name of the enumeration (if
any) where the symbolic value is defined, and symbol is the name of the value. Note that the
symbol appears @em first in the macro. Here follows an example:
@@sbmlconstant{AST_MINUS, ASTNodeType_t}
If the value is a @#define constant and not located inside an
enumeration, then omit the type argument
value; however, leave the comma regardless. For example:
@@sbmlconstant{L3P_COLLAPSE_UNARY_MINUS,}
(The need for the comma is because Doxygen does not support optional
arguments in alias/macro definitions. Rather than define two separate forms,
it seems simpler to have only one---i.e., @@sbmlconstant---and
simply remember to leave the second argument empty if necessary.)
Finally, sometimes you will want to refer the enumeration type itself rather
than a specific value, for example to say something along the lines of "the
values are drawn from the enumeration X". Unfortunately, this poses a
portability problem, because the enumerations do not explicitly exist outside
of C and C++. The simplest way around this problem is to conditionalize the
text such that in the case of clike, the text mentions the
enumeration name, and otherwise, the text describes integer constants more
generally. The following is an example:
@htmlinclude libsbml-coding-enum-text-example.html
In the example above, when the condition is not satisfied (meaning,
@@if clike is false and thus C/C++ documentation is not being
generated), the text above will result in the output "This uses integer type
codes, which may come from the of static integer constants whose names begin
with the prefix AST_". Such a description works for Java,
Python and other languages equally, and while it is not as specific as
possible, it is better than attempting to a list all the alternatives
explicitly.
@subsubsection coding-function-refs 4.1.2 Referring to libSBML pure functions
Some functions in libSBML are defined outside of any class. This poses a
special challenge for creating hyperlinks, because the names of the functions
and their references are different for Python and Java from the basic C, C++
and C# versions. To stop the unreadable and unmaintainable insanity of
repeated @@if clike ... @@endif @@if java ... @@endif @@if python
... @@endif (especially because the Java case required explicit HTML
@c a elements and full argument lists, with fully qualified data types), we
developed another custom Doxygen macro that is recognized and treated
specially by src/bindings/swig/swigdoc.py.
The macro is named @c @@sbmlfunction; it takes the name of the libSBML
function, followed by a comma, followed by a list of arguments to the
function. The list of arguments is @em mandatory; if the libSBML function in
question takes no arguments, then simply leave the list empty, but keep the
comma. In addition, when writing the function name, omit the leading
SBML_ part that appears in the function's C/C++
definition; the prefix it will be added automatically for C++ and C# and
omitted from the other languages, where libSBML function names are written
without the SBML_ part.
The following illustrates the syntax for the case of a function that takes no
arguments:
@@sbmlfunction{name,}
where name is the name of a libSBML function
that takes no arguments. If the function does take arguments, use
the arguments as they appear in the Java API. The following is an
example of a function that takes a single argument:
@@sbmlfunction{name, arg1type}
If the function takes more than one argument, use commas quoted with
a backslash to separate multiple arguments from each other. In
other words, functions that take multiple arguments should be written like
this:
@@sbmlfunction{name, arg1type\, arg2type\, ...}
Again, use the argument data types that appear in the Java version of the
API. (I.e., use @c String instead of char *, etc.) Here are
two real examples:
@@sbmlfunction{parseL3Formula, String}
@@sbmlfunction{parseL3FormulaWithSettings, String\, %L3ParserSettings}
The data types do not have to be fully qualified. Line breaks may be used to
split long lines.
The reason the Java types are used is because the argument list is only used
for producing the Java API documentation---in order for the correct
hyperlinks to be made, the documentation toolchain (specifically, Javadoc)
needs the argument list. (It is not required for the other language API
documentation, and is actually ignored when producing non-Java manuals.)
This macro is currently @em only usable for pure functions in libSBML. It is
not designed nor tested for use with methods on classes or other situations.
@subsection coding-reusing-text 4.2 Reusing common text
One often encounters the need to repeat the same text in different places in
the documentation, such as to add a detail to each method where the detail
may be relevant. In software documentation, unlike in non-technical prose or
creative writing, it is often @em better to repeat text---or refer to a
common section---everywhere that it might be relevant, because a reader does
not normally read class and method documentation linearly: they jump to a
method description from elsewhere. This means that the descriptions need to
be reasonably self-contained. However, repeating information by copy-pasting
text leads to a maintenance nightmare, requiring any updates or changes to be
made in multiple places. We avoid this in libSBML by writing common text as
reusable blocks, then using text inclusion mechanisms to insert the common
text where it is needed.
A surprising limitation of Doxygen is that it only provides two mechanisms
for copying repeated text: @@htmlinclude, and the
@@copydoc/@@copybrief/@@copydetails
set of commands. The former has the limitation that the content is not
processed by Doxygen at all: it is inserted raw, and @@ commands
are not interpreted. This means that cross-references are not performed,
conditionals are not expanded, etc. Conversely, the latter set of commands
can be used to reuse text with Doxygen commands in it, but the commands are
oriented towards use in the context of method and data member documentation,
and in other contexts have unfortunate behaviors with respect to how they
treat the first sentence of the text inside them.
We use both mechanisms, i.e., @@htmlinclude and
@@copydetails (and more rarely, @@copydoc) in
libSBML, but do so with conventions to work around the behaviors of the
latter set of commands.
@subsubsection coding-copydetails 4.2.1 Using "@@copydetails"
Experienced Doxygen users may be initially confused by our use of
@@copydetails, because strictly speaking, we are not using it
exactly as intended. The Doxygen command @@copydetails is
actually intended for copying the "non-brief" part of the documentation of an
object, such as a class, for use in documenting multiple similar objects. It
can also be used as a general means of copying text fragments if certain
conventions are followed. As mentioned above, compared to
@@htmlinclude, it has the advantage that Doxygen commands inside
the fragment are processed normally, including the automatic linking of
cross-reference to classes, methods, and other objects. Consequently, we
have resorted to using @@copydetails in combination with some
conventions to achieve what we need.
@li To define a block of text to be reused, use the @@class
command and give the class a name that begins with the prefix
doc_. Separate the class declaration with a blank line. Here
is an example:
@verbatim
/**
* @class doc_what_is_listof
*
* @par
* The various ListOf___ classes in SBML are merely containers used for
* organizing the main components of an SBML model. ...
*/
@endverbatim
We configure Doxygen to ignore symbols that begin with the string
doc_, so these class definitions will never really be defined in
the formatted output---they are fake class declarations used simply so
that we can employ @@copydetails elsewhere.
@li Note the use of @@par in the example above. This is a hack
to force Doxygen to treat the rest of the text as the "detail" portion of a
class documentation. Make sure to put @@par on a line
by itself, or it will not work properly. Special cases: if your text
block begins with @@note or @@warning or similar,
you do not need to put the @@par first.
@li For readability in the source code file, if you have more than one
@@class doc_... definition, separate them with an HTML comment
consisting of a line of dashes. Example:
@verbatim
/**
* @class doc_what_are_sbmlnamespaces
*
* @par
* The SBMLNamespaces object encapsulates SBML Level/Version/namespaces
* information. It is used to communicate the SBML Level, Version, and
* (in Level 3) packages used in addition to SBML Level 3
* Core. A common approach to using libSBML's SBMLNamespaces facilities
* is to create an SBMLNamespaces object somewhere in a program once,
* then hand that object as needed to object constructors that accept
* SBMLNamespaces as arguments.
*
*
* @class doc_what_is_SBMLDocument
*
* @par
* LibSBML uses the class SBMLDocument as a top-level container for
*/
@endverbatim
@li To use the text, that is, to insert a text block somewhere in the body of
a documentation string, use the command @@copydetails followed
by the name of the (fake) documentation class. Here is an example:
@htmlinclude libsbml-coding-copydetails-example.html
Finally where should you put these @@class definitions for
creating reusable text blocks? Use one of the following two locations:
-# An individual file where references to the block are made (such as a @c .h
file), when the text is specific to that file and never used outside of it; or
-# The file src/sbml/common/common-documentation.h, when the
text is something to be reused in multiple other files.
In general, the use of @@copydetails is preferable to the use of
@@htmlinclude described below, but in some situations you need to
resort to the latter command. In some other situations, you may want to copy
the entire method documentation for methods that are repeated on every class;
for this, you can use @@copydoc, described next.
@htmlinclude libsbml-coding-copydetails-example.html
@subsubsection coding-copydoc 4.2.2 Using "@@copydoc"
As mentioned above, the Doxygen @@copydetails command is
actually intended for reusing the "details" portion of a method or other
member documentation. If you use @@copydoc instead, Doxygen
will treat the first sentence of the documentation as a "brief" explanation
and the rest as the "details". The effect is the following: in summary
lists, it only prints the first sentence, and in every other context, it
prints the first sentence separated from the rest of the text with a
paragraph break. This paragraph-separated behavior is undesirable when you
want to reuse text fragments for general purposes. However, sometimes you
really @em do this behavior, in particular to reuse the entire method
documentation from one method to another. That is a situation where
@@copydoc is perfect.
An example of where @@copydoc is useful is in the definition of
renameSIdRef() virtual methods that are present on many libSBML
classes. For this case, we first define one common documentation block in
the file src/sbml/common/common-documentation.h mentioned above:
@htmlinclude libsbml-coding-copydoc-example.html
Notice how the block above is complete, and includes such things as the
definition of parameters with @@param. (If return values and
other information were appropriate, those would be included as well.) Then,
for the definition of renameSIdRef() in each class where it
appears, we use @@copydoc as follows:
@verbatim
/**
* @copydoc doc_renamesidref_common
*/
virtual void renameSIdRefs(const std::string& oldid,
const std::string& newid);
@endverbatim
Of course, for this to make sense, the block of text must match the methods
exactly, right down to the use of the same parameter names
(oldid and newid in the example above), the return
values, the purpose of the method, and so on.
@subsubsection coding-htmlinclude 4.2.3 Using "@@htmlinclude"
The @@copydetails and @@copydoc methods described
above works well for most situations, except when you need to use significant
HTML commands for special formatting. Some HTML commands will either be
intercepted by Doxygen, or else it may become very awkward to write the HTML
as comments in a .h file. In those cases, using Doxygen's
@@htmlinclude can be a better option.
The @@htmlinclude command takes a single argument, the name of a
file. This file must be placed in a preconfigured location; we use the
directory docs/src/common-text/ to store files for use with this
command. Here is an example of the use of @@htmlinclude:
@verbatim
* The list of possible types is quite long, because it covers all the
* mathematical functions that are permitted in SBML. The values are shown
* in the following table:
*
* @htmlinclude astnode-types.html
@endverbatim
The file will be included in-line at the location where the reference is made
in a documentation string.
It is worth reiterating that normal Doxygen processing is not performed
inside the contents of the file included through this mechanism.
Cross-references will not be made, the Doxygen @@ commands will
be ignored, etc. For most cases, it is preferable to use the
@@copydetails approach described in the previous section.
@subsection coding-links 4.3 Links
Most of the time, you can rely on Doxygen's ability to connect a written
reference to a class or method to the definition of that class or method. In
a few cases, however, you must write an explicit @@link
... @@endlink command. The syntax of this Doxygen command
consists of the target of the link, optionally followed by a name to be used
for the link.
In libSBML, the most common situation where an explicit link is needed is in
references to enumeration values such as method/function return codes. In
those cases, to create a link, use the name of the enumeration (e.g.,
OperationReturnValues_t), followed by a pound sign (@c #),
followed by the enumeration member, optionally followed by a space and then a
name for the link. If the optional space and name are omitted, the name of
the link is made the same as the full name of the target; this is generally
@em not desirable because the result is more difficult to read.
Here is an example, drawn from the documentation of the return type of a
method on the Compartment class. In these cases, the name of the link is
given as simply the name of the enumeration member without the enumeration
prefix:
@htmlinclude libsbml-coding-link-example.html
Another situation that calls for explicit links involves the non-C++
languages. There, it is common to need to refer to a constant defined on the
class or package libsbml. Here is an example:
@verbatim
* @if python LibSBML attaches an identifying
* code to every kind of SBML object. These are known as SBML type
* codes. In the Python language interface for libSBML, the type
* codes are defined as static integer constants in the interface class
* @link libsbml@endlink. @endif
@endverbatim
@subsection coding-conditionals 4.4 Conditional text
Speaking of non-C++ languages, it very often happens that one needs to adapt
the documentation for something based on the programming language. We have
configured Doxygen to define different symbols depending on the language for
which the output is being generated; these symbols can be used with Doxygen's
@@if command to introduce text conditionally. The following
table lists the symbols defined for different languages:
| Language |
Symbols defined |
| C |
conly, clike, doxygenCOnly, doxygenCLikeOnly |
| C++ |
cpp, clike, doxygenCppOnly |
| C# |
csharp, notclike, doxygenCsharpOnly |
| Java |
java, notclike |
| Perl |
perl, notclike, doxygenPerlOnly |
| Python |
python, notclike, doxygenPythonOnly |
Important: Doxygen removes the white space surrounding the
text inside the conditional and after the @c @@endif. This is highly
problematic in most situations, because it produces run-together text in the
output. We believe this is a bug and have reported it to the Doxygen
developers, but as of version 1.8.6, the behavior persists. To avoid the
problem, use the following hack: unless the next character after @c @@endif
is a punctuation character or it is the end of the text block, put the
sequence @@~ after the @c @@endif. In other words, write
@@endif@@~ in the input, rather than a bare @c @@endif.
@subsection coding-common-text 4.5 Notes and warnings
We use two Doxygen commands to produce text that is highlighted in the output
in certain ways, to call attention to special issues. These commands do not
take any arguments and should be placed before the paragraph of the text to
be highlighted.
To call out something special about a class, function, file or other entity,
such as a behavior that should be brought to the attention of users or a note
about API changes, please use the @c @@note command. This formats the next
paragraph with the heading "Note:".
To make a stronger statement, for example to warn users about potentially
error-provoking situations or backward-incompatible changes in the API, use
the @c @@warning command. This formats the following paragraph with the
heading "Warning:". Important: due to limitations in our
documentation pipeline (in particular, in the use of Javadoc), the desired
formatting can currently only be achieved through the use of an additional
explicit bit of HTML code. Specifically, please wrap the paragraph with an
HTML <span> element that puts the paragraph contents
inside the CSS class "warning". The following example fragment illustrates
this:
@verbatim
* @class doc_warning_typecodes_not_unique
*
* @warning The specific integer values of
* the possible type codes may be reused by different Level 3
* package plug-ins.
@endverbatim
As a convention, please put @c @@note blocks after other text such as
parameter lists and general explanations. Put @c @@warning blocks after any
@c @@note blocks, but put @c @@warning blocks @em before @c @@see blocks, and
put @c @@see very last in documentation. Sometimes there are exceptional
situations were it's better to put warnings higher in the documentation of a
class or method, but in most cases, the sequence should be: @c @@note, @c
@@warning, and @c @@see.
@subsection coding-figures 4.6 Figures
Including images and other figures is a relatively simple matter. Copy the file
to the directory docs/src/common-graphics/, and then refer to it
in the text using the Doxygen command @c @@image. This command takes three
arguments: the output type for which the image is to be used, the name of the
file, and a text string constituting the caption to be placed under the
image. Here is an example:
@verbatim
* @image html model-qualifiers.png "Model qualifier relationships"
* @image latex model-qualifiers.png "Model qualifier relationships"
@endverbatim
Since we may at some point generate latex output, always use two @c @@image
commands when you use it: once with @c html and once with @c latex.
@subsection coding-verbatim 4.7 Code and verbatim text
Putting fragments of sample code in the documentation is always helpful for
readers. Doing it in a way that produces text with syntactic elements
highlighted makes the text more readable. Doxygen can perform syntax
coloring on code fragments written in C++, C#, C, Java, and Python, but not
other languages, and (particularly unfortunate for libSBML), not for XML
either. Here is the approach used in the libSBML documentation for the
different cases in order to cope with this limitation.
@li For code written in C++, C#, C, Java, and Python, enclose the code in
Doxygen's @@code/@@endcode construct. Indicate
the language as an option to @@code in curly braces, using
standard filename extensions. For example: @@code{.py} for
Python, @@code{.java} for Java, etc.
@li Provide different versions of the code for different languages.
Conditionalize them using the standard @@if construct. Here
is an example:
@verbatim
@if cpp
@code{.cpp}
... C++ version ...
@endcode
@endif
@if java
@code{.java}
... Java version ...
@endcode
@endif
@if python
@code{.py}
... Python version ...
@endcode
@endif
... etc. ...
@endverbatim
@li For XML (which is not one of types recognized by Doxygen natively), we
have to use an entirely different approach: store the content in a file
that is processed by a syntax coloring tool, and then use @c @@htmlinclude
to incorporate the result in the libSBML documentation. Here is a
step-by-step procedure:
-# Save the XML content in a file with a .xml extension in the
directory docs/src/common-text/.
-# Obtain the Python-based syntax highlighting application Pygments and use it to perform syntax
coloring on the .xml file. Save the result to another file
with the same basename but the extension .html in the
directory docs/src/common-text/. Here is a general command
line for using the program @c pygmentize provided by the Pygments distribution:
@code{.sh}
pygmentize -f html -o outputfile.html intputfile.xml
@endcode
-# Finally, use the Doxygen command @c @@htmlinclude to include the
.html file produced by the previous step. See section @ref
coding-htmlinclude for more information about using @c @@htmlinclude.
@section coding-doxygen-summary 5. Commonly-used commands
The following is a summary of the Doxygen commands we have found useful so
far in documenting libSBML. This is only intended as a quick orientation;
they are illustrated in the other sections above, and the complete details
of their definitions and use can be found online at the Doxygen website.
| Command |
Meaning |
| @c @@author |
Names the author of the entity being described (a file, a class, etc.).
|
| @c @@brief |
Provides a one-sentence description of the entity being described (a file,
a class, etc.). |
| @c @@bug |
Formats the following paragraph with the heading "Bugs:". Useful to
indicate that something is known to be a problem in some part of the code.
As a convention, please put @c @@bug blocks at the end of a documentation
block, for uniformity in the API documentation.
|
| @c @@c |
Puts the following word in typewriter ("code") font. To style more than one
word, use <code>the words</code>. If you need to
put something that contains HTML tags in typewriter font, use the
<code>the words</code> form, and use the HTML
character codes \< and\> to embed the
opening '@c <' and '@c >' characters inside the words.
|
@@code{.x} ... @c @@endcode |
Formats the text as code in the programming language indicated by a filename
extension .x. For example, @@code{.py} interprets
the contents as Python code. See section @ref coding-verbatim above for more
information about how to use this.
|
| @c @@class |
Declares that the following documentation block refers to the named class.
Useful only when the block does not immediately precede the class
definition (e.g., when it's at the beginning of the file).
|
| @c @@copydetails |
Copies the "detail" portion of the documentation of the given symbol. Please
see Section @ref coding-copydetails for more information.
|
| @c @@copydoc |
Copies the entire documentation of the given symbol---both the one-sentence
brief lead-in explanation and the detailed body. Please see Section
@ref coding-copydoc for more information.
|
| @c @@em |
Puts the following word in italic font, for emphasis. To put multiple words
in italics, use <em>the words</em>.
|
| @c @@enum |
Defines an enumeration. Otherwise identical to @c @@class.
|
| @c @@file |
Defines the name of the current file. |
| @c @@htmlinclude |
Insert the contents of the named file. The file can contain HTML
formatting instructions.
|
| @c @@if ... @em symbol @c @@else ... @c @@endif |
Makes content visible depending on whether the @em symbol immediately
following the @c @@if is defined. If it is defined, the text after the
symbol and before either the @c @@else (if it is present) or the @c @@endif
is used in the output. Important: As noted above in Section
@ref coding-conditionals, Doxygen removes the white space surrounding the
text inside the conditional and after the @c @@endif. This is problematic in
most situations, because it produces run-together text in the output. We
believe this is a bug and have reported it, but as of Doxygen version 1.8.6,
the behavior persists. To avoid the problem, use the following hack: unless
the next character after @c @@endif is a punctuation character or it is the
end of the text block, put the sequence @@~ after the @c
@@endif. In other words, write @@endif@@~ in the input, rather
than a bare @c @@endif.
|
| @c @@li |
Starts (or continues) a bullet list. You can insert the first @c @@li in
a comment, and the item will continue until a paragraph break or the
next @c @@li command. (Note: even though Doxygen will also recognize
hyphens at the beginning of a line as starting a list item, avoid using
that approach in favor of the @c @@li command.
|
| @c @@p |
Puts the following word in typewriter ("code") font. This form is preferred
when the word is a parameter to a method or function.
|
| @c @@param |
Declares a parameter to a method or function. The first word following
@c @@param will be the name of the parameter, and the rest of the text (up to
a period or blank) will be used as the description.
|
| @c @@n |
Forces a newline, like HTML's <br>.
|
| @c @@note |
Formats the following paragraph with the heading "Note:". Useful to call
out something special about a class, function, file or other entity, such
as a behavior that should be brought to the attention of users or a note
about API changes compared to previous versions of the software or SBML.
|
| @c @@return |
Declares the return value from a method or function.
|
| @c @@sbmlbrief |
Special command defined for libSBML; see Section @ref coding-doc-h for
more information.
|
| @c @@sbmlconstant |
Special command defined for libSBML; see Section @ref coding-constant-refs for
more information.
|
| @c @@sbmlfunction |
Special command defined for libSBML; see Section @ref coding-function-refs for
more information.
|
| @c @@see |
Formats a reference to another entity in the documentation. Commonly used
to refer to related classes or methods. Always put @c @@see blocks
at the very end of a documentation block, both for uniformity in the
API documentation and to avoid a bug in our Javadoc-based document production
pipeline.
|
| @c @@warning |
Formats the following paragraph with the heading "Warning:". This is a
stronger statement than @c @@note, and is useful to call attention to
backward-incompatible changes or potentially error-provoking situations.
As a convention, please put @c @@warning blocks after @c @@note blocks
in documentation, and please wrap them with
an HTML span element with the CSS class "warning". (See discussion in
Section @ref coding-common-text.)
|
Many HTML commands will work in comments for Doxygen. For example, a
common one is the @c a tag for linking text to a URL, as in <a
href="http://sbml.org">home page</a>. Unfortunately, many
(most?) HTML commands will @em not work. For those situations, you may have
to resort to using @c @@htmlinclude'ed raw HTML files.
@section coding-doc-process 6. LibSBML's documentation-generation process
The sequence of events in generating the finished, formatted user
documentation is complex. However, it can be useful to have a general sense
for how it works, to help find problems when the output produced is not
what's expected. This section summarizes the sequences of events for the
different types of documentation.
@subsection doc-process-c 6.1 Generating C++ and C docs
The steps below are executed by the Makefile located in the directory
docs/src/. They are invoked by the command make
cpp-manual (for C++) or make c-manual (for C).
-# The process first generates a CSS stylesheet
(css/libsbml-package-stylesheet.css) to define formatting
rules tailored for each class defined by each Level 3 package
extension for libSBML. This is done by the Python program
css/generate-pkg-stylesheet.py. This program works by
walking down the libSBML package source code directory, examining every
.h file looking for @c @@class statements, and collecting the
list of class names, then producing a .css file with rules
for every class found. The rules define the color symbols associated with
every SBML Level 3 package class in the libSBML API documentation.
-# Next, Doxygen is executed @em twice. This double run of Doxygen is
necessary to use the @c @@ingroup command in the way we use it to produce
pages that list all the classes associated with a given SBML Level 3
package.
- In the first run of Doxygen, the definition of the macro @c
@@sbmlbrief is altered so that it invokes the Doxygen command @c
@@addindex with the name of the each libSBML Python class. The results of
this run are a number of JavaScript files produced by Doxygen (files
like
navtreeindex.js, navtree.js, etc.). These
files are saved aside temporarily while the next step is performed.
- In the second run of Doxygen, the definition of @c @@sbmlbrief is reverted
to its normal form, in which it invokes the Doxygen command @c @@ingroup.
This produces the pages in the section titled "Level 3 Extensions"
in the final documentation.
- The (correct) index files produced in the first run of Doxygen are used
to replace the (incorrect) index files from the second run.
-# Finally, a number of unmodified additional files are copied to the
destination directory: CSS style files, JavaScript files, image files, and
so on.
Without the double run of Doxygen described above, the left-hand table of
contents produced by Doxygen is dysfunctional. If you encounter a broken
table of contents, then it may indicate something went wrong in the two-step
process described above.
@subsection doc-process-python 6.2 Generating Python docs
The process for generating the Python API documentation is more involved than
the one for C++ and C documentation described above, though some parts are
the same. The process for Python begins @em before you run make
python-manual in the docs/src/ directory: it begins with
the process involving the execution of SWIG. For completeness, the sequence
below encompasses this.
-# Before the documentation can be produced---that is, before the
remaining steps below can be executed---the Python language interface
code for libSBML must be generated. This process is triggered by a
regular make or cmake at the top level of the
libSBML source code directory. Unlike the other language bindings,
however, the process for Python has extra complexity because two kinds of
output have to be produced: one for use with Doxygen to generate the API
documentation, and one for creating plain-text comment strings embedded
with the Python code, which users will see when they use Python's
interactive help facilities. The steps involved can be summarized like
this:
- The Python program
rewrite_pydoc.py in the subdirectory
src/bindings/python/doc-converter/ is executed. This Python
program reads all the libSBML source code files, copies the class and
method comments found therein, performs pattern matching and substitution
in the text of those comments to produce versions that follow Python
documentation conventions, and finally, produces the file that will
ultimately be used by SWIG when it creates the real language interface
code.
- The Python program
src/bindings/swig/swigdoc.py is executed.
Like the previous program, it also reads all the libSBML source code
files, copies the class and method comments found therein, performs
pattern matching and substitution in the text of those comments; however,
it produces a @em different, temporary file that is fed to SWIG only to
produce output for the next step.
- SWIG is executed once on the temporary file from the previous step to
produce the file
src/bindings/python/libsbml-doxygen.py.
This will be the file used read by Doxygen to produce the formatted API
documentation.
- SWIG is executed a second time on the output from
rewrite_doc.py (explained above), to produce the actual
Python binding definitions in
src/bindings/python/libsbml_wrap.cpp.
-# The remaining steps below to produce the formatted API documentation
output are executed by the Makefile located in the directory
docs/src/. They are invoked by the command make
java-manual. (Note that the steps @em above are always performed
during a build of libSBML, regardless of whether you generate
documentation.)
-# The make python-manual process first generates a CSS
stylesheet (css/libsbml-package-stylesheet.css) to define
formatting rules tailored for each class defined by each Level 3
package extension for libSBML. This is done by the Python program
css/generate-pkg-stylesheet.py. This program works by
walking down the libSBML package source code directory, examining every
.h file looking for @c @@class statements, and collecting the
list of class names, then producing a .css file with rules
for every class found. The rules define the color symbols associated with
every SBML Level 3 package in the libSBML API documentation.
-# Next, a substitution step is performed on the file produced by SWIG. This
substitution step is implemented by the Python program
pythondocpreprocessor.py in docs/src/. This
program reads files found in docs/src/python-substitutions
(each file is named after a libSBML Python class), and also reads the file
libsbml-doxygen.py previously produced by SWIG in the
src/bindings/python/ directory (as described above). For
each file in the substitutions directory, the program takes the contents
of that file and uses the comment strings found therein instead of the
comment strings found for that same class in the SWIG-produced
libsbml-doxygen.py file. If a subtitution file exists for a
class but is empty, then this has the effect of @em deleting that class
from the documentation produced. This admittedly complicated step has two
roles: it adds documentation for classes only defined in the language
bindings that we could not find another way to document directly (e.g.,
for classes ASTNodeList, CVTermList, etc.), and second, it omits some
internal classes from the API documentation.
-# Next, the make python-manual process in
docs/src/ runs Doxygen @em twice. This double
run of Doxygen is necessary to use the @c @@ingroup command in the way we
use it to produce pages that list all the classes associated with a given
SBML Level 3 package.
- In the first run of Doxygen, the definition of the macro @c
@@sbmlbrief is altered so that it invokes the Doxygen command @c
@@addindex with the name of the each libSBML Python class. The results of
this run are a number of JavaScript files produced by Doxygen (files
like
navtreeindex.js, navtree.js, etc.). These
files are saved aside temporarily while the next step is performed.
- In the second run of Doxygen, the definition of @c @@sbmlbrief is reverted
to its normal form, in which it invokes the Doxygen command @c @@ingroup.
This produces the pages in the section titled "Level 3 Extensions"
in the final documentation.
- The (correct) index files produced in the first run of Doxygen are used
to replace the (dysfunctional) index files from the second run.
-# Finally, a number of unmodified additional files are copied to the
destination directory: CSS style files, JavaScript files, image files, and
so on.
@subsection doc-process-java 6.3 Generating Java docs
The process for the Java API documentation is different from all the others
because it does not use Doxygen; instead, it uses Javadoc, the common Java
documentation-generation tool. In principle we @em could use Doxygen for
Java as well, but the output produced by Doxygen is different in appearance
and structure than what Javadoc produces. We felt that using Javadoc would
provide something closer to what Java developers are accustomed to seeing,
and therefore would be better for Java developers.
The process for generating the Java API documentation actually begins @em
before you run make java-manual in the docs/src/
directory: it begins with the process involving the execution of SWIG. For
completeness, the sequence below encompasses this.
-# Before the documentation can be produced---that is, before the
remaining steps below can be executed---the Java bindings files for
libSBML must be generated. This process is triggered by a regular
make or cmake at the top level of the libSBML
source code directory. It will invoke SWIG at some point, but before it
invokes SWIG, it will run the custom Python program
src/bindings/swig/swigdoc.py. This Python program reads all
the libSBML source code files, copies the class and method comments found
therein, performs pattern matching and substitution in the text of those
comments to produce versions that follow Javadoc conventions, and writes
the modified results to the file src/bindings/java/javadoc.i.
This file will be read by SWIG when it runs. When SWIG produces the
actual Java files that it writes in
src/bindings/java/java-files/, it uses the comment strings in
this file as the source of the documentation strings attached to the Java
class and method definitions.
-# The remaining steps below to produce the formatted API documentation
output are executed by the Makefile located in the directory
docs/src/. They are invoked by the command make
java-manual. (Note that the steps @em above are always performed
during a build of libSBML, regardless of whether you generate documentation.)
-# The make java-manual process first generates a CSS stylesheet
(css/libsbml-package-stylesheet.css) to define formatting
rules tailored for each class defined by each Level 3 package
extension for libSBML. This is done by the Python program
css/generate-pkg-stylesheet.py. This program works by
walking down the libSBML package source code directory, examining every
.h file looking for @c @@class statements, and collecting the
list of class names, then producing a .css file with rules for
every class found. The rules define the color symbols associated with every
package and written in places such as the left-hand list of class names in
the Javadoc output. (This complicated process is necessary because
Javadoc provides no other hooks to modify the appearance of class
description pages.)
-# The Java files previously produced by SWIG for the Java API are copied
from their location in src/bindings/java/java-files/ to a
temporary directory in docs/src.
-# The Java files located in docs/src/java-substitutions/ are
copied into the same temporary directory as the previous step, @em
overwriting some of the files originally created by SWIG. These
substitutions are necessary for various reasons, including the inability
to attach documentation to some types of objects produced by SWIG. The
files in docs/src/java-substitutions/ do not contain any Java
code, only comments. Two points are important to note. First, the
comments are in Javadoc format, @em not in Doxygen format, because the
next step will feed the files as-is to Javadoc. Second, if the original
source code changes, the substitution files must be modified by
hand to account for the changes. This is an obvious maintenance
problem, but we currently have no better solution.
-# Next, Javadoc is executed on the contents of the temporary directory
mentioned in the previous step, to generate the basic HTML output files to
the destination directory. Javadoc is invoked with a custom doclet that
implements features not available in the default Javadoc doclet, such as
skipping internal SWIG methods with a certain name, detecting the tag @c
@@internal in method comments and omitting those methods from the output,
and adding some comments to some methods (at the moment, the
delete() method).
-# A number of unmodified additional files are copied to the destination
directory: CSS style files, JavaScript files, image files, and so on.
-# A number of additional HTML files are copied from docs/src/
to the destination directory, but using a procedure that prepends a
header, appends a footer, and performs substitutions on variables in the
files (for the title and the libSBML version number) to produce their
final version in the output directory. These files are for the front
page of the API documentation, installation procedures, etc.; basically,
content that is not class or method documentation.
-# The HTML page that lists the libSBML SBML Level 3 extensions is
generated using a Python program,
docs/src/generate-extensions-summary.py. The file is
generated by rewriting an HTML page generated by Javadoc. The
transformations include adding the color codes for different Level 3
packages.
-# All of the HTML files in the output directory are modified to insert a
directive to include the sbml.js JavaScript file and to
rewrite some of the text in the files (e.g., to remove the word "Package",
which is a Java term that has a different meaning for SBML).
-# Finally, the Java example files are copied from
examples/java/ to a subdirectory in the destination output
directory, along the way being modified to wrap them in HTML code.
@section coding-misc-doxygen 7. Miscellaneous Doxygen notes
The following are some notes and warnings that did not easily fit elsewhere
in this section.
@li The doxygen command @c @@internal is (according to the doxygen
documentation) supposed to let you flag things as internal implementation
code, such that it is not put in the finished documentation. This would be
great if we could use it, but I (MH) have been unable to make this work.
(Yes, there is a configuration flag, and yes, I've tried setting it both
ways.)
*/