32. Pike AutoDoc markup
AutoDoc is Pike's documentation system for public modules, classes, functions and other declarations. Documentation is kept beside the implementation in specially marked comments, then extracted into XML and rendered as reference documentation. This keeps descriptions and signatures together and allows the same documentation to be presented in different formats.
In Pike source, use adjacent //! comments to describe a declaration. In C and cmod source, use /*! comments with *! continuation lines and explicit Pike declarations and scope tags such as @decl, @module and @class. Describe what callers need to know: arguments, results, errors, side effects and any platform or library requirements.
//! Adds two integers.
//! @param left
//! @param right
//! The values to add.
//! @returns
//! The sum of the two values.
int add(int left, int right)
{
return left + right;
}
Consecutive parameter tags share a description in this example. Within descriptions, @expr{left + right@} marks a Pike expression and @[add()] marks a reference to a documented declaration. The following sections describe comment syntax, association with source declarations and scope tags. The final section describes the intermediate XML format for authors of extractors and documentation tools; ordinary API documentation should normally be written in source comments.
32.1. Syntax
32.1.1. Line orientation
The markup is line oriented. If you need to write a line which is very long, it can be broken into several lines. A trailing @ on the line indicates that it continues on the next line. The @ and the newline character will be discarded, and the lines merged. Thus:
//! @variable thisVariableNameIsSoLong@ //!YouJustCantBelieveIt
will appear to the parser as:
//! @variable thisVariableNameIsSoLongYouJustCantBelieveIt
This is sometimes necessary because keywords that take parameters expect all the parameters to appear on the same line and treat the end of the line as the end of the parameter list.
The character '\r' is also discarded. The same applies to all other non-printable and control characters except for '\n' and '\t'.
In text (see the nonterminal 'text' in the grammar at the end of this file), a blank line with surrounding non-blank lines will give a paragraph break. Thus:
//! - I love you, said Danny. //! //! - You have no right to come here after what you did to //! my little dog, screamed Penny in despair.
will generate the following XML:
<p> - I love you, said Danny.</p>
<p> - You have no right to come here after what you did to
my little dog, screamed Penny in despair.</p>
32.1.2. Keywords
Keywords always begin with an at-sign: @. A @ is quoted by writing two of them: @@. There are four types of keywords (the keywords in []'s are examples of keywords of the different types):
Meta keywords [@decl, @class, @endclass, @module and @endmodule] Must stand alone on one line, preceded only by whitespace. These are not really part of the markup. They must come before any text or other keywords in the doc block. They provide information about what is being documented etc. and do not result in any text in the documentation. Meta keywords have keyword specific parameter syntaxes.
Delimiter keywords [@param, @member, @item, @note, ...] Must stand alone on one line, preceded only by whitespace. These are keywords that begin a section inside their block. They have no end marker, but rather the section ends when the next delimiter keyword on the same level is found. Can have parameters.
Block/endblock keywords [@dl - @enddl, @mapping - @endmapping, ...] Must stand alone on one line, preceded only by whitespace. These open or close a block. If a block is started with @foo, it must end with a matching @endfoo. The lines inside the block can be divided into sections by using delimiter keywords. The start keyword can have parameters, but the corresponding end keyword can not.
Short markup keywords [@ref{..@}, @i{..@}, ...] These are used in the text to perform cosmetic tasks, for example changing text to italic (@i), teletype(@tt) or marking a word as a reference to a pike entity (@ref). They can be nested, but a short markup keyword can not contain a keyword of types 1-3. They begin with @keyword{ and end with @}.
The magic keyword @xml{ ... @} This is a special keyword that provides an escape to XML. All ordinary text inside it is passed unquoted to the output. However, the short markup keywords are still valid and may be used inside it, and thus @ must still be quoted with @@. < and > must also be quoted unless the intention really is to write XML. For example:
//! He is so @xml{<i>italic</i> and @b{bold@}!@}!! will generate the following XML:
He is so <i>italic</i> and <b>bold</b>!!!
NOTA BENE: Delimiter keywords (2) and block keywords (3) must stand alone (with their parameters, if any) on one line.
32.1.3. Delimiter keyword grouping
Delimiter keywords that indicate a new section inside the block can be grouped together in the interest of not writing the same docstring for multiple parameters etc. Delimiters are grouped if they appear on consecutive lines. For example, when documenting a method:
//! @decl int dist(int x, int y) //! Calculates the distance. //! @param x //! @param y //! The coordinates of the vector.
Above, the two @param's x and y are grouped together and share the same docstring: "The coordinates of the vector.". It is an error to try to group together different keywords:
//! Error, can't group @note and @param: //! @param x //! @note //! Don't use this function. At all. Ever.
32.1.4. Keyword parameters
After the leading @keyword (that may be preceded only by whitespace) on the line, the rest of the line is interpreted as a parameter list. The syntax of this parameter list can be different depending on the keyword:
Special keyword parameter list syntax Here the parameters can be parsed according to Pike syntax or in some other way. Examples of keywords that use these kinds of special syntaxes are all the meta keywords, @member and @elem.
Default parameter list syntax The meaning of parameters is determined by the order in which they appear, much like the arguments in a unix shell command line - hence they are not named as in HTML or XML. Parameters are separated by whitespace. If you wish to have a parameter string with whitespace in it, you must surround the string with a pair of ' or ". When the quoting character itself is in the string, a duplication is used to quote it:
//! @question "He is a ""swapper""?!" However, if your parameter contains only one of ' and ", then it is smarter to choose the other one as the quouting character:
//! @question 'He is a "swapper"?!' It is an error not to end a quote before the end of the line:
//! @wrong "Aww, come on now, this worked fine in C64 basic! If a quoted parameter is too long to fit in one line, use the @ at the end of the line to merge it with the following:
//! @right "Oh, joy! Now I can make my parameters just as@ //! long as I want them!" The parameters are not parsed so you can not have markup inside them. Pike style quoting is not used either, which means that if you write:
//! @look "\n" The parameter will be a string with two characters, a backslash followed by the letter n.
32.1.5. Grammar
Here comes a BNF-ish grammar for documentation blocks. Note that before the parsing of the block, all lines ending with a @ will be merged with the next line (see (a) above)
docblock:
metaline*, blockbody
metaline:
start_of_line, white_space*, metakeyword, any_char_but_newline,
end_of_line
blockbody:
section?, (delimiter+, section)*, delimiter?
delimiter:
start_of_line, white_space*, delimiterkeyword, parameterlist,
end_of_line
section:
(text|block)+
block:
blockbegin, blockbody, blockend
blockbegin:
start_of_line, white_space*, blockkeyword, parameterlist,
end_of_line
blockend:
start_of_line, white_space*, blockkeyword, white_space*, end_of_line
parameterlist:
white_space*, (parameter, white_space+)*
parameter:
qoutedparameter | any_char_but_white_space+
quotedparameter:
('"', (any_char_but_new_line_or_" | '""'), '"')
| ('\'', (any_char_but_new_line_or_' | '\'\''), '\'')
text:
(character|shortmarkup|xmlescape)+
xmlescape:
'@xml{', any_char_sequence_not_containing_@}, '@}'
character:
any_char_but_@ | '@@'
shortmarkup:
shortmarkupkeyword, '{', text, '@}'
metakeyword, blockkeyword, delimiterkeyword, shortmarkupkeyword:
keyword
keyword:
'@', alpha_char+
endblockkeyword:
'@end', alpha_char+
white_space:
' ' | '\t'
32.2. Pike autodoc inlining
The autodoc extractor works either in C mode or in Pike mode. The reason why the two modes are not the same is that they perform two very different tasks. The C mode only has to find comments in the file, and ignores the surrounding code totally, while the Pike mode on the other hand is supposed to be smarter and distill a lot of information from the Pike code that surrounds the comments.
Both work at the file level. That makes it easy to use for example "make" to generate documentation for the source tree. Another benefit is that the generation will not have to reparse all of the tree if only one source file is changed.
For Pike module trees, the extractor can recurse through the file tree on its own, but for C files, where the directory structure gives insufficient cues about what is what, there must be make targets set up manually. All generated XML files can then be merged together into the final Pike namespace.
32.2.1. C files
In C files, the doc comments look like:
/*! yadda yadda *! yadda yadda yadda */
Note that only lines that start with *! count, so above are only two doc lines. Any whitespace before the leading *! is skipped, so that the lines can be indented freely.
In the C files, no parsing of the surrounding code is done. The context lies completely in the doc comments themselves, and the target of the doc comment is determined by special meta keywords that are not really part of the doc blocks, but rather modifiers that tell which Pike entity the doc is about.
/*! @module Foo
*! ... doc for the Foo module ...
*! ... */
/*! @decl int a()
*! ... doc for the method Foo.a() ...
*! .... */
/*! @class Bar
*! ... doc for the class Foo.Bar ...
*! ... */
/*! @decl mapping(string:string) userprefs()
*! ... doc for the method Foo.Bar->userprefs() ...
*! ... */
/*! @decl int a
*! @decl int b
*! ... doc for the variables Foo.Bar->a and Foo.Bar->b ...
*! ... */
/*! @endclass */
/*! @endmodule */
The @module and @class keywords work like segment directives in assembler source files. That is, you can have @module foo in several C files, if the module source is spread over multiple files. However, if you write doc for the module itself in several places, an error will be triggered.
32.2.2. Pike files
Doc comments look like:
//! yadda yadda yadda //! yadda yadda
To be considered one doc block, the comments must be separated only by whitespace and \n, that is they have to be on adjacent lines in the code. Each doc block in the Pike code has one or more targets; the Pike entities (modules, classes, variables etc.) that the doc block is documenting. The target of a doc comment is the coherent block of declarations adjacent to (immediately before or after) it in the code, without intervening blank lines. Examples:
//! Doc for alpha
int alpha()
{
return 4711;
}
protected int undocumented;
//! Error! This doc block has no destination!
int beta;
//! Doc for beta
//! Doc for gamma, delta, and epsilon
int gamma, delta;
float epsilon;
//! Error here!
int zeta;
//! ambiguous which doc to associate with zeta.
int eta;
//! Error here too! ambiguous which variable is documented.
int theta;
//! Doc for two methods. This is so UGLY! We strongly recommend
//! using the decl keywords instead to accomplish this effect.
int methodOne()
{
...
}
int methodTwo()
{
...
}
//! However, it can be useful sometimes, for really short methods:
int very_short() { return 4711; }
int even_shorter() { return 0; }
In Pike files, you can not use @class or @module to tell which module or class you are in. To document a class, you simply write:
//! Doc for the class
class CheeseMaker
{
//! You can even document inherits!
inherit Earth : earth;
//! Doc for CheeseMaker->a()
int a()
{
...
}
void create(string s) { ... }
}
The parser will automatically identify a() as a member method of the class CheeseMaker, and will detect that Earth is inherited by CheeseMaker. If a class has no documentation comment, it's internals will not be examined, thus it is an error if a class contains documentation comments but is itself undocumented:
class a()
{
//! @decl foo
//! ... doc for foo ...
}
A special inlining case is that of functions and classes. When documenting these, the doc comment can be put between the head of the function/class, and the opening {, like this:
class Roy
//! Documentation for Roy
{
....
}
int un_randomize(int x)
//! This function takes a random number, and transforms it into
//! a predictable number.
{
return x = 4711;
}
If a doc block is the first in a file, and it has no target, then it is treated as doc for the file (or rather: the module/class that the file compiles into) itself. In any other case it is an error to have a targetless doc block. A target can also be set with the @decl meta keyword. If a doc comment begins with some @decl keywords, these @decl's act just like real declarations standing next to the doc. Thus:
//! @decl int a(int x) //! @decl int b(int x) //! Here is some doc for these functions....
is autodocwise equivalent to:
//! Here is some doc for these functions....
int a(int x)
{
.....
}
int b(int x)
{
.....
}
In case it is legal to have both an adjacent declaration and the @decl keyword at the block beginning. That is when you document "polymorph" methods. Then the adjacent declaration must be a method, and all @decl's must be methods that have the same name as the real method:
//! @decl float cube(float x)
//! @decl int cube(int x)
//! Gives x**3.
//! @param x
//! The number to cube.
int|float cube(int|float x)
{
....
}
The real method prototype is discarded in favour to the @decl'ed variants, who will be shown in the documentation instead.
One problem that is unsolved so far is how to handle #if .. #else .. #endif constructions. The approach so far has been to ignore preprocessor directives totally. For example, the parser does not handle:
#ifdef MALE
int bertil()
#else
int berit()
#endif
{
... body ...
}
It a portion of the code is unextractable because it contains too much preprocessor macros and stuff, you can make the extractor skip it by using @ignore:
//! @ignore HERE_ARE_SOME_STRANGE_THINGS #ifdef A A #endif //! @endignore
All @ignore-@endignore sections of the file are removed before any extraction is done, so they can cross class boundaries and the like. You can nest @ignore inside eachother. Another application for @ignore is to hide actual class boundaries from the extractor:
//! @ignore
class C {
//! @endignore
//! To the parser, this function appears to be on the top level
int f() { ... }
//! @ignore
}
//! @endignore
32.3. Pike autodoc tags
We have defined some different categories of markup, each with its own semantics. Seen from the parser, there are two main construct levels:
The "what-are-we-documenting level" constructs; @decl for Pike files and @module, @endmodule, @class and @endclass on top of that for C files. These are the meta level tags covered in section a).
Inside-of-comment level constructs for documentation markup, covered in sections b), c) and d).
All markup can also be divided into categories based on their look and semantics; there are three categories here (with examples):
Grouping constructs that mark the opening/closing of a section of some sort (@mapping/@endmapping, @dl/@enddl, @module/@endmodule). Most of these not already covered by secion a) appear in b).
subdividers that break up an outer grouping construct into subsections (@member, @item, @param)
short text markup constructs that basically map to XML containers (@i{...@}, @ref{...@})
32.3.1. Meta level tags
These tags all serve the purpose of denoting what pike entities your comments should be tied to. This is particularly needed in (and in part only applies to) C files, where the autodoc extractor does not try to interpret and parse class and method definitions.
Keyword: @module Legal for: C files only (neither needed nor legal for Pike files) Arguments: (the last segment of) the module name (ie no "." allowed)
Example: To document the module Parser.XML module, you need two consecutive module tags:
/*! @module Parser */ /*! @module XML */
A @module keyword sets the scope of documentation comments following it. @module tags nest, as shown in the example above, and must be ended with a matching number of @endmodule tags, as in:
/*! @endmodule XML */ /*! @endmodule Parser */
A @module keyword may also have a text child documenting the module itself:
/*! @module Parser *! *! The common roof under which parsers of various kinds, such as *! @[Parser.XML], @[Parser.Pike] and @[Parser.C] are housed. */
There are two special @module targets available; the predef:: module and the lfun:: module. The predef:: module, although more of a scope than a module, contains the definitions for all methods in Pike's predef:: scope, as in:
/*! @module predef:: *! @decl int equal(mixed a, mixed b) *! This function checks if the values @[a] and @[b] are equal. *! @endmodule */
The lfun:: module scope does not legally exist in Pike, but it houses the docs for all lfuns (the virtual methods for fulfilling the Pike object API). An example:
/*! @module lfun:: *! @decl int(0..1) `!=(mixed arg1, mixed arg2, mixed ... extras) *! The inequality operator. *! @endmodule */
This also means that referencing (via @ref{...@} or @[...]) the lfun documentation strings can be done using @[lfun::`!=] and the like, as can predefs via @[predef::sort()] et cetera.
Keyword: @endmodule Legal for: C files only (neither needed nor legal for Pike files) Arguments: (the last segment of) the module name (optional)>
When the optional argument to @endmodule is given (for code clarity), the extractor will verify that the module scope you close was indeed the one you opened, as in the @module example above. The following would trigger an error:
/*! @module Parser *! @module XML */ /*! ... some autodoc comments ... */ /*! @endmodule Parser *! @endmodule XML */
while the same example, ending in
/*! @endmodule *! @endmodule */
would be considered legal.
Keyword: @class Legal for: C files only (neither needed nor legal for Pike files) Arguments: (the last segment of) the class name (ie no "." allowed)
Example: to document the Process.create_process class, you would use:
/*! @module Process *! @class create_process */
And end the scope similar to @module:
/*! @endclass create_process *! @endmodule Process */
Like @module tags, @class tags may be nested any number of levels (when documenting subclasses to subclasses to subclasses to ...).
Keyword: @endclass Legal for: C files only (neither needed nor legal for Pike files) Arguments: (the last segment of) the class name (optional)
When the optional argument to @endclass is given (for code clarity), the extractor will verify that the class scope you close was indeed the one you opened, just as with @endmodule above.
Keyword: @decl Legal for: All source code (C and Pike files) Arguments: (the last segment of) the identifier name (ie "." illegal)
The @decl keyword is used to target a specific (...more to come! :-)
32.3.2. Aliases and canonical documentation
The @alias meta keyword marks an existing declaration as an alternate name for a documented API. References to the alternate name link to the canonical declaration while retaining the reference text written by the author. For example:
//! @alias Canonical.run() constant old_run = Canonical.run;
A reference such as @[old_run()] is displayed with that name, but its destination is the documentation for Canonical.run(). The canonical declaration supplies the main documentation; the alias needs no repeated description. The tag describes an alias that already exists in the API, independently of how its implementation exports it.
Give the complete canonical name within the current namespace, or include an explicit namespace prefix such as @alias predef::Canonical.run. An optional empty () suffix is accepted for a function. Place @alias before the comment's descriptive text and after any explicit @decl, @module or @class tags. It applies to modules, classes, functions, constants and variables.
To document a module file as an alias, put the directive in its first standalone documentation comment, separated from following declarations by a blank line. For example, in Legacy.pmod:
//! @alias Canonical // Existing module implementation follows.
This also redirects member references: @[Legacy.run()] links to Canonical.run(). Explicitly marked member aliases can give renamed members their own canonical targets. For C or cmod documentation, put the directive in the scope or declaration comment:
/*! @module Legacy *! @alias Canonical */ /*! @decl int old_run(int value) *! @alias Canonical.run() */ /*! @endmodule */
The XML retains an alias attribute on the entity or its docgroup. Reference resolution follows alias chains to their final canonical target, including for object-type and inheritance links. The canonical target must be present in the joined documentation tree. Missing targets, conflicting targets and cycles are errors. Resolve aliases after joining source fragments, so an alias and its target may be documented in different files.
32.4. AutoDoc XML format
AutoDoc XML separates the declarations being documented from their descriptions. Extractors produce this representation, the joiner merges fragments into a hierarchy and resolves references, and presentation tools render the result. XML examples below show the relevant structure; optional source metadata and attributes are omitted where they are not needed to explain the format.
32.4.1. Documentation pipeline
The documentation build proceeds through these stages:
Write documentation in Pike, C or cmod source comments.
Extract declarations and comments into per-source XML fragments with extract_autodoc.
Merge the fragments, resolve references and organize the namespace with join_autodoc and the XML processing tools.
Apply the manual structure and split or render the resulting XML into reference pages with the presentation tools.
The extraction format is an intermediate representation, not HTML. Consumers must retain declaration information and documentation structure even if a particular output format does not display every field. Handwritten manual chapters use a separate chapter and section structure around the reference material.
32.4.2. Hierarchy and merging
The current top-level container is <autodoc>. It contains <namespace> elements, such as <namespace name="predef"> for predef:: and <namespace name="lfun"> for lfun documentation. Modules, classes and other entities are placed inside their namespace and enclosing modules or classes. Earlier formats used an empty-name module as the root; new extractors should use the namespace structure.
<autodoc>
<namespace name="predef">
<module name="Example">
<class name="Counter">
<doc><text><p>A counter with independent object state.</p></text></doc>
<!-- Member declarations and their documentation go here. -->
</class>
</module>
</namespace>
</autodoc>
Each source file may describe only part of a module or class. Enclosing elements establish the fragment's position in the hierarchy even when they have no documentation of their own. These skeletal containers are merged with containers for the same entity from other files. The resulting entity keeps the documented content and combined declarations. Avoid supplying conflicting descriptions of the same module or class in several files.
32.4.3. Grouped declarations
Modules, classes and enums have their own containers and may carry a <doc> child. Methods, variables, constants and other declarations are placed in a <docgroup> when they share documentation. Even a single documented declaration forms a group.
//! Two counters. int a; int b;
<docgroup homogen-type="variable"> <doc><text><p>Two counters.</p></text></doc> <variable name="a"><type><int/></type></variable> <variable name="b"><type><int/></type></variable> </docgroup>
An alias attribute on a docgroup specifies the canonical documentation target of its declarations. The same attribute can appear on a module or class. Joined reference destinations are canonicalized while the alias declaration remains in the XML hierarchy.
The group contains its declarations and their shared description. homogen-type identifies the declaration kind when all grouped declarations have that kind. homogen-name identifies their common name when they share one, for example overloaded methods. The <doc> child is not included when determining either attribute. A consumer should use the actual declarations as well as these grouping hints.
32.4.4. Entity metadata
Entity elements carry their name in a name attribute where applicable. Shared metadata can appear as child elements:
| Element | Meaning |
| <modifiers> | Declaration modifiers represented by child elements, for example <protected/> or <final/>. It can be omitted when no modifiers apply. |
| <source-position> | Source filename and starting line in file and first-line attributes. An optional last-line records the end of a declaration or method body. |
| <annotations>, <attributes> | Additional declaration annotations and type attributes emitted by extractors that support them. |
<variable name="value"> <source-position file="Example.pmod/Counter.pike" first-line="12"/> <modifiers><protected/></modifiers> <type><int/></type> </variable>
Source positions describe the implementation location. Reference resolution may add metadata later, so do not assume that every attribute present in joined XML was originally emitted by the source extractor.
32.4.5. Entity elements
| Element | Contents |
| <namespace>, <module>, <class> | Containers for child entities, docgroups and optional documentation of the container itself. |
| <method> | An arguments container with ordered argument children, and a returntype container. Named arguments have a name attribute and a type child. |
| <variable> | A type child describing the variable type. |
| <constant> | A named constant with optional type and source metadata. A constant representing a type can also have a typevalue child. |
| <typedef> | A named type alias with a type child. |
| <enum> | A container with documentation of the enum and docgroups containing its named constant elements. |
| <inherit> | The inherited program in a classname child. An optional name attribute holds its local alias. |
| <import> | The imported module in a classname child. The optional symbol and recurse attributes describe symbol-import behavior for consumers that support it. |
| <directive> | A named preprocessor directive documented as part of an API. |
| <generic> | A generic parameter with its name, zero-based index, type constraint and default type. |
| <modifier> | A modifier-range container for declarations sharing modifiers, corresponding to a block such as protected final { ... }. |
For example, int add(int left, int right) has this method declaration:
<method name="add">
<arguments>
<argument name="left"><type><int/></type></argument>
<argument name="right"><type><int/></type></argument>
</arguments>
<returntype><int/></returntype>
</method>
An aliased inheritance declaration such as inherit Base : Parent; is represented by <inherit name="Parent"> containing <classname>Base</classname>. A filename used in an inheritance declaration retains its quotes in the class-name text. Inheritance declarations are normally carried in docgroups, whether or not they have their own description.
Enum constants may share a description just like variables:
<enum name="State">
<doc><text><p>A set of states.</p></text></doc>
<docgroup homogen-type="constant">
<doc><text><p>Active states.</p></text></doc>
<constant name="OPEN"/>
<constant name="READY"/>
</docgroup>
<docgroup homogen-type="constant" homogen-name="CLOSED">
<doc><text><p>The final state.</p></text></doc>
<constant name="CLOSED"/>
</docgroup>
</enum>
32.4.6. Type descriptions
A declaration's <type> or <returntype> contains a type representation. Unqualified types use empty elements, for example <int/>, <float/>, <string/>, <mixed/>, <program/> and <void/>. Unqualified container types can also use empty elements. Qualified types contain their component types or bounds:
| Pike type | XML representation |
| array(int) | <array><valuetype><int/></valuetype></array> |
| mapping(string:int) | <mapping><indextype><string/></indextype><valuetype><int/></valuetype></mapping> |
| multiset(string) | <multiset><indextype><string/></indextype></multiset> |
| int(0..255) | <int><min>0</min><max>255</max></int> |
| string(0..255) | <string><min>0</min><max>255</max></string> |
| object(Example.Counter) | <object>Example.Counter</object> |
| string|int | <or><string/><int/></or> |
Function types use ordered <argtype> children and a <returntype> child. A variable-length argument type is wrapped in <varargs>. For function(string, mixed ... : void):
<function> <argtype><string/></argtype> <argtype><varargs><mixed/></varargs></argtype> <returntype><void/></returntype> </function>
Type representations can be nested. For example, an array whose elements are mappings nests a mapping representation inside its valuetype. Integer and string bounds are text values and can include identifiers. Consumers should also account for newer type constructions, such as generic bindings, rather than assuming every type is one of the simple empty elements.
32.4.7. Documentation text and groups
The <doc> element contains the description attached to an entity or docgroup. Its initial prose is placed in a <text> child with <p> paragraphs. Delimiter keywords such as @param and @returns create <group> children. Each group contains its delimiter elements and the <text> describing them.
The introductory add() example produces this documentation element:
<doc>
<text><p>Adds two integers.</p></text>
<group>
<param name="left"/>
<param name="right"/>
<text><p>The values to add.</p></text>
</group>
<group>
<returns/>
<text><p>The sum of the two values.</p></text>
</group>
</doc>
Consecutive compatible delimiter tags share a group, so the two parameters above have one description. Containers such as @mapping and @array have their own groups. For example:
//! @mapping //! @member int "ip" //! The numeric address. //! @member float "latitude" //! @member float "longitude" //! The coordinates. //! @endmapping
<mapping>
<group>
<member><type><int/></type><index>"ip"</index></member>
<text><p>The numeric address.</p></text>
</group>
<group>
<member><type><float/></type><index>"latitude"</index></member>
<member><type><float/></type><index>"longitude"</index></member>
<text><p>The coordinates.</p></text>
</group>
</mapping>
A group's text can contain further documentation containers. They appear in document order alongside its paragraphs, rather than as children of the delimiter element. Thus a nested mapping description belongs inside the enclosing group's text:
<mapping>
<group>
<member><type><mapping/></type><index>"nested"</index></member>
<text>
<p>A mapping containing a postal code:</p>
<mapping>
<group>
<member><type><string/></type><index>"zip-code"</index></member>
<text><p>The postal code.</p></text>
</group>
</mapping>
<p>Additional information about the nested mapping.</p>
</text>
</group>
</mapping>
Blank lines in the source markup divide paragraphs. Leading and trailing whitespace is trimmed, and empty paragraphs are not emitted. Short markup appears inside paragraphs as inline elements. Container and delimiter arguments are not translated identically: a simple parameter name becomes an attribute, while a mapping member's type and index become child elements. The rules are implemented in Tools.AutoDoc.DocParser.
32.4.8. Presentation elements
Documentation text uses a defined set of formatting elements. Escape literal XML characters in their text; a displayed example containing XML must not accidentally become part of the document hierarchy.
| Element | Purpose |
| <p> | A paragraph. |
| <h> | A documentation heading. |
| <i>, <b>, <tt> | Italic, bold and fixed-width inline text. |
| <expr>, <code> | An inline Pike expression or a block of Pike source code. |
| <pre> | Preformatted text that does not require Pike syntax highlighting. |
| <ref> | A reference to a documented entity; reference processing supplies information used by the renderer. |
| <image> | An image with its source path as text. Optional width and height set dimensions; file can identify the normalized image filename. |
| <matrix> | A table containing r rows, each containing c cells. |
Use separate paragraphs for paragraph breaks. Source comments should normally use AutoDoc markup such as @i{...@} and @expr{...@}, rather than injecting presentation XML through @xml{...@}. A table, type description or other block belongs in the appropriate documentation-text container, not inside a declaration's type metadata merely because its element name is the same.
32.4.9. Top-level documentation sections
The legal delimiter tags depend on the entity being documented. General documentation sections include notes, examples, known bugs, deprecation information and related references. Their XML is represented by a group containing the section marker and its text.
| Context | Additional section markers |
| Any documented entity | note, example, bugs, deprecated, seealso and other general sections accepted by the markup parser. |
| Method | <param name="..."/>, <returns/> and <throws/>. |
| Class | <param name="..."/> for documented class parameters. |
| Enum | constant sections describing its enum values. |
| Mapping, array and multiset descriptions | member, elem and index, respectively, inside the matching documentation container. |
These section markers describe prose; they do not replace the
declaration elements. For example, a method's returns section
explains its result, while the method's returntype records its
declared type. See Tools.AutoDoc.DocParser for accepted markup
and Tools.AutoDoc.PikeObjects for the declaration serializers.