Beispiel #1
0
 /**
  * Constructs a doc generator.
  *
  * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run.
  *
  * @see generate()
  */
 public function __construct(Ruleset $ruleset)
 {
     $this->ruleset = $ruleset;
     $standardFiles = array();
     foreach ($ruleset->sniffs as $className => $sniffClass) {
         $file = Autoload::getLoadedFileName($className);
         $docFile = str_replace(DIRECTORY_SEPARATOR . 'Sniffs' . DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR . 'Docs' . DIRECTORY_SEPARATOR, $file);
         $docFile = str_replace('Sniff.php', 'Standard.xml', $docFile);
         if (is_file($docFile) === true) {
             $this->docFiles[] = $docFile;
         }
     }
 }
Beispiel #2
0
 /**
  * Loads existing cache data for the run, if any.
  *
  * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run.
  * @param \PHP_CodeSniffer\Config  $config  The config data for the run.
  *
  * @return void
  */
 public static function load(Ruleset $ruleset, Config $config)
 {
     // Look at every loaded sniff class so far and use their file contents
     // to generate a hash for the code used during the run.
     // At this point, the loaded class list contains the core PHPCS code
     // and all sniffs that have been loaded as part of the run.
     if (PHP_CODESNIFFER_VERBOSITY > 1) {
         echo PHP_EOL . "\tGenerating loaded file list for code hash" . PHP_EOL;
     }
     $codeHash = '';
     $classes = array_keys(Autoload::getLoadedClasses());
     sort($classes);
     $installDir = dirname(__DIR__);
     $installDirLen = strlen($installDir);
     $standardDir = $installDir . DIRECTORY_SEPARATOR . 'Standards';
     $standardDirLen = strlen($standardDir);
     foreach ($classes as $file) {
         if (substr($file, 0, $standardDirLen) !== $standardDir) {
             if (substr($file, 0, $installDirLen) === $installDir) {
                 // We are only interested in sniffs here.
                 continue;
             }
             if (PHP_CODESNIFFER_VERBOSITY > 1) {
                 echo "\t\t=> external file: {$file}" . PHP_EOL;
             }
         } else {
             if (PHP_CODESNIFFER_VERBOSITY > 1) {
                 echo "\t\t=> internal sniff: {$file}" . PHP_EOL;
             }
         }
         $codeHash .= md5_file($file);
     }
     // Add the content of the used rulesets to the hash so that sniff setting
     // changes in the ruleset invalidate the cache.
     $rulesets = $ruleset->paths;
     sort($rulesets);
     foreach ($rulesets as $file) {
         if (substr($file, 0, $standardDirLen) !== $standardDir) {
             if (PHP_CODESNIFFER_VERBOSITY > 1) {
                 echo "\t\t=> external ruleset: {$file}" . PHP_EOL;
             }
         } else {
             if (PHP_CODESNIFFER_VERBOSITY > 1) {
                 echo "\t\t=> internal ruleset: {$file}" . PHP_EOL;
             }
         }
         $codeHash .= md5_file($file);
     }
     // Go through the core PHPCS code and add those files to the file
     // hash. This ensures that core PHPCS changes will also invalidate the cache.
     // Note that we ignore sniffs here, and any files that don't affect
     // the outcome of the run.
     $di = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($installDir), 0, \RecursiveIteratorIterator::CATCH_GET_CHILD);
     $di = new \RecursiveDirectoryIterator($installDir);
     $filter = new \RecursiveCallbackFilterIterator($di, function ($file, $key, $iterator) {
         // Skip hidden files.
         $filename = $file->getFilename();
         if (substr($filename, 0, 1) === '.') {
             return false;
         }
         $filePath = Common::realpath($file->getPathname());
         if ($filePath === false) {
             return false;
         }
         if (is_dir($filePath) === true && ($filename === 'Standards' || $filename === 'Exceptions' || $filename === 'Reports' || $filename === 'Generators')) {
             return false;
         }
         return true;
     });
     $iterator = new \RecursiveIteratorIterator($filter);
     foreach ($iterator as $file) {
         if (PHP_CODESNIFFER_VERBOSITY > 1) {
             echo "\t\t=> core file: {$file}" . PHP_EOL;
         }
         $codeHash .= md5_file($file);
     }
     $codeHash = md5($codeHash);
     // Along with the code hash, use various settings that can affect
     // the results of a run to create a new hash. This hash will be used
     // in the cache file name.
     $rulesetHash = md5(var_export($ruleset->ignorePatterns, true) . var_export($ruleset->includePatterns, true));
     $configData = array('tabWidth' => $config->tabWidth, 'encoding' => $config->encoding, 'recordErrors' => $config->recordErrors, 'codeHash' => $codeHash, 'rulesetHash' => $rulesetHash);
     $configString = implode(',', $configData);
     $cacheHash = substr(sha1($configString), 0, 12);
     if (PHP_CODESNIFFER_VERBOSITY > 1) {
         echo "\tGenerating cache key data" . PHP_EOL;
         echo "\t\t=> tabWidth: " . $configData['tabWidth'] . PHP_EOL;
         echo "\t\t=> encoding: " . $configData['encoding'] . PHP_EOL;
         echo "\t\t=> recordErrors: " . (int) $configData['recordErrors'] . PHP_EOL;
         echo "\t\t=> codeHash: " . $configData['codeHash'] . PHP_EOL;
         echo "\t\t=> rulesetHash: " . $configData['rulesetHash'] . PHP_EOL;
         echo "\t\t=> cacheHash: {$cacheHash}" . PHP_EOL;
     }
     if ($config->cacheFile !== null) {
         $cacheFile = $config->cacheFile;
     } else {
         // Determine the common paths for all files being checked.
         // We can use this to locate an existing cache file, or to
         // determine where to create a new one.
         if (PHP_CODESNIFFER_VERBOSITY > 1) {
             echo "\tChecking possible cache file paths" . PHP_EOL;
         }
         $paths = array();
         foreach ($config->files as $file) {
             $file = Common::realpath($file);
             while ($file !== DIRECTORY_SEPARATOR) {
                 if (isset($paths[$file]) === false) {
                     $paths[$file] = 1;
                 } else {
                     $paths[$file]++;
                 }
                 $lastFile = $file;
                 $file = dirname($file);
                 if ($file === $lastFile) {
                     // Just in case something went wrong,
                     // we don't want to end up in an infinite loop.
                     break;
                 }
             }
         }
         ksort($paths);
         $paths = array_reverse($paths);
         $numFiles = count($config->files);
         $tmpDir = sys_get_temp_dir();
         $cacheFile = null;
         foreach ($paths as $file => $count) {
             if ($count !== $numFiles) {
                 unset($paths[$file]);
                 continue;
             }
             $fileHash = substr(sha1($file), 0, 12);
             $testFile = $tmpDir . DIRECTORY_SEPARATOR . "phpcs.{$fileHash}.{$cacheHash}.cache";
             if ($cacheFile === null) {
                 // This will be our default location if we can't find
                 // an existing file.
                 $cacheFile = $testFile;
             }
             if (PHP_CODESNIFFER_VERBOSITY > 1) {
                 echo "\t\t=> {$testFile}" . PHP_EOL;
                 echo "\t\t\t * based on shared location: {$file} *" . PHP_EOL;
             }
             if (file_exists($testFile) === true) {
                 $cacheFile = $testFile;
                 break;
             }
         }
         //end foreach
         if ($cacheFile === null) {
             // Unlikely, but just in case $paths is empty for some reason.
             $cacheFile = $tmpDir . DIRECTORY_SEPARATOR . "phpcs.{$cacheHash}.cache";
         }
     }
     //end if
     self::$path = $cacheFile;
     if (PHP_CODESNIFFER_VERBOSITY > 1) {
         echo "\t=> Using cache file: " . self::$path . PHP_EOL;
     }
     if (file_exists(self::$path) === true) {
         self::$cache = json_decode(file_get_contents(self::$path), true);
         // Verify the contents of the cache file.
         if (self::$cache['config'] !== $configData) {
             self::$cache = array();
             if (PHP_CODESNIFFER_VERBOSITY > 1) {
                 echo "\t* cache was invalid and has been cleared *" . PHP_EOL;
             }
         }
     } else {
         if (PHP_CODESNIFFER_VERBOSITY > 1) {
             echo "\t* cache file does not exist *" . PHP_EOL;
         }
     }
     self::$cache['config'] = $configData;
 }
