Example #1
0
 /**
  * Processes this test, when one of its tokens is encountered.
  *
  * @param PHP_CodeSniffer_File $phpcsFile The current file being scanned.
  * @param int                  $stackPtr  The position of the current token in the
  *                                        stack passed in $tokens.
  * @param int                  $currScope A pointer to the start of the scope.
  *
  * @return void
  */
 public function processTokenWithinScope(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');
         }
     }
     //end if
 }
Example #2
0
 /**
  * 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(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, 'Internal.ParseError.NonAbstractDefinedAbstract');
                 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 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(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->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->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->replaceToken($closingBracket + 1, $comment . $phpcsFile->eolChar);
         }
         return;
     }
 }
Example #4
0
 /**
  * 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(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) {
             $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;
     }
     // If it's a private method, it must have an underscore on the front.
     if ($isPublic === false) {
         if ($methodName[0] !== '_') {
             $error = 'Private method name "%s" must be prefixed with an underscore';
             $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData);
             $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'no');
             return;
         } else {
             $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'yes');
         }
     }
     // If it's not a private method, it must not have an underscore on the front.
     if ($isPublic === true && $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, '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 (Common::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]);
             $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(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;
     }
     // 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 (Common::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);
         }
         $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no');
         return;
     } else {
         $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes');
     }
 }