|
12 | 12 |
|
13 | 13 | namespace MoodlePluginCI\Command; |
14 | 14 |
|
15 | | -use MoodlePluginCI\Bridge\CodeSnifferCLI; |
16 | 15 | use MoodlePluginCI\StandardResolver; |
| 16 | +use PHP_CodeSniffer\Config; |
| 17 | +use PHP_CodeSniffer\Reporter; |
| 18 | +use PHP_CodeSniffer\Runner; |
| 19 | +use PHP_CodeSniffer\Util\Timing; |
17 | 20 | use Symfony\Component\Console\Input\InputInterface; |
18 | 21 | use Symfony\Component\Console\Input\InputOption; |
19 | 22 | use Symfony\Component\Console\Output\OutputInterface; |
20 | 23 | use Symfony\Component\Finder\Finder; |
21 | 24 |
|
| 25 | +// Cannot be autoload from composer, because this autoloader is used for both |
| 26 | +// phpcs and any standard Sniff, so it must be loaded at the end. For more info, see: |
| 27 | +// https://github.com/squizlabs/PHP_CodeSniffer/issues/1463#issuecomment-300637855 |
| 28 | +// |
| 29 | +// The alternative is to, instead of using PHP_CodeSniffer like a library, just |
| 30 | +// use the binaries bundled with it (phpcs, phpcbf...) but we want to use as lib for now. |
| 31 | +require_once __DIR__.'/../../vendor/moodlehq/moodle-local_codechecker/phpcs/autoload.php'; |
| 32 | + |
22 | 33 | /** |
23 | 34 | * Run Moodle Code Checker on a plugin. |
24 | 35 | */ |
@@ -72,24 +83,86 @@ protected function execute(InputInterface $input, OutputInterface $output) |
72 | 83 | return $this->outputSkip($output); |
73 | 84 | } |
74 | 85 |
|
75 | | - // Must define this before the sniffer due to odd code inclusion resulting in sniffer being included twice. |
76 | | - $cli = new CodeSnifferCLI([ |
77 | | - 'reports' => ['full' => null], |
78 | | - 'colors' => $output->isDecorated(), |
79 | | - 'encoding' => 'utf-8', |
80 | | - 'showProgress' => true, |
81 | | - 'reportWidth' => 120, |
82 | | - ]); |
| 86 | + // Needed constant. |
| 87 | + if (defined('PHP_CODESNIFFER_CBF') === false) { |
| 88 | + define('PHP_CODESNIFFER_CBF', false); |
| 89 | + } |
83 | 90 |
|
84 | | - \PHP_CodeSniffer::setConfigData('testVersion', PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION, true); |
| 91 | + Timing::startTiming(); |
| 92 | + |
| 93 | + $runner = new Runner(); |
| 94 | + $runner->config = new Config(['--parallel=1']); // Pass a param to shortcut params coming from caller CLI. |
| 95 | + |
| 96 | + // This is not needed normally, because phpcs loads the CodeSniffer.conf from its |
| 97 | + // root directory. But when this is run from within a .phar file, it expects the |
| 98 | + // config file to be out from the phar, in the same directory. |
| 99 | + // |
| 100 | + // While this approach is logic and enabled to configure phpcs, we don't want that |
| 101 | + // in this case, we just want to ensure phpcs knows about our standards, |
| 102 | + // so we are going to force the installed_paths config here. |
| 103 | + // |
| 104 | + // And it needs need to do it BEFORE the runner init! (or it's lost) |
| 105 | + // |
| 106 | + // Note: the "moodle" one is not really needed, because it's autodetected normally, |
| 107 | + // but the PHPCompatibility one is. There are some issues about version PHPCompatibility 10 |
| 108 | + // to stop requiring to be configured here, but that's future version. Revisit this when |
| 109 | + // available. |
| 110 | + // |
| 111 | + // Note: the paths are relative to the base CodeSniffer directory, aka, the directory |
| 112 | + // where "src" sits. |
| 113 | + $runner->config->setConfigData('installed_paths', './../PHPCompatibility'); |
| 114 | + $runner->config->standards = [$this->standard]; // Also BEFORE init() or it's lost. |
| 115 | + |
| 116 | + $runner->init(); |
| 117 | + |
| 118 | + $runner->config->parallel = 1; |
| 119 | + $runner->config->reports = ['full' => null]; |
| 120 | + $runner->config->colors = $output->isDecorated(); |
| 121 | + $runner->config->verbosity = 0; |
| 122 | + $runner->config->encoding = 'utf-8'; |
| 123 | + $runner->config->showProgress = true; |
| 124 | + $runner->config->showSources = true; |
| 125 | + $runner->config->interactive = false; |
| 126 | + $runner->config->cache = false; |
| 127 | + $runner->config->extensions = ['php' => 'PHP']; |
| 128 | + $runner->config->reportWidth = 132; |
| 129 | + |
| 130 | + $runner->config->files = $files; |
| 131 | + |
| 132 | + $runner->config->setConfigData('testVersion', PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION, true); |
| 133 | + |
| 134 | + // Create the reporter to manage all the reports from the run. |
| 135 | + $runner->reporter = new Reporter($runner->config); |
| 136 | + |
| 137 | + // And build the file list to iterate over. |
| 138 | + /** @var object[] $todo */ |
| 139 | + $todo = new \PHP_CodeSniffer\Files\FileList($runner->config, $runner->ruleset); |
| 140 | + $numFiles = count($todo); |
| 141 | + $numProcessed = 0; |
| 142 | + |
| 143 | + foreach ($todo as $file) { |
| 144 | + if ($file->ignored === false) { |
| 145 | + try { |
| 146 | + $runner->processFile($file); |
| 147 | + ++$numProcessed; |
| 148 | + $runner->printProgress($file, $numFiles, $numProcessed); |
| 149 | + } catch (\PHP_CodeSniffer\Exceptions\DeepExitException $e) { |
| 150 | + echo $e->getMessage(); |
| 151 | + |
| 152 | + return $e->getCode(); |
| 153 | + } catch (\Exception $e) { |
| 154 | + $error = 'Problem during processing; checking has been aborted. The error message was: '.$e->getMessage(); |
| 155 | + $file->addErrorOnLine($error, 1, 'Internal.Exception'); |
| 156 | + } |
| 157 | + $file->cleanUp(); |
| 158 | + } |
| 159 | + } |
85 | 160 |
|
86 | | - $sniffer = new \PHP_CodeSniffer(); |
87 | | - $sniffer->setCli($cli); |
88 | | - $sniffer->process($files, $this->standard); |
89 | | - $results = $sniffer->reporting->printReport('full', false, $sniffer->cli->getCommandLineValues(), null, 120); |
| 161 | + // Have finished, generate the final reports. |
| 162 | + $runner->reporter->printReports(); |
90 | 163 |
|
91 | 164 | $maxwarnings = (int) $input->getOption('max-warnings'); |
92 | 165 |
|
93 | | - return ($results['errors'] > 0 || ($maxwarnings >= 0 && $results['warnings'] > $maxwarnings)) ? 1 : 0; |
| 166 | + return ($runner->reporter->totalErrors > 0 || ($maxwarnings >= 0 && $runner->reporter->totalWarnings > $maxwarnings)) ? 1 : 0; |
94 | 167 | } |
95 | 168 | } |
0 commit comments