DocBlocks

DocBlocks are multi-line comments properly formatted from which PHPLint acquires the detailed description of the PHP item defined below it, including constants, variables, functions and classes.

What is a DocBlock

Constants, variables, functions, classes, class constants, properties and methods can be preceded by a multi-line comment properly formatted. The symbol /** marks the beginning of the DocBlock:

/**   Two asterisks after the slash mark the beginning of the DocBlock.  */

Every line of the DocBlock may begin with an optional asterisk "*", which is ignored and discarded:

/**
 * The asterisk at the beginning of every line has only an
 * aesthetic purpose and, if present, is ignored and will
 * not be rendered in the generated document.
 */

Every line, leading asterisk and the possible next space apart, is the content of the DocBlock. The structure of a DocBlock consists of three sections: the short description, the long description and the line tags, in this order.

/**
 * The first sentence is the short description. Any text that
 * follows up to the first line tag is the long description.
 * The short description should be short, possibly incomplete
 * but meaningful, usually not longer than one line of text.
 * @param int $i  A line that begins with @ is a line tag.
 * @return void  And this is another line tag.
 */

The short description starts at the first non-empty line and spans up to the first empty line, the end of the DocBlock or the first period not included inside a word. If the short description so determined results to be more than 3 lines long, only the first line is taken. If the short description is terminated by a period, the period itself is removed.

All the text between the short description and the first line tag or the end of the DocBlock is the long description.

The short description, the long description and the descriptive text allowed in some of the line tags can contain a subset of the HTML entities as listed below:

<b> <i> <code> <br> <kbd> <p> <pre> <ul> <ol> <li>

Currently PHPLint does not allow upper-case letter, nor it allows spaces inside the tags, so take care to write them exactly as indicated here otherwise they would be signaled as errors. Moreover, PHPLint checks for proper usage of these entities, and raises an error on unclosed tags, wrong nesting, badly formed punctuated lists, etc.

The following tag and special sequences are additions of PHPLint and may be incompatible with other documentation systems:

Single Unicode characters can be entered as "&#123;" in decimal notation, or as "&#x1ab;" in hexadecimal notation. For example, the asterisk is &#42;.

Others tag specific of PHPLint:

<h1> <h2> <h3> <h4> <h5> <h6> <u> <sub> <sup> <blockquote> <center>

These tags, and only these, can be used to format the text of the long description. Any other entity or special character including < > & gets rendered literally (i.e. < is converted to &lt; and so on).

The text enclosed between <pre> and </pre> is always rendered literally.

The line tags are all the lines with a leading "@" (extra spaces and tabulations between the asterisk and the "@" are ignored). The first line tag found opens the line tags section of the DocBlock.

What can be commented with a DocBlock

PHPLint recognizes DocBlocks for: package, constants, global variables, functions, classes and interfaces, class constants, properties and methods.

The other elements of the source that cannot be documented and PHPLint signals an error because the DocBlock is not used:
the namespace statement,
the use statement,
the declare statement,
the include, include_once, require statements.

Documenting a package

A PHP source file can contain only one package DocBlock. A package DocBlock is a DocBlock containing the @package line tag; this latter line-tag is then the only mandatory line-tag in this kind of DocBlock. Example:

/**
 * Utility functions.
 * @author Umberto Salsi
 * @package utils
 */

The name chosen for the package has not particular meaning for PHPLint and currently is used only to give a title to the HTML generated for that package.

Documenting a constant

Constants can be defined with the define(); statement or the const statement. There are no mandatory line-tags. The type of the constant is guessed from the expression assigned. Example:

/**
 * Popular value of "PI".
 */
define("PI_POPULAR", 3.14);

/**
 * Root of the library files.
 */
const LIBS = __DIR__ . "/../../libs";

/**
 * Format of the file.
 */
const TEXT_FMT = 0, TEXT_EXT = ".txt",
      HTML_FMT = 1, HTML_EXT = ".html",
      PDF_FMT = 3,  PDF_EXT = ".pdf";

If the const statement defines 2 or more constants in a list of comma separated assignments, then the same DocBlock applies to all these constants; each constant may have its own different type.

Documenting a variable

Only variables at global scope can be documented, and the statement that follows must be the assignment of their initial value. The @var TYPE line tag is not mandatory and can be added to define the detailed structure of the type when it cannot be guessed from the type of the expression. Examples:

