/** * Populates the array of PHP_CodeSniffer_Sniff's for this file. * * @return void * @throws RuntimeException If sniff registration fails. */ public function populateTokenListeners() { // Construct a list of listeners indexed by token being listened for. $this->tokenListeners = array(); foreach ($this->sniffs as $sniffClass => $sniffObject) { $this->sniffs[$sniffClass] = null; $this->sniffs[$sniffClass] = new $sniffClass(); $sniffCode = Util\Common::getSniffCode($sniffClass); $this->sniffCodes[$sniffCode] = $sniffClass; // Set custom properties. if (isset($this->ruleset[$sniffCode]['properties']) === true) { foreach ($this->ruleset[$sniffCode]['properties'] as $name => $value) { $this->setSniffProperty($sniffClass, $name, $value); } } $tokenizers = array(); $vars = get_class_vars($sniffClass); if (isset($vars['supportedTokenizers']) === true) { foreach ($vars['supportedTokenizers'] as $tokenizer) { $tokenizers[$tokenizer] = $tokenizer; } } else { $tokenizers = array('PHP' => 'PHP'); } $tokens = $this->sniffs[$sniffClass]->register(); if (is_array($tokens) === false) { $msg = "Sniff {$sniffClass} register() method must return an array"; throw new RuntimeException($msg); } $ignorePatterns = array(); $patterns = $this->getIgnorePatterns($sniffCode); foreach ($patterns as $pattern => $type) { $replacements = array('\\,' => ',', '*' => '.*'); $ignorePatterns[] = strtr($pattern, $replacements); } $includePatterns = array(); $patterns = $this->getIncludePatterns($sniffCode); foreach ($patterns as $pattern => $type) { $replacements = array('\\,' => ',', '*' => '.*'); $includePatterns[] = strtr($pattern, $replacements); } foreach ($tokens as $token) { if (isset($this->tokenListeners[$token]) === false) { $this->tokenListeners[$token] = array(); } if (isset($this->tokenListeners[$token][$sniffClass]) === false) { $this->tokenListeners[$token][$sniffClass] = array('class' => $sniffClass, 'source' => $sniffCode, 'tokenizers' => $tokenizers, 'ignore' => $ignorePatterns, 'include' => $includePatterns); } } } //end foreach }
/** * Adds an error to the error stack. * * @param boolean $error Is this an error message? * @param string $message The text of the message. * @param int $line The line on which the message occurred. * @param int $column The column at which the message occurred. * @param string $code A violation code unique to the sniff message. * @param array $data Replacements for the message. * @param int $severity The severity level for this message. A value of 0 * will be converted into the default severity level. * @param boolean $fixable Can the problem be fixed by the sniff? * * @return boolean */ protected function addMessage($error, $message, $line, $column, $code, $data, $severity, $fixable) { if (isset($this->tokenizer->ignoredLines[$line]) === true) { return false; } $includeAll = true; if ($this->configCache['cache'] === false || $this->configCache['recordErrors'] === false) { $includeAll = false; } // Work out which sniff generated the message. $parts = explode('.', $code); if ($parts[0] === 'Internal') { // An internal message. $listenerCode = Util\Common::getSniffCode($this->activeListener); $sniffCode = $code; $checkCodes = array($sniffCode); } else { if ($parts[0] !== $code) { // The full message code has been passed in. $sniffCode = $code; $listenerCode = substr($sniffCode, 0, strrpos($sniffCode, '.')); } else { $listenerCode = Util\Common::getSniffCode($this->activeListener); $sniffCode = $listenerCode . '.' . $code; $parts = explode('.', $sniffCode); } $checkCodes = array($sniffCode, $parts[0] . '.' . $parts[1] . '.' . $parts[2], $parts[0] . '.' . $parts[1], $parts[0]); } //end if // Filter out any messages for sniffs that shouldn't have run // due to the use of the --sniffs command line argument. if ($includeAll === false && (empty($this->configCache['sniffs']) === false && in_array($listenerCode, $this->configCache['sniffs']) === false || empty($this->configCache['exclude']) === false && in_array($listenerCode, $this->configCache['exclude']) === true)) { return false; } // If we know this sniff code is being ignored for this file, return early. foreach ($checkCodes as $checkCode) { if (isset($this->ignoredCodes[$checkCode]) === true) { return false; } } $oppositeType = 'warning'; if ($error === false) { $oppositeType = 'error'; } foreach ($checkCodes as $checkCode) { // Make sure this message type has not been set to the opposite message type. if (isset($this->ruleset->ruleset[$checkCode]['type']) === true && $this->ruleset->ruleset[$checkCode]['type'] === $oppositeType) { $error = !$error; break; } } if ($error === true) { $configSeverity = $this->configCache['errorSeverity']; $messageCount =& $this->errorCount; $messages =& $this->errors; } else { $configSeverity = $this->configCache['warningSeverity']; $messageCount =& $this->warningCount; $messages =& $this->warnings; } if ($includeAll === false && $configSeverity === 0) { // Don't bother doing any processing as these messages are just going to // be hidden in the reports anyway. return false; } if ($severity === 0) { $severity = 5; } foreach ($checkCodes as $checkCode) { // Make sure we are interested in this severity level. if (isset($this->ruleset->ruleset[$checkCode]['severity']) === true) { $severity = $this->ruleset->ruleset[$checkCode]['severity']; break; } } if ($includeAll === false && $configSeverity > $severity) { return false; } // Make sure we are not ignoring this file. foreach ($checkCodes as $checkCode) { if (isset($this->configCache['ignorePatterns'][$checkCode]) === false) { continue; } foreach ($this->configCache['ignorePatterns'][$checkCode] as $pattern => $type) { // While there is support for a type of each pattern // (absolute or relative) we don't actually support it here. $replacements = array('\\,' => ',', '*' => '.*'); // We assume a / directory separator, as do the exclude rules // most developers write, so we need a special case for any system // that is different. if (DIRECTORY_SEPARATOR === '\\') { $replacements['/'] = '\\\\'; } $pattern = '`' . strtr($pattern, $replacements) . '`i'; if (preg_match($pattern, $this->path) === 1) { $this->ignoredCodes[$checkCode] = true; return false; } } //end foreach } //end foreach $messageCount++; if ($fixable === true) { $this->fixableCount++; } if ($this->configCache['recordErrors'] === false && $includeAll === false) { return true; } // Work out the error message. if (isset($this->ruleset->ruleset[$sniffCode]['message']) === true) { $message = $this->ruleset->ruleset[$sniffCode]['message']; } if (empty($data) === false) { $message = vsprintf($message, $data); } if (isset($messages[$line]) === false) { $messages[$line] = array(); } if (isset($messages[$line][$column]) === false) { $messages[$line][$column] = array(); } $messages[$line][$column][] = array('message' => $message, 'source' => $sniffCode, 'listener' => $this->activeListener, 'severity' => $severity, 'fixable' => $fixable); if (PHP_CODESNIFFER_VERBOSITY > 1 && $this->fixer->enabled === true && $fixable === true) { @ob_end_clean(); echo "\tE: [Line {$line}] {$message} ({$sniffCode})" . PHP_EOL; ob_start(); } return true; }