/** * Will iterate tokens looking for comments and if found will determine the regex * to test the comment against. * * @param Testable $testable The testable object * @return void */ public function apply($testable, array $config = array()) { $tokens = $testable->tokens(); $comments = $testable->findAll(array(T_COMMENT)); foreach ($comments as $tokenId) { $token = $tokens[$tokenId]; $parentId = $tokens[$tokenId]['parent']; if ($parentId === -1 || $tokens[$parentId]['id'] !== T_FUNCTION) { $this->addViolation(array('message' => 'Inline comments should never appear.', 'line' => $token['line'])); } elseif (preg_match('/^test/', Parser::label($parentId, $tokens)) === 0) { $this->addViolation(array('message' => 'Inline comments should only appear in testing methods.', 'line' => $token['line'])); } } }
/** * Will iterate the tokens looking for functions validating they have the * correct camelBack naming style. * * @param Testable $testable The testable object * @return void */ public function apply($testable, array $config = array()) { $tokens = $testable->tokens(); $filtered = $testable->findAll(array(T_FUNCTION)); foreach ($filtered as $key) { $token = $tokens[$key]; $label = Parser::label($key, $tokens); $modifiers = Parser::modifiers($key, $tokens); $isClosure = Parser::closure($key, $tokens); if (in_array($label, $this->_magicMethods)) { continue; } if ($testable->findNext(array(T_PROTECTED), $modifiers) !== false) { $label = preg_replace('/^_/', '', $label); } if (!$isClosure && $label !== Inflector::camelize($label, false)) { $this->addViolation(array('message' => 'Function "' . $label . '" is not in camelBack style', 'line' => $tokens[$tokens[$key]['parent']]['line'])); } } }
/** * Will iterate all the tokens looking for tokens in inspectableTokens * The token needs an access modifier if it is a T_FUNCTION or T_VARIABLE * and is in the first level of T_CLASS. This prevents functions and variables * inside methods and outside classes to register violations. * * @param Testable $testable The testable object * @return void */ public function apply($testable, array $config = array()) { $message = '{:name} has no declared visibility.'; $tokens = $testable->tokens(); $classes = $testable->findAll(array(T_CLASS)); $filtered = $testable->findAll($this->inspectableTokens); foreach ($classes as $classId) { $children = $tokens[$classId]['children']; foreach ($children as $member) { if (!in_array($member, $filtered)) { continue; } $modifiers = Parser::modifiers($member, $tokens); $visibility = $testable->findNext($this->findTokens, $modifiers); if ($visibility === false) { $token = $tokens[$member]; $this->addViolation(array('modifiers' => $modifiers, 'message' => String::insert($message, $token), 'line' => $token['line'])); } } } }
/** * Will iterate the tokens looking for protected methods and variables, once * found it will validate the name of it's parent starts with an underscore. * * @param Testable $testable The testable object * @return void */ public function apply($testable, array $config = array()) { $message = 'Protected method {:name} must start with an underscore'; $tokens = $testable->tokens(); $filtered = $testable->findAll(array(T_PROTECTED)); foreach ($filtered as $tokenId) { $token = $tokens[$tokenId]; $parent = $testable->findNext(array(T_FUNCTION, T_VARIABLE), $tokenId); $parentLabel = Parser::label($parent, $tokens); if (substr($parentLabel, 0, 1) !== '_') { $classTokenId = $testable->findNext(array(T_STRING), $token['parent']); $classname = $tokens[$classTokenId]['content']; $params = array('message' => String::insert($message, array('name' => $parentLabel)), 'line' => $token['line']); if ($this->_strictMode($classname)) { $this->addViolation($params); } else { $this->addWarning($params); } } } }
/** * Accessor method for the tokens. * * It only tokenizes the file when the tokens are actually needed, * which increases performance in cases where you only need to * apply regex checks on the file. The result is cached afterwards. * * @return array */ public function tokens() { if ($this->_tokens === null) { $tokenized = Parser::tokenize($this->source(), $this->_config); $this->_tokens = $tokenized['tokens']; $this->_lineCache = $tokenized['lineCache']; $this->_typeCache = $tokenized['typeCache']; } return $this->_tokens; }
public function testFindNextContentWithArray() { $code = <<<EOD class foo { \tprivate function bar() { \t} } EOD; $testable = $this->_testable(array('source' => $code)); $tokens = $testable->tokens(); $contentToFind = array('public', 'protected', 'private'); $id = $testable->findNext(array(T_FUNCTION), 0); // function bar $modifiers = Parser::modifiers($id, $tokens); $visibility = $testable->findNextContent($contentToFind, $modifiers); $this->assertIdentical('private', $tokens[$visibility]['content']); }
public function testParseSwitchWithoutBreak() { $code = <<<EOD switch (true) { \tcase \$a: \t\treturn \$value1; \tcase \$b: \t\treturn \$value2; } return false; EOD; $tokenized = Parser::tokenize($code); $tokens = $tokenized['tokens']; $this->assertCount(34, $tokens); $this->assertIdentical('}', $tokens[28]['content']); $this->assertIdentical(0, $tokens[28]['nestLevel']); }