/**
 * Current number of records read.
 */
$record_read_no = 0;

/**
 * Collected users' names as UTF-8 strings.
 * @var string[int]
 */
$users_names = array();

/**
 * Peer input socket.
 * @var resource
 */
$peer_in_socket = NULL;

/**
 * Collected exceptions to be reported at the end of the program.
 * @var Exception[int]
 */
$exceptions = array();

/**
 * Rotational 3x3 matrix.
 */
$rotation = array(
	array(1.0, 0.0, 0.0),
	array(0.0, 1.0, 0.0),
	array(0.0, 0.0, 1.0));

If the assignment statement involves 2 or more variables $v1 = $v2 = $v3 = EXPR; in a list of comma separated assignments, then the same DocBlock applies to all these variables.

Documenting a function

The DocBlock of a function MUST always declare unhandled errors and uncaught checked exceptions using the @triggers E_XXXXX and the @throws SomeException line tags. Also the mandatory arguments, those that have not a default value, MUST be declared with a @param TYPE $name line tag. Usually, the return type is always guessed automatically by PHPLint. Examples:

/**
 * Returns the area of the circle given its radius.
 * <b>Attention!</b> This function performs the
 * calculation using the popular, approximated value of PI.
 * @param float $r Radius of the circle. Must be non-negative.
 * @return float Area of the circle.
 * @throws \InvalidArgumentException Negative radius.
 */
function circle_area($r){
	if( $r < 0.0 )
		throw new \InvalidArgumentException("r=$r");
	return PI_POPULAR * $r * $r;
}

In normal situations, PHPLint can guess the return type from the first return EXPR; statement it encounters in the body of the function, but there may be cases in which this guess may fail and an error is signaled, for example on recursive functions or when class autoloading on mutually dependent packages is triggered (for example, the body of the function references a class that gets loaded by the autoloader, and in turn this class calls the function). In some others cases you may want to provide a @return TYPE line-tags anyway to direct the IDE, which might not be so smart to guess this information from the code.

In the example above, the function may throw the unchecked exception InvalidArgumentException. It is not mandatory to declare the unchecked exceptions, but here it has been specified just to document what happen if the client program violates the contract of the interface (the argument must be non-negative).

Note that a @access private line tag can be added to functions that are private to the file: these private functions cannot be called from the other packages.

PHP 5 and PHP 7 type-hints can be used as well, so for example the function above becomes:

/**
 * @throws \InvalidArgumentException Negative radius.
 */
function circle_area(float $r): float
{
	...
}

Note that we still have to provide a DocBlock just to the pourpose to declare the exception this function can throw. In general DocBlocks are mandatory to properly document the meaning of each argument and each returned value; in this case the types declared in the DocBlock must match exactly the types declared through type-hints or PHPLint will complain.

Documenting a class

Classes and interfaces can be documented as well. There are no mandatory line-tags here, but @author NAME and @version VER are very common. Example:

/**
 * Input stream of bytes. Possible implementations of this abstract class
 * may provide, for example, access to the file system or to data in memory.
 *
 * @author Umberto Salsi <salsi@icosaedro.it>
 * @version $Date: 2019/02/06 09:40:46 $
 */
abstract class InputStream {
	...
}

Documenting a class constant

There are no mandatory line tags. The type of the constant is guessed from the expression assigned. Example:

/**
 * Popular value of "PI".
 */
const PI_POPULAR = 3.14;

If the const statement defines 2 or more constants in a list of comma separated assignments, then the same DocBlock applies to all these constants; each constant may have its own different type.

Documenting a property

In PHPLint, properties of the simple type boolean, int and float MUST always be initialized to some value. This is required because PHP would otherwise initialize them to the NULL value, which is forbidden for those types under PHPLint. The type of these properties can then be guessed by PHPLint from the type of the expression assigned, so a @var TYPE is not required here and can be omitted.

The @var TYPE line tag is not mandatory and can be added to define the detailed structure of the type when it cannot be guessed from the type of the expression. Examples:

/**
 * Current number of records read.
 */
public $record_read_no = 0;

/**
 * Collected users' names as UTF-8 strings.
 * @var string[int]
 */
public $users_names = array();

/**
 * Peer input socket. Its initial value is NULL.
 * @var resource
 */
private $peer_in_socket;

/**
 * Collected exceptions to be reported at the end of the program.
 * @var Exception[int]
 */
