[cfe-dev] Notes on Doxygen documentation style
Douglas Gregor
dgregor at apple.com
Tue Jan 20 09:46:06 PST 2009
I'm a documentation nut, and there are some places in Clang's internal
documentation that I think we can do even better. Here are some
comments on the subject.
Coverage
========
Naturally, every data type and non-private function should be
documented. Most important for clients of Clang are the AST nodes: we
should strive to have good documentation for each Expr, Stmt, and Decl
node, including code examples illustrating where these kinds of
declarations will show up in the source code.
I don't have any concerns about this in particular: we have decent
documentation coverage, and we'll keep improving it as we go.
Style
====
In my view, good documentation always includes a brief one-sentence
description (so the reader can answer the question "does this look
like what I want?") followed by an in-depth description of the
routine's behavior and its parameters and (often) language-standard
citations and examples. Our current style of documentation doesn't fit
this quite so well; picking one example of many, Action::isTypeName is
documented like this:
/// isTypeName - Return non-null if the specified identifier is a
type name
/// in the current scope.
/// An optional CXXScopeSpec can be passed to indicate the C++
scope (class or
/// namespace) that the identifier must be a member of.
/// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
virtual TypeTy *isTypeName(IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS = 0) = 0;
That says what we need, but it doesn't format well with Doxygen:
http://clang.llvm.org/doxygen/classclang_1_1Sema.html#6dc9964792711aab89e41067aca3581c
Also, scroll down to isTypeName within Sema's documentation:
http://clang.llvm.org/doxygen/classclang_1_1Sema.html
Then, scroll down a little further to "LookupName". This is how I,
personally, would like to see documentation for a function. First of
all, we've used Doxygen to give a one-sentence description of what
LookupName does, and it shows up under the declaration of LookupName:
that's great for finding what operation we need, quickly.
Clicking on LookupName, we get the lengthier description with an
example, specific information about the parameters, language
citations, etc. It takes some extra Doxygen markup to do this, but in
my opinion it's absolutely worth it. Here's how LookupName is written:
/// @brief Perform unqualified name lookup starting from a given
/// scope.
///
/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is
/// used to find names within the current scope. For example, 'x' in
/// @code
/// int x;
/// int f() {
/// return x; // unqualified name look finds 'x' in the global scope
/// }
/// @endcode
///
/// Different lookup criteria can find different names. For example, a
/// particular scope can have both a struct and a function of the same
/// name, and each can be found by certain lookup criteria. For more
/// information about lookup criteria, see the documentation for the
/// class LookupCriteria.
///
/// @param S The scope from which unqualified name lookup will
/// begin. If the lookup criteria permits, name lookup may also search
/// in the parent scopes.
///
/// @param Name The name of the entity that we are searching for.
///
/// @param Criteria The criteria that this routine will use to
/// determine which names are visible and which names will be
/// found. Note that name lookup will find a name that is visible by
/// the given criteria, but the entity itself may not be semantically
/// correct or even the kind of entity expected based on the
/// lookup. For example, searching for a nested-name-specifier name
/// might result in an EnumDecl, which is visible but is not permitted
/// as a nested-name-specifier in C++03.
///
/// @returns The result of name lookup, which includes zero or more
/// declarations and possibly additional information used to diagnose
/// ambiguities.
Sema::LookupResult
Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria
Criteria) {
The important bits are @brief (for the one-sentence description),
@param (for parameter documentation) and @code/@endcode (for examples).
Grouping
=======
Sema::LookupName was also an experiment with grouping routines
together. The Sema class is large, but we can give it structure using
Doxygen's //@{ and //@} grouping constructs. If you look back at
http://clang.llvm.org/doxygen/classclang_1_1Sema.html
and search for "Name lookup", you'll come across a grouping of the
various name-lookup routines. I really like this style: it logically
groups related pieces of the (large!) Sema class, and puts them all in
context together. It also gives some guidance for someone who knows
they need name lookup but doesn't necessarily know what kind.
Groups are easy to make. The heading of the group should use @name or
\name, then provide documentation for the group as a whole:
/// \name Name lookup
///
/// These routines provide name lookup that is used during semantic
/// analysis to resolve the various kinds of names (identifiers,
and so on
Then,
//@{
starts grouping all of the methods, classes, etc., that will be
documented together. Terminate the group with
//@}
Not all of the groups will be obvious, but there are some sets of
routines that really need it, such as C++ function overloading.
Architectural Descriptions
====================
We currently have a Clang "internals" manual, with documentation about
various subsystems within Clang:
http://clang.llvm.org/docs/InternalsManual.html
We could consider bringing this documentation in with the rest of the
Doxygen documentation using, e.g., Doxygen's \page and \newpage
markup. The benefit of bringing all of the internals documentation
into Doxygen is that we can more easily cross-link between specific
function/class documentation and the more general, architectural
information.
- Doug
More information about the cfe-dev
mailing list