Beispiel #3
0
 /**
  * Loads and stores sniffs objects used for sniffing files.
  *
  * @param array $files        Paths to the sniff files to register.
  * @param array $restrictions The sniff class names to restrict the allowed
  *                            listeners to.
  * @param array $exclusions   The sniff class names to exclude from the
  *                            listeners list.
  *
  * @return void
  */
 public function registerSniffs($files, $restrictions, $exclusions)
 {
     $listeners = array();
     foreach ($files as $file) {
         // Work out where the position of /StandardName/Sniffs/... is
         // so we can determine what the class will be called.
         $sniffPos = strrpos($file, DIRECTORY_SEPARATOR . 'Sniffs' . DIRECTORY_SEPARATOR);
         if ($sniffPos === false) {
             continue;
         }
         $slashPos = strrpos(substr($file, 0, $sniffPos), DIRECTORY_SEPARATOR);
         if ($slashPos === false) {
             continue;
         }
         $className = Autoload::loadFile($file);
         // If they have specified a list of sniffs to restrict to, check
         // to see if this sniff is allowed.
         if (empty($restrictions) === false && isset($restrictions[strtolower($className)]) === false) {
             continue;
         }
         // If they have specified a list of sniffs to exclude, check
         // to see if this sniff is allowed.
         if (empty($exclusions) === false && isset($exclusions[strtolower($className)]) === true) {
             continue;
         }
         // Skip abstract classes.
         $reflection = new \ReflectionClass($className);
         if ($reflection->isAbstract() === true) {
             continue;
         }
         $listeners[$className] = $className;
         if (PHP_CODESNIFFER_VERBOSITY > 2) {
             echo "Registered {$className}" . PHP_EOL;
         }
     }
     //end foreach
     $this->sniffs = $listeners;
 }