private $exceptions = array();

/**
 * Rotational 3x3 matrix.
 */
private $rotation = array(
	array(1.0, 0.0, 0.0),
	array(0.0, 1.0, 0.0),
	array(0.0, 0.0, 1.0));

In the examples above, note that $record_read_no has an initial value 0 from which PHPLint guesses the type of the property, that is int.

$users_names, instead, is initialized to an empty array array(), so that an explicit declaration of type string[int] is required to specify that the keys of the array are int numbers and the elements are strings. Without this explicit declaration of type, the resulting array would be a generic mixed[] because PHPLint cannot otherwise guess the structure from an empty array.

$rotation is initialized with a non-empty array from which PHPLint can guess the type float[int][int]. No explicit type declaration is required in this case.

If the assignment statement lists 2 or more properties, for example public $p1, $p2 = EXPR, $p3; then the same DocBlock applies to all these variables and all the variables MUST have the same exact type; if their type is boolean or numeric, an initial value MUST be indicated.

As of PHP 7.4, type-hints are allowed in class properties. Here too, DocBlocks may or may not declare the type again, but if they do, the type in the annotation must match the type-hint:

/**
 * Current parth for temporary files.
 * @var string
 */
private string $tmp;

Documenting a method

The DocBlock of a method follows the same rules we already saw for a normal function:

/**
 * Returns the area of the circle given its radius.
 * <b>Attention!</b> This function performs the
 * calculation using the popular, approximated value of PI.
 * @param float $r Radius of the circle.
 * @return float Area of the circle.
 * @throws \InvalidArgumentException Negative radius.
 */
public static function circle_area($r){
	if( $r < 0.0 )
		throw new \InvalidArgumentException("r=$r");
	return self::PI_POPULAR * $r * $r;
}

Supported line tags

The syntax of every line tag is described with the aid of these definitions:

WORD is any sequence of characters not including spaces, tabulations an new-lines. WORDs are rendered literally.

$VAR is the name of a variable. Note that the dollar sign is required.

TEXT is any text, possibly spanning on several lines up to the next line tag or the end of the DocBlock. A TEXT is rendered literally.

DESCR is an HTML text, and the subset of tags already listed for the long description are allowed. The DESCR can span several lines up to the next line tag or the end of the DocBlock. A DESCR enclosed between square parenthesis [DESCR] is optional.

The following table summarizes all the available line tags, their syntax, and the context where they are legal, that is for which named items the line-tag can be used; "always" means for any item, that is any package, constant, global variable, function, interface, class, class constant, property and method.


Line tag Applicable to: Description
@access private constant, global variable, function, class, class constant Allows to make the item private to the file (aka "package" in the PHPLint terminology) so it cannot be used elsewhere.
@author TEXT (always) Name of the author to be reported in the document.
@copyright DESCR (always) Copyright statement to be reported in the document.
@deprecated DESCR (always) Error message to be reported if the item is used anywhere outside its package. Obsolete, not supported or unsafe items should be marked with this line-tag.
@license [TEXT] (always) License statement to be reported in the document.
@link WORD [TEXT] (always)  
@package WORD package Name of this package, reported as main title of the generated document. The presence of this line-tag makes the DocBlock related to the package and not to the following item.
@param TYPE [&] [...] $VAR [DESCR] function, method Declares the type of a function or method parameter.
@return TYPE [DESCR] function, method Declares the type of the returned value from a function or method.
@see WORD (always)  
@since DESCR (always)  
@triggers WORD [DESCR] function, method Declares an error that might be raised by this function or method, for example E_USER_NOTICE. All the errors raised MUST be declared. You may want to add even more errors to account for future development. Note that errors raised by concrete and abstract methods are inherited by overriding method and implementing methods. Vice-versa, overriding methods and implementation methods cannot raise more errors than those declared in their parent method.
@throws TYPE [DESCR] function, method Declares an exception that might be thrown by this function or method. All the exceptions thrown MUST be declared. You may want to add even more exceptions to account for future development. Note that exceptions thrown by concrete and abstract methods are inherited by overriding methods and implementing methods. Vice-versa, overriding and implementing methods cannot throw more exceptions that those declared in their parent method.
@todo DESCR (always)  
@var TYPE property  
@version TEXT (always)  

The supported TYPEs are described in the introductory chapter "Annotations".

