From b8f4cb8a0c818f24782e4cf3c258d856bac39550 Mon Sep 17 00:00:00 2001 From: Teemu Murtola Date: Sun, 9 Feb 2014 14:15:32 +0200 Subject: [PATCH] Add documentation for using Doxygen - Add a page that provides guidelines and examples for using Doxygen. Hopefully, this would make simple examples easier to find, and help people write correct comments from the beginning. - Remove unnecessary \addtopublicapi and \addtolibraryapi. Once the contents are there, it is easy to enhance the documentation by adding content whenever noticing things that are tricky. Change-Id: I319e30452004998df73c249f46570cb2254daa87 --- .gitattributes | 2 + doxygen/Doxyfile-common.cmakein | 4 +- doxygen/Doxyfile-full.cmakein | 2 - doxygen/Doxyfile-lib.cmakein | 2 - doxygen/Doxyfile-user.cmakein | 3 +- doxygen/doxygen.md | 485 +++++++++++++++++++ doxygen/examples/doxygen-example-issues.cpp | 41 ++ doxygen/examples/doxygen-example-module.cpp | 17 + doxygen/examples/doxygen-example-scoping.cpp | 119 +++++ doxygen/examples/doxygen-example.c | 50 ++ doxygen/examples/doxygen-example.cpp | 71 +++ doxygen/mainpage.md | 8 +- src/gromacs/utility/gmxassert.h | 9 +- 13 files changed, 800 insertions(+), 13 deletions(-) create mode 100644 doxygen/doxygen.md create mode 100644 doxygen/examples/doxygen-example-issues.cpp create mode 100644 doxygen/examples/doxygen-example-module.cpp create mode 100644 doxygen/examples/doxygen-example-scoping.cpp create mode 100644 doxygen/examples/doxygen-example.c create mode 100644 doxygen/examples/doxygen-example.cpp diff --git a/.gitattributes b/.gitattributes index 1e09923537..1aa10d59e3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -27,6 +27,8 @@ cmake/*.c !filter cmake/*.c.cmakein !filter doxygen/Doxyfile-*.cmakein !filter doxygen/*.cpp !filter +doxygen/examples/*.cpp filter=uncrustify_only +doxygen/examples/*.c filter=uncrustify_only manual/UseLATEX.cmake !filter scripts/GMXRC.* !filter scripts/make_gromos_rtp.py !filter diff --git a/doxygen/Doxyfile-common.cmakein b/doxygen/Doxyfile-common.cmakein index 5794347350..44a3a185da 100644 --- a/doxygen/Doxyfile-common.cmakein +++ b/doxygen/Doxyfile-common.cmakein @@ -6,7 +6,8 @@ INPUT = @CMAKE_CURRENT_SOURCE_DIR@ \ @CMAKE_SOURCE_DIR@/share/template EXAMPLE_PATH = @CMAKE_SOURCE_DIR@ RECURSIVE = YES -EXCLUDE = @CMAKE_SOURCE_DIR@/src/contrib \ +EXCLUDE = @CMAKE_SOURCE_DIR@/doxygen/examples \ + @CMAKE_SOURCE_DIR@/src/contrib \ @CMAKE_SOURCE_DIR@/src/external \ @CMAKE_SOURCE_DIR@/src/gromacs/legacyheaders/thread_mpi/atomic \ @CMAKE_SOURCE_DIR@/src/gromacs/selection/parser.cpp \ @@ -43,6 +44,7 @@ GENERATE_LATEX = NO # Setting this to NO has a side effect to hide undocumented headers from the # file list, which makes it generally look nicer. VERBATIM_HEADERS = NO +STRIP_CODE_COMMENTS = NO EXTRACT_LOCAL_CLASSES = NO diff --git a/doxygen/Doxyfile-full.cmakein b/doxygen/Doxyfile-full.cmakein index 8cf48a79a2..269b787838 100644 --- a/doxygen/Doxyfile-full.cmakein +++ b/doxygen/Doxyfile-full.cmakein @@ -17,7 +17,5 @@ INLINE_INHERITED_MEMB = NO # Makes it easier to go through all documentation ALIASES += inpublicapi="\ingroup group_publicapi" ALIASES += inlibraryapi="\ingroup group_libraryapi" -ALIASES += addtopublicapi="\addtogroup group_publicapi" -ALIASES += addtolibraryapi="\addtogroup group_libraryapi" ALIASES += libinternal= ALIASES += endlibinternal= diff --git a/doxygen/Doxyfile-lib.cmakein b/doxygen/Doxyfile-lib.cmakein index 3924070d57..497e358c10 100644 --- a/doxygen/Doxyfile-lib.cmakein +++ b/doxygen/Doxyfile-lib.cmakein @@ -8,7 +8,5 @@ HTML_OUTPUT = html-lib ALIASES += inpublicapi="\ingroup group_publicapi" ALIASES += inlibraryapi="\ingroup group_libraryapi" -ALIASES += addtopublicapi="\addtogroup group_publicapi" -ALIASES += addtolibraryapi="\addtogroup group_libraryapi" ALIASES += libinternal= ALIASES += endlibinternal= diff --git a/doxygen/Doxyfile-user.cmakein b/doxygen/Doxyfile-user.cmakein index 4e67502929..da37fa9c4e 100644 --- a/doxygen/Doxyfile-user.cmakein +++ b/doxygen/Doxyfile-user.cmakein @@ -4,6 +4,7 @@ # exclude them from the generated file list EXCLUDE += @CMAKE_SOURCE_DIR@/src/programs EXCLUDE += @CMAKE_SOURCE_DIR@/src/testutils +EXCLUDE += @CMAKE_SOURCE_DIR@/doxygen/doxygen.md EXCLUDE += @CMAKE_SOURCE_DIR@/doxygen/unittesting.md EXCLUDE += @CMAKE_SOURCE_DIR@/doxygen/wrapperbinary.md @@ -15,7 +16,5 @@ HTML_OUTPUT = html-user ALIASES += inpublicapi="\ingroup group_publicapi" ALIASES += inlibraryapi="\ingroup group_libraryapi" -ALIASES += addtopublicapi="\addtogroup group_publicapi" -ALIASES += addtolibraryapi="\addtogroup group_libraryapi" ALIASES += libinternal="\internal" ALIASES += endlibinternal="\endinternal" diff --git a/doxygen/doxygen.md b/doxygen/doxygen.md new file mode 100644 index 0000000000..0bdea5ea9b --- /dev/null +++ b/doxygen/doxygen.md @@ -0,0 +1,485 @@ +Using Doxygen {#page_doxygen} +============= + +This page documents how Doxygen is set up in the \Gromacs source tree, +as well as guidelines for adding new Doxygen comments. Examples are included, +as well as tips and tricks for avoiding Doxygen warnings. The guidelines focus +on C++ code and other new code that follows the new module layout. +Parts of the guidelines are still applicable to documenting older code (e.g., +within `gmxlib/` or `mdlib/`), in particular the guidelines about formatting +the Doxygen comments and the use of \c \\internal. +\ref page_codelayout documents the overall structure of the documentation. + +To get started quickly, you only need to read the first two sections to +understand the overall structure of the documentation, and take a look at the +examples at the end. The remaining sections provide the details for +understanding why the examples are the way they are, and for more complex +situations. They are meant more as a reference to look up solutions for +particular problems, rather than single-time reading. To understand or find +individual Doxygen commands, you should first look at Doxygen documentation +(http://www.stack.nl/~dimitri/doxygen/manual/index.html). + + +Documentation flavors +===================== +The \Gromacs source tree is set up to produce three different levels of Doxygen +documentation: + +1. Public API documentation (suffix `-user`), which documents functions and + classes exported from the library and intended for use outside the \Gromacs + library. +2. Library API documentation (suffix `-lib`), which additionally includes + functions and classes that are designed to be used from other parts of + \Gromacs, as well as some guidelines that are mostly of interest to + developers. +3. Full documentation (suffix `-full`), which includes (nearly) all (documented) + functions and classes in the source tree. + +Each subsequent level of documentation includes all the documentation from the +levels above it. The suffixes above refer to the suffixes of Doxygen input and +output files, as well as the name of the output directory. When all the +flavors have been built, the front pages of the documentation contain links to +the other flavors, and explain the differences in more detail. + +As a general guideline, the public API documentation should be kept free of +anything that a user linking against an unmodified \Gromacs does not see. +In other words, the public API documentation should mainly document the +contents of installed headers, and provide the necessary overview of using +those. Also, verbosity requirements for the public API documentation are +higher: ideally, readers of the documentation could immediately start using the +API based on the documentation, without any need to look at the implementation. + +Similarly, the library API documentation should not contain things that other +modules in \Gromacs can or should never call. In particular, anything declared +locally in source files should be only available in the full documentation. +Also, if something is documented, and is not identified to be in the library +API, then it should not be necessary to call that function from outside its +module. + + +Building the documentation +========================== + +If you simply want to see up-to-date documentation, you can go to +http://jenkins.gromacs.org/job/Doxygen_Nightly_master/javadoc/html-lib/index.xhtml +to see the documentation for the current development version. +Jenkins also runs Doxygen for all changes pushed to Gerrit for master, and the +resulting documentation can be viewed from the link posted by Jenkins. The +Doxygen build is marked as unstable if it introduces any Doxygen warnings. + +You may need to build the documentation locally if you want to check the +results after adding/modifying a significant amount of comments. This is +recommended in particular if you do not have much experience with Doxygen. +It is a good idea to build with all the different settings to see that the +result is what you want, and that you do not produce any warnings. +For local work, it is generally a good idea to set `GMX_COMPACT_DOXYGEN=ON` +CMake option, which removes some large generated graphs from the documentation +and speeds up the process significantly. + +All files related to Doxygen reside in the `doxygen/` subdirectory in the source +and build trees. In a freshly checked out source tree, this directory contains +various `Doxyfile-*.cmakein` files. When you run CMake, corresponding files +`Doxyfile-user`, `Doxyfile-lib`, and `Doxyfile-full` are generated at the +corresponding location in the build tree. There is also a +`Doxyfile-common.cmakein`, which is used to produce `Doxyfile-common`. +This file contains settings that are shared between all the input files. +`Doxyfile-compact` provides the extra settings for `GMX_COMPACT_DOXYGEN=ON`. + +You can run Doxygen directly with one of the generated files (all output will +be produced under the current working directory), or build one of the +`doc-user`, `doc-lib`, and `doc-full` targets. The targets run Doxygen in a +quieter mode and only show the warnings if there were any, and put the output +under `doxygen/` in the build tree. The `doc-all` target builds all three +targets with less typing. + +The generated documentation is put under `html-user/`, `html-lib/`, and/or +`html-full/` in the output directory. Open `index.xhtml` file from one of +these subdirectories to start browsing (for \Gromacs developers, the +`html-lib/` is a reasonable starting point). Log files with all Doxygen +warnings are also produced as `doxygen-*.log`, so you can inspect them after +the run. + +You will need Doxygen 1.8.5 to build the current documentation. Other versions +may work, but likely also produce warnings. Additionally, +[graphviz](http://www.graphviz.org) and +[mscgen](http://www.mcternan.me.uk/mscgen/) are required for some graphs in +the documentation, and `latex` for formulas. Working versions are likely +available through most package managers. It is possible to build the +documentation without these tools, but you will see some errors and the related +figures will be missing from the documentation. + + +General guidelines for Doxygen markup +===================================== + +Doxygen provides quite a few different alternative styles for documenting the +source code. There are subtleties in how Doxygen treats the different types of +comments, and this also depends somewhat on the Doxygen configuration. It is +possible to change the meaning of a comment by just changing the style of +comment it is enclosed in. To avoid such issues, and to avoid needing to +manage all the alternatives, a single style throughout the source tree is +preferable. When it comes to treatment of styles, \Gromacs uses the default +Doxygen configuration with one exception: `JAVADOC_AUTOBRIEF` is set ON to +allow more convenient one-line brief descriptions in C code. + +Majority of existing comments in \Gromacs uses Qt-style comments (`/*!` and +`//!` instead of `/*``*` and `///`, \c \\brief instead of \c \@brief etc.), +so these should be used also for new documentation. There is a single +exception for brief comments in C code; see below. + +Similarly, existing comments use `/*!` for multiline comments in both C and +C++ code, instead of using multiple `//!` lines for C++. The rationale is that +since the code will be a mixture of both languages for a long time, it is more +uniform to use similar style in both. Also, since files will likely transition +from C to C++ gradually, rewriting the comments because of different style +issues should not generally be necessary. Finally, multi-line `//!` comments +can work differently depending on Doxygen configuration, so it is better to +avoid that ambiguity. + +When adding comments, ensure that a short brief description is always produced. +This is used in various listings, and should briefly explain the purpose of the +method without unnecessarily expanding those lists. +The basic guideline is to start all comment blocks with \c \\brief (possibly +after some other Doxygen commands). +If you want to avoid the \c \\brief for one-liners, you can use `//!`, but the +description must fit on a single line; otherwise, it is not interpreted as a +brief comment. Note in particular that a simple `/*!` without a \c \\brief +does not produce a brief description. +Also note that \c \\brief marks the whole following paragraph as a brief +description, so you should insert an empty line after the intended brief +description. + +In C code, `//` comments must be avoided because some compilers do not like +them. If you want to avoid the \c \\brief for one-liners in C code, use +`/*``*` instead of `//!`. If you do this, the brief description should not +contain unescaped periods except at the end. Because of this, you should +prefer `//!` in C++ code. + +Put the documentation comments in the header file that contains the +declaration, if such a header exists. +Implementation-specific comments that do not influence how a method +is used can go into the source file, just before the method definition, with an +\c \\internal tag in the beginning of the comment block. Doxygen-style comments +within functions are not generally usable. + +At times, you may need to exclude some part of a header or a source file such +that Doxygen does not see it at all. In general, you should try to avoid this, +but it may be necessary to remove some functions that you do not want to appear +in the public API documentation, and which would generate warnings if left +undocumented, or to avoid Doxygen warnings from code it does not understand. +Prefer \c \\cond and \c \\endcond to do this. If \c \\cond does not work for +you, you can also use \c \#ifndef `DOXYGEN`. If you exclude a class method in +a header, you also need to exclude it in the source code to avoid warnings. + + +\Gromacs specifics +================= + +The general guidelines on the style of Doxygen comments were given above. +This section introduces \Gromacs specific constructs currently used in Doxygen +documentation, as well as how \Gromacs uses Doxygen groups to organize the +documentation. + +Controlling documentation visibility +------------------------------------ + +To control in which level of documentation a certain function appears, three +different mechanisms are used: +* Global Doxygen configuration. This is mainly used to include + declarations local to source files only in the full documentation. + You can find the details from the `Doxyfile-*.cmakein` files, and some of + them are also mentioned below on individual code constructs. +* The standard Doxygen commands \c \\internal and \c \\endinternal mark the + documentation to be only extracted into the full documentation + (`INTERNAL_DOCS` is `ON` only for the full documentation). + In addition, \Gromacs specific custom Doxygen commands \c \\libinternal and + \c \\endlibinternal are provided, which only exclude the documentation from + the public API documentation. These are implemented by expanding the + commands to either \c \\internal or to a no-op, depending on the + documentation level. +* Doxygen commands \c \\if and \c \\cond can be used with section names + `libapi` and `internal` to only include the documentation in library API and + the full documentation, respectively. `libapi` is also defined in the full + documentation. These are declared using `ENABLED_SECTIONS` in the Doxygen + configuration files. + +Examples of locations where it is necessary to use these explicit commands are +given below in the sections on individual code constructs. + +Modules as Doxygen groups +------------------------- + +As described in \ref page_codelayout, each subdirectory under `src/gromacs/` +represents a _module_, i.e., a somewhat coherent collection of routines. +Doxygen cannot automatically generate a list of routines in a module; it only +extracts various alphabetical indexes that contain more or less all documented +functions and classes. To help reading the documentation, the routines for a +module should be visible in one place. + +\Gromacs uses Doxygen groups to achieve this: for each documented module, there +is a \c \\defgroup definition for the module, and all the relevant classes and +functions need to be manually added to this group using \c \\ingroup and +\c \\addtogroup. +The group page also provides a natural place for overview documentation about +the module, and can be navigated to directly from the "Modules" tab in the +generated documentation. + +Public API and library API groups +--------------------------------- + +In addition to the module groups, two fixed groups are provided: +`group_publicapi` and `group_libraryapi`. Classes and files can be added to +these groups using \Gromacs specific custom \c \\inpublicapi and +\c \\inlibraryapi commands. The generated group documentation pages are not +very useful, but annotated classes and files show the API definition under the +name, making this information more easily accessible. These commands in +file-level comments are also used for some automatic intermodule dependency +validation (see below). + +Note that functions, enumerations, and other entities that do not have a +separate page in the generated documentation can only belong to one group; +in such a case, the module group is preferred over the API group. + +Automatic dependency checking +----------------------------- + +The build system provides three targets, `depcheck`, `doccheck`, and +`depgraphs`, that depend on correct usage of the above commands, in particular +the visibility and API definitions in file-level comments. +These checks also provide some level of enforcement for rules about +dependencies between the modules, but currently the checks are not run +automatically. + +The `depcheck` target checks for issues that either completely or subtly break +the installed headers: an installed header including a non-installed header, or +an installed header installing another header using a path that does not +resolve correctly when the headers are installed. It also checks for +consistent usage of +\code +#include "..." // This should be used for Gromacs headers +\endcode +versus +\code +#include <...> // This should be used for system and external headers. +\endcode + +The `doccheck` target additionally checks that if an included file is +documented, it is not used against the API definition specified in the +file-level comment. For example, including a file without any API definition +from another module produces an error. Another example of a check is that a +non-installed header with public documentation triggers an error. + +The `depgraphs` target generates include dependency graphs. One graph is +produced that shows all the modules under `src/gromacs/`, and their include +dependencies. Additionally, a file-level graph is produced for each module, +showing the include dependencies within that module. Currently, these are +mostly for eye candy, but they can also be used for analyzing problematic +dependencies to clean up the architecture. A legend for the graphs is +currently included as comments in `admin/includedeps.py`. The output is put in +`doxygen/depgraphs/`. + +These targets require Python 2.7; the graph generation additionally requires +`graphviz`. + + +Documenting specific code constructs +==================================== + +This section describes the techical details and some tips and tricks for +documenting specific code constructs such that useful documentation is +produced. If you are wondering where to document a certain piece of +information, see the documentation structure section on \ref page_codelayout. +The focus of the documentation should be on the overview content: Doxygen pages +and the module documentation. An experienced developer can relatively easily +read and understand individual functions, but the documentation should help +in getting the big picture. + +Doxygen pages +------------- + +The pages that are accessible through navigation from the front page are +written using Markdown and are located under `doxygen/`. Each page should be +placed in the page hierarchy by making it a subpage of another page, i.e., it +should be referenced once using \c \\subpage. `mainpage.md` is the root of the +hierarchy. + +If you need to exclude a page from the public API docs, you need to add it to +an exclude list in `Doxyfile-user.cmakein`, and ensure that there are no +references to the page from public API documentation. \c \\if `libapi` can be +used to add references in content that is otherwise public. +Generally, the pages should be on a high enough level and provide overview +content that is useful enough such that it is not necessary to exclude them +from the library API documentation. + +Modules +------- + +For each module, decide on a header file that is the most important one for +that module (if there is no self-evident header, it may be better to designate, +e.g., module-doc.h for this purpose, but this is currently not done for any +module). This header should contain the \c \\defgroup definition for the +module. The name of the group should be `module_`name, where _name_ +is the name of the subdirectory that hosts the module. + +The module should be added to an appropriate group (see `doxygen/misc.cpp` for +definitions) using \c \\ingroup to organize the "Modules" tab in the generated +documentation. + +One or more contact persons who know about the contents of the module should be +listed using \c \\author commands. This provides a point of contact if one +has questions. + +Classes/structs +--------------- + +Classes and structs in header files appear always in Doxygen documentation, +even if their enclosing file is not documented. So start the documentation +blocks of classes that are not part of the public API with \c \\internal or +\c \\libinternal. Classes declared locally in source files or in unnamed +namespaces only appear in the full documentation. + +If a whole class is not documented, this does not currently generate any +warning. The class is simply exluded from the documentation. But if a member +of a documented class is not documented, a warning is generated. Guidelines for +documenting free functions apply to methods of a class as well. + +For base classes, the API classification (\c \\inpublicapi or +\c \\inlibraryapi) should be based on where the class is meant to be +subclassed. The visibility (\c \\internal or \c \\libinternal), in contrast, +should reflect the API classification of derived classes such that the base +class documentation is always generated together with the derived classes. + +For classes that are meant to be subclassed and have protected members, the +protected members should only appear at the documentation level where the class +is meant to be subclassed. For example, if a class is meant to be subclassed +only within a module, the protected members should only appear in the +full documentation. This can be accomplished using \c \\cond (note that you +will need to add the \c \\cond command also to the source files to hide the +same methods from Doxygen, otherwise you will get confusing warnings). + +Methods/functions/enums/macros +------------------------------ + +These items do not appear in the documentation unless their enclosing scope is +documented. For class members, the scope is the class; otherwise, it is the +namespace if one exists, or the file. An \c \\addtogroup can also define a +scope if the group has higher visibility than the scope outside it. +So if a function is not within a namespace (mostly applicable to C code) and +has the same visibility as its enclosing file, it is not necessary to add a +\c \\internal or \c \\libinternal. + +Static functions are currently extracted for all documentation flavors to allow +headers to declare `static inline` functions (used in, for example, math code). +Functions in anonymous namespaces are only extracted into the full +documentation. Together with the above rules, this means that you should avoid +putting a `static` function within a documented namespace, even within source +files, or it may inadvertently appear in the public API documentation. + +If you want to exclude an item from the documentation, you need to put in +inside a \c \\cond block such that Doxygen does not see it. +Otherwise, a warning for an undocumented function is generated. You need to +enclose both the declaration and the definition with \c \\cond. + +Files +----- + +Each documented file should start with a documentation block (right after the +copyright notice) that documents the file. See the examples section for exact +formatting. Things to note: +* Please do not specify the file name explicitly after \c \\file. By default, + a file comment applies to the file it is contained in, and an explicit file + name only adds one more thing that can get out of date. +* \c \\brief cannot appear on the same line as the \c \\file, but should be on + the next line. +* \c \\internal or \c \\libinternal should indicate where the header is visible. + As a general guideline, all installed headers should appear in the public API + documentation, i.e., not contain these commands. If nothing else, then to + document that it does not contain any public API functions. Headers that + declare anything in the library API should be marked with \c \\libinternal, + and the rest with \c \\internal. +* All source files, as well as most test files, should be documented with + \c \\internal, since they do not provide anything to public or library API, + and this avoids unintentionally extracting things from the file into those + documentations. Shared test files used in tests from other modules should be + marked with \c \\libinternal. +* \c \\inpublicapi or \c \\inlibraryapi should be used to indicate where the + header is meant to be directly included. +* As with files, one or more contact persons should be listed with \c \\author. + If you make significant modifications or additions to a file, consider adding + an \c \\author line for yourself. + +Directories +----------- + +Directory documentation does not typically contain useful information beyond a +possible brief description, since they correspond very closely to modules, and +the modules themselves are documented. A brief description is still useful to +provide a high-level overview of the source tree on the generated "Files" page. +A reference to the module is typically sufficient as a brief description for a +directory. All directories are currently documented in +`doxygen/directories.cpp`. + + +Examples +======== + +Basic C++ +--------- + +Here is an example of documenting a C++ class and its containing header file. +Comments in the code and the actual documentation explain the used Doxygen +constructs. + +\includelineno doxygen-example.cpp + +Basic C +------- + +Here is another example of documenting a C header file (so avoiding all +C++-style comments), and including free functions. It also demonstrates the use +of \c \\addtogroup to add multiple functions into a module group without repeated +\c \\ingroup tags. + +\includelineno doxygen-example.c + +Scoping and visibility rules +---------------------------- + +The rules where Doxygen expects something to be documented, and when are +commands like \c \\internal needed, can be complex. The examples below +describe some of the pitfalls. + +\includelineno doxygen-example-scoping.cpp + +Module documentation +-------------------- + +Documenting a new module should place a comment like this in a central header +for the module, such that the "Modules" tab in the generated documentation can +be used to navigate to the module. + +\includelineno doxygen-example-module.cpp + +Common mistakes +--------------- + +The most common mistake, in particular in C code, is to forget to document the +file. This causes Doxygen to ignore most of the comments in the file, so it +does not validate the contents of the comments either, nor is it possible to +actually check how the generated documentation looks like. + +The following example shows some other common mistakes that do not produce +correct documentation. The issues are explained in normal comments above each +code fragment. + +\includelineno doxygen-example-issues.cpp + +Existing code +------------- + +More examples you can find by looking at existing code in the source tree. In +particular new C++ code such as that in the `src/gromacs/analysisdata/` and +`src/gromacs/options/` subdirectories contains a large amount of code +documented mostly along these guidelines. Some comments in +`src/gromacs/selection/` (in particular, any C-like code) predate the +introduction of these guidelines, so those are not the best examples. diff --git a/doxygen/examples/doxygen-example-issues.cpp b/doxygen/examples/doxygen-example-issues.cpp new file mode 100644 index 0000000000..de1f300392 --- /dev/null +++ b/doxygen/examples/doxygen-example-issues.cpp @@ -0,0 +1,41 @@ +// The struct itself is not documented; other comments within the declaration +// are ignored. + +struct t_struct { + + // The comment tries to document both members at once, but it only + // applies to the first. The second produces warnings about missing + // documentation (if the enclosing struct was documented). + + //! Angle parameters. + double alpha, beta; +}; + + +// This does not produce any brief documentation. +// An explicit \brief is required, or //! (C++) or /** */ (C) should be used. + +/*! Brief comment. */ +int gmx_function(); + + +// This does not produce any documentation at all, since a ! is missing at +// the beginning. + +/* \brief + * Brief description. + * + * More details. + */ +int gmx_function(); + + +// This puts the whole paragraph into the brief description. +// A short description is preferable, separated by an empty line from the rest +// of the text. + +/*! \brief + * Brief description. The description continues with all kinds of details about + * what the function does and how it should be called. + */ +int gmx_function(); diff --git a/doxygen/examples/doxygen-example-module.cpp b/doxygen/examples/doxygen-example-module.cpp new file mode 100644 index 0000000000..d94b4427c4 --- /dev/null +++ b/doxygen/examples/doxygen-example-module.cpp @@ -0,0 +1,17 @@ +/*! \defgroup module_example "Example module (example)" + * \ingroup group_utilitymodules + * \brief + * Brief description for the module. + * + * Detailed description of the module. Can link to a separate Doxygen page for + * overview, and/or describe the most important headers and/or classes in the + * module as part of this documentation. + * + * For modules not exposed publicly, \\libinternal can be added at the + * beginning (before \\defgroup). + * + * \author Author Name + */ + +// In other code, use \addtogroup module_example and \ingroup module_example to +// add content (classes, functions, etc.) onto the module page. diff --git a/doxygen/examples/doxygen-example-scoping.cpp b/doxygen/examples/doxygen-example-scoping.cpp new file mode 100644 index 0000000000..36c6ae9bc3 --- /dev/null +++ b/doxygen/examples/doxygen-example-scoping.cpp @@ -0,0 +1,119 @@ +/*! \libinternal \file + * \brief + * ... + * + * The examples below assume that the file is documented like this: + * with an \\libinternal definition at the beginning, with an intent to not + * expose anything from the file in the public API. Things work similarly for + * the full documentation if you replace \\libinternal with \\internal + * everywhere in the example. + * + * \ingroup module_example + */ + + +/*! \brief + * Brief description for a free function. + * + * A free function is not extracted into the documentation unless the enclosing + * scope (in this case, the file) is. So a \\libinternal is not necessary. + */ +void gmx_function(); + +// Assume that the module_example group is defined in the public API. + +//! \addtogroup module_example +//! \{ + +//! \cond libapi +/*! \brief + * Brief description for a free function within \\addtogroup. + * + * In this case, the enclosing scope is actually the module_example group, + * which is documented, so the function needs to be explicitly excluded. + * \\libinternal does not work, since it would produce warnings about an + * undocumented function, so the whole declaration is hidden from Doxygen. + */ +void gmx_function(); +//! \endcond + +//! \} + +// For modules that are only declared in the library API, \addtogroup +// cannot be used without an enclosing \cond. Otherwise, it will create +// a dummy module with the identifier as the name... + +//! \cond libapi +//! \addtogroup module_libmodule +//! \{ + +/*! \brief + * Brief description. + * + * No \\libinternal is necessary here because of the enclosing \\cond. + */ +void gmx_function(); + +//! \} +//! \endcond + +/*! \libinternal \brief + * Brief description for a struct. + * + * Documented structs and classes from headers are always extracted into the + * documentation, so \\libinternal is necessary to exclude it. + * Currently, undocumented structs/classes do not produce warnings, so \\cond + * is not necessary. + */ +struct t_example +{ + int member1; //!< Each non-private member should be documented. + bool member2; //!< Otherwise, Doxygen will produce warnings. +}; + +// This namespace is documented in the public API. +namespace gmx +{ + +//! \cond libapi +/*! \brief + * Brief description for a free function within a documented namespace. + * + * In this case, the enclosing scope is the documented namespace, + * so a \\cond is necessary to avoid warnings. + */ +void gmx_function(); +//! \endcond + +/*! \brief + * Class meant for subclassing only within the module, but the subclasses will + * be public. + * + * This base class still provides public methods that are visible through the + * subclasses, so it should appear in the public documentation. + * But it is not marked with \\inpublicapi. + */ +class BaseClass +{ + public: + /*! \brief + * A public method. + * + * This method also appears in the documentation of each subclass in + * the public and library API docs. + */ + void method(); + + protected: + // The \cond is necessary to exlude this documentation from the public + // API, since the public API does not support subclassing. + //! \cond internal + //! A method that only subclasses inside the module see. + void methodForSubclassToCall(); + + //! A method that needs to be implemented by subclasses. + virtual void virtualMethodToImplement() = 0; + //! \endcond +}; + +} // namespace gmx diff --git a/doxygen/examples/doxygen-example.c b/doxygen/examples/doxygen-example.c new file mode 100644 index 0000000000..900f464054 --- /dev/null +++ b/doxygen/examples/doxygen-example.c @@ -0,0 +1,50 @@ +/*! \file + * \brief + * Declares a collection of functions for performing a certain task. + * + * More details can go here. + * + * \author Example Author + * \inpublicapi + * \ingroup module_mymodule + */ + +/*! \addtogroup module_mymodule */ +/*! \{ */ + +/*! \brief + * Brief description for the data structure. + * + * More details. + * + * \inpublicapi + */ +typedef struct { + /** Brief description for member. */ + int member; + int second; /**< Brief description for the second member. */ + /*! \brief + * Brief description for the third member. + * + * Details. + */ + int third; +} gmx_mystruct_t; + +/*! \brief + * Performs a simple operation. + * + * \param[in] value Input value. + * \returns Computed value. + * + * Detailed description. + * \\inpublicapi cannot be used here, because Doxygen only allows a single + * group for functions, and module_mymodule is the preferred group. + */ +int gmx_function(int value); + +/* Any . in the brief description should be escaped as \. */ +/** Brief description for this function. */ +int gmx_simple_function(); + +/*! \} */ diff --git a/doxygen/examples/doxygen-example.cpp b/doxygen/examples/doxygen-example.cpp new file mode 100644 index 0000000000..159f90cc03 --- /dev/null +++ b/doxygen/examples/doxygen-example.cpp @@ -0,0 +1,71 @@ +/*! \libinternal \file + * \brief + * Declares gmx::MyClass. + * + * More details. The documentation is still extracted for the class even if + * this whole comment block is missing. + * + * \author Example Author + * \inlibraryapi + * \ingroup module_mymodule + */ + +namespace gmx +{ + +/*! \libinternal + * \brief + * Brief description for the class. + * + * More details. The \\libinternal tag is required for classes, since they are + * extracted into the documentation even in the absence of documentation for + * the enclosing scope. + * The \\libinternal tag is on a separate line because of a bug in Doxygen + * 1.8.5 (only affects \\internal, but for clarity it is also worked around + * here). + * + * \inlibraryapi + * \ingroup module_mymodule + */ +class MyClass +{ + public: + // Trivial constructors or destructors do not require documentation. + // But if a constructor takes parameters, it should be documented like + // methods below. + MyClass(); + ~MyClass(); + + /*! \brief + * Brief description for the method. + * + * \param[in] param1 Description of the first parameter. + * \param[in] param2 Description of the second parameter. + * \returns Description of the return value. + * \throws std::bad_alloc if out of memory. + * + * More details describing the method. It is not an error to put this + * above the parameter block, but most existing code has it here. + */ + int myMethod(int param1, const char *param2) const; + + //! Brief description for the accessor. + int simpleAccessor() const { return var_; } + /*! \brief + * Alternative, more verbose way of specifying a brief description. + */ + int anotherAccessor() const; + /*! \brief + * Brief description for another accessor that is so long that it does + * not conveniently fit on a single line cannot be specified with //!. + */ + int secondAccessor() const; + + private: + // Private members (whether methods or variables) are currently ignored + // by Doxygen, so they don't need to be documented. Documentation + // doesn't hurt, though. + int var_; +}; + +} // namespace gmx diff --git a/doxygen/mainpage.md b/doxygen/mainpage.md index 4efaf5300b..e395782212 100644 --- a/doxygen/mainpage.md +++ b/doxygen/mainpage.md @@ -22,6 +22,8 @@ to be used outside a single module. \elseif libapi documentation of functions in the library intended for reuse within the library (a subset of these functions is also exposed as a public API). +Also overview documentation aimed at \Gromacs developers is included at this +level. The main audience for this level of detail are users and developers who want to understand the \Gromacs code in general. @@ -38,7 +40,8 @@ preliminary, and subject to change. The main audience for this level of detail are users of \Gromacs who are interested in writing their own analysis tools that use \Gromacs as a library, as well as other developers who want to link against \Gromacs. -To understand the inner workings of \Gromacs, see the more detailed +To understand the inner workings of \Gromacs, or if you want to contribute to +\Gromacs, see the more detailed [library API documentation](../html-lib/index.xhtml) or [full documentation](../html-full/index.xhtml). \endif @@ -56,6 +59,9 @@ give an overview of some of the topics that are documented: Provides general guidance for writing software that uses the \Gromacs library. \if libapi + - \subpage page_doxygen
+ Provides an overview and some instructions for using Doxygen to document the + source code. - \subpage page_unittesting
Provides an overview of unit testing in \Gromacs. - \subpage page_wrapperbinary
diff --git a/src/gromacs/utility/gmxassert.h b/src/gromacs/utility/gmxassert.h index 432473b938..0259b611f1 100644 --- a/src/gromacs/utility/gmxassert.h +++ b/src/gromacs/utility/gmxassert.h @@ -1,7 +1,7 @@ /* * This file is part of the GROMACS molecular simulation package. * - * Copyright (c) 2011,2012,2013, by the GROMACS development team, led by + * Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, * and including many others, as listed in the AUTHORS file in the * top-level source directory and at http://www.gromacs.org. @@ -46,9 +46,8 @@ #include #include -/*! \addtopublicapi - * \{ - */ +//! \addtogroup module_utility +//! \{ /*! \def GMX_RELEASE_ASSERT * \brief @@ -84,7 +83,7 @@ #define GMX_ASSERT(condition, msg) GMX_RELEASE_ASSERT(condition, msg) #endif -/*!\}*/ +//! \} namespace gmx { -- 2.22.0