/** * visitToken(): defined by TokenRuleInterface. * * @see TokenRuleInterface::visitToken() * @param File $file * @return void */ public function visitToken(File $file) { $token = $file->current(); if (false !== strpos($token->getLexeme(), "\t")) { $this->addViolation($file, $token->getLine(), $token->getColumn(), 'Tabulator found'); } }
/** * visitFile(): defined by FileRuleInterface. * * @see FileRuleInterface::visitFile() * @param File $file * @return void */ public function visitFile(File $file) { $lastToken = $file->top(); if ($lastToken->getType() !== T_WHITESPACE || $lastToken->getNewlineCount() !== 1 || $lastToken->getTrailingLineLength() !== 0) { $this->addViolation($file, $lastToken->getLine(), $lastToken->getColumn(), 'File does not end with a single blank line'); } }
/** * visitFile(): defined by FileRuleInterface. * * @see FileRuleInterface::visitFile() * @param File $file * @return void */ public function visitFile(File $file) { foreach ($file->getLines() as $line => $data) { if (preg_match('(\\s+$)', $data['content'])) { $this->addViolation($file, $line, 0, 'Line contains trailing whitespace'); } } }
/** * visitFile(): defined by FileRuleInterface. * * @see FileRuleInterface::visitFile() * @param File $file * @return void */ public function visitFile(File $file) { foreach ($file->getLines() as $line => $data) { if ($data['ending'] !== '' && $data['ending'] !== $this->eolChar) { $ending = str_replace(array("\r", "\n"), array('\\r', '\\n'), $data['ending']); $this->addViolation($file, $line, 0, sprintf('Line must end with "%s", found "%s"', $this->eolName, $ending)); } } }
/** * Assert a specific set of violations. * * @param File $file * @param array $expectedViolations * @return void */ public function assertRuleViolations(File $file, array $expectedViolations) { // Get all violations and convert them to an array for comparision. $violations = array(); foreach ($file->getViolations() as $error) { $violations[] = array('line' => $error->getLine(), 'column' => $error->getColumn(), 'message' => $error->getMessage(), 'source' => $error->getSource()); } $this->assertEquals($expectedViolations, $violations); }
/** * visitToken(): defined by TokenRuleInterface. * * @see TokenRuleInterface::visitToken() * @param File $file * @return void */ public function visitToken(File $file) { if (!$file->seekTokenType(T_STRING, false, ';')) { return; } $token = $file->current(); if (!preg_match('(^' . $this->format . '$)', $token->getLexeme())) { $this->addViolation($file, $token->getLine(), $token->getColumn(), sprintf('Constant name does not match format "%s"', $this->format)); } }
/** * visitToken(): defined by TokenRuleInterface. * * @see TokenRuleInterface::visitToken() * @param File $file * @return void */ public function visitToken(File $file) { if (!$file->seekTokenType(T_STRING, false, '(')) { return; } $token = $file->current(); if (!in_array($token->getLexeme(), self::$magicMethods) && !preg_match('(^' . $this->format . '$)', $token->getLexeme())) { $this->addViolation($file, $token->getLine(), $token->getColumn(), sprintf('Method name does not match format "%s"', $this->format)); } }
/** * Add a violation to the current file. * * @param File $file * @param integer $line * @param integer $column * @param string $message * @param integer|null $severity * @return void */ protected function addViolation(File $file, $line, $column, $message, $severity = null) { $source = get_class($this); if (strpos($source, 'Flitch\\Rule\\') === 0) { $source = 'Flitch\\' . substr($source, strlen('Flitch\\Rule\\')); } if ($severity === null) { $severity = $this->severity; } $file->addViolation(new Violation($line, $column, $severity, $message, $source)); }
/** * visitFile(): defined by FileRuleInterface. * * @see FileRuleInterface::visitFile() * @param File $file * @return void */ public function visitFile(File $file) { $source = $file->getSource(); if (@iconv($this->encoding, $this->encoding, $source) !== $source) { $this->addViolation($file, 0, 0, sprintf('File is not encoded in "%s"', $this->encoding)); return; } if (!$this->allowBom && isset(self::$byteOrderMarks[$this->encoding])) { $bom = self::$byteOrderMarks[$this->encoding]; if (substr($source, 0, strlen($bom)) === $bom) { $this->addViolation($file, 0, 0, sprintf('File starts with a BOM', $this->encoding)); } } }
/** * addFile(): defined by Report interface. * * @see Report::addFile() * @param File $file * @return void */ public function addFile(File $file) { $this->writer->startElement('file'); $this->writer->writeAttribute('name', $file->getFilename()); foreach ($file->getViolations() as $violation) { $this->writer->startElement('error'); $this->writer->writeAttribute('line', $violation->getLine()); if ($violation->getColumn() > 0) { $this->writer->writeAttribute('column', $violation->getColumn()); } $this->writer->writeAttribute('severity', $violation->getSeverity()); $this->writer->writeAttribute('message', $violation->getMessage()); $this->writer->writeAttribute('source', $violation->getSource()); $this->writer->endElement(); } $this->writer->endElement(); }
/** * visitToken(): defined by TokenRuleInterface. * * @see TokenRuleInterface::visitToken() * @param File $file * @return void */ public function visitToken(File $file) { $previousToken = null; $currentToken = $file->current(); $file->next(); $secondStatement = false; while ($file->valid()) { $token = $file->current(); $tokenType = $token->getType(); if (in_array($tokenType, array(T_COMMENT, T_DOC_COMMENT))) { $lexeme = $token->getLexeme(); if (strpos($lexeme, '//') === 0 || strpos($lexeme, '#') === 0) { // Single line comments end the line break; } elseif ($token->getNewlineCount() > 0) { // So do block comments with new lines break; } } elseif ($tokenType === T_WHITESPACE) { if ($token->getNewlineCount() > 0) { // Whitespace new lines are fine as well break; } } else { $secondStatement = true; break; } $file->next(); } if ($previousToken !== null) { if ($currentToken->getLine() === $previousToken->getLine()) { $this->addViolation($file, $currentToken->getLine(), $currentToken->getColumn(), 'Found multiple statements on same line'); } } }
/** * visitToken(): defined by TokenRuleInterface. * * @see TokenRuleInterface::visitToken() * @param File $file * @return void */ public function visitToken(File $file) { if (!$file->seekTokenType(T_STRING, false, '{')) { return; } $token = $file->current(); $psr0Compliant = true; if ($token->getNamespace() !== null) { $fqcn = $token->getNamespace() . '\\' . $token->getLexeme(); $path = str_replace('\\', '/', $token->getNamespace()) . '/' . str_replace('_', '/', $token->getLexeme()); } else { $fqcn = $token->getLexeme(); $path = str_replace('_', '/', $token->getLexeme()); if ($this->requireVendorNamespace) { $psr0Compliant = false; } } if ($psr0Compliant) { $expectedPathParts = array_diff(explode('/', $path), array('')); $expectedFilename = array_pop($expectedPathParts) . '.php'; $pathParts = explode('/', str_replace('\\', '/', realpath($file->getFilename()))); $filename = array_pop($pathParts); if ($filename !== $expectedFilename) { // Class name should match filename. $psr0Compliant = false; } elseif (count($expectedPathParts) === 0) { // Vendor level namespace required. $psr0Compliant = false; } else { // Path should match namespace structure. $pathParts = array_slice($pathParts, -count($expectedPathParts)); if ($pathParts !== $expectedPathParts) { $psr0Compliant = false; } } } if (!$psr0Compliant) { $this->addViolation($file, $token->getLine(), $token->getColumn(), sprintf('Class name "%s" is not PSR0 compliant', $fqcn)); } }
/** * addFile(): defined by Report interface. * * @see Report::addFile() * @param File $file * @return void */ public function addFile(File $file) { $violations = $file->getViolations(); if ($violations) { if ($this->firstFile) { $this->firstFile = false; } else { echo PHP_EOL; } echo $file->getFilename() . ':' . PHP_EOL; echo str_repeat('-', 80) . PHP_EOL; foreach ($violations as $violation) { echo $violation->getLine() . ':'; if ($violation->getColumn() > 0) { echo $violation->getColumn() . ':'; } echo $violation->getSeverityName() . ': '; echo $violation->getMessage() . PHP_EOL; } flush(); } }
/** * check(): defined by Rule interface. * * @see Rule::check() * @param File $file * @return void */ public function check(File $file) { $indentation = str_repeat($this->indentStyle === 'space' ? ' ' : "\t", $this->indentCount); $file->rewind(); while (true) { $token = $file->current(); $level = $token->getLevel(); $file->next(); if ($file->current()->getType() === '}' || $file->current()->getType() === ')') { $level--; } $file->prev(); $expectedIndentation = str_repeat($indentation, $level); $actualIndentation = $token->getTrailingWhitespace(); if ($expectedIndentation !== $actualIndentation) { $this->addViolation($file, $token, $column, $message); } if (!$file->seekNextLine()) { return; } } }
/** * visitFile(): defined by FileRuleInterface. * * @see FileRuleInterface::visitFile() * @param File $file * @return void */ public function visitFile(File $file) { foreach ($file->getLines() as $line => $data) { $lineLength = iconv_strlen(str_replace("\t", str_repeat(' ', $this->tabExpand), $data['content']), $file->getEncoding()); $violationLimit = null; $severity = null; if ($this->errorLimit !== null && $lineLength > $this->errorLimit) { $violationLimit = $this->errorLimit; $severity = Violation::SEVERITY_ERROR; } elseif ($this->warningLimit !== null && $lineLength > $this->warningLimit) { $violationLimit = $this->warningLimit; $severity = Violation::SEVERITY_WARNING; } elseif ($this->infoLimit !== null && $lineLength > $this->infoLimit) { $violationLimit = $this->infoLimit; $severity = Violation::SEVERITY_INFO; } if ($violationLimit !== null) { $this->addViolation($file, $line, 0, sprintf('Line is longer than %d characters', $violationLimit), $severity); } } }