PHPLint raises a notice if a line tags is used in the wrong context, for example @var in a function description.

PHPLint raises an error if a DocBlock omits to declare the type of a variable, function, argument, property or method when this type cannot be guessed from the code.

The @triggers line tag

This line-tag allows to declare all the errors the function or method may trigger. It is mandatory for functions and methods that may trigger unhandled errors, including E_NOTICE.

If the mapping of errors into ErrorException is enabled, all the errors are assumed to be ErrorException. In this case, using that function or method requires to either capture the exception or declare the exception as thrown in the client code.

Example:

/**
 * Save data to file.
 * @param string $d Data to save.
 * @param string $fn Destination file name.
 * @triggers E_WARNING File access failure; data might not be
 * properly written or might not be written at all.
 */
function save_data($d, $fn){
	$f = fopen($fn, "wb");
	if( $f !== FALSE )
		fwrite($f, $d);
	fclose($f);
}

The following error labels are recognized: E_ERROR, E_WARNING, E_PARSE, E_NOTICE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, E_STRICT, E_RECOVERABLE_ERROR, E_DEPRECATED, E_USER_DEPRECATED, E_ALL.

The @throws line tag

The @throws WORD [DESCR] line tag allows to declare an exception the function or the method may throw, where WORD is the name of the exception and DESCR describes the conditions that causes this exception to be thrown:

/**
 *  Return the size of the file. On 32-bit systems, this function
 *  returns the correct value also for files whose size is up to 4 GB.
 *
 *  @param string $filename  Path of the file.
 *
 *  @return float  Size of the file (bytes). Being a float, this value
 *                 may be greater than the maximum allowed for int.
 *
 *  @throws ErrorException  If an error occurs accessing the file.
 */
function BigFileSize($filename)
{
    $size = @filesize($filename);
    if( $size === FALSE )
        throw new ErrorException((string) error_get_last()['message']);
    if( $size >= 0 )
        return (float) $size;
    else
        return (float) $size + 2.0 * (1.0 + PHP_INT_MAX);
}


interface MyCollection {

    /**
     *  Return the element of the given index in the list.
     *
     *  @param int $index  Index of the element.
     *
     *  @return mixed      The element.
     *
     *  @throws OutOfBoundException  If the $index is out of bound.
     *
     *  @throws ErrorException   Implementing methods may also throw this,
     *                           depending on the specific code that will
     *                           implement this method.
     */
    function getElement($index);

    ...
}

All the checked exceptions a function or method may throw must be declared. It is allowed to add also unchecked exceptions, but these exceptions are reported in the generated documentation only if a descriptive text is also provided; if no descriptive text is provided, the declaration of the unchecked exception is parsed but it is otherwise completely ignored.

The programmer may still add more exceptions the are still not thrown, but that might thrown later in some overriding or implementing method. In fact, as explained in more details in the PHPLint manual, the list of thrown checked exceptions is part of the method contract that implementing and overriding methods must comply with. Basically, implementing and overriding methods can only throw the same checked exceptions the original method throws, or even more specialized exceptions derived from these. In other words, implementing and overriding methods cannot throw new, unrelated exceptions.

In the document generated by PHPLint Documentator, thrown exceptions are always listed in the order from more specialized ones to more general ones (that is, parent classes) so to suggest to the programmer the proper order of the catch() branches.

Namespaces and names resolution

ATTENTION!
Namespaces are still not supported by the official phpDocumentor program, so what follows must be considered as an extension specific of PHPLint.

PHP 5.3 introduces the concept of namespaces with which, for example, the fully qualified name of a class consists of one or more identifiers separated by a back-slash character, like in this example: it\icosaedro\bignumbers\BigInt. To be more precise, we will use the following nomenclature with examples applied to the class above:

The fully qualified name (FQN) of the class is a sequence of identifiers separated by the back-slash character that univocally identify the item; you may think at it as the real, complete name of the class or function:

it\icosaedro\bignumbers\BigInt

A qualified name is a sequence of two or more identifiers separated by the back-slash character, that may represent only part of a FQN:

bignumbers\BigInt

The absolute name of the class is its FQN with a leading back-slash appended to it:

\it\icosaedro\bignumbers\BigInt

Proper name of the class is the last identifier of the FQN:

BigInt

