Home/Section index | www.icosaedro.it | ![]() |
Last updated: 2009-05-13
PHPLint provides support for the phpDocumentor's DocBlock comments (www.phpdoc.org). PHPLint parses and gathers the informations found inside a DocBlock and merges these informations with those gathered from the PHP source and the PHPLint meta-code.
From a DocBlock, PHPLint acquires not only textual descriptions, but it acquires also the types of variables, function arguments and returned values.
What is a DocBlock
Example
Supported line tags
Types
Literal arrays
The @throws line tag
Supported inline tags
Missing features and differences
References
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.
Every line of the DocBlock MUST begin with an asterisk "*"; lines missing
this asterisk are ignored (PHPLint reports an error). Every line, apart
from the asterisk and the possible surrounding spaces, 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 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 determinated results to be more than 3 lines long, only the first line is taken. If the short description was terminated by a period, the period itself is removed. The short description is rendered literally.
All the text between the short description and the first line tag is the long description. The long description can contain a subset of the HTML entities listed below:
<b> <i> <code> <br> <kbd> <p> <pre>
<ul> <ol> <li> <samp> <var>
The last two entities are not HTML entities, but special tags defined by phpDocumentor; they are passed unchaged but are ignored by WEB browsers. 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 rendered literally. Moreover, PHPLint checks for proper usage of these entities, and raises an error on unclosed tags, wrong nesting, badly formed punctuated lists, etc.
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 <
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.
The following source illustrates the main features of a DocBlock. It declares a package with some copyright, and a function:
<?php /** * PhpDoc test source. * * This is a <i>package description</i>. This source does nothing * useful, it is intended only to illustrate the features of the * phpDocumentor and how a DocBlock looks like. * * @package PhpDocTest * @author Umberto Salsi <phplint@icosaedro.it> * @version 1.0 * @deprecated Do not use this package, it is completely unuseful! */ /*. require_module 'standard'; .*/ /** * Last error code found * @global int $last_error */ $last_error = 0; /** * Search a name inside an array of names. The long description * starts with this second sentence. Both the short * description and the long description are optionals. * * @param string $name Name of the item we are looking for. * @param array[int]string $arr List of items. * * Note that we have indicated both the type of the * index (int) and the type of the elements * (string): this is a PHPLint extension that * works also for phpDocumentor. * * @return int The index of the element found, or -1 if not found. */ function searchName($name, $arr) { foreach($arr as $k => $v) if( $v === $name ) return $k; return -1; } ?>
Also the PHP 4 classes can be documented: properties and methods can have a visibility attribute, and methods can have also the static and the final attributes:
<?php /*. require_module 'pgsql'; .*/ /** * Example of class to access to the PostgreSQL DB. * * @author Umberto Salsi <phplint@icosaedro.it> */ class DBAccess { /** * Name of the current DB * @var string * @access public */ var $db_name; /** * Current connection to the DB * @var resource * @access private */ var $db_conn; /** * Opens the connection with the given DB * @access public * @param string $db_name Name of the DB * @return void */ function DBAccess($db_name) { $this->db_conn = pg_connect("dbname=$db_name"); if( $this->db_conn === FALSE ) die("connection to $db_name failed"); $this->db_name = $db_name; } /* ... */ } ?>
PHP 5 classes already have their own attributes keywords abstract final static private protected public built-in, and these keywords must be used instead of the DocBlock tags. Also PHP 5 class constants can be documented:
abstract class DBLogger extends GenericDB implements Logger { /** * Timeout for any operation on the DB (s) */ const TIMEOUT = 0.5; /** * Commenting a method in PHP 5. Note that the @access * tag cannot be used since PHP 5 already has its own * keyword. * @param string $query * @return bool */ public abstract function testTimeout($query); /* ... */ }
Abstract classes and interfaces can be commented with DocBlocks as you can expect:
/** * Documenting an interface class */ interface TreeInterface { /** * Constants are always public. No type declaration is * required, as their value already says all. */ const ROOT_NODE_LEVEL = 0; /** * Methods are always abstract, public and non-final. * * @param mixed $key * @return void */ function addNode($key); }
The syntax of every line tag is described with the aid of these elements:
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:
Line tag | PHP 4 | PHP 5 |
---|---|---|
@abstract | class, method | See note 1. |
@access private | constant, global variable, function, class, property, method | constant, global variable, function, class, class constant |
@access protected | property, method | See note 1. |
@access public | property, method | See note 1. |
@author TEXT | (always) | (always) |
@copyright DESCR | (always) | (always) |
@deprecated DESCR | (always) | (always) |
@final | class, method | See note 1. |
@global TYPE $VAR | global variable | global variable |
@license WORD [TEXT] | (always) | (always) |
@link WORD [TEXT] | (always) | (always) |
@package WORD | package | package |
@param TYPE [&] $VAR [DESCR] | function, method | function, method |
@return TYPE [DESCR] | function, method | function, method |
@see WORD | (always) | (always) |
@since DESCR | (always) | (always) |
@static | method | See note 1. |
@throws WORD [DESCR] | function, method | See note 2. |
@todo DESCR | (always) | (always) |
@var TYPE [DESCR] | property | property |
@version TEXT | (always) | (always) |
Note 1. PHP 5 already has the attributes abstract final private
protected public static . These keywords must be used instead of
the corresponding phpDocumentor line tags.
Note 2. The |
The supported TYPEs are described in the next paragraph.
PHPLint raises a notice if a line tags is used in the wrong context,
for example @var
in a function description.
PHPLint raises a warning if a DocBlock omits to declare the type of a variable, function, argument, property or method and this type cannot be guessed from the code.
All the basic PHP types are supported, with the addition of void
.
The general syntax in EBNF format is:
TYPE = type_name | array; type_name = "void" | "bool" | "boolean" | "FALSE" | "false" | "int" | "float" | "double" | "number" | "string" | "resource" | "mixed" | "object" | CLASS_NAME | array; array = "array" [ index {index} [TYPE] ]; index = "[" ["int"|"string"] "]";
The following table summarize the allowed types:
Type | Description |
---|---|
void | Functions and methods that do not return a value are declared to retun a value of this dummy type. |
bool or boolean | A boolean value, either FALSE or TRUE. 0 and 1 are numbers in PHPLint and cannot be used in place of the boolean values. |
int or integer | An integer number. |
float or double | A floating point number. |
number | Either an integer or a floating point number. Probably you should simply use float instead, since int is a subset of this. |
string | A string of bytes. PHPLint allows also the value NULL. |
array | Array of undefined key type and undefined elements, equivalent to the PHPLint type array[]. PHPLint allows also the value NULL for a variable of this type. |
resource | Typically an opened file, or a network socket. PHPLint allows also the value NULL. |
object | Generic object. PHPLint allows also the value NULL. |
CLASS_NAME | An object of the specified class. PHPLint allows also the value NULL. |
mixed | Anything. |
An array can be described including the type of the index and the type of
the elements. This is an extension of the array
type already
supported by phpDocumentor. Some examples:
array |
index can be both integers and strings, elements mixed |
array[] |
index can be both integers and strings, elements mixed |
array[int]string |
array of strings with int index |
array[int][int]float |
matrix of floating-point numbers |
array[string]mixed |
associative array of generic values |
array[]SomeClass |
array of objects of the class SomeClass, the keys can be both integer numbers and strings |
Some functions and methods can return values of different types that
can be listed separated by a vertical bar. Many functions of the
standard library can return some result or FALSE
on error.
For example fopen()
can return either a resource
or the FALSE
value. This practice is discuraged by PHPLint,
but it is tolerated; in this case PHPLint keeps only the first type, then
the remaining types are parsed but ignored. Example:
/** * Opens my data file * * @return resource|FALSE */ function my_fopen() { return fopen("data.txt", "r"); }
Note that PHPLint allows to indicate the value FALSE
in place
of the correct type boolean
just to support this common practice.
The Tutorial expands this topic with
several practical examples.
Please, in new software you write (or at least, if it is intended to be
validated by PHPLint) try to choose among the alternatives indicated there.
In PHP, literal arrays can be defined through the array()
constructor. PHPLint parses accurately the literal arrays in order to
guess their type (both index and elements). The manual of PHPLint
explains in detail how these guesses are made. Basically, if no
keys are specified, the type of the index default to int
.
The type of the elements is the type of the expression giving
the value of the elements.
For example:
Literal array | Guessed type |
---|---|
array() |
array |
array( array( ) ) |
array[int][] |
array("AA", "BB") |
array[int]string |
array(0=>"AA", 1=>"BB") |
array[int]string |
array("a"=>"AA", "b"=>"BB") |
array[string]string |
array( new SOME_CLASS() ) |
array[int]SOME_CLASS |
array(array(1.0,0.0), array(0.0,1.0)) |
array[int][int]float |
Note that PHPLint encounters a difficulty when the literal array is empty,
because no keys nor elements are available and the resulting type is a generic
"array
". Such generic type is likely to produce an error if
it is assigned to some variable or passed by value to a function. The same
hold when the value to be assigned or passed to function is NULL: NULL is a
special value that is assignment-compatible with every array, but that cannot
provide to PHPLint the informations about the structure of the array.
In these cases the correct type should be indicated through a PHPLint
formal type-cast, like in these examples:
<?php /** * List of names, initially empty */ $names = /*. (array[int]string) .*/ array(); /** * List of names, initially NULL. * Here using phpDocumentor line tag. * @global array[int]string $names2 */ $names2 = NULL; /** * List of names, initially NULL. * Here using PHPLint formal type-cast. */ $names3 = /*. (array[int]string) .*/ NULL; /** * List of names, initially NULL * * When a @global or @var line tag is used, the type * specified must match the type of the expression. * In this case, since every array is assignment-compatible * with the value NULL, no formal type-cast is required. * * @global array[int]string $names3 */ $names3 = NULL; /** * Matrix of coefficients, initially empty */ $m = /*. (array[int][int]float) .*/ array(); /** * Prints a list of names. This function requires * an array of a well defined structure. * * @param array[int]string $a the list of names * @return void */ function print_names($a) { echo count($a), " names in list:\n"; for($i=0; $i<count($a); $i++) echo $a[$i], "\n"; } print_names( array( "Foo", "Bar" ) ); print_names( /*. (array[int]string) .*/ array() ); /* Note the empty list and the formal typecast. Without this formal type-cast PHPLint would raise an error because array() is not assignment- compatible with the formal type expected as argument of the function. */ ?>
The @throws
line tag is an important extension of PHPLint to the
format of the DocBlock, but it is not officially supported by phpDocumentor.
phpDocumentor simply reports this line tag verbatim.
The @throws WORD [DESCR]
line tag allows to declare an exception
the function or the method may throws, 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 that 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($php_errormsg); 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); ... }
Usually there is no need to list all the exceptions the method may throw, since PHPLint automatically collects uncought exceptions while parsing the source. As a consequence, the generated document may list more exceptions than those the programmer has explicitly entered in the DocBlock.
The programmer may still add one or more @throws
line tag either
to add a descriptive text, or also to add an exception that is not currently
thrown by the method, but it is planned to be thown later in some overriding or
implementing method. In fact, as explained in more details in the PHPLint
manual, the list of thrown exceptions is part of the method signature that
implementing and overriding methods must comply with. Basically, implementing
and overriding methods can only throw the same exceptions the original method
throws, or even more specialized exceptions derived from these; it is important
to note that 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()
statements.
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 inline 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:
{@}
{@
that would be otherwise forbidden because them are reserved to start
an inline tag.
{@*}
*/
that would be otherwise forbidden in a multi-line comment. It is mostly
usefult when a long chunk of code has to be inserted into the text.
{@link
ITEM}
{@link
ITEM text to be displayed}
{@link
URL}
{@link
URL text to be displayed}
{@link M_PI}
inserts a reference to the constantM_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 functionfuncName()
. Note that the perenttheses 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)}
.
{@link SomeClass}
inserts a reference to the class or interfaceSomeClass
.
{@link SomeClass::SOME_CONST}
inserts a reference to the class constantSomeClass::SOME_CONST
.
{@link SomeClass::$aProperty}
inserts a reference to the propertySomeClass::$aProperty
.
{@link SomeClass::aMethod()}
inserts a reference to the methodSomeClass::aMethod()
. Between parentheses, you may enter some specific actual argument just like already explained for functions.
In DocBlocks related to a class, the class name itself can be omitted, so bringing to these shorter references:
{@link ::SOME_CONST}
inserts a reference to the class constantSOME_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 methodaMethod()
defined inside the same class to which the DocBlock belongs.
The ITEMs that can be refereced 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.
Private items cannot be referenced.
The {@link}
inline 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 mailto:bugs@company.com}
{@link ./anotherPackage.htm}
{@link ../otherLib/otherPackage.htm}
{@link /home/Me/projects/myProject/index.htm}
{@link c:/php-lib/index.htm}
Unsupported inline tags {@example} {@internal} {@inheritdoc}
{@source} {@tutorial}
are reported verbatim.
Invalid inline tags are reported as errors.
Nested inline tags are not allowed.
@category
@example
@exception
@filesource
@ignore
@internal
@method
@name
@property
@staticvar
@subpackage
@tutorial
@uses
.
{@example} {@internal} {@inheritdoc} {@source} {@tutorial}
@package
line tag (in PHPLint it
is simply a PHP source file).
@param
line tag, the name of the parameter is mandatory,
and it must start with the dollar sign "$
". So these lines
are not valid:
@param int maxlen (missing $) @param $maxlen (missing type) @param $maxlen int (TYPE/NAME exchanged)
/**#@+*/ /**#@-*/
are scanned but ignored.
@author
line tag: text contained between <> is rendered
literally, not as email hyper-link.
include*()
and require*()
statements cannot be
documented. PHPLint automatically lists packages imported with
required_once()
.
@global
line tag is only partially supported. phpDocumentor
allows to document a global variable defined inside the scope of a function
or a method (or defined inside a file included by these) using a syntax
similar to this one:
function someFunc() { /** * @global int $GLOBALS['myvar'] */ $GLOBALS['myvar'] = 123; }
PHPLint requires that global variables be defined in global scope, so the previous code must be rewritten moving the definition of the global variable into the global scope as follows:
/** * @global int $myvar */ $myvar = 0; function someFunc() { $GLOBALS['myvar'] = 123; }
This can be parsed by PHPLint. If you are not interested into produce the documentation through phpDocumentor, remember that PHPLint is capable to guess the type of the variable from the expression giving its value, so the DocBlock is checked but unuseful for PHPLint and it can also be removed at all, bringing to the even shorter version that follows:
$myvar = 0; function someFunc() { $GLOBALS['myvar'] = 123; }
@ignore
line tag is not supported. You can use the
@access private
line tag instead with a similar effect.
www.phpdoc.org - Official WEB site of the phpDocumentor project.
Umberto Salsi | Contact | Site map | Home/Section index |