/** * 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(); // Make sure this is the first PHP open tag so we don't process // the same file twice. $prevOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1); if ($prevOpenTag !== false) { return; } $fileName = $phpcsFile->getFileName(); $extension = substr($fileName, strrpos($fileName, '.')); $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE), $stackPtr); if ($extension === '.php') { if ($nextClass !== false) { $error = '%s found in ".php" file; use ".inc" extension instead'; $data = array(ucfirst($tokens[$nextClass]['content'])); $phpcsFile->addError($error, $stackPtr, 'ClassFound', $data); } } else { if ($extension === '.inc') { if ($nextClass === false) { $error = 'No interface or class found in ".inc" file; use ".php" extension instead'; $phpcsFile->addError($error, $stackPtr, 'NoClass'); } } } }
/** * 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) { // Only run this sniff once per info file. $end = count($phpcsFile->getTokens()) + 1; $fileExtension = strtolower(substr($phpcsFile->getFilename(), -4)); if ($fileExtension !== 'info') { return $end; } $tokens = $phpcsFile->getTokens(); $contents = file_get_contents($phpcsFile->getFilename()); $info = Drupal_Sniffs_InfoFiles_ClassFilesSniff::drupalParseInfoFormat($contents); if (isset($info['name']) === false) { $error = '"name" property is missing in the info file'; $phpcsFile->addError($error, $stackPtr, 'Name'); } if (isset($info['description']) === false) { $error = '"description" property is missing in the info file'; $phpcsFile->addError($error, $stackPtr, 'Description'); } if (isset($info['core']) === false) { $error = '"core" property is missing in the info file'; $phpcsFile->addError($error, $stackPtr, 'Core'); } else { if ($info['core'] === '7.x' && isset($info['php']) === true && $info['php'] <= '5.2') { $error = 'Drupal 7 core already requires PHP 5.2'; $ptr = Drupal_Sniffs_InfoFiles_ClassFilesSniff::getPtr('php', $info['php'], $phpcsFile); $phpcsFile->addError($error, $ptr, 'D7PHPVersion'); } } return $end; }
/** * Search token stream for the corresponding node * * @param PHPParser_Node $node Current node * * @return integer */ private function findStackPointer($node) { $tokens = $this->phpcsFile->getTokens(); foreach ($tokens as $stackPtr => $token) { if ($node->getLine() > $token['line']) { continue; } return $stackPtr; } }
/** * @param \PHP_CodeSniffer_File $phpcs_file * @param int $stack_ptr */ public function process(\PHP_CodeSniffer_File $phpcs_file, $stack_ptr) { // Search till interface name. $index = 0; while (isset($phpcs_file->getTokens()[$stack_ptr + $index]) && $phpcs_file->getTokens()[$stack_ptr + $index]['type'] !== 'T_STRING') { $index++; } $ptr = $stack_ptr + $index; $f_name = $phpcs_file->getTokens()[$ptr]['content']; if (preg_match('/Interface$/', $f_name)) { return; } $phpcs_file->addError('Invalid interface name, interface should be postfixed with Interface.', $ptr); return; }
/** * 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(PHP_CodeSniffer_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); $name = trim($phpcsFile->getTokensAsString($nameStart, $nameEnd - $nameStart)); // Check for camel caps format. $valid = PHP_CodeSniffer::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); } }
/** * 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(); $ignore = array(T_DOUBLE_COLON, T_OBJECT_OPERATOR, T_FUNCTION, T_CONST, T_USE, T_NS_SEPARATOR); $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if (in_array($tokens[$prevToken]['code'], $ignore) === true) { // Not a call to a PHP function. return; } $function = strtolower($tokens[$stackPtr]['content']); $pattern = null; if ($this->patternMatch === true) { $count = 0; $pattern = preg_replace($this->forbiddenFunctionNames, $this->forbiddenFunctionNames, $function, 1, $count); if ($count === 0) { return; } // Remove the pattern delimiters and modifier. $pattern = substr($pattern, 1, -2); } else { if (in_array($function, $this->forbiddenFunctionNames) === false) { return; } } $this->addError($phpcsFile, $stackPtr, $function, $pattern); }
/** * 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(); // 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 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) { $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr - 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space before opening brace of class definition; 0 found'; $phpcsFile->addError($error, $stackPtr); } else { $content = $tokens[$stackPtr - 1]['content']; if ($content !== ' ') { $length = strlen($content); if ($length === 1) { $length = 'tab'; } $error = "Expected 1 space before opening brace of class definition; {$length} found"; $phpcsFile->addError($error, $stackPtr); } } //end if $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true); if ($next !== false && $tokens[$next]['line'] !== $tokens[$stackPtr]['line'] + 1) { $num = $tokens[$next]['line'] - $tokens[$stackPtr]['line'] - 1; $error = "Expected 0 blank lines after opening brace of class definition; {$num} found"; $phpcsFile->addError($error, $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['content'] === 'ob_end_flush') { $phpcsFile->addError('Use of ob_end_flush() is not allowed; use ob_get_contents() and ob_end_clean() instead', $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $prev = $phpcsFile->findPrevious(T_SEMICOLON, $stackPtr - 1); if ($prev === false) { return; } // Ignore multiple statements in a FOR condition. if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { foreach ($tokens[$stackPtr]['nested_parenthesis'] as $bracket) { if (isset($tokens[$bracket]['parenthesis_owner']) === false) { // Probably a closure sitting inside a function call. continue; } $owner = $tokens[$bracket]['parenthesis_owner']; if ($tokens[$owner]['code'] === T_FOR) { return; } } } if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { $error = 'Each PHP statement must be on a line by itself'; $phpcsFile->addError($error, $stackPtr, 'SameLine'); 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(); $token = $tokens[$stackPtr]; // Skip for-statements without body. if (isset($token['scope_opener']) === false) { return; } $next = ++$token['scope_opener']; $end = --$token['scope_closer']; $emptyBody = true; for (; $next <= $end; ++$next) { if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) { $emptyBody = false; break; } } if ($emptyBody === true) { // Get token identifier. $name = $phpcsFile->getTokensAsString($stackPtr, 1); $error = sprintf('Empty %s statement detected', strtoupper($name)); if ($this->_tokens[$token['code']] === true) { $phpcsFile->addError($error, $stackPtr); } else { $phpcsFile->addWarning($error, $stackPtr); } } }
/** * 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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $path = $phpcsFile->getFileName(); if (!preg_match("/(views)/i", $path)) { return; } $tokens = $phpcsFile->getTokens(); $classname = $tokens[$phpcsFile->findNext(T_STRING, $stackPtr)]['content']; if (preg_match("/(helpers)/i", $path)) { $final_classname = $this->classname_without_type($classname, "Helper"); $msg_on_error = "Cake convention expects the helper class name to end with 'Helper'"; } else { $final_classname = $this->classname_with_type($classname, "View"); $msg_on_error = "Cake convention expects the view class name to end with 'View'"; } if (is_null($final_classname)) { $phpcsFile->addError($msg_on_error, $stackPtr); return; } $expected_file_name = preg_replace('/([A-Z])/', '_${1}', $final_classname); if (strpos($expected_file_name, "_") === 0) { $expected_file_name = substr($expected_file_name, 1, strlen($expected_file_name)); } $expected_file_name = strtolower($expected_file_name) . ".php"; if (!preg_match("/" . $expected_file_name . "/", $path)) { $error = "File name is expected to be, '" . $expected_file_name . "' for Class with name, '" . $classname . "'"; $phpcsFile->addError($error, $stackPtr); } }
/** * 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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $start = $tokens[$stackPtr]['scope_opener']; $end = $tokens[$stackPtr]['scope_closer']; $properties = array(); $wantedTokens = array(T_PROPERTY, T_OPEN_CURLY_BRACKET); $next = $phpcsFile->findNext($wantedTokens, $start + 1, $end); while ($next !== false && $next < $end) { // Skip nested objects. if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) { $next = $tokens[$next]['bracket_closer']; } else { $propName = $tokens[$next]['content']; if (isset($properties[$propName]) === true) { $line = $tokens[$properties[$propName]]['line']; $error = "Duplicate property definition found for \"{$propName}\"; previously defined on line {$line}"; $phpcsFile->addError($error, $next); } $properties[$propName] = $next; } //end if $next = $phpcsFile->findNext($wantedTokens, $next + 1, $end); } //end while }
/** * Processes this function call. * * @param PHP_CodeSniffer_File $phpcsFile * The file being scanned. * @param int $stackPtr * The position of the function call in the stack. * @param int $openBracket * The position of the opening parenthesis in the stack. * @param int $closeBracket * The position of the closing parenthesis in the stack. * @param Drupal_Sniffs_Semantics_FunctionCallSniff $sniff * Can be used to retreive the function's arguments with the getArgument() * method. * * @return void */ public function processFunctionCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $closeBracket, Drupal_Sniffs_Semantics_FunctionCallSniff $sniff) { $tokens = $phpcsFile->getTokens(); // We assume that the sequence '#default_value' => variable_get(...) // indicates a variable that the module owns. $arrow = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($arrow === false || $tokens[$arrow]['code'] !== T_DOUBLE_ARROW) { return; } $arrayKey = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $arrow - 1, null, true); if ($arrayKey === false || $tokens[$arrayKey]['code'] !== T_CONSTANT_ENCAPSED_STRING || substr($tokens[$arrayKey]['content'], 1, -1) !== '#default_value') { return; } $argument = $sniff->getArgument(1); // Variable name is not a literal string, so we return early. if ($argument === false || $tokens[$argument['start']]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } $moduleName = DrupalPractice_Project::getName($phpcsFile); if ($moduleName === false) { return; } $variableName = substr($tokens[$argument['start']]['content'], 1, -1); if (strpos($variableName, $moduleName) !== 0) { $warning = 'All variables defined by your module must be prefixed with your module\'s name to avoid name collisions with others. Expected start with "%s" but found "%s"'; $data = array($moduleName, $variableName); $phpcsFile->addWarning($warning, $argument['start'], 'VariableName', $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); // Ignore abstract methods. if (isset($tokens[$stackPtr]['scope_opener']) === false) { return; } // Detect start and end of this function definition. $start = $tokens[$stackPtr]['scope_opener']; $end = $tokens[$stackPtr]['scope_closer']; $nestingLevel = 0; // Find the maximum nesting level of any token in the function. for ($i = $start + 1; $i < $end; $i++) { $level = $tokens[$i]['level']; if ($nestingLevel < $level) { $nestingLevel = $level; } } // We subtract the nesting level of the function itself. $nestingLevel = $nestingLevel - $tokens[$stackPtr]['level'] - 1; if ($nestingLevel > $this->absoluteNestingLevel) { $error = "Function's nesting level ({$nestingLevel}) exceeds allowed maximum of " . $this->absoluteNestingLevel; $phpcsFile->addError($error, $stackPtr); } else { if ($nestingLevel > $this->nestingLevel) { $warning = "Function's nesting level ({$nestingLevel}) exceeds " . $this->nestingLevel . '; consider refactoring the function'; $phpcsFile->addWarning($warning, $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $operator = $tokens[$stackPtr]['content']; $previousToken = $tokens[$stackPtr - 1]; $nextToken = $tokens[$stackPtr + 1]; $previousSpaces = $previousToken['code'] === T_WHITESPACE ? strlen($previousToken['content']) : 0; $nextSpaces = $nextToken['code'] === T_WHITESPACE ? strlen($nextToken['content']) : 0; $previousNonEmpty = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); $previousSplitsLine = $tokens[$previousNonEmpty]['line'] !== $tokens[$stackPtr]['line']; $nextNonEmpty = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); $nextSplitsLine = $tokens[$nextNonEmpty]['line'] !== $tokens[$stackPtr]['line']; if (DWS_Helpers_Operator::isUnary($phpcsFile, $stackPtr)) { if (!$previousSplitsLine && $previousSpaces !== 1 && !in_array($tokens[$previousNonEmpty]['code'], [T_OPEN_PARENTHESIS, T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY])) { $phpcsFile->addError('Expected 1 space before "%s"; %s found', $stackPtr, 'SpacingBefore', [$operator, $previousSpaces]); } if ($nextSpaces !== 0) { $phpcsFile->addError('Expected 0 spaces after "%s"; %s found', $stackPtr, 'SpacingAfterUnary', [$operator, $nextSpaces]); } } else { if ($tokens[$stackPtr]['code'] === T_INLINE_ELSE && $tokens[$previousNonEmpty]['code'] === T_INLINE_THEN) { if ($previousSpaces !== 0) { $phpcsFile->addError('Expected 0 spaces inside "?:"; %s found', $stackPtr, 'SpacingInTernary', [$previousSpaces]); } } elseif (!$previousSplitsLine && $previousSpaces !== 1) { $phpcsFile->addError('Expected 1 space before "%s"; %s found', $stackPtr, 'SpacingBefore', [$operator, $previousSpaces]); } $isTernaryShortcut = $tokens[$stackPtr]['code'] === T_INLINE_THEN && $tokens[$nextNonEmpty]['code'] === T_INLINE_ELSE; if (!$isTernaryShortcut && !$nextSplitsLine && $nextSpaces !== 1) { $phpcsFile->addError('Expected 1 space after "%s"; %s found', $stackPtr, 'SpacingAfter', [$operator, $nextSpaces]); } } }
/** * Processes class member variables. * * @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 processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $memberProps = $phpcsFile->getMemberProperties($stackPtr); if (empty($memberProps) === true) { return; } $memberName = ltrim($tokens[$stackPtr]['content'], '$'); $isPublic = $memberProps['scope'] === 'private' ? false : true; $scope = $memberProps['scope']; $scopeSpecified = $memberProps['scope_specified']; // If it's a private member, it must have an underscore on the front. if ($isPublic === false && $memberName[0] !== '_') { $error = 'Private member variable "%s" must be prefixed with an underscore'; $data = array($memberName); $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data); return; } // If it's not a private member, it must not have an underscore on the front. if ($isPublic === true && $scopeSpecified === true && $memberName[0] === '_') { $error = '%s member variable "%s" must not be prefixed with an underscore'; $data = array(ucfirst($scope), $memberName); $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data); 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 */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $start = $stackPtr + 1; $end = $tokens[$stackPtr]['bracket_closer'] - 1; $inStyle = null; for ($i = $start; $i <= $end; $i++) { // Skip nested definitions as they are checked individually. if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { $i = $tokens[$i]['bracket_closer']; continue; } if ($tokens[$i]['code'] === T_STYLE) { $inStyle = $tokens[$i]['content']; } if ($tokens[$i]['code'] === T_SEMICOLON) { $inStyle = null; } if ($inStyle === 'progid') { // Special case for IE filters. continue; } if ($tokens[$i]['code'] === T_STYLE || $inStyle !== null && $tokens[$i]['code'] === T_STRING) { $expected = strtolower($tokens[$i]['content']); if ($expected !== $tokens[$i]['content']) { $error = 'Style definitions must be lowercase; expected %s but found %s'; $data = array($expected, $tokens[$i]['content']); $phpcsFile->addError($error, $i, 'FoundUpper', $data); } } } //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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') { return; } $commentLine = $tokens[$stackPtr]['line']; $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true); if ($tokens[$lastContent]['line'] !== $commentLine) { return; } if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { return; } // Special case for JS files. if ($tokens[$lastContent]['code'] === T_COMMA || $tokens[$lastContent]['code'] === T_SEMICOLON) { $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, $lastContent - 1, null, true); if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { return; } } $error = 'Comments may not appear after statements'; $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); if ($fix === true) { $phpcsFile->fixer->addNewlineBefore($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(PHP_CodeSniffer_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 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 (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(); } } }
/** * Process the package tag. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param array $tags The tokens for these tags. * */ protected function processPackage(PHP_CodeSniffer_File $phpcsFile, array $tags) { $tokens = $phpcsFile->getTokens(); foreach ($tags as $tag) { if ($tokens[$tag + 2]['code'] !== T_DOC_COMMENT_STRING) { // No content. continue; } $namespace = $this->extractNamespace($phpcsFile); $content = $tokens[$tag + 2]['content']; if ($namespace !== $content) { $phpcsFile->addError('Package name "%s" should be "%s"', $tag, 'InvalidPackage', [$content, $namespace]); continue; } if (PHP_CodeSniffer::isUnderscoreName($content) === true) { continue; } $newContent = str_replace(' ', '_', $content); $newContent = trim($newContent, '_'); $newContent = preg_replace('/[^A-Za-z_]/', '', $newContent); $nameBits = explode('_', $newContent); $firstBit = array_shift($nameBits); $newName = strtoupper($firstBit[0]) . substr($firstBit, 1) . '_'; foreach ($nameBits as $bit) { if ($bit !== '') { $newName .= strtoupper($bit[0]) . substr($bit, 1) . '_'; } } $error = 'Package name "%s" is not valid; consider "%s" instead'; $validName = trim($newName, '_'); $data = [$content, $validName]; $phpcsFile->addError($error, $tag, 'InvalidPackage', $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(PHP_CodeSniffer_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); } }
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { // do nothing if opening tag is the first character if ($stackPtr == 0) { return; } $tokens = $phpcsFile->getTokens(); $isNotFirstOpenTag = $phpcsFile->findPrevious(array(T_OPEN_TAG), $stackPtr - 1, null, false); // some other character beginning file if ($isNotFirstOpenTag === false) { $validShebang = false; // a shebang is allowed on first line only if // it is followed by a php open tag on next line if ($stackPtr == 1 && $tokens[1]['line'] == 2) { // the php tag is the second token and it is on second line // so the first token is on the first line // check if it is valid shebang // T_HASHBANG is a token used in HHVM >=3.5, <3.7 (T103119) if (in_array($tokens[0]['type'], array('T_INLINE_HTML', 'T_HASHBANG')) && substr($tokens[0]['content'], 0, 2) == '#!') { $validShebang = true; } } if (!$validShebang) { $error = 'Extra character found before first <?'; $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $token = $tokens[$stackPtr]; // Skip invalid statement. if (isset($token['parenthesis_opener']) === false) { return; } $next = ++$token['parenthesis_opener']; $end = --$token['parenthesis_closer']; $parts = array(0, 0, 0); $index = 0; for (; $next <= $end; ++$next) { $code = $tokens[$next]['code']; if ($code === T_SEMICOLON) { ++$index; } else { if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === false) { ++$parts[$index]; } } } if ($parts[0] === 0 && $parts[2] === 0 && $parts[1] > 0) { $error = 'This FOR loop can be simplified to a WHILE loop'; $phpcsFile->addWarning($error, $stackPtr, 'CanSimplify'); } }
/** * 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) { $tokens = $phpcsFile->getTokens(); // Find the content of each style definition name. $end = $tokens[$stackPtr]['bracket_closer']; $next = $phpcsFile->findNext(T_STYLE, $stackPtr + 1, $end); if ($next === false) { // Class definition is empty. return; } $styleNames = array(); while ($next !== false) { $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; } $next = $phpcsFile->findNext(T_STYLE, $next + 1, $end); } //end while }
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $currentToken = $tokens[$stackPtr]; if ($currentToken['code'] === T_OPEN_PARENTHESIS && $tokens[$stackPtr - 1]['code'] === T_WHITESPACE && ($tokens[$stackPtr - 2]['code'] === T_STRING || $tokens[$stackPtr - 2]['code'] === T_ARRAY)) { // String (or 'array') followed by whitespace followed by // opening brace is probably a function call. $phpcsFile->addWarning('Space found before opening parenthesis of function call', $stackPtr - 1, 'SpaceBeforeOpeningParenthesis'); } // Check for space between parentheses without any arguments if ($currentToken['code'] === T_OPEN_PARENTHESIS && $tokens[$stackPtr + 1]['code'] === T_WHITESPACE && $tokens[$stackPtr + 2]['code'] === T_CLOSE_PARENTHESIS) { $phpcsFile->addWarning('Unnecessary space found within parentheses', $stackPtr + 1, 'UnnecessarySpaceBetweenParentheses'); return; } // Same check as above, but ignore since it was already processed if ($currentToken['code'] === T_CLOSE_PARENTHESIS && $tokens[$stackPtr - 1]['code'] === T_WHITESPACE && $tokens[$stackPtr - 2]['code'] === T_OPEN_PARENTHESIS) { return; } if ($currentToken['code'] === T_OPEN_PARENTHESIS) { $this->processOpenParenthesis($phpcsFile, $tokens, $stackPtr); } else { // T_CLOSE_PARENTHESIS $this->processCloseParenthesis($phpcsFile, $tokens, $stackPtr); } }
/** * 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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { // We are only interested if this is the first open tag. if ($stackPtr !== 0) { if ($phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1) !== false) { return; } } $found = $phpcsFile->eolChar; $found = str_replace("\n", '\\n', $found); $found = str_replace("\r", '\\r', $found); if ($found !== $this->eolChar) { // Check for single line files without an EOL. This is a very special // case and the EOL char is set to \n when this happens. if ($found === '\\n') { $tokens = $phpcsFile->getTokens(); $lastToken = $phpcsFile->numTokens - 1; if ($tokens[$lastToken]['line'] === 1 && $tokens[$lastToken]['content'] !== "\n") { return; } } $error = 'End of line character is invalid; expected "%s" but found "%s"'; $expected = $this->eolChar; $expected = str_replace("\n", '\\n', $expected); $expected = str_replace("\r", '\\r', $expected); $data = array($expected, $found); $phpcsFile->addError($error, $stackPtr, 'InvalidEOLChar', $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(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($tokens[$prev]['code'] !== T_STYLE) { // The colon is not part of a style definition. return; } if ($tokens[$prev]['content'] === 'progid') { // Special case for IE filters. return; } if ($tokens[$stackPtr - 1]['code'] === T_WHITESPACE) { $error = 'There must be no space before a colon in a style definition'; $phpcsFile->addError($error, $stackPtr, 'Before'); } if ($tokens[$stackPtr + 1]['code'] !== T_WHITESPACE) { $error = 'Expected 1 space after colon in style definition; 0 found'; $phpcsFile->addError($error, $stackPtr, 'NoneAfter'); } else { $content = $tokens[$stackPtr + 1]['content']; if (strpos($content, $phpcsFile->eolChar) === false) { $length = strlen($content); if ($length !== 1) { $error = 'Expected 1 space after colon in style definition; %s found'; $data = array($length); $phpcsFile->addError($error, $stackPtr, 'After', $data); } } else { $error = 'Expected 1 space after colon in style definition; newline found'; $phpcsFile->addError($error, $stackPtr, 'AfterNewline'); } } //end if }
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { $var = $phpcsFile->getTokens()[$stackPtr]['content']; if (in_array($var, $this->superglobals)) { $phpcsFile->addError('Direct use of %s Superglobal detected.', $stackPtr, 'SuperglobalUsage', array($var)); } }