The namespace\ operator can be used as abbreviation to reference an item which is reachable from the current namespace and the name so generated is considered absolute. For example, if the current namespace is it\icosaedro then namespace\bignumbers\BigInt is the absolute name of the intended item.

Incomplete names, that is qualified and bare identifiers, are also allowed but a special resolution algorithm has to be applied in order to recover the actual absolute name of the intended item. PHPLint applies the same resolution algorithm the PHP interpreter applies. The only difference is that PHPLint performs namespace resolution also in PHPLint meta-code and in DocBlocks.

Then the @param line tag, the @return line tag and the {@link} all can make reference to constants, functions and classes using fully qualified names, qualified names, and bare identifiers. Also the namespace\ operator and the use clauses are interpreted as usual.

There are only two restrictions to names that occurs in a DocBlock:

The name resolution is performed in the same context of the DocBlock, so using the same current namespace and the same list of use mappings. The following example illustrate the issue with two DocBlocks, the first appears before a namespace, and the second appears after the namespace:

<?php
/**
 *  DocBlock outside the namespace. The namespace below declared the class
 *  BigInt and the function One.  To refer to the class BigInt we must use a
 *  fully qualified name, for example {@link \it\icosaedro\bignumbers\BigInt}
 *  because this DocBlock is still in global namespace.
 * 
 *  Unqualified names as {@link BigInt} and qualified names as {@link
 *  bignumbers\One()} DOES NOT WORK and gives an error because it cannot be
 *  resolved in the context of this DocBlock, and because the `use' clauses
 *  below have a scope limited to their namespace.
 *
 *  Now the mandatory @package line tag, as usual, to give a name to this
 *  package:
 *  @package it/icosaedro/bignumbers/BigInt
 */

namespace it\icosaedro\bignumbers;

use it\icosaedro\bignumbers;

use it\icosaedro\bignumbers as BN;

class BigInt {
    # ...
}

/**
 *  Quite useless function that returns a cached BigInt(0).
 *
 *  @return BigInt
 *          Unqualified name here works, but also {@link bignumbers\BigInt}
 *          and {@link BN\BigInt} are allowed.
 *
 *  @throws \Exception  Inherited from BigInt for this and that reason.
 *          Useless (but allowed) leading back-slash.
 */
function Zero()
{
    static $zero = /*. (BigInt) .*/ NULL;
    if( $zero == NULL )
        $zero = new BigInt(0);
    return $zero;
}

And here is how a possible client package might use the package above:

<?php

require_once __DIR__ . "/../../bignumbers/BigInt.php";

namespace it\icosaedro\stats\Test;
use it\icosaedro\bignumbers\BigInt;
use it\icosaedro\bignumbers as BN;

/**
 *  This package performs simple statistical calculations using
 *  big numbers from the {@link BigInt} class.
 *
 *  @package it\icosaedro\stats\Test
 */

/**
 *  Calculates the arithmetic mean between {@link BigInt} numbers.  This link
 *  can be resolved using the first "use" clause.  With the second "use"
 *  clause we might also write {@link BN\BigInt} but it is mostly useful to
 *  build short names of non-class items like the {@link BN\Zero()} function.
 *  Without any "use" clause we would need to write the fully qualified name
 *  {@link \it\icosaedro\bignumbers\BigInt}.
 *
 *  @param array[]BN\BigInt $a  One, two or more numbers.
 *
 *     Illustrates how the second "use" clause can be used to
 *     resolve the name. A bare BigInt[] would be sufficient
 *     because we have imported the class with the first "use".
 *
 *  @return it\icosaedro\bignumbers\BigInt   The arithmetic mean.
 *
 *     Here too, a bare BigInt would be sufficient.
 */
function Mean($a)
{
    $n = count($a);
    $sum = $a[0];
    for( $i = 1; $i < $n; $i++ )
        $sum = $sum->add($a[$i]);
    return $sum->div( new BigInt($n) );
}

Summarizing, fully qualified, qualified and unqualified names of constants, functions and classes may appear in the {@link} in line tag and in the @param and @return line tags as class names, and in all these cases namespace resolution algorithm applies.

All the items parsed by PHPLint are reported in the generated document with their fully qualified names.

Namespaces declarations by themselves are not reported and cannot be documented with a DocBlock.

Supported in-line tags