Beispiel #4
0
 /**
  * Initialise the reporter.
  *
  * All reports specified in the config will be created and their
  * output file (or a temp file if none is specified) initialised by
  * clearing the current contents.
  *
  * @param \PHP_CodeSniffer\Config $config The config data for the run.
  *
  * @return void
  * @throws RuntimeException If a report is not available.
  */
 public function __construct(Config $config)
 {
     $this->config = $config;
     foreach ($config->reports as $type => $output) {
         $type = ucfirst($type);
         if ($output === null) {
             $output = $config->reportFile;
         }
         if (strpos($type, '.') !== false) {
             // This is a path to a custom report class.
             $filename = realpath($type);
             if ($filename === false) {
                 echo "ERROR: Custom report \"{$type}\" not found" . PHP_EOL;
                 exit(3);
             }
             $reportClassName = Autoload::loadFile($filename);
         } else {
             $reportClassName = 'PHP_CodeSniffer\\Reports\\' . $type;
         }
         $reportClass = new $reportClassName();
         if (false === $reportClass instanceof Report) {
             throw new RuntimeException('Class "' . $reportClassName . '" must implement the "PHP_CodeSniffer\\Report" interface.');
         }
         $this->reports[$type] = array('output' => $output, 'class' => $reportClass);
         if ($output === null) {
             // Using a temp file.
             $this->tmpFiles[$type] = tempnam(sys_get_temp_dir(), 'phpcs');
             file_put_contents($this->tmpFiles[$type], '');
         } else {
             file_put_contents($output, '');
         }
     }
     //end foreach
 }
Beispiel #5
0
 /**
  * Get the class name of the filter being used for the run.
  *
  * @return string
  */
 private function getFilterClass()
 {
     $filterType = $this->config->filter;
     if ($filterType === null) {
         $filterClass = '\\PHP_CodeSniffer\\Filters\\Filter';
     } else {
         if (strpos($filterType, '.') !== false) {
             // This is a path to a custom filter class.
             $filename = realpath($filterType);
             if ($filename === false) {
                 echo "ERROR: Custom filter \"{$filterType}\" not found" . PHP_EOL;
                 exit(3);
             }
             $filterClass = \PHP_CodeSniffer\Autoload::loadFile($filename);
         } else {
             $filterClass = '\\PHP_CodeSniffer\\Filters\\' . $filterType;
         }
     }
     return $filterClass;
 }