/** * Run the code sniffs over a single given file. * * Processes the file and runs the PHP_CodeSniffer sniffs to verify that it * conforms with the standard. Returns the processed file object, or NULL * if no file was processed due to error. * * @param string $file The file to process. * @param string $contents The contents to parse. If NULL, the content * is taken from the file system. * * @return PHP_CodeSniffer_File * @throws PHP_CodeSniffer_Exception If the file could not be processed. * @see _processFile() */ public function processFile($file, $contents = null) { if ($contents === null && file_exists($file) === false) { throw new PHP_CodeSniffer_Exception("Source file {$file} does not exist"); } $filePath = self::realpath($file); if ($filePath === false) { $filePath = $file; } // Before we go and spend time tokenizing this file, just check // to see if there is a tag up top to indicate that the whole // file should be ignored. It must be on one of the first two lines. $firstContent = $contents; if ($contents === null && is_readable($filePath) === true) { $handle = fopen($filePath, 'r'); if ($handle !== false) { $firstContent = fgets($handle); $firstContent .= fgets($handle); fclose($handle); if (strpos($firstContent, '@codingStandardsIgnoreFile') !== false) { // We are ignoring the whole file. if (PHP_CODESNIFFER_VERBOSITY > 0) { echo 'Ignoring ' . basename($filePath) . PHP_EOL; } return null; } } } //end if try { $phpcsFile = $this->_processFile($file, $contents); } catch (Exception $e) { $trace = $e->getTrace(); $filename = $trace[0]['args'][0]; if (is_object($filename) === true && get_class($filename) === 'PHP_CodeSniffer_File') { $filename = $filename->getFilename(); } elseif (is_numeric($filename) === true) { // See if we can find the PHP_CodeSniffer_File object. foreach ($trace as $data) { if (isset($data['args'][0]) === true && $data['args'][0] instanceof PHP_CodeSniffer_File === true) { $filename = $data['args'][0]->getFilename(); } } } elseif (is_string($filename) === false) { $filename = (string) $filename; } $errorMessage = '"' . $e->getMessage() . '" at ' . $e->getFile() . ':' . $e->getLine(); $error = "An error occurred during processing; checking has been aborted. The error message was: {$errorMessage}"; $phpcsFile = new PHP_CodeSniffer_File($filename, $this->_tokenListeners, $this->ruleset, $this); $phpcsFile->addError($error, null); } //end try $cliValues = $this->cli->getCommandLineValues(); if (PHP_CODESNIFFER_INTERACTIVE === false) { // Cache the report data for this file so we can unset it to save memory. $this->reporting->cacheFileReport($phpcsFile, $cliValues); $phpcsFile->cleanUp(); return $phpcsFile; } /* Running interactively. Print the error report for the current file and then wait for user input. */ // Get current violations and then clear the list to make sure // we only print violations for a single file each time. $numErrors = null; while ($numErrors !== 0) { $numErrors = $phpcsFile->getErrorCount() + $phpcsFile->getWarningCount(); if ($numErrors === 0) { continue; } $reportClass = $this->reporting->factory('full'); $reportData = $this->reporting->prepareFileReport($phpcsFile); $reportClass->generateFileReport($reportData, $phpcsFile, $cliValues['showSources'], $cliValues['reportWidth']); echo '<ENTER> to recheck, [s] to skip or [q] to quit : '; $input = fgets(STDIN); $input = trim($input); switch ($input) { case 's': break 2; case 'q': exit(0); break; default: // Repopulate the sniffs because some of them save their state // and only clear it when the file changes, but we are rechecking // the same file. $this->populateTokenListeners(); $phpcsFile = $this->_processFile($file, $contents); break; } } //end while return $phpcsFile; }