The sequence of characters {@ has a special meaning as it is the beginning of an inline tag. The general syntax of an inline tag is as follows:

{@TAG}

Some in-line tags may have one or more arguments separated by one or more spaces, tabulator characters or line feed; the general structure of an inline tag requiring arguments is a follows:

{@TAG ARG1 ARG2 ... ARGn}

Inline tags are allowed in the short description, in the long description, and in the descriptive text of line tags that have a descriptive text. Inline tags are not allowed, that is are passed verbatim, in any other location.

The inline tags PHPLint supports are listed below:

{@}
This tag allows to insert the sequence of characters {@ that would be otherwise forbidden because them are reserved to start an inline tag.
{@*}
This tag allows to insert the sequence of characters */ that would be otherwise forbidden in a multi-line comment. It is mostly useful when a long chunk of code has to be inserted into the text.
{@link ITEM}
{@link ITEM HTML}
{@link URL}
{@link URL HTML}
This tag allows to insert an hypertext link to some documented item (constant, variable, function, etc.) or to some generic resource available in Internet through an URL. ITEMs can be specified using their name, for example:

{@link M_PI}
inserts a reference to the constant M_PI.

{@link $varName}
inserts a reference to the global variable $varName. Note that the $ symbol is mandatory. Variables that are local to a function or method and formal arguments of function and method cannot be referenced.

{@link funcName()}
inserts a reference to the function funcName(). Note that the parentheses are mandatory as them allows to distinguish between constants and functions. You may also add specific arguments inside the parentheses, but still spaces are not allowed. For example you may write {@link tan(M_PI)}. If the function belongs to a namespace, the fully qualified name must be reported.

{@link SomeClass}
inserts a reference to the class or interface SomeClass. If the class belongs to a namespace, the fully qualified name must be reported.

{@link SomeClass::SOME_CONST}
inserts a reference to the class constant SomeClass::SOME_CONST. If the class belongs to a namespace, the fully qualified name must be reported.

{@link SomeClass::$aProperty}
inserts a reference to the property SomeClass::$aProperty.

{@link SomeClass::aMethod()}
inserts a reference to the method SomeClass::aMethod(). Between parentheses, you may enter some specific actual argument just like already explained for functions. If the class belongs to a namespace, the fully qualified name must be reported.

In DocBlocks related to a class, self and parent are recognized, or the name of the class name itself can be omitted at all so bringing to these shorter references:

{@link ::SOME_CONST}
inserts a reference to the class constant SOME_CONST defined inside the same class to which the DocBlock belongs.

{@link ::$aProperty}
inserts a reference to the property $aProperty defined inside the same class to which the DocBlock belongs.

{@link ::aMethod()}
inserts a reference to the method aMethod() defined inside the same class to which the DocBlock belongs.

The ITEMs that can be referenced are only those that are available in the current package, including imported standard modules (see require_module) and imported packages (see require_once). Instead, ITEMs that are not accessible from the current package cannot be referenced directly but, if really needed, a full URL or a relative path can be provided instead.

In-line tags are resolved by the PHPLint Documentator while generating the HTML file. At that time, all the items collected from the source are available, so any item, also those defined after the in-line tag itself, can be referenced. This offers a more freedom and flexibility. For example, the DocBlock describing a class can make reference to any of its methods that are defined only below that DocBlock.

Private items cannot be referenced.

The {@link} in-line tag also allows to insert links either to local file or to remote resources. To avoid URLs and file paths be confused with PHP documented items, URLs must always indicate the protocol used and file paths must always be indicated as relative to the directory of the current document file or as absolute path. For example:

{@link ftp://sources.company.com/myproject/package-1.0.zip}
{@link http://www.company.com/}
{@link https://www.company.com/}
{@link mailto:bugs@company.com Please, send bug reports here}
{@link ./anotherPackage.htm}
{@link ../otherLib/otherPackage.htm}

{@img URL}
This tag allows to insert an image. This tag is an extension specific of PHPLint and may be incompatible with other documentation systems.

Unsupported in-line tags {@example} {@internal} {@inheritdoc} {@source} {@tutorial} are reported verbatim. Invalid in-line tags are reported verbatim but signaled as errors.

Nested in-line tags are not allowed.

Absolute file paths C:/xxx or /user/www are not recognized, only relative paths that starts with ./xxx or ../xxx are. Note that the directory separator character is the slash, NOT the back-slash, this latter being reserved to PHP namespaces.

Missing features and differences