Documentation Style

Rule: Write correct English

Nowadays most editors provide interactive spell checking, including for sources (strings and comments). For instance, see flyspell-mode in Emacs, and in particular the flyspell-prog-mode. To trigger this automatically, install the following in your ~/.emacs.el:

(add-hook 'c-mode-hook        'flyspell-prog-mode 1)
(add-hook 'c++-mode-hook      'flyspell-prog-mode 1)
(add-hook 'cperl-mode-hook    'flyspell-prog-mode 1)
(add-hook 'makefile-mode-hook 'flyspell-prog-mode 1)
(add-hook 'python-mode-hook   'flyspell-prog-mode 1)
(add-hook 'sh-mode-hook       'flyspell-prog-mode 1)

and so forth.

End comments with a period.

Rule: Be concise

For documentation as for any other kind of writing, the shorter, the better: hunt useless words. See The Elements of Style, for an excellent set of writing guidelines.

Here are a few samples of things to avoid:

Don’t document the definition instead of its object

Don’t write:

/// Declaration of the Foo class.
class Foo
{
  ...
};

Of course you’re documenting the definition of the entities! “Declaration of the” is totally useless, just use /// Foo class. But read bellow.

Don’t qualify obvious entity kinds

Don’t write:

/// Foo class.
class Foo
{
public:
  /// Construct a Foo object.
  Foo(Bar& bar)
  ...
};

It is so obvious that you’re documenting the class and the constructor that you should not write it down. Instead of documenting the kind of an entity (class, function, namespace, destructor…), document its goal.

/// Wrapper around Bar objects.
class Foo
{
public:
  /// Bind to \a bar.
  Foo(Bar& bar)
  ...
};
Rule: Use the Imperative

Use the imperative when documenting, as if you were giving order to the function or entity you are describing. When describing a function, there is no need to repeat “function” in the documentation; the same applies obviously to any syntactic category. For instance, instead of:

/// \brief Swap the reference with another.
/// The method swaps the two references and returns the first.
ref& swap(ref& other);

write:

/// \brief Swap the reference with another.
/// Swap the two references and return the first.
ref& swap(ref& other);

The same rules apply to ChangeLogs.

Rule: Write Documentation in Doxygen

Documentation is a genuine part of programming, just as testing. We use Doxygen (Doxygen) to maintain the developer documentation of the Tiger Compiler. The quality of this documentation can change the grade.

Beware that Doxygen puts the first letter of documentation in upper case. As a result,

/// \file  ast/arrayexp.hh
/// \brief ast::ArrayExp declaration.

will not work properly, since Doxygen will transform ast::ArrayExp into Ast::ArrayExp, which will not be recognized as an entity name. As a workaround, write the slightly longer:

/// \file  ast/arrayexp.hh
/// \brief Declaration of ast::ArrayExp.

Of course, Doxygen documentation is not appropriate everywhere.

Rule: Document namespaces in :file:`lib*.hh` files
Rule: Document classes in their :file:`*.hh` file There must be a single location, that’s our standard.
Rule: Use directive

Prefer backslash (\) to the commercial at (@) to specify directives.

Rule: Prefer C Comments for Long Comments

Prefer C comments (/** ... */) to C++ comments (/// ...). This is to ensure consistency with the style we use.

Rule: Prefer C++ Comments for One Line Comments

Because it is lighter, instead of

/** \brief Name of this program. */
extern const char* program_name;

prefer

/// Name of this program.
extern const char* program_name;

For instance, instead of

/* Construct an InterferenceGraph. */
InterferenceGraph(const std::string& name,
                  const assem::instrs_t& instrs, bool trace = false);

or

/** @brief Construct an InterferenceGraph.
 ** @param name    its name, hopefully based on the function name
 ** @param instrs  the code snippet to study
 ** @param trace   trace flag
 **/
InterferenceGraph(const std::string& name,
                  const assem::instrs_t& instrs, bool trace = false);

or

/// \brief Construct an InterferenceGraph.
/// \param name    its name, hopefully based on the function name
/// \param instrs  the code snippet to study
/// \param trace   trace flag
InterferenceGraph(const std::string& name,
                  const assem::instrs_t& instrs, bool trace = false);

write

/** \brief Construct an InterferenceGraph.
    \param name    its name, hopefully based on the function name
    \param instrs  the code snippet to study
    \param trace   trace flag
  */
InterferenceGraph(const std::string& name,
                  const assem::instrs_t& instrs, bool trace = false);