Вы здесь

Документирование кода

Doxygen — это система генерации документации. В Друпале, документирование функций, классов, констант и так далее, делается с помощью специально оформленных комментариев. Документация извлекается прямо из исходного кода, что делает более удобным хранение документации вместе с исходным кодом. На сайте Doxygen находится замечательное руководство по этой системе. Следующие рекомендации имеют отношению к работе с Doxygen в Друпале.

Общие правила

Эти стандартны применяются как к внутристрочным, так и к вынесенным комментариям:

  • Документация и комментарии состоят из предложений с соблюдением грамматики и пунктуации
  • Предложения разделяются пробелом
  • Комментарии и названия переменных пишутся на английском языке. Используется американское написание (например, color, а не colour)
  • Все буквы в верхнем регистре используются только для написания констант (например, TRUE)
  • Используются строки шириной не более 80 знаков (здесь есть несколько исключений, которые описаны ниже (основными из них являются @code и @link). Ширина в 80 знаков заполняется максимально полно

Внутристрочное комментирование

Приветствуется использование внутристрочных и невынесенных комментариев общего характера. Общее правило их использования: если вы смотрите на код и думаете про себя «Ого! Я даже не хочу попробовать это описать», — вам нужно обязательно это описать, пока вы не забыли как это работает.

Комментарий должен идти перед строкой или блоком кода к которому он относиться и не должен отделяться от него пустой строкой, например:

// Unselect all other contact categories.
db_query('UPDATE {contact} SET selected = 0');

В случае, если комментирование требуется для каждой строки кода и используются внутристрочные комментарии, для их выравнивания могут использоваться пробелы — это улучшает чтение.

Используйте комментирование в стиле C (/* */) или в стиле C++ (//). Комментирование в стиле Perl/shell (#) не приветствуется.

Общий синтаксис надстрочных комментариев

Чтобы документировать блок определённого кода, например, функции, класса, метода, константу и так далее, используется следующий синтаксис:

/**
* Текст документации.
*/

Doxygen поймёт любые комментарии расположенные в таком блоке. Ваш стиль должен содержать по возможности команды стандартные для Doxygen, таким образом, мы сохраняем источник разборчивым. Любые упоминания функций или названий файлов в документации автоматически создадут ссылки на тот код, на который они ссылаются. Блок с документацией должен идти перед описываемым кодом, без пустых строк между блоком и кодом.

Директивы Doxygen — общие замечания

/**
* Краткое описание; одно предложение на строке (не более 80 знаков).
*
* Более подробное описание.
*
* Пустые строки формируют абзацы. В конце строк не должно быть пробелов.
*
* @param $first
*   "@param" это директива Doxygen, описывающая параметр функции. Как и другие
*   директивы, она состоит из термина/краткого описания на одной строке и
*   описания (этот текст) с отступом в 2 пробела на следующей строке. Весь текст
*   строки не должен быть больше 80 знаков без перехода. Эта директива не
*   поддерживает пустые строки; если перед этим текстом будет пустая строка, то
*   он будет добавлен в основное описание выше.
* @param $second
*   Между несколькими директивами одного типа не должно быть пустых строк.
* @param $third
*   (дополнительно) TRUE если Third должен быть. Стандартно FALSE. Только
*   дополнительные параметры явно фиксируются. Описание должно объяснять
*   стандартное значение, если оно опущено.
*
* @return
*   "@return" это директива Doxygen, описывающая возвращаемое функцией значение.
*/
function mymodule_foo($first, $second, $third = FALSE) {
}

Списки

* @param $variables
*   Ассоциативный массив содержащий:
*   - tags: массив меток для управления пейджером:
*     - first: строка использующаяся для первого элемента пейджера.
*     - last: строка использующаяся для последнего элемента пейджера.
*   - element: (дополнительно) целое число, чтобы отличать несколько пейджеров
*     на странице. Стандартное значение = 0 (ноль).
*   - style: целое число, являющееся одной из следующих констант:
*     - PAGER_FULL: (стандартно) полный пейджер.
*     - PAGER_MINI: мини-пейджер.
*   Дальнейшее описание по-прежнему будет принадлежать данному параметру, но
*   оно не будет являться частью списка.
*
* Это уже не принадлежит параметру.

В Doxygen, списки могут находиться где угодно. Парсер документации требует строгого следования синтаксису, чтобы текст мог быть корректно выведен в HTML-формате:

  • A hyphen is used to indicate the list bullet. The hyphen is aligned with (uses the same indentation level as) the paragraph before it, with no newline before or after the list.
  • No newlines between list items in the same list.
  • Each list item starts with the key, followed by a colon, followed by a space, followed by the key description. The key description starts with a capital letter and ends with a period.
  • If the list has no keys, start each list item with a capital letter and end with a period.
  • The keys should not be put in quotes unless they contain colons (which is unlikely).
  • If a list element is optional or default, indicate (optional) or (default) after the colon and before the key description.
  • If a list item exceeds 80 chars, it needs to wrap, and the following lines need to be aligned with the key (indented by 2 more spaces).
  • For text after the list that needs to be in the same block, use the same alignment/indentation as the initial text.
  • Again: within a Doxygen directive, or within a list, blank lines are NOT supported.
  • Lists can appear within lists, and the same rules apply recursively.

Секция «Смотрите также»

/**
* (rest of function/file/etc. header)
*
* @see foo_bar()
* @see ajax.inc
* @see MyModuleClass
* @see MyClass::myMethod()
* @see groupname
* @see http://drupal.org/node/1354
*/

The @see directive may be used to link to (existing) functions, files, classes, methods, constants, groups/topics, URLs, etc. @see directives should always be placed on their own line, and generally at the bottom of the documentation header. Use the same format in @see that you would for automatic links (see below, or see examples above). In addition, you can link to a group/topic using the internal name of the group (what follows the @defgroup in its definition).

Ссылки

/**
* (rest of function/file/etc. header)
*
* See also @link group_name Topic name goes here, @endlink and the
* @link http://example.com web page explaining it further. @endlink
*/

The @link...@endlink directive may be used to output a HTML link in line with the text. Some notes:

  • Everything between @link and @endlink needs to be on one line. The line is allowed to exceed 80 characters, but if it does, it should be by itself on the line (break surrounding text before/after the link line).
  • The first word (i.e., string of characters without spaces) after @link is either a full URL, or the name of a function, group/topic defined elsewhere with @defgroup, or file.
  • The remaining words are used as the link text. Don't use @link for full URLs or file names if the link text is the URL or file name -- it's not necessary, since URLs and file names turn into links automatically anyway.
  • Put following punctuation into the link text, rather than after the @endlink.

Автоматические ссылки

* This function invokes hook_foo() on all implementing modules.
* It calls MyClass::methodName(), which includes foo.module as
* a side effect.

Any function, file, constant, class, etc. in the documentation will automatically be linked to the page where that item is documented (assuming that item has a doxygen header). For functions and methods, you must include () after the function/method name to get the link. For files, just put the file name in (not the path to the file). Groups will not be automatically linked; use @see or @link.

Образцы кода

* Пример использования:
* @code
*   mymodule_print('Hello World!');
* @endcode
* Текст следующий за блоком кода.

Примеры кода могут быть встроены в документацию Doxygen с использованием директив @code и @endcode. Любой код между этими директивами будет выводиться отформатированным.

Планируемые изменения

/**
* ...
* Предыдущий текст (оставьте пустую строку перед директивой @todo).
*
* @todo Удалить это в Д8.
* @todo Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
*   nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed
*   diam voluptua.
*/

To document known issues and development tasks in code, @todo statements may be used. Notes:

  • Каждая директива @todo должна содержать важную задачу
  • Оставляйте пустую строку перед первой директивой @todo. Не оставляйте пустых строк между несколькими директивами @todos
  • Put @todo statements at the bottom of the doc block, unless they pertain to something specific (like a specific @param, in which case they should be placed in that @param section).
  • Если длина первой строки превышает 80 знаков, то для следующих строк делайте отступ в 2 пробела

  // Здесь какой-то другой комментарий.
  // @todo Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
  //   nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
  //   sed diam voluptua.
  // Явно удаляем все комментарии.
  comment_delete($cid);

@todo statements in inline comments follow the same rules as above, especially regarding indentation of subsequent comments, but you don't need to leave a blank line between other comments and the @todo line.

Документирование файлов

Каждый файл должен начинаться с комментария, который описывает то, что он делает. Пример:

/**
* @file
* The theme system, which controls the output of Drupal.
*
* The theme system allows for nearly all output of the Drupal system to be
* customized by user themes.
*/

Note that a blank line should follow a @file documentation block.

Строка, которая идёт сразу за директивой @file, это описание, которое показывается на странице со списком всех файлов. Если строка начинается с глагола, то он должен быть в настоящем времени, например, «Обрабатывает загрузку файлов». Описание, которое не нужно добавлять на страницу со списком всех файлов, должно идти после пустой строки.

Вообще, директива @file не должна содержать подробного описания, которое лучше поместить в директиву @defgroup. Таким образом, разработчики смогут просматривать документацию верхнего уровня, пользуясь группами (смотрите список тем/групп API ядра на странице http://api.drupal.org/api/drupal/groups).

Для файлов .install используйте шаблон:

/**
* @file
* Install, update, and uninstall functions for the XXX module.
*/

Для файлов содержащих определение только одного класса, используйте шаблон:

/**
* @file
* Definition of NameOfTheClass.
*/

Документирование функций и методов

Все функции и методы должны быть документированы. Блок комментирования функции должен ей непосредственно предшествовать.

/**
* Verifies the syntax of the given e-mail address.
*
* Empty e-mail addresses are allowed. See RFC 2822 for details.
*
* @param $mail
*   A string containing an email address.
*
* @return
*   TRUE if the address is in a valid format, and FALSE if it isn't.
*/
function valid_email_address($mail) {

Note that some types of functions have special forms of documentation that do not follow this exact format -- see sections below for details (e.g., hook declarations, form generating functions, etc.).

Примечания к синтаксису документирования функций

Первая строка: описание
The first line of the block should contain a brief description of what the function does, limited to 80 characters, and beginning with a verb in the form "Does such and such" (third person, as in "This function does such and such", rather than second person imperative "Do such and such").
Дополнительное описание
A longer description with usage notes should follow after a blank line, if more explanation is needed.
Параметры
After the long description, each parameter should be listed with a @param directive, with a description indented by two extra spaces on the following line or lines. If there are no parameters, omit the @param section entirely. Do not include any blank lines in the @param section.
Аргументы переменной
If a function uses variable arguments, use this syntax:

* @param ...
*    Description of the variable arguments goes here.
Возвращаемое значение
After all the parameters, a @return directive should be used to document the return value if there is one. There should be a blank line between the @param section and @return directive.

If there is no return value, omit the @return directive entirely.

Краткая форма
Functions that are easily described in one line may use the function summary only, for example:

/**
* Converts an associative array to an anonymous object.
*/
function mymodule_array2object($array) {

If the abbreviated syntax is used, the parameters and return value must be described within the one-line summary.

Data types on param/return
Note: This section of the standard was adopted as of Drupal 8. In previous versions, data type specification was recommended in the case of non-obvious types or specific classes/interfaces only.

The data type of a parameter or return value MUST be specified in @param or @return directives, if it is not obvious or of a specific class or interface type.

The data type MAY be specified (as in: recommended) for other @param or @return directives, including those with primitive data types, arrays, and generic objects (stdClass).

* @param int $number
*   Description of this parameter, which takes an integer.
* @param float $number
*   Description of this parameter, which takes a floating-point number.
* @param string $description
*   Description of this parameter, which takes a string.
* @param bool $flagged
*   Description of this parameter, which takes a Boolean TRUE/FALSE value.
* @param array $args
*   Description of this parameter, which takes a PHP array value.
* @param object $account
*   Description of this parameter, which takes a PHP stdClass value.
* @param DatabaseStatementInterface $query
*   Description of this parameter, which takes an object of a class that
*   implements the DatabaseStatementInterface interface.
* @param string|bool $string_or_boolean
*   Description of this parameter, which takes a string or a Boolean TRUE/FALSE
*   value.
* @param string|null $string_or_null
*   (optional) Description of this optional parameter, which takes a string or
*   can be NULL.
*
* @return string
*   Description of the return value, which is a string.

Отметьте:

  • For primitive and non-specific types, use the lower-case type name; int, string, bool, array, object, etc.
  • For special constants, use the lower-case value name: null, false, true. Use bool instead of true|false though. Only specify true or false if the opposite is not supported (e.g., @return string|false).
  • For optional parameters, the default value should only be mentioned on the @param line if its type differs from non-default values. For instance, use @param string|null or @param int|false but never @param string|'' or @param int|0.
  • For classes and interfaces, use the most general class/interface possible. For example, the return value of db_select() is properly documented as SelectQueryInterface rather than a particular class implementation such as SelectQuery.
  • Return values are documented by @return and use the same conventions as @param, but with no variable name.
  • If a function may return NULL in some but not all cases, then document this possibility. For instance, if the return value may either be a string value or NULL, then use @return string|null followed by a description of the circumstances in which each may be returned.
  • The @return section should be omitted if the function lacks an explicit return value.
  • In general, if there are more than two choices (e.g., string|bool|null) for a parameter or return data type, the function should probably be refactored for simplicity.
Callback functions
For callbacks, add a blank line after the summary, followed by a line that identifies the callback's purpose. Use the following format:

* Callback for uasort() within system_themes_page().

This line should indicate which PHP or Drupal function directly takes this callback as an argument, and also which Drupal API function calls that function. If multiple API functions call it, format as a list.

Note that there are also specific standards for some functions that might be considered callbacks, such as hook implementations, menu callbacks, and form callbacks.

Документирование определений хуков

/**
* Отвечает за удаление документа.
*
* Этот хук вызывается функцией node_delete_multiple() после удаления
* документа из таблицы {node}, после вызова определённого типа hook_delete()
* и до вызова field_attach_delete().
*
* @param $node
*   Удаляемый документ.
*
* @ingroup node_api_hooks
* @ingroup hooks
*/
function hook_node_delete($node) {
  db_delete('mytable')
    ->condition('nid', $node->nid)
    ->execute();
}

Документирование определения хука следует тем же правилам, что и документирование обычных функций (смотрите выше) за исключением того, что в первой строке используется глагол в повелительном наклонении. Кроме того, приводится пример содержания функции, обычно из реализации хука в модуле ядра. Также полезно упомянуть откуда вызывается хук.

Documenting hook implementations and theme preprocess functions

If the implementation of a hook is rather standard and does not require more explanation than the hook reference provides, a shorthand documentation form may be used in place of the full function documentation block described above:

/**
* Implements hook_help().
*/
function blog_help($section) {
  // ...
}

This generates a link to the hook reference, reminds the developer that this is a hook implementation, and avoids having to document parameters and return values that are the same for every implementation of the hook.

Optionally, you can add more information in a separate paragraph to describe the particular quirks of your hook implementation. But do not include documentation of the parameters and return values -- this should be in the hook definition documentation, not in the hook implementation documentation.

In the case of hooks that have variables in the names, such as hook_form_FORM_ID_alter(), a slightly expanded syntax should be used:

/**
* Implements hook_form_FORM_ID_alter() for node_type_form().
*/
function mymodule_form_node_type_form_alter(&$form, &$form_state) {
  // ...
}

This generates a link to the hook reference, as well as to the particular form that is being altered. Again, optionally you can add more information in a separate paragraph to describe the particular quirks of your hook implementation.

Theme preprocess functions work the same as hook_form_FORM_ID_alter(). Example:

/**
* Implements hook_preprocess_HOOK() for theme_panels_pane().
*/
function mymodule_preprocess_panels_pane(&$variables) {}

Note that the "for ..." part could reference either a theme function like theme_panels_pane(), or a theme template file like search-result.tpl.php.

For hook_update_N() implementations, there is a different standard, because the documentation's first line is displayed to tell people what will happen (or did happen) when update.php is run. So they are documented as follows:

/**
* Add several fields to the {node_revision} table.
*
* Longer description can go here, if necessary.
*/
function  module_name_update_7002() {
}

Note that the first line should start with an imperative verb, so it will make sense to people running update.php.

Документирование функций генерирующих формы

/**
* Form constructor for the user login form.
*
* @param $message
*   The message to display.
*
* @see user_login_form_validate()
* @see user_login_form_submit()
* @ingroup forms
*/
function user_login_form($form, &$form_state, $message = '')

/**
* Form validation handler for user_login_form().
*
* @see user_login_form_submit()
*/
function user_login_form_validate($form, &$form_state) {
  ...
}

/**
* Form submission handler for user_login_form().
*
* @see user_login_form_validate()
*/
function user_login_form_submit($form, &$form_state) {
  ...
}

Отметьте:

  • @param and @return for the standard parameters and return value should be omitted from all form-generating functions. Do include @param documentation for additional parameters beyond $form and $form_state, if there are any.
  • A form constructor is a callback meant to be used as an argument for drupal_get_form().
  • You may indicate that a function is a form constructor by adding the @ingroup forms directive. This groups all forms into the Form Builder topic on api.drupal.org.
  • Do not add @ingroup forms to validation, submission, or other handlers of the form.
  • Correlating validation and submit handlers should contain the form constructor function name in their phpDoc summary, as visible above.
  • You may add @see directives to link to correlating validation and submission handlers, and vice-versa.

If the form generates a page (i.e., in a hook_menu() implementation, the page callback is 'drupal_get_form' and the page argument is this form), include an @see reference to the hook_menu() implementation that uses it.

Documenting Render API callbacks

The Render API uses various callbacks functions, which you can assign to a render element when setting up a render array (or a form). Document them as follows:

/**
* Render API callback: Validates the maximum upload size field.
*
* Ensures that a size has been entered and that it can be parsed by
* parse_size().
*
* This function is assigned as an #element_validate callback in
* file_field_instance_settings_form().
*/
function _file_generic_settings_max_filesize($element, &$form_state) {

Отметьте:

  • The first line starts with "Render API callback:", and then has a description of what the function does (with verb in 3rd person as is standard in functions).
  • The next (optional) paragraphs contain further description.
  • Somewhere in the function, there should be a paragraph saying where the callback is assigned and what particular Render API callback it is being used for.
  • @param and @return are omitted if the parameters and return value are the standard callback parameters/return. If there are additional parameters, document them.

Этот блок добавлен для Друпала 8.

Документирование функций темизации

/**
* Returns HTML for a foo.
*
* @param $variables
*   An associative array containing:
*   - foo: The foo object that is being formatted.
*   - show_bar: TRUE to show the bar component, FALSE to omit it.
*
* @ingroup themeable
*/
function theme_foo($variables) {
  ...
}

In order to provide a quick reference for themers, we tag all themeable functions so that Doxygen can group them together. A themeable function is defined as any function meant to be called via theme(), and you can indicate that a function is themeable by adding an @ingroup themeable directive. It is also beneficial to use @see directives to link the theme function with its preprocessing functions.

In the rare case that your theme function returns some other type of formatted output other than HTML, you should add a @return directive with a description of what the function generates and returns.

See also the hook implementations section for how to document preprocess functions.

Документирование шаблонов тем

If a template file (themeablename.tpl.php) and a preprocess function is used instead of a theming function, both the template file and the preprocessing function need to be documented. The template file should be documented with a @file directive, should have @ingroup themeable in the file documentation header, and should contain a list of the variables that the template_preprocess_HOOK has prepared for it. If any of these variables contain data that is unsafe to output for XSS reasons, that should be documented; otherwise it can be assumed that variables available have already been appropriately filtered. Anything not listed should not be assumed to be safe to output. It should also contain a @see directive to link back to the preprocessing function.

/**
* @file
* Displays a list of forums.
*
* Available variables:
* - $forums: An array of forums to display. Each $forum in $forums contains:
*   - $forum->is_container: Is TRUE if the forum can contain other forums. Is
*     FALSE if the forum can contain only topics.
*   - $forum->depth: How deep the forum is in the current hierarchy.
*   - $forum->name: The name of the forum.
*   - $forum->link: The URL to link to this forum.
*   - $forum->description: The description of this forum.
*   - $forum->new_topics: True if the forum contains unread posts.
*   - $forum->new_url: A URL to the forum's unread posts.
*   - $forum->new_text: Text for the above URL which tells how many new posts.
*   - $forum->old_topics: A count of posts that have already been read.
*   - $forum->num_posts: The total number of posts in the forum.
*   - $forum->last_reply: Text representing the last time a forum was posted
*     or commented in.
*
* @see template_preprocess_forum_list()
*
* @ingroup themeable
*/

See also the hook implementations section for how to document preprocess functions.

Documenting hook_menu() callbacks

(This standard was adopted for Drupal version 8.x.) The page, access, title, and other callbacks that are registered in hook_menu() are documented as follows:

/**
* Page callback: Displays a list of content.
*
* Longer description can go here.
*
* @param $foo
*   Description of a parameter for this page.
*
* @return
*   A render array for a page containing a list of content.
*
* @see node_menu()
*/

Отметьте:

  • In the first line, declare what type of callback it is (Page callback, Access callback, etc.), and give a short description of what it does (like you would for any function). Total line length: 80 characters, ending in "."
  • After a blank line, include a longer description of the function (if needed), followed by parameters and return value.
  • At the end, include an @see line that points to the hook_menu() implementation where this callback is registered. If multiple hook implementations use the callback, include one @see line for each.
  • Forms that generate pages (i.e., the page callback function is drupal_get_form() and the page argument is the form name): see the form generating function section.

Документирование констант и переменных

/**
* Denotes that a block is not enabled in any region and should not be shown.
*/
define('BLOCK_REGION_NONE', -1);

/**
* The base URL of the drupal installation.
*
* @see conf_init()
*/
global $base_url;

Constants, global variables, and member variables of classes should have documentation blocks. As usual, the documentation block should start with a one-line description, and any additional needed documentation should be separated from the summary line by a blank line (though usually only one line is needed).

Документирование классов и интерфейсов

Each class and interface should have a doxygen documentation block, and each member variable, constant, and function/method within the class or interface should also have its own documentation block. Example:

<?php
/**
* Defines a common interface for a prepared statement.
*/
interface DatabaseStatementInterface extends Traversable {

 
/**
   * Executes a prepared statement.
   *
   * @param array $args
   *   Array of values to substitute into the query.
   * @param array $options
   *   Array of options for this query.
   *
   * @return
   *   TRUE on success, FALSE on failure.
   */
 
public function execute($args = array(), $options = array());
}

/**
* Represents a prepared statement.
*
* Default implementation of DatabaseStatementInterface.
*/
class DatabaseStatementBase extends PDOStatement implements DatabaseStatementInterface {

 
/**
   * The database connection object for this statement's DatabaseConnection.
   *
   * @var DatabaseConnection
   */
 
public $dbh;

 
/**
   * Constructs a DatabaseStatementBase object.
   *
   * @param DatabaseConnection $dbh
   *   Database connection object.
   */
 
protected function __construct($dbh) {
   
// Function body here.
 
}

 
/**
   * Implements DatabaseStatementInterface::execute().
   *
   * Optional explanation of the specifics of this implementation goes here.
   */
 
public function execute($args = array(), $options = array()) {
   
// Function body here.
 
}

 
/**
   * Returns the foo information.
   *
   * @return object
   *   The foo information as an object.
   *
   * @throws MyFooUndefinedException
   */
 
public function getFoo() {
   
// Function body here.
 
}

 
/**
   * Overrides PDOStatement::fetchAssoc().
   *
   * Optional explanation of the specifics of this override goes here.
  */
 
public function fetchAssoc() {
   
// Call PDOStatement::fetch to fetch the row.
   
return $this->fetch(PDO::FETCH_ASSOC);
  }
}
?>

Отметьте:

  • Leave a blank line between class declaration and first internal docblock.
  • Make sure to have a docblock on each member variable and method. Short documentation forms should be used for the overridden/extended methods (don't repeat what is documented on the base method, just link to it by saying "Overrides BaseClassName::method()." or "Implements BaseInterfaceName::method().", and then document any specifics to this implementation, leaving out param/return docs).
  • Use a 3rd person verb to begin the description of a class, interface, or method (e.g. Represents not Represent).
  • For a member variable, use @var to tell what data type the variable is.
  • Use @throws if your method can throw an exception, followed by the name of the exception class. If the exception class is not specific enough to explain why the exception will be thrown, you should probably define a new exception class.
  • Make sure when documenting function and method return values, as well as member variable types, to use the most general class/interface possible. E.g., document the return value of db_select() to be a SelectQueryInterface, not a particular class that implements SelectQuery.

Документирование групп/тем

You can make "Topics" pages by defining a "group", also known as a "module" in Doxygen terminology. We use topic/group pages to group functions that form an API that is meant to be used by multiple modules. Do not define a topic/group for functions that are internal to a particular file or module. See http://api.drupal.org/api/drupal/groups for a list of existing API topics/groups in Drupal Core.

Here is the basic syntax for defining a group:

/**
* @defgroup group_identifier Name of the group for Topics page
* @{
* One line, one sentence description of the topic/group.
*
* One or more additional paragraphs of information, which will appear
* on the topic page.
* @}
*/

The @defgroup line gives the name of the group that will be used in the URL, and then the name that will be used as the page title and in the Topics listing. Any text within the @defgroup's own doxygen header appears as text on the topic page.

If you put the group definition immediately before one or more functions that belong in the group, you can automatically add functions to the group by using this syntax:

/**
* @defgroup group_identifier Name of the group for Topics page
* @{
* One line, one sentence description of the topic/group.
*
* One or more additional paragraphs of information, which will appear
* on the topic page.
*/

// Functions here are automatically added to the group.

/**
* @} End of "defgroup group_identifier".
*/

If you have functions that need to be added to a group whose definition is not right above the functions, there are two ways to do it:

  • If there is just one function to be added, add
    * @ingroup group_identifier

    to the documentation block for the function.

  • If there are multiple functions to be added, put

    /**
    * @addtogroup group_identifier
    * @{
    */

    before the functions, and

    /**
    * @} End of "addtogroup group_identifier".
    */

    after the group of functions.

Отметьте:

  • Modules work at a global level, creating a new page for each group. They should be used only to group functions that provide some kind of API, which possibly spans multiple files. Or the other way round: they should not be used to group functions in a file when these functions are only used in that very file. Thats what Member Groups are for (which unfortunately aren't supported by api.module yet).
  • @defgroups can be defined only once - trying to define a second @defgroup name with a name already used will result in an error. Use @defgroup name in the "most important" section/file of that group and add to it from other places with @addtogroup / @ingroup (see above).
  • In pure Doxygen, the name in @defgroup name Explanation of that group must be single-word identifier, like a PHP variable or function name. Or, as regular expression: [a-zA-Z_][a-zA-Z0-9_]*. However, in the Drupal API module, we also allow period (.) and hyphen (-) in group names.
  • You can put @defgroup @{ when defining your group, and then the @} after a group of functions that should be included in the group. You can also do @addtogroup @{ @}, and everything between the {} will be included in the group. However, if you have a class or interface within the {}, that also means that every member function and member variable will be itself also included in the function/class/variable lists generated on the group page. This is probably not what you want, so it is best to just use the one-line @ingroup syntax when indicating that a particular class is part of a group.

Ограничения и советы

Drupal's Doxygen processing module, API module, currently only supports a small subset of all Doxygen commands and makes some assumptions about the formatting of the source. Code to be processed by api.module is advised to stick to these conventions.

The API module currently supports only one of Doxygen's three grouping mechanisms: Modules (@defgroup, @ingroup, @addtogroup, @{, @}). See groups section above for more information on how we use modules/groups.

Документирование дополнительных модулей и тем

  • Don't use @mainpage. There can be only one @mainpage in the contributions repository, which is reserved for an index page of all contributes modules and themes.
  • Use Doxygen topics/groups (@defgroup, @ingroup, @addtogroup, see "Grouping" above) sparingly. There are currently thousands of modules in contrib, many of them consisting of more than one module. If each of these modules used just one @defgroup, there would be more than thousands more entries in the topic list on api.drupal.org. If each used more than one ...
  • If you do use Doxygen groups, make sure you give them a unique namespace, which would be your module's name. E.g. @defgroup views ... for the views.module, @defgroup views_ui ... for the views_ui.module. Don't use group names which are defined in Drupal core (hooks, themeable, file, batch, database, forms, form_api, format, image, validation, search, etc.).
  • If your module has only one file in it, it's not really necessary to define a group for it, because all of the functions, constants, etc. in the file will already be grouped together on the file page.