/** * Processes single-line calls. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * @param int $openBracket The position of the opening bracket * in the stack passed in $tokens. * @param array $tokens The stack of tokens that make up * the file. * * @return void */ public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) { // If the first argument is on a new line, this is a multi-line // function call, even if there is only one argument. $next = $phpcsFile->findNext(Tokens::$emptyTokens, $openBracket + 1, null, true); if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { return true; } $closeBracket = $tokens[$openBracket]['parenthesis_closer']; $end = $phpcsFile->findEndOfStatement($openBracket + 1); while ($tokens[$end]['code'] === T_COMMA) { // If the next bit of code is not on the same line, this is a // multi-line function call. $next = $phpcsFile->findNext(Tokens::$emptyTokens, $end + 1, $closeBracket, true); if ($next === false) { return false; } if ($tokens[$next]['line'] !== $tokens[$end]['line']) { return true; } $end = $phpcsFile->findEndOfStatement($next); } // We've reached the last argument, so see if the next content // (should be the close bracket) is also on the same line. $next = $phpcsFile->findNext(Tokens::$emptyTokens, $end + 1, $closeBracket, true); if ($next !== false && $tokens[$next]['line'] !== $tokens[$end]['line']) { return true; } return false; }
/** * 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(); $firstContent = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); // If the first non-whitespace token is not an opening parenthesis, then we are not concerned. if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) { $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); return; } $end = $phpcsFile->findNext(array(T_SEMICOLON, T_CLOSE_TAG), $stackPtr, null, false); // If the token before the semi-colon is not a closing parenthesis, then we are not concerned. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $end - 1, null, true); if ($tokens[$prev]['code'] !== T_CLOSE_PARENTHESIS) { $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); return; } // If the parenthesis don't match, then we are not concerned. if ($tokens[$firstContent]['parenthesis_closer'] !== $prev) { $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); return; } $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'yes'); if ($phpcsFile->findNext(Tokens::$operators, $stackPtr, $end, false) === false) { // There are no arithmetic operators in this. $error = 'Echoed strings should not be bracketed'; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'HasBracket'); if ($fix === true) { $phpcsFile->fixer->beginChangeset(); $phpcsFile->fixer->replaceToken($firstContent, ''); $phpcsFile->fixer->replaceToken($end - 1, ''); $phpcsFile->fixer->endChangeset(); } } }
/** * 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(); // Check if the next non whitespace token is a string. $index = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$index]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } // Make sure it is the only thing in the square brackets. $next = $phpcsFile->findNext(T_WHITESPACE, $index + 1, null, true); if ($tokens[$next]['code'] !== T_CLOSE_SQUARE_BRACKET) { return; } // Allow indexes that have dots in them because we can't write // them in dot notation. $content = trim($tokens[$index]['content'], '"\' '); if (strpos($content, '.') !== false) { return; } // Also ignore reserved words. if ($content === 'super') { return; } // Token before the opening square bracket cannot be a var name. $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] === T_STRING) { $error = 'Object indexes must be written in dot notation'; $phpcsFile->addError($error, $prev, 'Found'); } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The current file being processed. * @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 (isset($tokens[$stackPtr]['scope_opener']) === false) { $error = 'Possible parse error: %s missing opening or closing brace'; $data = array($tokens[$stackPtr]['content']); $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); return; } // Determine the name of the class or interface. Note that we cannot // simply look for the first T_STRING because a class name // starting with the number will be multiple tokens. $opener = $tokens[$stackPtr]['scope_opener']; $nameStart = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, $opener, true); $nameEnd = $phpcsFile->findNext(T_WHITESPACE, $nameStart, $opener); if ($nameEnd === false) { $name = $tokens[$nameStart]['content']; } else { $name = trim($phpcsFile->getTokensAsString($nameStart, $nameEnd - $nameStart)); } // Check for camel caps format. $valid = Common::isCamelCaps($name, true, true, false); if ($valid === false) { $type = ucfirst($tokens[$stackPtr]['content']); $error = '%s name "%s" is not in camel caps format'; $data = array($type, $name); $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); $phpcsFile->recordMetric($stackPtr, 'CamelCase class name', 'no'); } else { $phpcsFile->recordMetric($stackPtr, 'CamelCase class name', 'yes'); } }
/** * 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 */ protected function processVariable(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $varName = ltrim($tokens[$stackPtr]['content'], '$'); $phpReservedVars = array('_SERVER', '_GET', '_POST', '_REQUEST', '_SESSION', '_ENV', '_COOKIE', '_FILES', 'GLOBALS', 'http_response_header', 'HTTP_RAW_POST_DATA', 'php_errormsg'); // If it's a php reserved var, then its ok. if (in_array($varName, $phpReservedVars) === true) { return; } $objOperator = $phpcsFile->findNext(array(T_WHITESPACE), $stackPtr + 1, null, true); if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR) { // Check to see if we are using a variable from an object. $var = $phpcsFile->findNext(array(T_WHITESPACE), $objOperator + 1, null, true); if ($tokens[$var]['code'] === T_STRING) { $bracket = $phpcsFile->findNext(array(T_WHITESPACE), $var + 1, null, true); if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { $objVarName = $tokens[$var]['content']; // There is no way for us to know if the var is public or // private, so we have to ignore a leading underscore if there is // one and just check the main part of the variable name. $originalVarName = $objVarName; if (substr($objVarName, 0, 1) === '_') { $objVarName = substr($objVarName, 1); } if (Common::isCamelCaps($objVarName, false, true, false) === false) { $error = 'Variable "%s" is not in valid camel caps format'; $data = array($originalVarName); $phpcsFile->addError($error, $var, 'NotCamelCaps', $data); } } //end if } //end if } //end if // There is no way for us to know if the var is public or private, // so we have to ignore a leading underscore if there is one and just // check the main part of the variable name. $originalVarName = $varName; if (substr($varName, 0, 1) === '_') { $objOperator = $phpcsFile->findPrevious(array(T_WHITESPACE), $stackPtr - 1, null, true); if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { // The variable lives within a class, and is referenced like // this: MyClass::$_variable, so we don't know its scope. $inClass = true; } else { $inClass = $phpcsFile->hasCondition($stackPtr, array(T_CLASS, T_INTERFACE, T_TRAIT)); } if ($inClass === true) { $varName = substr($varName, 1); } } if (Common::isCamelCaps($varName, false, true, false) === false) { $error = 'Variable "%s" is not in valid camel caps format'; $data = array($originalVarName); $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); } }
/** * Processes this sniff, 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(); $varName = $tokens[$stackPtr]['content']; if ($varName !== '$_REQUEST' && $varName !== '$_GET' && $varName !== '$_POST' && $varName !== '$_FILES') { return; } // The only place these super globals can be accessed directly is // in the getRequestData() method of the Security class. $inClass = false; foreach ($tokens[$stackPtr]['conditions'] as $i => $type) { if ($tokens[$i]['code'] === T_CLASS) { $className = $phpcsFile->findNext(T_STRING, $i); $className = $tokens[$className]['content']; if (strtolower($className) === 'security') { $inClass = true; } else { // We don't have nested classes. break; } } else { if ($inClass === true && $tokens[$i]['code'] === T_FUNCTION) { $funcName = $phpcsFile->findNext(T_STRING, $i); $funcName = $tokens[$funcName]['content']; if (strtolower($funcName) === 'getrequestdata') { // This is valid. return; } else { // We don't have nested functions. break; } } } //end if } //end foreach // If we get to here, the super global was used incorrectly. // First find out how it is being used. $globalName = strtolower(substr($varName, 2)); $usedVar = ''; $openBracket = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$openBracket]['code'] === T_OPEN_SQUARE_BRACKET) { $closeBracket = $tokens[$openBracket]['bracket_closer']; $usedVar = $phpcsFile->getTokensAsString($openBracket + 1, $closeBracket - $openBracket - 1); } $type = 'SuperglobalAccessed'; $error = 'The %s super global must not be accessed directly; use Security::getRequestData('; $data = array($varName); if ($usedVar !== '') { $type .= 'WithVar'; $error .= '%s, \'%s\''; $data[] = $usedVar; $data[] = $globalName; } $error .= ') instead'; $phpcsFile->addError($error, $stackPtr, $type, $data); }
/** * 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(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($next === false) { return; } if ($tokens[$next]['code'] !== T_CLOSE_TAG) { $found = $tokens[$next]['line'] - $tokens[$stackPtr]['line'] - 1; if ($found !== 1) { $error = 'Expected one blank line after closing brace of class definition; %s found'; $data = array($found); $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterClose', $data); if ($fix === true) { if ($found === 0) { $phpcsFile->fixer->addNewline($stackPtr); } else { $nextContent = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); $phpcsFile->fixer->beginChangeset(); for ($i = $stackPtr + 1; $i < $nextContent - 1; $i++) { $phpcsFile->fixer->replaceToken($i, ''); } $phpcsFile->fixer->addNewline($i); $phpcsFile->fixer->endChangeset(); } } } //end if } //end if // Ignore nested style definitions from here on. The spacing before the closing brace // (a single blank line) will be enforced by the above check, which ensures there is a // blank line after the last nested class. $found = $phpcsFile->findPrevious(T_CLOSE_CURLY_BRACKET, $stackPtr - 1, $tokens[$stackPtr]['bracket_opener']); if ($found !== false) { return; } $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($prev === false) { return; } if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { $error = 'Closing brace of class definition must be on new line'; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBeforeClose'); if ($fix === true) { $phpcsFile->fixer->addNewlineBefore($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 */ public function process(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Find the content of each style definition name. $styleNames = array(); $next = $stackPtr; $end = $tokens[$stackPtr]['bracket_closer']; do { $next = $phpcsFile->findNext(array(T_STYLE, T_OPEN_CURLY_BRACKET), $next + 1, $end); if ($next === false) { // Class definition is empty. break; } if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) { $next = $tokens[$next]['bracket_closer']; continue; } $name = $tokens[$next]['content']; if (isset($styleNames[$name]) === true) { $first = $styleNames[$name]; $error = 'Duplicate style definition found; first defined on line %s'; $data = array($tokens[$first]['line']); $phpcsFile->addError($error, $next, 'Found', $data); } else { $styleNames[$name] = $next; } } while ($next !== false); }
/** * Processes this sniff, 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) { $fileName = $phpcsFile->getFilename(); $matches = array(); if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|i', $fileName, $matches) === 0) { // Not an actions file. return; } $ownClass = $matches[2]; $tokens = $phpcsFile->getTokens(); $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, $stackPtr + 2, null, false, true); $typeName = trim($tokens[$typeName]['content'], " '"); switch (strtolower($tokens[$stackPtr + 1]['content'])) { case 'includesystem': $included = strtolower($typeName); break; case 'includeasset': $included = strtolower($typeName) . 'assettype'; break; case 'includewidget': $included = strtolower($typeName) . 'widgettype'; break; default: return; } if ($included === strtolower($ownClass)) { $error = "You do not need to include \"%s\" from within the system's own actions file"; $data = array($ownClass); $phpcsFile->addError($error, $stackPtr, 'NotRequired', $data); } }
/** * 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(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $lastLine = $tokens[$stackPtr]['line']; $end = $tokens[$stackPtr]['bracket_closer']; $endLine = $tokens[$end]['line']; // Do not check nested style definitions as, for example, in @media style rules. $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, $stackPtr + 1, $end); if ($nested !== false) { return; } $foundColon = false; $foundString = false; for ($i = $stackPtr + 1; $i <= $end; $i++) { if ($tokens[$i]['line'] !== $lastLine) { // We changed lines. if ($foundColon === false && $foundString !== false) { // We didn't find a colon on the previous line. $error = 'No style definition found on line; check for missing colon'; $phpcsFile->addError($error, $foundString, 'Found'); } $foundColon = false; $foundString = false; $lastLine = $tokens[$i]['line']; } if ($tokens[$i]['code'] === T_STRING) { $foundString = $i; } else { if ($tokens[$i]['code'] === T_COLON) { $foundColon = $i; } } } //end for }
/** * 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(); // Ignore this.something and other uses of "this" that are not // direct assignments. $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$next]['code'] !== T_SEMICOLON) { if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { return; } } // Something must be assigned to "this". $prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] !== T_EQUAL) { return; } // A variable needs to be assigned to "this". $prev = $phpcsFile->findPrevious(T_WHITESPACE, $prev - 1, null, true); if ($tokens[$prev]['code'] !== T_STRING) { return; } // We can only assign "this" to a var called "self". if ($tokens[$prev]['content'] !== 'self' && $tokens[$prev]['content'] !== '_self') { $error = 'Keyword "this" can only be assigned to a variable called "self" or "_self"'; $phpcsFile->addError($error, $prev, 'NotSelf'); } }
/** * Processes the function tokens within the class. * * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found. * @param int $stackPtr The position where the token was found. * * @return void */ protected function processMemberVar(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['content'][1] === '_') { $error = 'Property name "%s" should not be prefixed with an underscore to indicate visibility'; $data = array($tokens[$stackPtr]['content']); $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data); } // Detect multiple properties defined at the same time. Throw an error // for this, but also only process the first property in the list so we don't // repeat errors. $find = Tokens::$scopeModifiers; $find = array_merge($find, array(T_VARIABLE, T_VAR, T_SEMICOLON)); $prev = $phpcsFile->findPrevious($find, $stackPtr - 1); if ($tokens[$prev]['code'] === T_VARIABLE) { return; } if ($tokens[$prev]['code'] === T_VAR) { $error = 'The var keyword must not be used to declare a property'; $phpcsFile->addError($error, $stackPtr, 'VarUsed'); } $next = $phpcsFile->findNext(array(T_VARIABLE, T_SEMICOLON), $stackPtr + 1); if ($tokens[$next]['code'] === T_VARIABLE) { $error = 'There must not be more than one property declared per statement'; $phpcsFile->addError($error, $stackPtr, 'Multiple'); } $modifier = $phpcsFile->findPrevious(Tokens::$scopeModifiers, $stackPtr); if ($modifier === false || $tokens[$modifier]['line'] !== $tokens[$stackPtr]['line']) { $error = 'Visibility must be declared on property "%s"'; $data = array($tokens[$stackPtr]['content']); $phpcsFile->addError($error, $stackPtr, 'ScopeMissing', $data); } }
/** * 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 (isset($tokens[$stackPtr]['scope_opener']) === false) { // Probably an interface method. return; } $openBrace = $tokens[$stackPtr]['scope_opener']; $nextContent = $phpcsFile->findNext(T_WHITESPACE, $openBrace + 1, null, true); if ($nextContent === $tokens[$stackPtr]['scope_closer']) { // The next bit of content is the closing brace, so this // is an empty function and should have a blank line // between the opening and closing braces. return; } $braceLine = $tokens[$openBrace]['line']; $nextLine = $tokens[$nextContent]['line']; $found = $nextLine - $braceLine - 1; if ($found > 0) { $error = 'Expected 0 blank lines after opening function brace; %s found'; $data = array($found); $fix = $phpcsFile->addFixableError($error, $openBrace, 'SpacingAfter', $data); if ($fix === true) { $phpcsFile->fixer->beginChangeset(); for ($i = $openBrace + 1; $i < $nextContent; $i++) { if ($tokens[$i]['line'] === $nextLine) { break; } $phpcsFile->fixer->replaceToken($i, ''); } $phpcsFile->fixer->addNewline($openBrace); $phpcsFile->fixer->endChangeset(); } } }
/** * 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(); $openTag = $tokens[$stackPtr]; if ($openTag['content'] === '<?') { $error = 'Short PHP opening tag used; expected "<?php" but found "%s"'; $data = array($openTag['content']); $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found', $data); if ($fix === true) { $phpcsFile->fixer->replaceToken($stackPtr, '<?php'); } $phpcsFile->recordMetric($stackPtr, 'PHP short open tag used', 'yes'); } else { $phpcsFile->recordMetric($stackPtr, 'PHP short open tag used', 'no'); } if ($openTag['code'] === T_OPEN_TAG_WITH_ECHO) { $nextVar = $tokens[$phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true)]; $error = 'Short PHP opening tag used with echo; expected "<?php echo %s ..." but found "%s %s ..."'; $data = array($nextVar['content'], $openTag['content'], $nextVar['content']); $fix = $phpcsFile->addFixableError($error, $stackPtr, 'EchoFound', $data); if ($fix === true) { if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $phpcsFile->fixer->replaceToken($stackPtr, '<?php echo '); } else { $phpcsFile->fixer->replaceToken($stackPtr, '<?php echo'); } } } }
/** * 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 }
/** * Processes this sniff, 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(); $functionName = $phpcsFile->findNext(T_STRING, $stackPtr + 1, null, false, null, true); while ($functionName !== false) { // Check if this is really a function. $bracket = $phpcsFile->findNext(T_WHITESPACE, $functionName + 1, null, true); if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { // Not a function call. $functionName = $phpcsFile->findNext(T_STRING, $functionName + 1, null, false, null, true); continue; } $error = 'The result of a function call should be assigned to a variable before being returned'; $phpcsFile->addWarning($error, $stackPtr, 'NotAssigned'); break; } }
/** * Processes this sniff, 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) { $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); if ($closeTag === false) { $error = 'The PHP open tag does not have a corresponding PHP close tag'; $phpcsFile->addError($error, $stackPtr, 'NotFound'); } }
/** * Processes this sniff, 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) { $nextClass = $phpcsFile->findNext($this->register(), $stackPtr + 1); if ($nextClass !== false) { $error = 'Only one class is allowed in a file'; $phpcsFile->addError($error, $nextClass, 'MultipleFound'); } }
/** * 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(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $next = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true); if ($next === false || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { $error = 'Class definition is empty'; $phpcsFile->addError($error, $stackPtr, 'Found'); } }
/** * 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(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $next = $phpcsFile->findNext(array(T_WHITESPACE, T_COLON), $stackPtr + 1, null, true); if ($next === false || $tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { $error = 'Style definition is empty'; $phpcsFile->addError($error, $stackPtr, 'Found'); } }
/** * 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(); $nextVar = $tokens[$phpcsFile->findNext(array(T_VARIABLE), $stackPtr)]; $varName = str_replace('$', '', $nextVar['content']); $error = 'Use of the "global" keyword is forbidden; use "$GLOBALS[\'%s\']" instead'; $data = array($varName); $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); }
/** * 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(); // Ignore default value assignments in function definitions. $function = $phpcsFile->findPrevious(T_FUNCTION, $stackPtr - 1, null, false, null, true); if ($function !== false) { $opener = $tokens[$function]['parenthesis_opener']; $closer = $tokens[$function]['parenthesis_closer']; if ($opener < $stackPtr && $closer > $stackPtr) { return; } } // Ignore values in array definitions. $array = $phpcsFile->findNext(T_ARRAY, $stackPtr + 1, null, false, null, true); if ($array !== false) { return; } // Ignore function calls. $ignore = array(T_STRING, T_WHITESPACE, T_OBJECT_OPERATOR); $next = $phpcsFile->findNext($ignore, $stackPtr + 1, null, true); if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS && $tokens[$next - 1]['code'] === T_STRING) { // Code will look like: $var = myFunction( // and will be ignored. return; } $endStatement = $phpcsFile->findNext(T_SEMICOLON, $stackPtr + 1); if ($tokens[$stackPtr]['conditions'] !== $tokens[$endStatement]['conditions']) { // This statement doesn't end with a semicolon, which is the case for // the last expression in a for loop. return; } for ($i = $stackPtr + 1; $i < $endStatement; $i++) { if (isset(Tokens::$comparisonTokens[$tokens[$i]['code']]) === true || $tokens[$i]['code'] === T_INLINE_THEN) { $error = 'The value of a comparison must not be assigned to a variable'; $phpcsFile->addError($error, $stackPtr, 'AssignedComparison'); break; } if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true || $tokens[$i]['code'] === T_BOOLEAN_NOT) { $error = 'The value of a boolean operation must not be assigned to a variable'; $phpcsFile->addError($error, $stackPtr, 'AssignedBool'); break; } } }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document. * @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(); $scopeStart = $tokens[$stackPtr]['scope_opener']; $firstContent = $phpcsFile->findNext(T_WHITESPACE, $scopeStart + 1, $tokens[$stackPtr]['scope_closer'], true); if ($firstContent === false) { $error = 'Empty CATCH statement must have a comment to explain why the exception is not handled'; $phpcsFile->addError($error, $scopeStart, 'Missing'); } }
/** * Processes this sniff, 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(); // Make sure it is an API function. We know this by the doc comment. $commentEnd = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr); $commentStart = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $commentEnd - 1); $comment = $phpcsFile->getTokensAsString($commentStart, $commentEnd - $commentStart); if (strpos($comment, '* @api') === false) { return; } // Find all the vars passed in as we are only interested in comparisons // to NULL for these specific variables. $foundVars = array(); $open = $tokens[$stackPtr]['parenthesis_opener']; $close = $tokens[$stackPtr]['parenthesis_closer']; for ($i = $open + 1; $i < $close; $i++) { if ($tokens[$i]['code'] === T_VARIABLE) { $foundVars[$tokens[$i]['content']] = true; } } if (empty($foundVars) === true) { return; } $start = $tokens[$stackPtr]['scope_opener']; $end = $tokens[$stackPtr]['scope_closer']; for ($i = $start + 1; $i < $end; $i++) { if ($tokens[$i]['code'] !== T_VARIABLE || isset($foundVars[$tokens[$i]['content']]) === false) { continue; } $operator = $phpcsFile->findNext(T_WHITESPACE, $i + 1, null, true); if ($tokens[$operator]['code'] !== T_IS_IDENTICAL && $tokens[$operator]['code'] !== T_IS_NOT_IDENTICAL) { continue; } $nullValue = $phpcsFile->findNext(T_WHITESPACE, $operator + 1, null, true); if ($tokens[$nullValue]['code'] !== T_NULL) { continue; } $error = 'Values submitted via Ajax requests should not be compared directly to NULL; use empty() instead'; $phpcsFile->addWarning($error, $nullValue, 'Found'); } //end for }
/** * Processes this sniff, 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(); $className = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if (strtolower($tokens[$className]['content']) === 'debug') { $method = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); $error = 'Call to debug function Debug::%s() must be removed'; $data = array($tokens[$method]['content']); $phpcsFile->addError($error, $stackPtr, 'Found', $data); } }
/** * 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 the close php tag is on the same line as the opening // then we have an inline embedded PHP block. $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); if ($closeTag === false || $tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) { $this->validateMultilineEmbeddedPhp($phpcsFile, $stackPtr); } else { $this->validateInlineEmbeddedPhp($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(); $namespace = ''; $findTokens = array(T_CLASS, T_INTERFACE, T_NAMESPACE, T_CLOSE_TAG); $stackPtr = $phpcsFile->findNext($findTokens, $stackPtr + 1); while ($stackPtr !== false) { if ($tokens[$stackPtr]['code'] === T_CLOSE_TAG) { // We can stop here. The sniff will continue from the next open // tag when PHPCS reaches that token, if there is one. return; } // Keep track of what namespace we are in. if ($tokens[$stackPtr]['code'] === T_NAMESPACE) { $nsEnd = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING, T_WHITESPACE), $stackPtr + 1, null, true); $namespace = trim($phpcsFile->getTokensAsString($stackPtr + 1, $nsEnd - $stackPtr - 1)); $stackPtr = $nsEnd; } else { $nameToken = $phpcsFile->findNext(T_STRING, $stackPtr); $name = $tokens[$nameToken]['content']; if ($namespace !== '') { $name = $namespace . '\\' . $name; } $compareName = strtolower($name); if (isset($this->foundClasses[$compareName]) === true) { $type = strtolower($tokens[$stackPtr]['content']); $file = $this->foundClasses[$compareName]['file']; $line = $this->foundClasses[$compareName]['line']; $error = 'Duplicate %s name "%s" found; first defined in %s on line %s'; $data = array($type, $name, $file, $line); $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); } else { $this->foundClasses[$compareName] = array('file' => $phpcsFile->getFilename(), 'line' => $tokens[$stackPtr]['line']); } } //end if $stackPtr = $phpcsFile->findNext($findTokens, $stackPtr + 1); } //end while }
/** * 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(); $argStart = $tokens[$stackPtr]['parenthesis_opener']; $argEnd = $tokens[$stackPtr]['parenthesis_closer']; // Flag for when we have found a default in our arg list. // If there is a value without a default after this, it is an error. $defaultFound = false; $nextArg = $argStart; while (($nextArg = $phpcsFile->findNext(T_VARIABLE, $nextArg + 1, $argEnd)) !== false) { if ($tokens[$nextArg - 1]['code'] === T_ELLIPSIS) { continue; } $argHasDefault = false; $next = $phpcsFile->findNext(Tokens::$emptyTokens, $nextArg + 1, null, true); if ($tokens[$next]['code'] === T_EQUAL) { $argHasDefault = true; } if ($argHasDefault === false && $defaultFound === true) { $error = 'Arguments with default values must be at the end of the argument list'; $phpcsFile->addError($error, $nextArg, 'NotAtEnd'); return; } if ($argHasDefault === true) { $defaultFound = true; // Check if the arg is type hinted and using NULL for the default. // This does not make the argument optional - it just allows NULL // to be passed in. $next = $phpcsFile->findNext(Tokens::$emptyTokens, $next + 1, null, true); if ($tokens[$next]['code'] === T_NULL) { $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $nextArg - 1, null, true); if ($tokens[$prev]['code'] === T_STRING || $tokens[$prev]['code'] === T_ARRAY_HINT) { $defaultFound = false; } } } } //end while }
/** * 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(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Find the content of each class definition name. $classNames = array(); $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, $stackPtr + 1); if ($next === false) { // No class definitions in the file. return; } // Save the class names in a "scope", // to prevent false positives with @media blocks. $scope = 'main'; $find = array(T_CLOSE_CURLY_BRACKET, T_OPEN_CURLY_BRACKET, T_COMMENT, T_OPEN_TAG); while ($next !== false) { $prev = $phpcsFile->findPrevious($find, $next - 1); // Check if an inner block was closed. $beforePrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, $prev - 1, null, true); if ($beforePrev !== false && $tokens[$beforePrev]['code'] === T_CLOSE_CURLY_BRACKET) { $scope = 'main'; } // Create a sorted name for the class so we can compare classes // even when the individual names are all over the place. $name = ''; for ($i = $prev + 1; $i < $next; $i++) { $name .= $tokens[$i]['content']; } $name = trim($name); $name = str_replace("\n", ' ', $name); $name = preg_replace('|[\\s]+|', ' ', $name); $name = str_replace(', ', ',', $name); $names = explode(',', $name); sort($names); $name = implode(',', $names); if ($name[0] === '@') { // Media block has its own "scope". $scope = $name; } else { if (isset($classNames[$scope][$name]) === true) { $first = $classNames[$scope][$name]; $error = 'Duplicate class definition found; first defined on line %s'; $data = array($tokens[$first]['line']); $phpcsFile->addError($error, $next, 'Found', $data); } else { $classNames[$scope][$name] = $next; } } $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, $next + 1); } //end while }
/** * 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(); $className = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); if ($tokens[$className]['code'] !== T_STRING) { return; } if (substr(strtolower($tokens[$className]['content']), -10) === 'widgettype') { $widgetType = substr($tokens[$className]['content'], 0, -10); $error = 'Manual creation of widget objects is banned; use Widget::getWidget(\'%s\'); instead'; $data = array($widgetType); $phpcsFile->addError($error, $stackPtr, 'Found', $data); } }