The format of the array is:
array(
'scope' => 'public', // public private or protected
'scope_specified' => true, // true is scope keyword was found.
'is_abstract' => false, // true if the abstract keyword was found.
'is_final' => false, // true if the final keyword was found.
'is_static' => false, // true if the static keyword was found.
'is_closure' => false, // true if no name is found.
);
public getMethodProperties ( integer $stackPtr ) : array | ||
$stackPtr | integer | The position in the stack of the T_FUNCTION token to acquire the properties for. |
return | array |
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); $errorData = array($className . '::' . $methodName); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->magicMethods) === false) { $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); } return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; // Methods should not contain underscores. if (strpos($methodName, '_') !== false) { if ($scopeSpecified === true) { $error = '%s method name "%s" is not in lowerCamel format, it must not contain underscores'; $data = array(ucfirst($scope), $errorData[0]); $phpcsFile->addError($error, $stackPtr, 'ScopeNotLowerCamel', $data); } else { $error = 'Method name "%s" is not in lowerCamel format, it must not contain underscores'; $phpcsFile->addError($error, $stackPtr, 'NotLowerCamel', $errorData); } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The current file being scanned. * @param integer $stackPtr The position of the current token in the * stack passed in $tokens. * @param integer $currScope A pointer to the start of the scope. * * @return void */ public function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $tokens = $phpcsFile->getTokens(); $function = $tokens[$stackPtr + 2]; if ($function['code'] !== T_STRING) { return; } $functionName = $function['content']; $classOpener = $tokens[$currScope]['scope_condition']; $className = $tokens[$classOpener + 2]['content']; $methodProps = $phpcsFile->getMethodProperties($stackPtr); if ($methodProps['is_static'] === true) { if (isset($tokens[$stackPtr]['scope_closer']) === false) { // There is no scope opener or closer, so the function // must be abstract. return; } $thisUsage = $stackPtr; while (($thisUsage = $phpcsFile->findNext(array(T_VARIABLE), $thisUsage + 1, $tokens[$stackPtr]['scope_closer'], false, '$this')) !== false) { if ($thisUsage === false) { return; } $error = 'Usage of "$this" in static methods will cause runtime errors'; $phpcsFile->addError($error, $thisUsage, 'Found'); } //while } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsfile The file being processed. * @param int $stackptr The position where this token was * found. * @param int $currscope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsfile, $stackptr, $currscope) { $classname = $phpcsfile->getDeclarationName($currscope); $methodname = $phpcsfile->getDeclarationName($stackptr); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodname) !== 0) { $magicpart = substr($methodname, 2); if (!in_array($magicpart, $this->magicmethods)) { $error = "method name \"{$classname}::{$methodname}\" is invalid; " . 'only PHP magic methods should be prefixed with a double underscore'; $phpcsfile->addError($error, $stackptr); } return; } $methodprops = $phpcsfile->getMethodProperties($stackptr); $scope = $methodprops['scope']; $scopespecified = $methodprops['scope_specified']; // Only lower-case accepted if (preg_match('/[A-Z]+/', $methodname) && !in_array($methodname, $this->permittedmethods)) { if ($scopespecified === true) { $error = ucfirst($scope) . ' method name "' . $classname . '::' . $methodname . '" must be in lower-case letters only'; } else { $error = 'method name "' . $classname . '::' . $methodname . '" must be in lower-case letters only'; } $phpcsfile->adderror($error, $stackptr); return; } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void * @see PHP_CodeSniffer_Sniff::process() */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $token = $tokens[$stackPtr]['content']; // Only accept class member functions if (false === $phpcsFile->hasCondition($stackPtr, T_CLASS)) { return; } $nextTokenIndex = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); $methodName = $tokens[$nextTokenIndex]['content']; $methodProperties = $phpcsFile->getMethodProperties($stackPtr); switch ($methodName) { case '__call': $this->_checkCall($phpcsFile, $stackPtr, $methodName, $methodProperties); break; case '__get': $this->_checkGet($phpcsFile, $stackPtr, $methodName, $methodProperties); break; case '__isset': $this->_checkIsset($phpcsFile, $stackPtr, $methodName, $methodProperties); break; case '__set': $this->_checkSet($phpcsFile, $stackPtr, $methodName, $methodProperties); break; case '__toString': $this->_checkToString($phpcsFile, $stackPtr, $methodName, $methodProperties); break; case '__unset': $this->_checkUnset($phpcsFile, $stackPtr, $methodName, $methodProperties); break; default: break; } }
protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $className = $phpcsFile->getDeclarationName($currScope); $methodName = $phpcsFile->getDeclarationName($stackPtr); // Only magic methods should be prefixed with "__" if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->magicMethods) === false) { $error = sprintf("Method name \"%s::%s\" is invalid; only PHP magic methods should be prefixed with a double underscore", $className, $methodName); $phpcsFile->addError($error, $stackPtr); } return; } // There should be given a valid scope $methodProperties = $phpcsFile->getMethodProperties($stackPtr); if ($methodProperties['scope_specified'] !== true) { $error = sprintf("No scope declaration for method \"%s::%s\" found", $className, $methodName); $phpcsFile->addWarning($error, $stackPtr); return; } // Method names should be camel-cased and not underscored if (PHP_CodeSniffer::isCamelCaps($methodName, false, true, false) === false) { $error = sprintf("Method name \"%s::%s\" is not in camel caps format", $className, $methodName); $phpcsFile->addError($error, $stackPtr); return; } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); $errorData = array($className . '::' . $methodName); // Is this a magic method. i.e., is prefixed with "__" ? if (preg_match('|^__|', $methodName) !== 0) { $magicPart = strtolower(substr($methodName, 2)); if (isset($this->magicMethods[$magicPart]) === false && isset($this->methodsDoubleUnderscore[$magicPart]) === false) { $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); } return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); if (PHP_CodeSniffer::isCamelCaps($methodName, false, true, $this->strict) === false) { if ($methodProps['scope_specified'] === true) { $error = '%s method name "%s" is not in lowerCamel format'; $data = array(ucfirst($methodProps['scope']), $errorData[0]); $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); } else { $error = 'Method name "%s" is not in lowerCamel format'; $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); } $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no'); return; } else { $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $className = $phpcsFile->getDeclarationName($currScope); $methodName = $phpcsFile->getDeclarationName($stackPtr); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->_magicMethods) === false) { $error = "Method name \"{$className}::{$methodName}\" is invalid; only PHP magic methods should be prefixed with a double underscore"; $phpcsFile->addError($error, $stackPtr); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $isPublic = $methodProps['scope'] === 'public' ? true : false; $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; // If it's a private method, it must have an underscore on the front. if ($isPublic === false && $methodName[0] !== '_') { $error = ucfirst($scope) . " method name \"{$className}::{$methodName}\" must be prefixed with an underscore"; $phpcsFile->addError($error, $stackPtr); return; } // If it's not a private method, it must not have an underscore on the front. if ($isPublic === true && $scopeSpecified === true && $methodName[0] === '_') { $error = "Public method name \"{$className}::{$methodName}\" must not be prefixed with an underscore"; $phpcsFile->addError($error, $stackPtr); return; } // If the scope was specified on the method, then the method must be // camel caps and an underscore should be checked for. If it wasn't // specified, treat it like a public method and remove the underscore // prefix if there is one because we cant determine if it is private or // public. $testMethodName = $methodName; if ($scopeSpecified === false && $methodName[0] === '_') { $testMethodName = substr($methodName, 1); } if (PHP_CodeSniffer::isCamelCaps($testMethodName, false, $isPublic, false) === false) { if ($scopeSpecified === true) { $error = ucfirst($scope) . " method name \"{$className}::{$methodName}\" is not in camel caps format"; } else { $error = "Method name \"{$className}::{$methodName}\" is not in camel caps format"; } $phpcsFile->addError($error, $stackPtr); return; } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in the * stack passed in $tokens.. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['code'] === T_FUNCTION) { $methodProps = $phpcsFile->getMethodProperties($stackPtr); // Abstract methods do not require a closing comment. if ($methodProps['is_abstract'] === true) { return; } // Closures do not require a closing comment. if ($methodProps['is_closure'] === true) { return; } // If this function is in an interface then we don't require // a closing comment. if ($phpcsFile->hasCondition($stackPtr, T_INTERFACE) === true) { return; } if (isset($tokens[$stackPtr]['scope_closer']) === false) { $error = 'Possible parse error: non-abstract method defined as abstract'; $phpcsFile->addWarning($error, $stackPtr); return; } $decName = $phpcsFile->getDeclarationName($stackPtr); $comment = '//end ' . $decName . '()'; } else { if ($tokens[$stackPtr]['code'] === T_CLASS) { $comment = '//end class'; } else { $comment = '//end interface'; } } //end if if (isset($tokens[$stackPtr]['scope_closer']) === false) { $error = 'Possible parse error: '; $error .= $tokens[$stackPtr]['content']; $error .= ' missing opening or closing brace'; $phpcsFile->addWarning($error, $stackPtr); return; } $closingBracket = $tokens[$stackPtr]['scope_closer']; if ($closingBracket === null) { // Possible inline structure. Other tests will handle it. return; } $error = 'Expected ' . $comment; if (isset($tokens[$closingBracket + 1]) === false || $tokens[$closingBracket + 1]['code'] !== T_COMMENT) { $phpcsFile->addError($error, $closingBracket); return; } if (rtrim($tokens[$closingBracket + 1]['content']) !== $comment) { $phpcsFile->addError($error, $closingBracket); return; } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param integer $stackPtr The position where this token was found. * @param integer $currScope The position of the current scope. * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); $errorData = array($className . '::' . $methodName); // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } // Ignore magic methods if (preg_match('/^__(' . implode('|', $this->_magicMethods) . ')$/', $methodName)) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); if ($methodProps['scope_specified'] === false) { // Let another sniffer take care of that return; } $isPublic = $methodProps['scope'] === 'public'; $isProtected = $methodProps['scope'] === 'protected'; $isPrivate = $methodProps['scope'] === 'private'; $scope = $methodProps['scope']; if ($isPublic === true) { if ($methodName[0] === '_') { $error = 'Public method name "%s" must not be prefixed with underscore'; $phpcsFile->addError($error, $stackPtr, 'PublicWithUnderscore', $errorData); return; } // Underscored public methods in controller are allowed to break our rules. if (substr($className, -10) === 'Controller') { return; } // Underscored public methods in shells are allowed to break our rules. if (substr($className, -5) === 'Shell') { return; } // Underscored public methods in tasks are allowed to break our rules. if (substr($className, -4) === 'Task') { return; } } elseif ($isPrivate === true) { $filename = $phpcsFile->getFilename(); $warning = 'Private method name "%s" in CakePHP core is discouraged'; $phpcsFile->addWarning($warning, $stackPtr, 'PrivateMethodInCore', $errorData); } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $methodName = $phpcsFile->getDeclarationName($stackPtr); $methodProps = $phpcsFile->getMethodProperties($stackPtr); if ($methodProps['is_static']) { if (!PHP_CodeSniffer_Standards_Silverstripe_SilverstripeCodingStandard::isLowerCaseWithUnderScore($methodName)) { $error = "Function name \"{$methodName}\" is invalid Static methods should be in lowercase_with_underscores() format."; $phpcsFile->addError($error, $stackPtr); } } else { } }
/** * Check if a method is a PHPUnit test class method. * @param int $stackPtr * @return bool */ public function isTestClassMethod($stackPtr) { if (!array_key_exists($stackPtr, $this->testClassMethods)) { $this->testClassMethods[$stackPtr] = false; if ($this->isTestClass($stackPtr)) { $props = $this->phpcsFile->getMethodProperties($stackPtr); if ('public' == $props['scope'] && !$props['is_abstract'] && !$props['is_closure'] && stripos($this->phpcsFile->getDeclarationName($stackPtr), 'test') === 0) { $this->testClassMethods[$stackPtr] = true; } } } return $this->testClassMethods[$stackPtr]; }
/** * {@inheritdoc} */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { if (false === ($commentEnd = $phpcsFile->findPrevious(array(T_COMMENT, T_DOC_COMMENT, T_CLASS, T_FUNCTION, T_OPEN_TAG), $stackPtr - 1))) { return; } $tokens = $phpcsFile->getTokens(); $code = $tokens[$commentEnd]['code']; $method = $phpcsFile->getMethodProperties($stackPtr); $commentRequired = $this->isRequiredScope($method['scope']); if ($code === T_COMMENT && !$commentRequired || $code !== T_DOC_COMMENT && !$commentRequired) { return; } parent::process($phpcsFile, $stackPtr); }
/** * Override parent function to allow custom code validation * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->magicMethods) === false) { $error = "Method name \"{$className}::{$methodName}\" is invalid; only PHP magic methods should be prefixed with a double underscore"; $phpcsFile->addError($error, $stackPtr); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $isPublic = $methodProps['scope'] === 'private' ? false : true; $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; // If it's a private method, it must have an underscore on the front. if ($isPublic === false && $methodName[0] !== '_') { $error = "Private method name \"{$className}::{$methodName}\" must be prefixed with an underscore"; $phpcsFile->addError($error, $stackPtr); return; } // We want to allow private and protected methods to start with an underscore $testMethodName = $methodName; if (($scopeSpecified === false || $scope == 'protected') && $methodName[0] === '_') { $testMethodName = substr($methodName, 1); } if (PHP_CodeSniffer::isCamelCaps($testMethodName, false, $isPublic, false) === false) { if ($scopeSpecified === true) { $error = ucfirst($scope) . " method name \"{$className}::{$methodName}\" is not in camel caps format"; } else { $error = "Method name \"{$className}::{$methodName}\" is not in camel caps format"; } $phpcsFile->addError($error, $stackPtr); return; } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); $errorData = array($className . '::' . $methodName); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = strtolower(substr($methodName, 2)); if (in_array($magicPart, $this->magicMethods) === false) { $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); } return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; // If it's not a private method, it must not have an underscore on the front. if ($scopeSpecified === true && $methodName[0] === '_') { $error = '%s method name "%s" must not be prefixed with an underscore'; $data = array(ucfirst($scope), $errorData[0]); $phpcsFile->addError($error, $stackPtr, 'MethodUnderscore', $data); return; } // If the scope was specified on the method, then the method must be // camel caps and an underscore should be checked for. If it wasn't // specified, treat it like a public method and remove the underscore // prefix if there is one because we cant determine if it is private or // public. $testMethodName = $methodName; if ($scopeSpecified === false && $methodName[0] === '_') { $testMethodName = substr($methodName, 1); } if (PHP_CodeSniffer::isCamelCaps($testMethodName, false, true, false) === false) { if ($scopeSpecified === true) { $error = '%s method name "%s" is not in camel caps format'; $data = array(ucfirst($scope), $errorData[0]); $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); } else { $error = 'Method name "%s" is not in camel caps format'; $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); } return; } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { if (false === ($commentEnd = $phpcsFile->findPrevious(array(T_COMMENT, T_DOC_COMMENT, T_CLASS, T_FUNCTION, T_OPEN_TAG), $stackPtr - 1))) { return; } $tokens = $phpcsFile->getTokens(); $code = $tokens[$commentEnd]['code']; // a comment is not required on protected/private methods $method = $phpcsFile->getMethodProperties($stackPtr); $commentRequired = in_array($method['scope'], array('public', 'protected', 'private')); if ($code === T_COMMENT && !$commentRequired || $code !== T_DOC_COMMENT && !$commentRequired) { return; } parent::process($phpcsFile, $stackPtr); }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $className = $phpcsFile->getDeclarationName($currScope); $methodName = $phpcsFile->getDeclarationName($stackPtr); $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr + 1]['code'] == T_WHITESPACE && $tokens[$stackPtr + 2]['code'] == T_OPEN_PARENTHESIS) { // \Closure instance return; } // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->_magicMethods) === false) { $error = "Method name \"{$className}::{$methodName}\" is invalid; only PHP magic methods should be prefixed with a double underscore"; $phpcsFile->addError($this->getReqPrefix('?') . $error, $stackPtr); } return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $isPublic = $methodProps['scope'] === 'private' ? false : true; $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; if ($this->isReserverMethodName($methodName)) { return; } $words = $this->getWordsByCapitalLetter($methodName); $fBit = array_shift($words); if (!$this->checkLowWord($fBit)) { $error = ucfirst($scope) . " method name \"{$className}::{$methodName}\" is not in camel caps format"; $phpcsFile->addError($this->getReqPrefix('REQ.PHP.1.4.1') . $error, $stackPtr); } if (!$this->checkVerb($fBit)) { $tokens = $phpcsFile->getTokens(); $error = ucfirst($scope) . " method name \"{$className}::{$methodName}\" is not in verb form"; $phpcsFile->addError($this->getReqPrefix('REQ.PHP.1.4.2') . $error, $stackPtr); } foreach ($words as $wk => $w) { $res = $this->checkCamelWord($w); if ($res == -2) { $error = "Часть '" . $w . "' из слова '" . $methodName . "' не валидна и возможно является аббревиатурой, о которой валидатор не знает. Аббревиатура должна быть зарегестрирована в массиве abbrs."; $phpcsFile->addError($this->getReqPrefix('REQ.PHP.1.2.1') . $error, $stackPtr); } elseif ($res < 0 && (!isset($words[$wk + 1]) || !in_array($w . $words[$wk + 1], $this->twoWordsAbbrs))) { $error = ucfirst($scope) . " method name \"{$className}::{$methodName}\" is not in camel caps format"; $phpcsFile->addError($this->getReqPrefix('REQ.PHP.1.4.1') . $error, $stackPtr); } } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $className = $phpcsFile->getDeclarationName($currScope); $methodName = $phpcsFile->getDeclarationName($stackPtr); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->_magicMethods) === false) { $error = "Method name \"{$className}::{$methodName}\" is invalid; only PHP magic methods should be prefixed with a double underscore"; $phpcsFile->addError($error, $stackPtr); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; if ($methodProps['scope'] === 'private') { $isPublic = false; } else { $isPublic = true; } // If the scope was specified on the method, then the method must be // camel caps and an underscore should be checked for. If it wasn't // specified, treat it like a public method and remove the underscore // prefix if there is one because we can't determine if it is private or // public. $testMethodName = $methodName; if ($scopeSpecified === false && $methodName[0] === '_') { $testMethodName = substr($methodName, 1); } if (strtolower($testMethodName) !== $testMethodName) { $suggested = preg_replace('/([A-Z])/', '_$1', $methodName); $suggested = strtolower($suggested); $suggested = str_replace('__', '_', $suggested); $error = "Function name \"{$methodName}\" is in camel caps format, try '" . $suggested . "'"; $phpcsFile->addError($error, $stackPtr); } }
/** * @param int $stackPtr * @param PHP_CodeSniffer_File $phpcsFile * * @return array */ protected function getMethods($stackPtr, $phpcsFile) { $methods = []; $classEnd = $phpcsFile->findEndOfStatement($stackPtr); while ($stackPtr < $classEnd) { $function = $phpcsFile->findNext([T_FUNCTION], $stackPtr, null); if (false === $function) { break; } $stackPtr = $function + 1; if (in_array($phpcsFile->getDeclarationName($function), ['setUp', 'tearDown'])) { continue; } $methodProperties = $phpcsFile->getMethodProperties($function); $methods[$methodProperties['scope']][] = $function; } return $methods; }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $whitelistedNames = ['__construct', 'setUp', 'tearDown', 'getMatchers', 'getIterator']; $tokens = $phpcsFile->getTokens(); $methodProperties = $phpcsFile->getMethodProperties($stackPtr); if ($methodProperties['scope'] == 'public') { $namePtr = $phpcsFile->findNext(T_STRING, $stackPtr + 1, $tokens[$stackPtr]['parenthesis_opener']); $name = $tokens[$namePtr]['content']; if (in_array($name, $whitelistedNames)) { return; } if (substr($name, 0, 3) == 'set' && ctype_upper(substr($name, 3, 1))) { $phpcsFile->addWarning(sprintf('Public setter "%s" starts with "set". Write a name that express a domain behavior', $name), $stackPtr, 'Invalid'); } if (substr($name, 0, 3) == 'get' && ctype_upper(substr($name, 3, 1))) { $phpcsFile->addWarning(sprintf('Public getter "%s" starts with "get". Write a name that express a domain behavior', $name), $stackPtr, 'Invalid'); } } }
/** * Processes the token in the specified PHP_CodeSniffer_File. * * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found. * @param int $stackPtr The position where the token was found. * @param array $currScope The current scope opener token. * * @return void */ protected final function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { if ($this->currentFile !== $phpcsFile) { $this->currentFile = $phpcsFile; $this->_functionOpen = false; $this->_endFunction = -1; } $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['code'] === T_FUNCTION) { $this->_functionOpen = true; $methodProps = $phpcsFile->getMethodProperties($stackPtr); // If the function is abstract, or is in an interface, // then set the end of the function to it's closing semicolon. if ($methodProps['is_abstract'] === true || $tokens[$currScope]['code'] === T_INTERFACE) { $this->_endFunction = $phpcsFile->findNext(array(T_SEMICOLON), $stackPtr); } else { $this->_endFunction = $tokens[$stackPtr]['scope_closer']; } } else { if ($stackPtr > $this->_endFunction) { $this->_functionOpen = false; } } if ($this->_functionOpen === true) { if ($tokens[$stackPtr]['code'] === T_VARIABLE) { $this->processVariable($phpcsFile, $stackPtr); } else { if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING) { // Check to see if this string has a variable in it. if (preg_match('|[^\\\\]\\$[a-zA-Z0-9_]+|', $tokens[$stackPtr]['content']) !== 0) { $this->processVariableInString($phpcsFile, $stackPtr); } } } return; } else { // What if we assign a member variable to another? // ie. private $_count = $this->_otherCount + 1;. $this->processMemberVar($phpcsFile, $stackPtr); } }
/** * Processes the tokens that this sniff is interested in. * * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found. * @param int $stackPtr The position in the stack where * the token was found. * * @return void * @see PHP_CodeSniffer_Sniff::process() */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $token = $tokens[$stackPtr]['content']; // Only accept class member functions if (false === $phpcsFile->hasCondition($stackPtr, T_CLASS)) { return; } $nextTokenIndex = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); $methodName = $tokens[$nextTokenIndex]['content']; $methodProperties = $phpcsFile->getMethodProperties($stackPtr); if (true === $methodProperties['is_abstract']) { // Warning for abstract static declared functions if (true === $methodProperties['is_static']) { $warning = sprintf('Abstract function "%s" should not be declared static!', $methodName); $phpcsFile->addWarning($warning, $stackPtr); } // Error for static abstract declared functions if ('private' === $methodProperties['scope']) { $error = sprintf('Abstract function "%s" can not be declared private!', $methodName); $phpcsFile->addError($error, $stackPtr); } } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $className = $phpcsFile->getDeclarationName($currScope); $methodName = $phpcsFile->getDeclarationName($stackPtr); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->_magicMethods) === false) { $phpcsFile->addError('La fonction de nom "' . $className . '::' . $methodName . '" est invalide, seules les méthodes PHP magic methods doivent être préfixés par un double souligné', $stackPtr, 'NameInvalidMagicMethodValidFunction'); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $isPublic = $methodProps['scope'] === 'private' ? false : true; $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; // // If it's a private method, it must have an underscore on the front. // if ($isPublic === false && $methodName{0} !== '_') { // $error = "Private method name \"$className::$methodName\" must be prefixed with an underscore"; // $phpcsFile->addError($error, $stackPtr); // return; // } // // // If it's not a private method, it must not have an underscore on the front. // if ($isPublic === true && $scopeSpecified === true && $methodName{0} === '_') { // $error = ucfirst($scope)." method name \"$className::$methodName\" must not be prefixed with an underscore"; // $phpcsFile->addError($error, $stackPtr); // return; // } // If the scope was specified on the method, then the method must be // camel caps and an underscore should be checked for. If it wasn't // specified, treat it like a public method and remove the underscore // prefix if there is one because we cant determine if it is private or // public. $testMethodName = $methodName; if ($scopeSpecified === false && $methodName[0] === '_') { $testMethodName = substr($methodName, 1); } if (PHP_CodeSniffer::isCamelCaps($testMethodName, false, $isPublic, false) === false) { if ($scopeSpecified === true) { $phpcsFile->addError('La méthode ' . ucfirst($scope) . ' "' . $className . '::' . $methodName . '" n\'est pas au format camelCase', $stackPtr, 'ScopeMethodNameNotCamelValidFunction'); } else { $phpcsFile->addError('La méthode "' . $className . '::' . $methodName . '" n\'est pas au format camelCase', $stackPtr, 'MethodNameNotCamelValidFunction'); } return; } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); // Is this a magic method i.e. is prefixed with "__". if (0 === strcmp(substr($methodName, 0, 2), '__')) { $magicPart = substr($methodName, 2); if (in_array($magicPart, self::$magicMethods) === false) { $error = "Method name \"{$className}::{$methodName}\" is invalid; only PHP magic methods should be prefixed with a double underscore"; $phpcsFile->addError($error, $stackPtr); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } if (0 !== strcmp($methodName, strtolower($methodName))) { $uscrdMethodName = preg_replace('/([A-Z])/', '_${1}', $methodName); $expectedMethodName = strtolower($uscrdMethodName); $error = "Class methods should be entirely lowercased. Please consider \"{$expectedMethodName}\" instead of \"{$methodName}\"."; $phpcsFile->addError($error, $stackPtr); return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; // If it's a private method, it must have an underscore on the front. if ($scope === 'private' && $methodName[0] !== '_') { $error = "Private method name \"{$className}::{$methodName}\" must be prefixed with an underscore"; $phpcsFile->addError($error, $stackPtr); return; } // If it's not a private method, it must not have an underscore on the front. if ($scope !== 'private' && $methodName[0] === '_') { if (true === $scopeSpecified) { $error = "Public method name \"{$className}::{$methodName}\" must not be prefixed with an underscore"; } else { $error = ucfirst($scope) . " method name \"{$className}::{$methodName}\" must not be prefixed with an underscore"; } $phpcsFile->addError($error, $stackPtr); return; } // If name is too verbose, // then either an error or a warning is displayed. $error_limit = 50; $warning_limit = 35; if (strlen($methodName) > $error_limit) { $error = "Overly long and verbose names are prohibited. Please find a name shorter than {$error_limit} chars."; $phpcsFile->addError($error, $stackPtr); return; } else { if (strlen($methodName) > $warning_limit) { $warning = "Try to avoid overly long and verbose names in finding a name shorter than {$warning_limit} chars."; $phpcsFile->addWarning($warning, $stackPtr); } } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $className = $phpcsFile->getDeclarationName($currScope); $methodName = $phpcsFile->getDeclarationName($stackPtr); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->_magicMethods) === false) { $phpcsFile->addEvent('NAME_INVALID_MAGIC_METHOD_VALID_FUNCTION', array('methodname' => "{$className}::{$methodName}"), $stackPtr); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $isPublic = $methodProps['scope'] === 'private' ? false : true; $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; // // If it's a private method, it must have an underscore on the front. // if ($isPublic === false && $methodName{0} !== '_') { // $error = "Private method name \"$className::$methodName\" must be prefixed with an underscore"; // $phpcsFile->addError($error, $stackPtr); // return; // } // // // If it's not a private method, it must not have an underscore on the front. // if ($isPublic === true && $scopeSpecified === true && $methodName{0} === '_') { // $error = ucfirst($scope)." method name \"$className::$methodName\" must not be prefixed with an underscore"; // $phpcsFile->addError($error, $stackPtr); // return; // } // If the scope was specified on the method, then the method must be // camel caps and an underscore should be checked for. If it wasn't // specified, treat it like a public method and remove the underscore // prefix if there is one because we cant determine if it is private or // public. $testMethodName = $methodName; if ($scopeSpecified === false && $methodName[0] === '_') { $testMethodName = substr($methodName, 1); } if (PHP_CodeSniffer::isCamelCaps($testMethodName, false, $isPublic, false) === false) { if ($scopeSpecified === true) { $phpcsFile->addEvent('SCOPE_METHOD_NAME_NOT_CAMEL_VALID_FUNCTION', array('scope' => ucfirst($scope), 'methodname' => "{$className}::{$methodName}"), $stackPtr); } else { $phpcsFile->addEvent('METHOD_NAME_NOT_CAMEL_VALID_FUNCTION', array('methodname' => "{$className}::{$methodName}"), $stackPtr); } return; } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); $errorData = array($className . '::' . $methodName); // Is this a magic method. i.e., is prefixed with "__" ? if (preg_match('|^__|', $methodName) !== 0) { $magicPart = strtolower(substr($methodName, 2)); if (in_array($magicPart, array_merge($this->magicMethods, $this->methodsDoubleUnderscore)) === false) { $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } // Ignore first underscore in methods prefixed with "_" $methodName = ltrim($methodName, '_'); $methodProps = $phpcsFile->getMethodProperties($stackPtr); if (PHP_CodeSniffer::isCamelCaps($methodName, false, true, $this->strict) === false) { if ($methodProps['scope_specified'] === true) { $error = '%s method name "%s" is not in camel caps format'; $data = array(ucfirst($methodProps['scope']), $errorData[0]); $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); } else { $error = 'Method name "%s" is not in camel caps format'; $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); } return; } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); $errorData = array($className . '::' . $methodName); // Is this a magic method. i.e., is prefixed with "__" ? if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->magicMethods) === false) { $error = 'Method name "%s" is invalid; ' . 'only PHP magic methods should be prefixed with a ' . 'double underscore'; $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); if ($methodProps['scope_specified'] !== true) { $error = 'Method visibility scope must be specified for "%s".'; $phpcsFile->addError($error, $stackPtr, 'VisibilityScope', $errorData); } // check underscore format and visibility scope if (static::isUnderscoreName($methodName) === false) { if ($methodProps['scope_specified'] === true) { $error = '%s method name "%s" does not use underscore format. ' . 'Upper case forbidden.'; $data = array(ucfirst($methodProps['scope']), $errorData[0]); $phpcsFile->addError($error, $stackPtr, 'ScopeNotUnderscore', $data); } else { $error = 'Method name "%s" does not use underscore format. ' . 'Upper case forbidden.'; $phpcsFile->addError($error, $stackPtr, 'NotUnderscore', $errorData); } return; } }
/** * Processes the tokens within the scope. * * Extends PEAR.NamingConventions.ValidFunctionName.processTokenWithinScope to remove the requirement * for leading underscores on private method names. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param integer $stackPtr The position where this token was found. * @param integer $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); $errorData = [$className . '::' . $methodName]; // Is this a magic method. i.e., is prefixed with "__" ? if (preg_match('|^__|', $methodName) !== 0) { $magicPart = strtolower(substr($methodName, 2)); if (isset($this->magicMethods[$magicPart]) === false) { $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; if ($methodProps['scope'] === 'private') { $isPublic = false; } else { $isPublic = true; } // YaAPI change: Methods must not have an underscore on the front. if ($scopeSpecified === true && $methodName[0] === '_') { $error = '%s method name "%s" must not be prefixed with an underscore'; $data = [ucfirst($scope), $errorData[0]]; $phpcsFile->addError($error, $stackPtr, 'MethodUnderscore', $data); $phpcsFile->recordMetric($stackPtr, 'Method prefixed with underscore', 'yes'); return; } /* * If the scope was specified on the method, then the method must be camel caps * and an underscore should be checked for. If it wasn't specified, treat it like a public method * and remove the underscore prefix if there is one because we cant determine if it is private or public. */ $testMethodName = $methodName; if ($scopeSpecified === false && $methodName[0] === '_') { $testMethodName = substr($methodName, 1); } if (PHP_CodeSniffer::isCamelCaps($testMethodName, false, true, false) === false) { if ($scopeSpecified === true) { $error = '%s method name "%s" is not in camel caps format'; $data = [ucfirst($scope), $errorData[0]]; $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); } else { $error = 'Method name "%s" is not in camel caps format'; $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); } return; } }
/** * Processes the token in the specified PHP_CodeSniffer_File. * * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this * token was found. * @param int $stackPtr The position where the token was found. * @param array $currScope The current scope opener token. * * @return void */ protected final function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { if ($this->currentFile !== $phpcsFile) { $this->currentFile = $phpcsFile; $this->_functionOpen = false; $this->_endFunction = -1; } $tokens = $phpcsFile->getTokens(); if ($stackPtr > $this->_endFunction) { $this->_functionOpen = false; } if ($tokens[$stackPtr]['code'] === T_FUNCTION && $this->_functionOpen === false) { $this->_functionOpen = true; $methodProps = $phpcsFile->getMethodProperties($stackPtr); // If the function is abstract, or is in an interface, // then set the end of the function to it's closing semicolon. if ($methodProps['is_abstract'] === true || $tokens[$currScope]['code'] === T_INTERFACE) { $this->_endFunction = $phpcsFile->findNext(array(T_SEMICOLON), $stackPtr); } else { if (isset($tokens[$stackPtr]['scope_closer']) === false) { $error = 'Possible parse error: non-abstract method defined as abstract'; $phpcsFile->addWarning($error, $stackPtr); return; } $this->_endFunction = $tokens[$stackPtr]['scope_closer']; } } //end if if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING || $tokens[$stackPtr]['code'] === T_HEREDOC) { // Check to see if this string has a variable in it. $pattern = '|(?<!\\\\)(?:\\\\{2})*\\${?[a-zA-Z0-9_]+}?|'; if (preg_match($pattern, $tokens[$stackPtr]['content']) !== 0) { $this->processVariableInString($phpcsFile, $stackPtr); } return; } if ($this->_functionOpen === true) { if ($tokens[$stackPtr]['code'] === T_VARIABLE) { $this->processVariable($phpcsFile, $stackPtr); } } else { // What if we assign a member variable to another? // ie. private $_count = $this->_otherCount + 1;. $this->processMemberVar($phpcsFile, $stackPtr); } }
/** * Processes the tokens within the scope. * * @param PHP_CodeSniffer_File $phpcsFile The file being processed. * @param int $stackPtr The position where this token was * found. * @param int $currScope The position of the current scope. * * @return void */ protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope) { $methodName = $phpcsFile->getDeclarationName($stackPtr); if ($methodName === null) { // Ignore closures. return; } $className = $phpcsFile->getDeclarationName($currScope); $errorData = array($className . '::' . $methodName); // Is this a magic method. IE. is prefixed with "__". if (preg_match('|^__|', $methodName) !== 0) { $magicPart = substr($methodName, 2); if (in_array($magicPart, $this->magicMethods) === false) { $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); } return; } // PHP4 constructors are allowed to break our rules. if ($methodName === $className) { return; } // PHP4 destructors are allowed to break our rules. if ($methodName === '_' . $className) { return; } $methodProps = $phpcsFile->getMethodProperties($stackPtr); $isPublic = $methodProps['scope'] === 'private' ? false : true; $scope = $methodProps['scope']; $scopeSpecified = $methodProps['scope_specified']; // Detect if it is marked deprecated $find = array(T_COMMENT, T_DOC_COMMENT, T_CLASS, T_FUNCTION, T_OPEN_TAG); $tokens = $phpcsFile->getTokens(); $commentEnd = $phpcsFile->findPrevious($find, $stackPtr - 1); if ($commentEnd !== false && $tokens[$commentEnd]['code'] === T_DOC_COMMENT) { $commentStart = $phpcsFile->findPrevious(T_DOC_COMMENT, $commentEnd - 1, null, true) + 1; $comment = $phpcsFile->getTokensAsString($commentStart, $commentEnd - $commentStart + 1); 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, 'FailedParse'); return; } $deprecated = $this->commentParser->getDeprecated(); return !is_null($deprecated); } else { return false; } // Methods must not have an underscore on the front. if ($isDeprecated === false && $scopeSpecified === true && $methodName[0] === '_') { $error = '%s method name "%s" must not be prefixed with an underscore'; $data = array(ucfirst($scope), $errorData[0]); // AJE Changed from error to warning. $phpcsFile->addWarning($error, $stackPtr, 'PublicUnderscore', $data); return; } // If the scope was specified on the method, then the method must be // camel caps and an underscore should be checked for. If it wasn't // specified, treat it like a public method and remove the underscore // prefix if there is one because we cant determine if it is private or // public. $testMethodName = $methodName; if ($scopeSpecified === false && $methodName[0] === '_') { $testMethodName = substr($methodName, 1); } if ($isDeprecated === false && PHP_CodeSniffer::isCamelCaps($testMethodName, false, $isPublic, false) === false) { if ($scopeSpecified === true) { $error = '%s method name "%s" is not in camel caps format'; $data = array(ucfirst($scope), $errorData[0]); // AJE Change to warning. $phpcsFile->addWarning($error, $stackPtr, 'ScopeNotCamelCaps', $data); } else { $error = 'Method name "%s" is not in camel caps format'; // AJE Change to warning. $phpcsFile->addWarning($error, $stackPtr, 'NotCamelCaps', $errorData); } return; } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in the * stack passed in $tokens.. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['code'] === T_FUNCTION) { $methodProps = $phpcsFile->getMethodProperties($stackPtr); // Abstract methods do not require a closing comment. if ($methodProps['is_abstract'] === true) { return; } // Closures do not require a closing comment. if ($methodProps['is_closure'] === true) { return; } // If this function is in an interface then we don't require // a closing comment. if ($phpcsFile->hasCondition($stackPtr, T_INTERFACE) === true) { return; } if (isset($tokens[$stackPtr]['scope_closer']) === false) { $error = 'Possible parse error: non-abstract method defined as abstract'; $phpcsFile->addWarning($error, $stackPtr, 'Abstract'); return; } $decName = $phpcsFile->getDeclarationName($stackPtr); $comment = '//end ' . $decName . '()'; } else { if ($tokens[$stackPtr]['code'] === T_CLASS) { $comment = '//end class'; } else { $comment = '//end interface'; } } //end if if (isset($tokens[$stackPtr]['scope_closer']) === false) { $error = 'Possible parse error: %s missing opening or closing brace'; $data = array($tokens[$stackPtr]['content']); $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); return; } $closingBracket = $tokens[$stackPtr]['scope_closer']; if ($closingBracket === null) { // Possible inline structure. Other tests will handle it. return; } $error = 'Expected ' . $comment; if (isset($tokens[$closingBracket + 1]) === false || $tokens[$closingBracket + 1]['code'] !== T_COMMENT) { $next = $phpcsFile->findNext(T_WHITESPACE, $closingBracket + 1, null, true); if (rtrim($tokens[$next]['content']) === $comment) { // The comment isn't really missing; it is just in the wrong place. $fix = $phpcsFile->addFixableError($error . ' directly after closing brace', $closingBracket, 'Misplaced'); if ($fix === true && $phpcsFile->fixer->enabled === true) { $phpcsFile->fixer->beginChangeset(); for ($i = $closingBracket + 1; $i < $next; $i++) { $phpcsFile->fixer->replaceToken($i, ''); } // Just in case, because indentation fixes can add indents onto // these comments and cause us to be unable to fix them. $phpcsFile->fixer->replaceToken($next, $comment . $phpcsFile->eolChar); $phpcsFile->fixer->endChangeset(); } } else { $fix = $phpcsFile->addFixableError($error, $closingBracket, 'Missing'); if ($fix === true && $phpcsFile->fixer->enabled === true) { $phpcsFile->fixer->replaceToken($closingBracket, '}' . $comment . $phpcsFile->eolChar); } } return; } //end if if (rtrim($tokens[$closingBracket + 1]['content']) !== $comment) { $fix = $phpcsFile->addFixableError($error, $closingBracket, 'Incorrect'); if ($fix === true && $phpcsFile->fixer->enabled === true) { $phpcsFile->fixer->replaceToken($closingBracket + 1, $comment . $phpcsFile->eolChar); } return; } }