annotate vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@17 1 <?php
Chris@17 2 /**
Chris@17 3 * Version control report base class for PHP_CodeSniffer.
Chris@17 4 *
Chris@17 5 * @author Ben Selby <benmatselby@gmail.com>
Chris@17 6 * @author Greg Sherwood <gsherwood@squiz.net>
Chris@17 7 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
Chris@17 8 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
Chris@17 9 */
Chris@17 10
Chris@17 11 namespace PHP_CodeSniffer\Reports;
Chris@17 12
Chris@17 13 use PHP_CodeSniffer\Files\File;
Chris@17 14 use PHP_CodeSniffer\Util\Timing;
Chris@17 15
Chris@17 16 abstract class VersionControl implements Report
Chris@17 17 {
Chris@17 18
Chris@17 19 /**
Chris@17 20 * The name of the report we want in the output.
Chris@17 21 *
Chris@17 22 * @var string
Chris@17 23 */
Chris@17 24 protected $reportName = 'VERSION CONTROL';
Chris@17 25
Chris@17 26
Chris@17 27 /**
Chris@17 28 * Generate a partial report for a single processed file.
Chris@17 29 *
Chris@17 30 * Function should return TRUE if it printed or stored data about the file
Chris@17 31 * and FALSE if it ignored the file. Returning TRUE indicates that the file and
Chris@17 32 * its data should be counted in the grand totals.
Chris@17 33 *
Chris@17 34 * @param array $report Prepared report data.
Chris@17 35 * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on.
Chris@17 36 * @param bool $showSources Show sources?
Chris@17 37 * @param int $width Maximum allowed line width.
Chris@17 38 *
Chris@17 39 * @return bool
Chris@17 40 */
Chris@17 41 public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
Chris@17 42 {
Chris@17 43 $blames = $this->getBlameContent($report['filename']);
Chris@17 44
Chris@17 45 $authorCache = [];
Chris@17 46 $praiseCache = [];
Chris@17 47 $sourceCache = [];
Chris@17 48
Chris@17 49 foreach ($report['messages'] as $line => $lineErrors) {
Chris@17 50 $author = 'Unknown';
Chris@17 51 if (isset($blames[($line - 1)]) === true) {
Chris@17 52 $blameAuthor = $this->getAuthor($blames[($line - 1)]);
Chris@17 53 if ($blameAuthor !== false) {
Chris@17 54 $author = $blameAuthor;
Chris@17 55 }
Chris@17 56 }
Chris@17 57
Chris@17 58 if (isset($authorCache[$author]) === false) {
Chris@17 59 $authorCache[$author] = 0;
Chris@17 60 $praiseCache[$author] = [
Chris@17 61 'good' => 0,
Chris@17 62 'bad' => 0,
Chris@17 63 ];
Chris@17 64 }
Chris@17 65
Chris@17 66 $praiseCache[$author]['bad']++;
Chris@17 67
Chris@17 68 foreach ($lineErrors as $column => $colErrors) {
Chris@17 69 foreach ($colErrors as $error) {
Chris@17 70 $authorCache[$author]++;
Chris@17 71
Chris@17 72 if ($showSources === true) {
Chris@17 73 $source = $error['source'];
Chris@17 74 if (isset($sourceCache[$author][$source]) === false) {
Chris@17 75 $sourceCache[$author][$source] = [
Chris@17 76 'count' => 1,
Chris@17 77 'fixable' => $error['fixable'],
Chris@17 78 ];
Chris@17 79 } else {
Chris@17 80 $sourceCache[$author][$source]['count']++;
Chris@17 81 }
Chris@17 82 }
Chris@17 83 }
Chris@17 84 }
Chris@17 85
Chris@17 86 unset($blames[($line - 1)]);
Chris@17 87 }//end foreach
Chris@17 88
Chris@17 89 // Now go through and give the authors some credit for
Chris@17 90 // all the lines that do not have errors.
Chris@17 91 foreach ($blames as $line) {
Chris@17 92 $author = $this->getAuthor($line);
Chris@17 93 if ($author === false) {
Chris@17 94 $author = 'Unknown';
Chris@17 95 }
Chris@17 96
Chris@17 97 if (isset($authorCache[$author]) === false) {
Chris@17 98 // This author doesn't have any errors.
Chris@17 99 if (PHP_CODESNIFFER_VERBOSITY === 0) {
Chris@17 100 continue;
Chris@17 101 }
Chris@17 102
Chris@17 103 $authorCache[$author] = 0;
Chris@17 104 $praiseCache[$author] = [
Chris@17 105 'good' => 0,
Chris@17 106 'bad' => 0,
Chris@17 107 ];
Chris@17 108 }
Chris@17 109
Chris@17 110 $praiseCache[$author]['good']++;
Chris@17 111 }//end foreach
Chris@17 112
Chris@17 113 foreach ($authorCache as $author => $errors) {
Chris@17 114 echo "AUTHOR>>$author>>$errors".PHP_EOL;
Chris@17 115 }
Chris@17 116
Chris@17 117 foreach ($praiseCache as $author => $praise) {
Chris@17 118 echo "PRAISE>>$author>>".$praise['good'].'>>'.$praise['bad'].PHP_EOL;
Chris@17 119 }
Chris@17 120
Chris@17 121 foreach ($sourceCache as $author => $sources) {
Chris@17 122 foreach ($sources as $source => $sourceData) {
Chris@17 123 $count = $sourceData['count'];
Chris@17 124 $fixable = (int) $sourceData['fixable'];
Chris@17 125 echo "SOURCE>>$author>>$source>>$count>>$fixable".PHP_EOL;
Chris@17 126 }
Chris@17 127 }
Chris@17 128
Chris@17 129 return true;
Chris@17 130
Chris@17 131 }//end generateFileReport()
Chris@17 132
Chris@17 133
Chris@17 134 /**
Chris@17 135 * Prints the author of all errors and warnings, as given by "version control blame".
Chris@17 136 *
Chris@17 137 * @param string $cachedData Any partial report data that was returned from
Chris@17 138 * generateFileReport during the run.
Chris@17 139 * @param int $totalFiles Total number of files processed during the run.
Chris@17 140 * @param int $totalErrors Total number of errors found during the run.
Chris@17 141 * @param int $totalWarnings Total number of warnings found during the run.
Chris@17 142 * @param int $totalFixable Total number of problems that can be fixed.
Chris@17 143 * @param bool $showSources Show sources?
Chris@17 144 * @param int $width Maximum allowed line width.
Chris@17 145 * @param bool $interactive Are we running in interactive mode?
Chris@17 146 * @param bool $toScreen Is the report being printed to screen?
Chris@17 147 *
Chris@17 148 * @return void
Chris@17 149 */
Chris@17 150 public function generate(
Chris@17 151 $cachedData,
Chris@17 152 $totalFiles,
Chris@17 153 $totalErrors,
Chris@17 154 $totalWarnings,
Chris@17 155 $totalFixable,
Chris@17 156 $showSources=false,
Chris@17 157 $width=80,
Chris@17 158 $interactive=false,
Chris@17 159 $toScreen=true
Chris@17 160 ) {
Chris@17 161 $errorsShown = ($totalErrors + $totalWarnings);
Chris@17 162 if ($errorsShown === 0) {
Chris@17 163 // Nothing to show.
Chris@17 164 return;
Chris@17 165 }
Chris@17 166
Chris@17 167 $lines = explode(PHP_EOL, $cachedData);
Chris@17 168 array_pop($lines);
Chris@17 169
Chris@17 170 if (empty($lines) === true) {
Chris@17 171 return;
Chris@17 172 }
Chris@17 173
Chris@17 174 $authorCache = [];
Chris@17 175 $praiseCache = [];
Chris@17 176 $sourceCache = [];
Chris@17 177
Chris@17 178 foreach ($lines as $line) {
Chris@17 179 $parts = explode('>>', $line);
Chris@17 180 switch ($parts[0]) {
Chris@17 181 case 'AUTHOR':
Chris@17 182 if (isset($authorCache[$parts[1]]) === false) {
Chris@17 183 $authorCache[$parts[1]] = $parts[2];
Chris@17 184 } else {
Chris@17 185 $authorCache[$parts[1]] += $parts[2];
Chris@17 186 }
Chris@17 187 break;
Chris@17 188 case 'PRAISE':
Chris@17 189 if (isset($praiseCache[$parts[1]]) === false) {
Chris@17 190 $praiseCache[$parts[1]] = [
Chris@17 191 'good' => $parts[2],
Chris@17 192 'bad' => $parts[3],
Chris@17 193 ];
Chris@17 194 } else {
Chris@17 195 $praiseCache[$parts[1]]['good'] += $parts[2];
Chris@17 196 $praiseCache[$parts[1]]['bad'] += $parts[3];
Chris@17 197 }
Chris@17 198 break;
Chris@17 199 case 'SOURCE':
Chris@17 200 if (isset($praiseCache[$parts[1]]) === false) {
Chris@17 201 $praiseCache[$parts[1]] = [];
Chris@17 202 }
Chris@17 203
Chris@17 204 if (isset($sourceCache[$parts[1]][$parts[2]]) === false) {
Chris@17 205 $sourceCache[$parts[1]][$parts[2]] = [
Chris@17 206 'count' => $parts[3],
Chris@17 207 'fixable' => (bool) $parts[4],
Chris@17 208 ];
Chris@17 209 } else {
Chris@17 210 $sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3];
Chris@17 211 }
Chris@17 212 break;
Chris@17 213 default:
Chris@17 214 break;
Chris@17 215 }//end switch
Chris@17 216 }//end foreach
Chris@17 217
Chris@17 218 // Make sure the report width isn't too big.
Chris@17 219 $maxLength = 0;
Chris@17 220 foreach ($authorCache as $author => $count) {
Chris@17 221 $maxLength = max($maxLength, strlen($author));
Chris@17 222 if ($showSources === true && isset($sourceCache[$author]) === true) {
Chris@17 223 foreach ($sourceCache[$author] as $source => $sourceData) {
Chris@17 224 if ($source === 'count') {
Chris@17 225 continue;
Chris@17 226 }
Chris@17 227
Chris@17 228 $maxLength = max($maxLength, (strlen($source) + 9));
Chris@17 229 }
Chris@17 230 }
Chris@17 231 }
Chris@17 232
Chris@17 233 $width = min($width, ($maxLength + 30));
Chris@17 234 $width = max($width, 70);
Chris@17 235 arsort($authorCache);
Chris@17 236
Chris@17 237 echo PHP_EOL."\033[1m".'PHP CODE SNIFFER '.$this->reportName.' BLAME SUMMARY'."\033[0m".PHP_EOL;
Chris@17 238 echo str_repeat('-', $width).PHP_EOL."\033[1m";
Chris@17 239 if ($showSources === true) {
Chris@17 240 echo 'AUTHOR SOURCE'.str_repeat(' ', ($width - 43)).'(Author %) (Overall %) COUNT'.PHP_EOL;
Chris@17 241 echo str_repeat('-', $width).PHP_EOL;
Chris@17 242 } else {
Chris@17 243 echo 'AUTHOR'.str_repeat(' ', ($width - 34)).'(Author %) (Overall %) COUNT'.PHP_EOL;
Chris@17 244 echo str_repeat('-', $width).PHP_EOL;
Chris@17 245 }
Chris@17 246
Chris@17 247 echo "\033[0m";
Chris@17 248
Chris@17 249 if ($showSources === true) {
Chris@17 250 $maxSniffWidth = ($width - 15);
Chris@17 251
Chris@17 252 if ($totalFixable > 0) {
Chris@17 253 $maxSniffWidth -= 4;
Chris@17 254 }
Chris@17 255 }
Chris@17 256
Chris@17 257 $fixableSources = 0;
Chris@17 258
Chris@17 259 foreach ($authorCache as $author => $count) {
Chris@17 260 if ($praiseCache[$author]['good'] === 0) {
Chris@17 261 $percent = 0;
Chris@17 262 } else {
Chris@17 263 $total = ($praiseCache[$author]['bad'] + $praiseCache[$author]['good']);
Chris@17 264 $percent = round(($praiseCache[$author]['bad'] / $total * 100), 2);
Chris@17 265 }
Chris@17 266
Chris@17 267 $overallPercent = '('.round((($count / $errorsShown) * 100), 2).')';
Chris@17 268 $authorPercent = '('.$percent.')';
Chris@17 269 $line = str_repeat(' ', (6 - strlen($count))).$count;
Chris@17 270 $line = str_repeat(' ', (12 - strlen($overallPercent))).$overallPercent.$line;
Chris@17 271 $line = str_repeat(' ', (11 - strlen($authorPercent))).$authorPercent.$line;
Chris@17 272 $line = $author.str_repeat(' ', ($width - strlen($author) - strlen($line))).$line;
Chris@17 273
Chris@17 274 if ($showSources === true) {
Chris@17 275 $line = "\033[1m$line\033[0m";
Chris@17 276 }
Chris@17 277
Chris@17 278 echo $line.PHP_EOL;
Chris@17 279
Chris@17 280 if ($showSources === true && isset($sourceCache[$author]) === true) {
Chris@17 281 $errors = $sourceCache[$author];
Chris@17 282 asort($errors);
Chris@17 283 $errors = array_reverse($errors);
Chris@17 284
Chris@17 285 foreach ($errors as $source => $sourceData) {
Chris@17 286 if ($source === 'count') {
Chris@17 287 continue;
Chris@17 288 }
Chris@17 289
Chris@17 290 $count = $sourceData['count'];
Chris@17 291
Chris@17 292 $srcLength = strlen($source);
Chris@17 293 if ($srcLength > $maxSniffWidth) {
Chris@17 294 $source = substr($source, 0, $maxSniffWidth);
Chris@17 295 }
Chris@17 296
Chris@17 297 $line = str_repeat(' ', (5 - strlen($count))).$count;
Chris@17 298
Chris@17 299 echo ' ';
Chris@17 300 if ($totalFixable > 0) {
Chris@17 301 echo '[';
Chris@17 302 if ($sourceData['fixable'] === true) {
Chris@17 303 echo 'x';
Chris@17 304 $fixableSources++;
Chris@17 305 } else {
Chris@17 306 echo ' ';
Chris@17 307 }
Chris@17 308
Chris@17 309 echo '] ';
Chris@17 310 }
Chris@17 311
Chris@17 312 echo $source;
Chris@17 313 if ($totalFixable > 0) {
Chris@17 314 echo str_repeat(' ', ($width - 18 - strlen($source)));
Chris@17 315 } else {
Chris@17 316 echo str_repeat(' ', ($width - 14 - strlen($source)));
Chris@17 317 }
Chris@17 318
Chris@17 319 echo $line.PHP_EOL;
Chris@17 320 }//end foreach
Chris@17 321 }//end if
Chris@17 322 }//end foreach
Chris@17 323
Chris@17 324 echo str_repeat('-', $width).PHP_EOL;
Chris@17 325 echo "\033[1m".'A TOTAL OF '.$errorsShown.' SNIFF VIOLATION';
Chris@17 326 if ($errorsShown !== 1) {
Chris@17 327 echo 'S';
Chris@17 328 }
Chris@17 329
Chris@17 330 echo ' WERE COMMITTED BY '.count($authorCache).' AUTHOR';
Chris@17 331 if (count($authorCache) !== 1) {
Chris@17 332 echo 'S';
Chris@17 333 }
Chris@17 334
Chris@17 335 echo "\033[0m";
Chris@17 336
Chris@17 337 if ($totalFixable > 0) {
Chris@17 338 if ($showSources === true) {
Chris@17 339 echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
Chris@17 340 echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m";
Chris@17 341 } else {
Chris@17 342 echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
Chris@17 343 echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m";
Chris@17 344 }
Chris@17 345 }
Chris@17 346
Chris@17 347 echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL;
Chris@17 348
Chris@17 349 if ($toScreen === true && $interactive === false) {
Chris@17 350 Timing::printRunTime();
Chris@17 351 }
Chris@17 352
Chris@17 353 }//end generate()
Chris@17 354
Chris@17 355
Chris@17 356 /**
Chris@17 357 * Extract the author from a blame line.
Chris@17 358 *
Chris@17 359 * @param string $line Line to parse.
Chris@17 360 *
Chris@17 361 * @return mixed string or false if impossible to recover.
Chris@17 362 */
Chris@17 363 abstract protected function getAuthor($line);
Chris@17 364
Chris@17 365
Chris@17 366 /**
Chris@17 367 * Gets the blame output.
Chris@17 368 *
Chris@17 369 * @param string $filename File to blame.
Chris@17 370 *
Chris@17 371 * @return array
Chris@17 372 */
Chris@17 373 abstract protected function getBlameContent($filename);
Chris@17 374
Chris@17 375
Chris@17 376 }//end class