mirror of
https://github.com/php/phpruntests.git
synced 2026-03-25 08:32:21 +01:00
611 lines
26 KiB
PHP
611 lines
26 KiB
PHP
<?php
|
|
|
|
class documentation_Sniffs_FunctionCommentSniff extends Squiz_Sniffs_Commenting_FunctionCommentSniff
|
|
{
|
|
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
|
{
|
|
$this->currentFile = $phpcsFile;
|
|
|
|
$tokens = $phpcsFile->getTokens();
|
|
|
|
$find = array(
|
|
T_COMMENT,
|
|
T_DOC_COMMENT,
|
|
T_CLASS,
|
|
T_FUNCTION,
|
|
T_OPEN_TAG,
|
|
);
|
|
|
|
$commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1));
|
|
|
|
if ($commentEnd === false) {
|
|
return;
|
|
}
|
|
|
|
// If the token that we found was a class or a function, then this
|
|
// function has no doc comment.
|
|
$code = $tokens[$commentEnd]['code'];
|
|
|
|
if ($code === T_COMMENT) {
|
|
$error = 'You must use "/**" style comments for a function comment';
|
|
$phpcsFile->addError($error, $stackPtr);
|
|
return;
|
|
} else if ($code !== T_DOC_COMMENT) {
|
|
$error = 'Missing function doc comment';
|
|
$phpcsFile->addError($error, $stackPtr);
|
|
return;
|
|
}
|
|
|
|
// If there is any code between the function keyword and the doc block
|
|
// then the doc block is not for us.
|
|
$ignore = PHP_CodeSniffer_Tokens::$scopeModifiers;
|
|
$ignore[] = T_STATIC;
|
|
$ignore[] = T_WHITESPACE;
|
|
$ignore[] = T_ABSTRACT;
|
|
$ignore[] = T_FINAL;
|
|
$prevToken = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true);
|
|
if ($prevToken !== $commentEnd) {
|
|
$phpcsFile->addError('Missing function doc comment', $stackPtr);
|
|
return;
|
|
}
|
|
|
|
$this->_functionToken = $stackPtr;
|
|
|
|
foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condition) {
|
|
if ($condition === T_CLASS || $condition === T_INTERFACE) {
|
|
$this->_classToken = $condPtr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Find the first doc comment.
|
|
$commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
|
|
$comment = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));
|
|
$this->_methodName = $phpcsFile->getDeclarationName($stackPtr);
|
|
|
|
try {
|
|
$this->commentParser = new PHP_CodeSniffer_CommentParser_FunctionCommentParser($comment, $phpcsFile);
|
|
$this->commentParser->parse();
|
|
} catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
|
|
$line = ($e->getLineWithinComment() + $commentStart);
|
|
$phpcsFile->addError($e->getMessage(), $line);
|
|
return;
|
|
}
|
|
|
|
$comment = $this->commentParser->getComment();
|
|
if (is_null($comment) === true) {
|
|
$error = 'Function doc comment is empty';
|
|
$phpcsFile->addError($error, $commentStart);
|
|
return;
|
|
}
|
|
|
|
$this->processParams($commentStart, $commentEnd);
|
|
// $this->processSince($commentStart, $commentEnd);
|
|
$this->processSees($commentStart);
|
|
$this->processReturn($commentStart, $commentEnd);
|
|
$this->processThrows($commentStart);
|
|
|
|
// Check for a comment description.
|
|
$short = $comment->getShortComment();
|
|
|
|
// No extra newline before short description.
|
|
$newlineCount = 0;
|
|
$newlineSpan = strspn($short, $phpcsFile->eolChar);
|
|
|
|
$newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);
|
|
|
|
// Exactly one blank line between short and long description.
|
|
$long = $comment->getLongComment();
|
|
if (empty($long) === false) {
|
|
$between = $comment->getWhiteSpaceBetween();
|
|
$newlineBetween = substr_count($between, $phpcsFile->eolChar);
|
|
|
|
$newlineCount += $newlineBetween;
|
|
|
|
$testLong = trim($long);
|
|
if (preg_match('|[A-Z]|', $testLong[0]) === 0) {
|
|
$error = 'Function comment long description must start with a capital letter';
|
|
$phpcsFile->addError($error, ($commentStart + $newlineCount));
|
|
}
|
|
}//end if
|
|
|
|
// Exactly one blank line before tags.
|
|
$params = $this->commentParser->getTagOrders();
|
|
if (count($params) > 1) {
|
|
$newlineSpan = $comment->getNewlineAfter();
|
|
if ($newlineSpan !== 2) {
|
|
$error = 'There must be exactly one blank line before the tags in function comment';
|
|
if ($long !== '') {
|
|
$newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
|
|
}
|
|
|
|
$phpcsFile->addError($error, ($commentStart + $newlineCount));
|
|
$short = rtrim($short, $phpcsFile->eolChar.' ');
|
|
}
|
|
}
|
|
|
|
$testShort = trim($short);
|
|
$lastChar = $testShort[(strlen($testShort) - 1)];
|
|
|
|
// Check for unknown/deprecated tags.
|
|
$unknownTags = $this->commentParser->getUnknown();
|
|
foreach ($unknownTags as $errorTag) {
|
|
$error = "@$errorTag[tag] tag is not allowed in function comment";
|
|
$phpcsFile->addWarning($error, ($commentStart + $errorTag['line']));
|
|
}
|
|
|
|
}//end process()
|
|
|
|
|
|
/**
|
|
* Process the since tag.
|
|
*
|
|
* @param int $commentStart The position in the stack where the comment started.
|
|
* @param int $commentEnd The position in the stack where the comment ended.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function processSince($commentStart, $commentEnd)
|
|
{
|
|
$since = $this->commentParser->getSince();
|
|
|
|
if ($since !== null) {
|
|
$errorPos = ($commentStart + $since->getLine());
|
|
$tagOrder = $this->commentParser->getTagOrders();
|
|
$firstTag = 0;
|
|
|
|
while ($tagOrder[$firstTag] === 'comment' || $tagOrder[$firstTag] === 'param') {
|
|
$firstTag++;
|
|
}
|
|
|
|
$this->_tagIndex = $firstTag;
|
|
$index = array_keys($this->commentParser->getTagOrders(), 'since');
|
|
if (count($index) > 1) {
|
|
$error = 'Only 1 @since tag is allowed in function comment';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
return;
|
|
}
|
|
|
|
if ($index[0] !== $firstTag) {
|
|
$error = 'The @since tag is in the wrong order; the tag preceds @see (if used) or @return';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
$content = $since->getContent();
|
|
if (empty($content) === true) {
|
|
$error = 'Version number missing for @since tag in function comment';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
return;
|
|
} else if ($content !== '%release_version%') {
|
|
if (preg_match('/^([0-9]+)\.([0-9]+)\.([0-9]+)/', $content) === 0) {
|
|
$error = 'Expected version number to be in the form x.x.x in @since tag';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
}
|
|
|
|
$spacing = substr_count($since->getWhitespaceBeforeContent(), ' ');
|
|
$return = $this->commentParser->getReturn();
|
|
$throws = $this->commentParser->getThrows();
|
|
$correctSpacing = ($return !== null || empty($throws) === false) ? 2 : 1;
|
|
|
|
if ($spacing !== $correctSpacing) {
|
|
$error = '@since tag indented incorrectly; ';
|
|
$error .= "expected $correctSpacing spaces but found $spacing.";
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
} else {
|
|
$error = 'Missing @since tag in function comment';
|
|
$this->currentFile->addError($error, $commentEnd);
|
|
}//end if
|
|
|
|
}//end processSince()
|
|
|
|
|
|
/**
|
|
* Process the see tags.
|
|
*
|
|
* @param int $commentStart The position in the stack where the comment started.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function processSees($commentStart)
|
|
{
|
|
$sees = $this->commentParser->getSees();
|
|
if (empty($sees) === false) {
|
|
$tagOrder = $this->commentParser->getTagOrders();
|
|
$index = array_keys($this->commentParser->getTagOrders(), 'see');
|
|
foreach ($sees as $i => $see) {
|
|
$errorPos = ($commentStart + $see->getLine());
|
|
$since = array_keys($tagOrder, 'since');
|
|
if (count($since) === 1 && $this->_tagIndex !== 0) {
|
|
$this->_tagIndex++;
|
|
if ($index[$i] !== $this->_tagIndex) {
|
|
$error = 'The @see tag is in the wrong order; the tag follows @since';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
}
|
|
|
|
$content = $see->getContent();
|
|
if (empty($content) === true) {
|
|
$error = 'Content missing for @see tag in function comment';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
continue;
|
|
}
|
|
|
|
$spacing = substr_count($see->getWhitespaceBeforeContent(), ' ');
|
|
if ($spacing !== 4) {
|
|
$error = '@see tag indented incorrectly; ';
|
|
$error .= "expected 4 spaces but found $spacing";
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
}//end foreach
|
|
}//end if
|
|
|
|
}//end processSees()
|
|
|
|
|
|
/**
|
|
* Process the return comment of this function comment.
|
|
*
|
|
* @param int $commentStart The position in the stack where the comment started.
|
|
* @param int $commentEnd The position in the stack where the comment ended.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function processReturn($commentStart, $commentEnd)
|
|
{
|
|
// Skip constructor and destructor.
|
|
$className = '';
|
|
if ($this->_classToken !== null) {
|
|
$className = $this->currentFile->getDeclarationName($this->_classToken);
|
|
$className = strtolower(ltrim($className, '_'));
|
|
}
|
|
|
|
$methodName = strtolower(ltrim($this->_methodName, '_'));
|
|
$isSpecialMethod = ($this->_methodName === '__construct' || $this->_methodName === '__destruct');
|
|
$return = $this->commentParser->getReturn();
|
|
|
|
if ($isSpecialMethod === false && $methodName !== $className) {
|
|
if ($return !== null) {
|
|
$tagOrder = $this->commentParser->getTagOrders();
|
|
$index = array_keys($tagOrder, 'return');
|
|
$errorPos = ($commentStart + $return->getLine());
|
|
$content = trim($return->getRawContent());
|
|
|
|
if (count($index) > 1) {
|
|
$error = 'Only 1 @return tag is allowed in function comment';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
return;
|
|
}
|
|
|
|
$since = array_keys($tagOrder, 'since');
|
|
if (count($since) === 1 && $this->_tagIndex !== 0) {
|
|
$this->_tagIndex++;
|
|
if ($index[0] !== $this->_tagIndex) {
|
|
$error = 'The @return tag is in the wrong order; the tag follows @see (if used) or @since';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
}
|
|
|
|
if (empty($content) === true) {
|
|
$error = 'Return type missing for @return tag in function comment';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
} else {
|
|
// Check return type (can be multiple, separated by '|').
|
|
$typeNames = explode('|', $content);
|
|
$suggestedNames = array();
|
|
foreach ($typeNames as $i => $typeName) {
|
|
$suggestedName = PHP_CodeSniffer::suggestType($typeName);
|
|
if (in_array($suggestedName, $suggestedNames) === false) {
|
|
$suggestedNames[] = $suggestedName;
|
|
}
|
|
}
|
|
|
|
$suggestedType = implode('|', $suggestedNames);
|
|
if ($content !== $suggestedType) {
|
|
$error = "Function return type \"$content\" is invalid";
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
$tokens = $this->currentFile->getTokens();
|
|
|
|
// If the return type is void, make sure there is
|
|
// no return statement in the function.
|
|
if ($content === 'null') {
|
|
if (isset($tokens[$this->_functionToken]['scope_closer']) === true) {
|
|
$endToken = $tokens[$this->_functionToken]['scope_closer'];
|
|
$return = $this->currentFile->findNext(T_RETURN, $this->_functionToken, $endToken);
|
|
if ($return !== false) {
|
|
// If the function is not returning anything, just
|
|
// exiting, then there is no problem.
|
|
$semicolon = $this->currentFile->findNext(T_WHITESPACE, ($return + 1), null, true);
|
|
if ($tokens[$semicolon]['code'] !== T_SEMICOLON) {
|
|
$error = 'Function return type is null, but function contains return statement';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
}
|
|
}
|
|
} else if ($content !== 'mixed') {
|
|
// If return type is not void, there needs to be a
|
|
// returns statement somewhere in the function that
|
|
// returns something.
|
|
if (isset($tokens[$this->_functionToken]['scope_closer']) === true) {
|
|
$endToken = $tokens[$this->_functionToken]['scope_closer'];
|
|
$return = $this->currentFile->findNext(T_RETURN, $this->_functionToken, $endToken);
|
|
if ($return === false) {
|
|
$error = 'Function return type is not null, but function has no return statement';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
} else {
|
|
$semicolon = $this->currentFile->findNext(T_WHITESPACE, ($return + 1), null, true);
|
|
if ($tokens[$semicolon]['code'] === T_SEMICOLON) {
|
|
$error = 'Function return type is not null, but function is returning void here';
|
|
$this->currentFile->addError($error, $return);
|
|
}
|
|
}
|
|
}
|
|
}//end if
|
|
}//end if
|
|
} else {
|
|
$error = 'Missing @return tag in function comment';
|
|
$this->currentFile->addError($error, $commentEnd);
|
|
}//end if
|
|
|
|
} else {
|
|
// No return tag for constructor and destructor.
|
|
if ($return !== null) {
|
|
$errorPos = ($commentStart + $return->getLine());
|
|
$error = '@return tag is not required for constructor and destructor';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
}//end if
|
|
|
|
}//end processReturn()
|
|
|
|
|
|
/**
|
|
* Process any throw tags that this function comment has.
|
|
*
|
|
* @param int $commentStart The position in the stack where the comment started.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function processThrows($commentStart)
|
|
{
|
|
if (count($this->commentParser->getThrows()) === 0) {
|
|
return;
|
|
}
|
|
|
|
$tagOrder = $this->commentParser->getTagOrders();
|
|
$index = array_keys($this->commentParser->getTagOrders(), 'throws');
|
|
|
|
foreach ($this->commentParser->getThrows() as $i => $throw) {
|
|
$exception = $throw->getValue();
|
|
$content = trim($throw->getComment());
|
|
$errorPos = ($commentStart + $throw->getLine());
|
|
if (empty($exception) === true) {
|
|
$error = 'Exception type and comment missing for @throws tag in function comment';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
} else if (empty($content) === true) {
|
|
$error = 'Comment missing for @throws tag in function comment';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
} else {
|
|
// Starts with a capital letter and ends with a fullstop.
|
|
$firstChar = $content{0};
|
|
if (strtoupper($firstChar) !== $firstChar) {
|
|
$error = '@throws tag comment must start with a capital letter';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
$lastChar = $content[(strlen($content) - 1)];
|
|
}
|
|
|
|
$since = array_keys($tagOrder, 'since');
|
|
if (count($since) === 1 && $this->_tagIndex !== 0) {
|
|
$this->_tagIndex++;
|
|
if ($index[$i] !== $this->_tagIndex) {
|
|
$error = 'The @throws tag is in the wrong order; the tag follows @return';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
}
|
|
}//end foreach
|
|
|
|
}//end processThrows()
|
|
|
|
|
|
/**
|
|
* Process the function parameter comments.
|
|
*
|
|
* @param int $commentStart The position in the stack where
|
|
* the comment started.
|
|
* @param int $commentEnd The position in the stack where
|
|
* the comment ended.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function processParams($commentStart, $commentEnd)
|
|
{
|
|
$realParams = $this->currentFile->getMethodParameters($this->_functionToken);
|
|
$params = $this->commentParser->getParams();
|
|
$foundParams = array();
|
|
|
|
if (empty($params) === false) {
|
|
|
|
// Parameters must appear immediately after the comment.
|
|
if ($params[0]->getOrder() !== 2) {
|
|
$error = 'Parameters must appear immediately after the comment';
|
|
$errorPos = ($params[0]->getLine() + $commentStart);
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
$previousParam = null;
|
|
$spaceBeforeVar = 10000;
|
|
$spaceBeforeComment = 10000;
|
|
$longestType = 0;
|
|
$longestVar = 0;
|
|
|
|
foreach ($params as $param) {
|
|
|
|
$paramComment = trim($param->getComment());
|
|
$errorPos = ($param->getLine() + $commentStart);
|
|
|
|
// Make sure that there is only one space before the var type.
|
|
if ($param->getWhitespaceBeforeType() !== ' ') {
|
|
$error = 'Expected 1 space before variable type';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
$spaceCount = substr_count($param->getWhitespaceBeforeVarName(), ' ');
|
|
if ($spaceCount < $spaceBeforeVar) {
|
|
$spaceBeforeVar = $spaceCount;
|
|
$longestType = $errorPos;
|
|
}
|
|
|
|
$spaceCount = substr_count($param->getWhitespaceBeforeComment(), ' ');
|
|
|
|
if ($spaceCount < $spaceBeforeComment && $paramComment !== '') {
|
|
$spaceBeforeComment = $spaceCount;
|
|
$longestVar = $errorPos;
|
|
}
|
|
|
|
// Make sure they are in the correct order, and have the correct name.
|
|
$pos = $param->getPosition();
|
|
$paramName = ($param->getVarName() !== '') ? $param->getVarName() : '[ UNKNOWN ]';
|
|
|
|
if ($previousParam !== null) {
|
|
$previousName = ($previousParam->getVarName() !== '') ? $previousParam->getVarName() : 'UNKNOWN';
|
|
|
|
// Check to see if the parameters align properly.
|
|
if ($param->alignsVariableWith($previousParam) === false) {
|
|
$error = 'The variable names for parameters '.$previousName.' ('.($pos - 1).') and '.$paramName.' ('.$pos.') do not align';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
if ($param->alignsCommentWith($previousParam) === false) {
|
|
$error = 'The comments for parameters '.$previousName.' ('.($pos - 1).') and '.$paramName.' ('.$pos.') do not align';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
}
|
|
|
|
// Variable must be one of the supported standard type.
|
|
$typeNames = explode('|', $param->getType());
|
|
foreach ($typeNames as $typeName) {
|
|
$suggestedName = PHP_CodeSniffer::suggestType($typeName);
|
|
if ($typeName !== $suggestedName) {
|
|
$error = "Expected \"$suggestedName\"; found \"$typeName\" for $paramName at position $pos";
|
|
$this->currentFile->addError($error, $errorPos);
|
|
} else if (count($typeNames) === 1) {
|
|
// Check type hint for array and custom type.
|
|
$suggestedTypeHint = '';
|
|
if (strpos($suggestedName, 'array') !== false) {
|
|
$suggestedTypeHint = 'array';
|
|
} else if (in_array($typeName, PHP_CodeSniffer::$allowedTypes) === false) {
|
|
$suggestedTypeHint = $suggestedName;
|
|
}
|
|
|
|
if ($suggestedTypeHint !== '' && isset($realParams[($pos - 1)]) === true) {
|
|
$typeHint = $realParams[($pos - 1)]['type_hint'];
|
|
if ($typeHint === '') {
|
|
$error = "Type hint \"$suggestedTypeHint\" missing for $paramName at position $pos";
|
|
$this->currentFile->addError($error, ($commentEnd + 2));
|
|
} else if ($typeHint !== $suggestedTypeHint) {
|
|
$error = "Expected type hint \"$suggestedTypeHint\"; found \"$typeHint\" for $paramName at position $pos";
|
|
$this->currentFile->addError($error, ($commentEnd + 2));
|
|
}
|
|
} else if ($suggestedTypeHint === '' && isset($realParams[($pos - 1)]) === true) {
|
|
$typeHint = $realParams[($pos - 1)]['type_hint'];
|
|
if ($typeHint !== '') {
|
|
$error = "Unknown type hint \"$typeHint\" found for $paramName at position $pos";
|
|
$this->currentFile->addError($error, ($commentEnd + 2));
|
|
}
|
|
}
|
|
}//end if
|
|
}//end foreach
|
|
|
|
// Make sure the names of the parameter comment matches the
|
|
// actual parameter.
|
|
if (isset($realParams[($pos - 1)]) === true) {
|
|
$realName = $realParams[($pos - 1)]['name'];
|
|
$foundParams[] = $realName;
|
|
|
|
// Append ampersand to name if passing by reference.
|
|
if ($realParams[($pos - 1)]['pass_by_reference'] === true) {
|
|
$realName = '&'.$realName;
|
|
}
|
|
|
|
if ($realName !== $param->getVarName()) {
|
|
$error = 'Doc comment var "'.$paramName;
|
|
$error .= '" does not match actual variable name "'.$realName;
|
|
$error .= '" at position '.$pos;
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
} else {
|
|
// We must have an extra parameter comment.
|
|
$error = 'Superfluous doc comment at position '.$pos;
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
if ($param->getVarName() === '') {
|
|
$error = 'Missing parameter name at position '.$pos;
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
if ($param->getType() === '') {
|
|
$error = 'Missing type at position '.$pos;
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
if ($paramComment === '') {
|
|
$error = 'Missing comment for param "'.$paramName.'" at position '.$pos;
|
|
$this->currentFile->addError($error, $errorPos);
|
|
} else {
|
|
// Param comments must start with a capital letter
|
|
$firstChar = $paramComment{0};
|
|
if (preg_match('|[A-Z]|', $firstChar) === 0) {
|
|
$error = 'Param comment must start with a capital letter';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
$lastChar = $paramComment[(strlen($paramComment) - 1)];
|
|
}
|
|
|
|
$previousParam = $param;
|
|
|
|
}//end foreach
|
|
|
|
if ($spaceBeforeVar !== 1 && $spaceBeforeVar !== 10000 && $spaceBeforeComment !== 10000) {
|
|
$error = 'Expected 1 space after the longest type';
|
|
$this->currentFile->addError($error, $longestType);
|
|
}
|
|
|
|
if ($spaceBeforeComment !== 1 && $spaceBeforeComment !== 10000) {
|
|
$error = 'Expected 1 space after the longest variable name';
|
|
$this->currentFile->addError($error, $longestVar);
|
|
}
|
|
|
|
}//end if
|
|
|
|
$realNames = array();
|
|
foreach ($realParams as $realParam) {
|
|
$realNames[] = $realParam['name'];
|
|
}
|
|
|
|
// Report missing comments.
|
|
$diff = array_diff($realNames, $foundParams);
|
|
foreach ($diff as $neededParam) {
|
|
if (count($params) !== 0) {
|
|
$errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart);
|
|
} else {
|
|
$errorPos = $commentStart;
|
|
}
|
|
|
|
$error = 'Doc comment for "'.$neededParam.'" missing';
|
|
$this->currentFile->addError($error, $errorPos);
|
|
}
|
|
|
|
}//end processParams()
|
|
|
|
|
|
}//end class
|
|
|
|
?>
|