/** * Process the function parameter comments. * * @param int $commentStart The position in the stack where * the comment started. * * @return void */ protected function processParams($commentStart, $commentEnd, $tagElements) { $realParams = $this->currentFile->getMethodParameters($this->_functionToken); $params = $this->commentParser->getParams(); $foundParams = array(); if (empty($params) === false) { $lastParm = count($params) - 1; if (substr_count($params[$lastParm]->getWhitespaceAfter(), $this->currentFile->eolChar) !== 2) { $error = 'Last parameter comment requires a blank newline after it'; $errorPos = $params[$lastParm]->getLine() + $commentStart; $this->currentFile->addError($this->getReqPrefix('REQ.PHP.4.1.20') . $error, $errorPos); } // 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($this->getReqPrefix('REQ.PHP.4.1.21') . $error, $errorPos); } $previousParam = null; $spaceBeforeVar = 10000; $spaceBeforeComment = 10000; $longestType = 0; $longestVar = 0; foreach ($params as $param) { $paramComment = trim($param->getComment()); $errorPos = $param->getLine() + $commentStart; // Check type $r = $this->checkType($param->getType(), $this->allowedParamTypes, 'param'); if (true !== $r) { $this->currentFile->addError($this->getReqPrefix('REQ.PHP.3.5.15') . $r, $errorPos); } // 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($this->getReqPrefix('REQ.PHP.4.1.22') . $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($this->getReqPrefix('REQ.PHP.4.1.23') . $error, $errorPos); } if ($param->alignsCommentWith($previousParam) === false) { $error = 'The comments for parameters ' . $previousName . ' (' . ($pos - 1) . ') and ' . $paramName . ' (' . $pos . ') do not align'; $this->currentFile->addError($this->getReqPrefix('REQ.PHP.4.1.24') . $error, $errorPos); } } //end if // 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($this->getReqPrefix('REQ.PHP.4.1.25') . $error, $errorPos); } if (isset($realParams[$pos - 1]['default']) && !preg_match('/ OPTIONAL$/Ss', $paramComment)) { $this->currentFile->addError($this->getReqPrefix('REQ.PHP.3.5.18') . 'Переменная "' . $paramName . '" опциональная, но служебного тэга OPTIONAL ее комментарий не имеет', $errorPos); } } else { // We must have an extra parameter comment. $error = 'Superfluous doc comment at position ' . $pos; $this->currentFile->addError($this->getReqPrefix('REQ.PHP.4.1.27') . $error, $errorPos); } if ($param->getVarName() === '') { $error = 'Missing parameter name at position ' . $pos; $this->currentFile->addError($this->getReqPrefix('REQ.PHP.4.1.26') . $error, $errorPos); } if ($param->getType() === '') { $error = 'Missing type at position ' . $pos; $this->currentFile->addError($this->getReqPrefix('REQ.PHP.4.1.26') . $error, $errorPos); } if ($paramComment === '') { $error = 'Missing comment for param "' . $paramName . '" at position ' . $pos; $this->currentFile->addError($this->getReqPrefix('REQ.PHP.4.1.26') . $error, $errorPos); } elseif (preg_match('/^[a-z]/Ss', trim($paramComment))) { $error = 'Комментарий параметра "' . $paramName . '" начинается с маленькой буквы'; $this->currentFile->addError($this->getReqPrefix('REQ.PHP.4.5.8') . $error, $errorPos); } $this->checkForDefaultValue($paramName, 'param', $errorPos); $this->checkForDefaultValue($paramComment, 'param', $errorPos); $previousParam = $param; } //end foreach if ($spaceBeforeVar !== 1 && $spaceBeforeVar !== 10000 && $spaceBeforeComment !== 10000) { $error = 'Expected 1 space after the longest type'; $this->currentFile->addError($this->getReqPrefix('?') . $error, $longestType); } if ($spaceBeforeComment !== 1 && $spaceBeforeComment !== 10000) { $error = 'Expected 1 space after the longest variable name'; $this->currentFile->addError($this->getReqPrefix('?') . $error, $longestVar); } } //end if $realNames = array(); foreach ($realParams as $realParam) { $realNames[] = $realParam['name']; } // Report and 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($this->getReqPrefix('REQ.PHP.4.1.27') . $error, $errorPos); } }