From 210b6fc207ca2b5f088cedaf74d42777d6930dd9 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 10:42:49 +0200 Subject: [PATCH 01/22] Create Reporter for setting up baseline. --- src/Reports/Baseline.php | 104 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/Reports/Baseline.php diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php new file mode 100644 index 0000000000..ccbb137497 --- /dev/null +++ b/src/Reports/Baseline.php @@ -0,0 +1,104 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use XMLWriter; + +class Baseline implements Report +{ + /** + * Generate a partial report for a single processed file. + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new XMLWriter; + $out->openMemory(); + $out->setIndent(true); + $out->setIndentString(' '); + $out->startDocument('1.0', 'UTF-8'); + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + foreach ($report['messages'] as $lineErrors) { + foreach ($lineErrors as $colErrors) { + foreach ($colErrors as $error) { + $out->startElement('violation'); + $out->writeAttribute('file', $report['filename']); + $out->writeAttribute('type', $error['type']); + $out->writeAttribute('source', $error['source']); + + $out->endElement(); + } + } + } + + // Remove the start of the document because we will + // add that manually later. We only have it in here to + // properly set the encoding. + $content = $out->flush(); + if (strpos($content, PHP_EOL) !== false) { + $content = substr($content, (strpos($content, PHP_EOL) + strlen(PHP_EOL))); + } else if (strpos($content, "\n") !== false) { + $content = substr($content, (strpos($content, "\n") + 1)); + } + + echo $content; + + return true; + } + + /** + * Prints all violations for processed files, in a proprietary XML format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + } +} From 0ad86470875761bb41be9a6ab07251768a712821 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 10:52:22 +0200 Subject: [PATCH 02/22] Add --baselineFile= to Config --- src/Config.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Config.php b/src/Config.php index 106b1c50b9..1811db7753 100644 --- a/src/Config.php +++ b/src/Config.php @@ -44,6 +44,7 @@ * If empty, all sniffs in the supplied standards will be used. * @property string[] $ignored Regular expressions used to ignore files and folders during checking. * @property string $reportFile A file where the report output should be written. + * @property string $baselineFile The baselined violations file to include. * @property string $generator The documentation generator to use. * @property string $filter The filter to use for the run. * @property string[] $bootstrap One of more files to include before the run begins. @@ -122,6 +123,7 @@ class Config 'exclude' => null, 'ignored' => null, 'reportFile' => null, + 'baselineFile' => null, 'generator' => null, 'filter' => null, 'bootstrap' => null, @@ -489,6 +491,7 @@ public function restoreDefaults() $this->exclude = []; $this->ignored = []; $this->reportFile = null; + $this->baselineFile = 'phpcs.baseline.xml'; $this->generator = null; $this->filter = null; $this->bootstrap = []; @@ -1023,6 +1026,17 @@ public function processLongArgument($arg, $pos) $error .= $this->printShortUsage(true); throw new DeepExitException($error, 3); } + } else if (substr($arg, 0, 13) === 'baselineFile=') { + if (substr($arg, 13) === '') { + $this->basepath = null; + break; + } + $this->baselineFile = Util\Common::realpath(substr($arg, 13)); + if (is_file($this->baselineFile) === false) { + $error = 'ERROR: The specified baselineFile "'.substr($arg, 13).'" points to a non-existent file'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } } else if ((substr($arg, 0, 7) === 'report=' || substr($arg, 0, 7) === 'report-')) { $reports = []; From 3228d8f40c5ad1b09a8de1380dd437bc6959e8aa Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 12:00:50 +0200 Subject: [PATCH 03/22] Read in baseline file and skip baselines --- src/Baseline/BaselineSet.php | 47 ++++++++++++++++++++++ src/Baseline/BaselineSetFactory.php | 62 +++++++++++++++++++++++++++++ src/Baseline/ViolationBaseline.php | 55 +++++++++++++++++++++++++ src/Config.php | 11 ++++- src/Files/File.php | 5 +++ src/Reports/Baseline.php | 3 +- 6 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 src/Baseline/BaselineSet.php create mode 100644 src/Baseline/BaselineSetFactory.php create mode 100644 src/Baseline/ViolationBaseline.php diff --git a/src/Baseline/BaselineSet.php b/src/Baseline/BaselineSet.php new file mode 100644 index 0000000000..fe2e4135b2 --- /dev/null +++ b/src/Baseline/BaselineSet.php @@ -0,0 +1,47 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Baseline; + +class BaselineSet +{ + /** @var array */ + private $violations = []; + + public function addEntry(ViolationBaseline $entry) + { + $this->violations[$entry->getSniffName()][] = $entry; + } + + /** + * @param string $sniffName + * @param string $fileName + * + * @return bool + */ + public function contains($sniffName, $fileName) + { + if (isset($this->violations[$sniffName]) === false) { + return false; + } + + // normalize slashes in file name + $fileName = str_replace('\\', '/', $fileName); + + foreach ($this->violations[$sniffName] as $baseline) { + if ($baseline->matches($fileName)) { + return true; + } + } + + return false; + } +} diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php new file mode 100644 index 0000000000..ac159cf7b4 --- /dev/null +++ b/src/Baseline/BaselineSetFactory.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Baseline; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util\Common; + +class BaselineSetFactory +{ + /** + * Read the baseline violations from the given filename path. Append the baseDir to all the file paths within + * the baseline file. + * + * @param string $fileName the baseline file to import + * + * @return BaselineSet|null + * @throws RuntimeException + */ + public static function fromFile($fileName) + { + if (file_exists($fileName) === false) { + return null; + } + + $xml = @simplexml_load_string(file_get_contents($fileName)); + if ($xml === false) { + throw new RuntimeException('Unable to read xml from: ' . $fileName); + } + + $baselineSet = new BaselineSet(); + + foreach ($xml->children() as $node) { + if ($node->getName() !== 'violation') { + continue; + } + + if (isset($node['sniff']) === false) { + throw new RuntimeException('Missing `sniff` attribute in `violation` in ' . $fileName); + } + + if (isset($node['file']) === false) { + throw new RuntimeException('Missing `file` attribute in `violation` in ' . $fileName); + } + + // normalize filepath (if needed) + $filePath = '/' . ltrim(str_replace('\\', '/', (string)$node['file']), '/'); + + $baselineSet->addEntry(new ViolationBaseline((string)$node['sniff'], $filePath)); + } + + return $baselineSet; + } +} diff --git a/src/Baseline/ViolationBaseline.php b/src/Baseline/ViolationBaseline.php new file mode 100644 index 0000000000..8296dd063a --- /dev/null +++ b/src/Baseline/ViolationBaseline.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Baseline; + +class ViolationBaseline +{ + /** @var string */ + private $sniffName; + + /** @var string */ + private $fileName; + + /** @var int */ + private $fileNameLength; + + /** + * @param string $ruleName + * @param string $fileName + */ + public function __construct($ruleName, $fileName) + { + $this->sniffName = $ruleName; + $this->fileName = $fileName; + $this->fileNameLength = strlen($fileName); + } + + /** + * @return string + */ + public function getSniffName() + { + return $this->sniffName; + } + + /** + * Test if the given filepath matches the relative filename in the baseline + * + * @param string $filepath + * + * @return bool + */ + public function matches($filepath) + { + return substr($filepath, -$this->fileNameLength) === $this->fileName; + } +} diff --git a/src/Config.php b/src/Config.php index 1811db7753..b63e72829c 100644 --- a/src/Config.php +++ b/src/Config.php @@ -12,6 +12,7 @@ namespace PHP_CodeSniffer; +use PHP_CodeSniffer\Baseline\BaselineSetFactory; use PHP_CodeSniffer\Exceptions\DeepExitException; use PHP_CodeSniffer\Exceptions\RuntimeException; @@ -140,6 +141,12 @@ class Config 'unknown' => null, ]; + /** + * The configured baselined violations + * @var \PHP_CodeSniffer\Baseline\BaselineSet|null + */ + public $baseline = null; + /** * Whether or not to kill the process when an unknown command line arg is found. * @@ -368,6 +375,9 @@ public function __construct(array $cliArgs=[], $dieOnUnknownArg=true) } while ($currentDir !== '.' && $currentDir !== $lastDir && @is_readable($currentDir) === true); }//end if + // load baseline file (if any) + $this->baseline = BaselineSetFactory::fromFile($this->baselineFile); + if (defined('STDIN') === false || strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ) { @@ -403,7 +413,6 @@ public function __construct(array $cliArgs=[], $dieOnUnknownArg=true) }//end if fclose($handle); - }//end __construct() diff --git a/src/Files/File.php b/src/Files/File.php index e4056bc8f8..28c8099c8b 100644 --- a/src/Files/File.php +++ b/src/Files/File.php @@ -1031,6 +1031,11 @@ protected function addMessage($error, $message, $line, $column, $code, $data, $s return false; } + // The message is part of the baselined violations + if ($this->config->baseline !== null && $this->config->baseline->contains($sniffCode, $this->path)) { + return false; + } + $messageCount++; if ($fixable === true) { $this->fixableCount++; diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php index ccbb137497..06c5734bee 100644 --- a/src/Reports/Baseline.php +++ b/src/Reports/Baseline.php @@ -46,8 +46,7 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, foreach ($colErrors as $error) { $out->startElement('violation'); $out->writeAttribute('file', $report['filename']); - $out->writeAttribute('type', $error['type']); - $out->writeAttribute('source', $error['source']); + $out->writeAttribute('sniff', $error['sniff']); $out->endElement(); } From d2384e8608fa8e9a8ee8e406d9a760591c7b03c2 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 12:21:17 +0200 Subject: [PATCH 04/22] Add coverage for baselines files --- src/Baseline/BaselineSetFactory.php | 1 - src/Reports/Baseline.php | 4 +- .../Core/Baseline/BaselineSetFactoryTest.php | 79 +++++++++++++++++++ tests/Core/Baseline/BaselineSetTest.php | 59 ++++++++++++++ tests/Core/Baseline/TestFiles/baseline.xml | 5 ++ .../Baseline/TestFiles/invalid-baseline.xml | 3 + .../TestFiles/missing-file-baseline.xml | 4 + .../TestFiles/missing-sniff-baseline.xml | 4 + tests/Core/Baseline/ViolationBaselineTest.php | 41 ++++++++++ 9 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 tests/Core/Baseline/BaselineSetFactoryTest.php create mode 100644 tests/Core/Baseline/BaselineSetTest.php create mode 100644 tests/Core/Baseline/TestFiles/baseline.xml create mode 100644 tests/Core/Baseline/TestFiles/invalid-baseline.xml create mode 100644 tests/Core/Baseline/TestFiles/missing-file-baseline.xml create mode 100644 tests/Core/Baseline/TestFiles/missing-sniff-baseline.xml create mode 100644 tests/Core/Baseline/ViolationBaselineTest.php diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php index ac159cf7b4..0984b52836 100644 --- a/src/Baseline/BaselineSetFactory.php +++ b/src/Baseline/BaselineSetFactory.php @@ -12,7 +12,6 @@ namespace PHP_CodeSniffer\Baseline; use PHP_CodeSniffer\Exceptions\RuntimeException; -use PHP_CodeSniffer\Util\Common; class BaselineSetFactory { diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php index 06c5734bee..b1e4671378 100644 --- a/src/Reports/Baseline.php +++ b/src/Reports/Baseline.php @@ -96,8 +96,8 @@ public function generate( $toScreen=true ) { echo ''.PHP_EOL; - echo ''.PHP_EOL; + echo ''.PHP_EOL; echo $cachedData; - echo ''.PHP_EOL; + echo ''.PHP_EOL; } } diff --git a/tests/Core/Baseline/BaselineSetFactoryTest.php b/tests/Core/Baseline/BaselineSetFactoryTest.php new file mode 100644 index 0000000000..df6773e059 --- /dev/null +++ b/tests/Core/Baseline/BaselineSetFactoryTest.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Baseline; + +use PHP_CodeSniffer\Baseline\BaselineSetFactory; +use PHPUnit\Framework\TestCase; + +/** + * @coversDefaultClass \PHP_CodeSniffer\Baseline\BaselineSetFactory + */ +class BaselineSetFactoryTest extends TestCase +{ + /** + * @covers ::fromFile + */ + public function testFromFileShouldSucceed() + { + $filename = __DIR__ . '/TestFiles/baseline.xml'; + $set = BaselineSetFactory::fromFile($filename); + + static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test/src/foo/bar')); + } + + /** + * @covers ::fromFile + */ + public function testFromFileShouldSucceedWithBackAndForwardSlashes() + { + $filename = __DIR__ . '/TestFiles/baseline.xml'; + $set = BaselineSetFactory::fromFile($filename); + + static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test\\src\\foo/bar')); + } + + /** + * @covers ::fromFile + */ + public function testFromFileShouldReturnNullIfAbsent() + { + static::assertNull(BaselineSetFactory::fromFile('foobar.xml')); + } + + /** + * @covers ::fromFile + */ + public function testFromFileShouldThrowExceptionForOnInvalidXML() + { + $this->expectException('PHP_CodeSniffer\Exceptions\RuntimeException'); + $this->expectExceptionMessage('Unable to read xml from'); + BaselineSetFactory::fromFile(__DIR__ .'/TestFiles/invalid-baseline.xml'); + } + + /** + * @covers ::fromFile + */ + public function testFromFileViolationMissingRuleShouldThrowException() + { + $this->expectException('PHP_CodeSniffer\Exceptions\RuntimeException'); + $this->expectExceptionMessage('Missing `sniff` attribute in `violation`'); + BaselineSetFactory::fromFile(__DIR__ .'/TestFiles/missing-sniff-baseline.xml'); + } + + /** + * @covers ::fromFile + */ + public function testFromFileViolationMissingFileShouldThrowException() + { + $this->expectException('PHP_CodeSniffer\Exceptions\RuntimeException'); + $this->expectExceptionMessage('Missing `file` attribute in `violation` in'); + BaselineSetFactory::fromFile(__DIR__ .'/TestFiles/missing-file-baseline.xml'); + } +} diff --git a/tests/Core/Baseline/BaselineSetTest.php b/tests/Core/Baseline/BaselineSetTest.php new file mode 100644 index 0000000000..8eb60a582f --- /dev/null +++ b/tests/Core/Baseline/BaselineSetTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Baseline; + +use PHP_CodeSniffer\Baseline\BaselineSet; +use PHP_CodeSniffer\Baseline\ViolationBaseline; +use PHPUnit\Framework\TestCase; + +/** + * @coversDefaultClass \PHP_CodeSniffer\Baseline\BaselineSet + */ +class BaselineSetTest extends TestCase +{ + /** + * @covers ::addEntry + * @covers ::contains + */ + public function testSetContainsEntryWithoutMethodName() + { + $set = new BaselineSet(); + $set->addEntry(new ViolationBaseline('sniff', 'foobar')); + + static::assertTrue($set->contains('sniff', 'foobar')); + } + + /** + * @covers ::addEntry + * @covers ::contains + */ + public function testShouldFindEntryForIdenticalRules() + { + $set = new BaselineSet(); + $set->addEntry(new ViolationBaseline('sniff', 'foo')); + $set->addEntry(new ViolationBaseline('sniff', 'bar')); + + static::assertTrue($set->contains('sniff', 'foo')); + static::assertTrue($set->contains('sniff', 'bar')); + static::assertFalse($set->contains('sniff', 'unknown')); + } + + /** + * @covers ::addEntry + * @covers ::contains + */ + public function testShouldNotFindEntryForNonExistingRule() + { + $set = new BaselineSet(); + $set->addEntry(new ViolationBaseline('sniff', 'foo')); + + static::assertFalse($set->contains('unknown', 'foo')); + } +} diff --git a/tests/Core/Baseline/TestFiles/baseline.xml b/tests/Core/Baseline/TestFiles/baseline.xml new file mode 100644 index 0000000000..2ea6dd6606 --- /dev/null +++ b/tests/Core/Baseline/TestFiles/baseline.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/Core/Baseline/TestFiles/invalid-baseline.xml b/tests/Core/Baseline/TestFiles/invalid-baseline.xml new file mode 100644 index 0000000000..54fb429d1d --- /dev/null +++ b/tests/Core/Baseline/TestFiles/invalid-baseline.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/Core/Baseline/TestFiles/missing-file-baseline.xml b/tests/Core/Baseline/TestFiles/missing-file-baseline.xml new file mode 100644 index 0000000000..cfac035c95 --- /dev/null +++ b/tests/Core/Baseline/TestFiles/missing-file-baseline.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/Core/Baseline/TestFiles/missing-sniff-baseline.xml b/tests/Core/Baseline/TestFiles/missing-sniff-baseline.xml new file mode 100644 index 0000000000..c120ec0c23 --- /dev/null +++ b/tests/Core/Baseline/TestFiles/missing-sniff-baseline.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/Core/Baseline/ViolationBaselineTest.php b/tests/Core/Baseline/ViolationBaselineTest.php new file mode 100644 index 0000000000..92a71478e2 --- /dev/null +++ b/tests/Core/Baseline/ViolationBaselineTest.php @@ -0,0 +1,41 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Baseline; + +use PHP_CodeSniffer\Baseline\ViolationBaseline; +use PHPUnit\Framework\TestCase; + +/** + * @coversDefaultClass \PHP_CodeSniffer\Baseline\ViolationBaseline + */ +class ViolationBaselineTest extends TestCase +{ + /** + * @covers ::__construct + * @covers ::getSniffName + */ + public function testGetSniffName() + { + $violation = new ViolationBaseline('sniff', 'foobar'); + static::assertSame('sniff', $violation->getSniffName()); + } + + /** + * @covers ::__construct + * @covers ::matches + */ + public function testMatches() + { + $violation = new ViolationBaseline('sniff', 'foobar.txt'); + static::assertTrue($violation->matches('foobar.txt')); + static::assertTrue($violation->matches('/test/foobar.txt')); + static::assertFalse($violation->matches('foo.txt')); + } +} From cccafdb7bea78fdee425e503a2cd86b7d051d385 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 12:34:06 +0200 Subject: [PATCH 05/22] Add coverage for baselines report --- tests/Core/Reports/BaselineTest.php | 73 +++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/Core/Reports/BaselineTest.php diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php new file mode 100644 index 0000000000..98e7f09f59 --- /dev/null +++ b/tests/Core/Reports/BaselineTest.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Baseline; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Reports\Baseline; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * @coversDefaultClass \PHP_CodeSniffer\Reports\Baseline + */ +class BaselineTest extends TestCase +{ + /** @var File|MockObject */ + private $file; + + protected function setup() + { + $this->file = $this->createMock('PHP_CodeSniffer\Files\File'); + } + + /** + * @covers ::generateFileReport + */ + public function testGenerateFileReportEmptyShouldReturnFalse() + { + $report = new Baseline(); + static::assertFalse($report->generateFileReport(['errors' => 0, 'warnings' => 0], $this->file)); + } + + /** + * @covers ::generateFileReport + */ + public function testGenerateFileReportShouldPrintReport() + { + $reportData = [ + 'filename' => '/test/foobar.txt', + 'errors' => 1, + 'warnings' => 0, + 'messages' => [[[['sniff' => 'MySniff']]]] + ]; + + $report = new Baseline(); + ob_start(); + static::assertTrue($report->generateFileReport($reportData, $this->file)); + $result = ob_get_clean(); + static::assertSame('' . "\n", $result); + } + + /** + * @covers ::generate + */ + public function testGenerate() + { + $expected = "" . PHP_EOL; + $expected .= "" . PHP_EOL; + $expected .= "" . PHP_EOL; + + $report = new Baseline(); + ob_start(); + $report->generate('', 1, 1, 0, 1); + $result = ob_get_clean(); + static::assertSame($expected, $result); + } +} From c9523f1f85cb401577a7a820b61fa39b251aab25 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 12:47:14 +0200 Subject: [PATCH 06/22] Added phpcbf fixes --- src/Baseline/BaselineSet.php | 21 +++++++--- src/Baseline/BaselineSetFactory.php | 19 +++++---- src/Baseline/ViolationBaseline.php | 29 ++++++++++---- src/Config.php | 3 ++ src/Reports/Baseline.php | 13 +++++-- .../Core/Baseline/BaselineSetFactoryTest.php | 39 +++++++++++++------ tests/Core/Baseline/BaselineSetTest.php | 17 ++++++-- tests/Core/Baseline/ViolationBaselineTest.php | 13 +++++-- tests/Core/Reports/BaselineTest.php | 35 +++++++++++------ 9 files changed, 136 insertions(+), 53 deletions(-) diff --git a/src/Baseline/BaselineSet.php b/src/Baseline/BaselineSet.php index fe2e4135b2..0d005235eb 100644 --- a/src/Baseline/BaselineSet.php +++ b/src/Baseline/BaselineSet.php @@ -13,17 +13,23 @@ class BaselineSet { - /** @var array */ + + /** + * @var array + */ private $violations = []; + public function addEntry(ViolationBaseline $entry) { $this->violations[$entry->getSniffName()][] = $entry; - } + + }//end addEntry() + /** - * @param string $sniffName - * @param string $fileName + * @param string $sniffName + * @param string $fileName * * @return bool */ @@ -43,5 +49,8 @@ public function contains($sniffName, $fileName) } return false; - } -} + + }//end contains() + + +}//end class diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php index 0984b52836..724037c949 100644 --- a/src/Baseline/BaselineSetFactory.php +++ b/src/Baseline/BaselineSetFactory.php @@ -15,6 +15,8 @@ class BaselineSetFactory { + + /** * Read the baseline violations from the given filename path. Append the baseDir to all the file paths within * the baseline file. @@ -32,7 +34,7 @@ public static function fromFile($fileName) $xml = @simplexml_load_string(file_get_contents($fileName)); if ($xml === false) { - throw new RuntimeException('Unable to read xml from: ' . $fileName); + throw new RuntimeException('Unable to read xml from: '.$fileName); } $baselineSet = new BaselineSet(); @@ -43,19 +45,22 @@ public static function fromFile($fileName) } if (isset($node['sniff']) === false) { - throw new RuntimeException('Missing `sniff` attribute in `violation` in ' . $fileName); + throw new RuntimeException('Missing `sniff` attribute in `violation` in '.$fileName); } if (isset($node['file']) === false) { - throw new RuntimeException('Missing `file` attribute in `violation` in ' . $fileName); + throw new RuntimeException('Missing `file` attribute in `violation` in '.$fileName); } // normalize filepath (if needed) - $filePath = '/' . ltrim(str_replace('\\', '/', (string)$node['file']), '/'); + $filePath = '/'.ltrim(str_replace('\\', '/', (string) $node['file']), '/'); - $baselineSet->addEntry(new ViolationBaseline((string)$node['sniff'], $filePath)); + $baselineSet->addEntry(new ViolationBaseline((string) $node['sniff'], $filePath)); } return $baselineSet; - } -} + + }//end fromFile() + + +}//end class diff --git a/src/Baseline/ViolationBaseline.php b/src/Baseline/ViolationBaseline.php index 8296dd063a..f155bcdeed 100644 --- a/src/Baseline/ViolationBaseline.php +++ b/src/Baseline/ViolationBaseline.php @@ -13,15 +13,23 @@ class ViolationBaseline { - /** @var string */ + + /** + * @var string + */ private $sniffName; - /** @var string */ + /** + * @var string + */ private $fileName; - /** @var int */ + /** + * @var integer + */ private $fileNameLength; + /** * @param string $ruleName * @param string $fileName @@ -31,7 +39,9 @@ public function __construct($ruleName, $fileName) $this->sniffName = $ruleName; $this->fileName = $fileName; $this->fileNameLength = strlen($fileName); - } + + }//end __construct() + /** * @return string @@ -39,7 +49,9 @@ public function __construct($ruleName, $fileName) public function getSniffName() { return $this->sniffName; - } + + }//end getSniffName() + /** * Test if the given filepath matches the relative filename in the baseline @@ -51,5 +63,8 @@ public function getSniffName() public function matches($filepath) { return substr($filepath, -$this->fileNameLength) === $this->fileName; - } -} + + }//end matches() + + +}//end class diff --git a/src/Config.php b/src/Config.php index b63e72829c..7c4fe11705 100644 --- a/src/Config.php +++ b/src/Config.php @@ -143,6 +143,7 @@ class Config /** * The configured baselined violations + * * @var \PHP_CodeSniffer\Baseline\BaselineSet|null */ public $baseline = null; @@ -413,6 +414,7 @@ public function __construct(array $cliArgs=[], $dieOnUnknownArg=true) }//end if fclose($handle); + }//end __construct() @@ -1040,6 +1042,7 @@ public function processLongArgument($arg, $pos) $this->basepath = null; break; } + $this->baselineFile = Util\Common::realpath(substr($arg, 13)); if (is_file($this->baselineFile) === false) { $error = 'ERROR: The specified baselineFile "'.substr($arg, 13).'" points to a non-existent file'.PHP_EOL.PHP_EOL; diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php index b1e4671378..610d425584 100644 --- a/src/Reports/Baseline.php +++ b/src/Reports/Baseline.php @@ -15,6 +15,8 @@ class Baseline implements Report { + + /** * Generate a partial report for a single processed file. * Function should return TRUE if it printed or stored data about the file @@ -66,7 +68,9 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, echo $content; return true; - } + + }//end generateFileReport() + /** * Prints all violations for processed files, in a proprietary XML format. @@ -99,5 +103,8 @@ public function generate( echo ''.PHP_EOL; echo $cachedData; echo ''.PHP_EOL; - } -} + + }//end generate() + + +}//end class diff --git a/tests/Core/Baseline/BaselineSetFactoryTest.php b/tests/Core/Baseline/BaselineSetFactoryTest.php index df6773e059..4d33920d3c 100644 --- a/tests/Core/Baseline/BaselineSetFactoryTest.php +++ b/tests/Core/Baseline/BaselineSetFactoryTest.php @@ -17,27 +17,33 @@ */ class BaselineSetFactoryTest extends TestCase { + + /** * @covers ::fromFile */ public function testFromFileShouldSucceed() { - $filename = __DIR__ . '/TestFiles/baseline.xml'; + $filename = __DIR__.'/TestFiles/baseline.xml'; $set = BaselineSetFactory::fromFile($filename); static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test/src/foo/bar')); - } + + }//end testFromFileShouldSucceed() + /** * @covers ::fromFile */ public function testFromFileShouldSucceedWithBackAndForwardSlashes() { - $filename = __DIR__ . '/TestFiles/baseline.xml'; + $filename = __DIR__.'/TestFiles/baseline.xml'; $set = BaselineSetFactory::fromFile($filename); static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test\\src\\foo/bar')); - } + + }//end testFromFileShouldSucceedWithBackAndForwardSlashes() + /** * @covers ::fromFile @@ -45,7 +51,9 @@ public function testFromFileShouldSucceedWithBackAndForwardSlashes() public function testFromFileShouldReturnNullIfAbsent() { static::assertNull(BaselineSetFactory::fromFile('foobar.xml')); - } + + }//end testFromFileShouldReturnNullIfAbsent() + /** * @covers ::fromFile @@ -54,8 +62,10 @@ public function testFromFileShouldThrowExceptionForOnInvalidXML() { $this->expectException('PHP_CodeSniffer\Exceptions\RuntimeException'); $this->expectExceptionMessage('Unable to read xml from'); - BaselineSetFactory::fromFile(__DIR__ .'/TestFiles/invalid-baseline.xml'); - } + BaselineSetFactory::fromFile(__DIR__.'/TestFiles/invalid-baseline.xml'); + + }//end testFromFileShouldThrowExceptionForOnInvalidXML() + /** * @covers ::fromFile @@ -64,8 +74,10 @@ public function testFromFileViolationMissingRuleShouldThrowException() { $this->expectException('PHP_CodeSniffer\Exceptions\RuntimeException'); $this->expectExceptionMessage('Missing `sniff` attribute in `violation`'); - BaselineSetFactory::fromFile(__DIR__ .'/TestFiles/missing-sniff-baseline.xml'); - } + BaselineSetFactory::fromFile(__DIR__.'/TestFiles/missing-sniff-baseline.xml'); + + }//end testFromFileViolationMissingRuleShouldThrowException() + /** * @covers ::fromFile @@ -74,6 +86,9 @@ public function testFromFileViolationMissingFileShouldThrowException() { $this->expectException('PHP_CodeSniffer\Exceptions\RuntimeException'); $this->expectExceptionMessage('Missing `file` attribute in `violation` in'); - BaselineSetFactory::fromFile(__DIR__ .'/TestFiles/missing-file-baseline.xml'); - } -} + BaselineSetFactory::fromFile(__DIR__.'/TestFiles/missing-file-baseline.xml'); + + }//end testFromFileViolationMissingFileShouldThrowException() + + +}//end class diff --git a/tests/Core/Baseline/BaselineSetTest.php b/tests/Core/Baseline/BaselineSetTest.php index 8eb60a582f..ba76717851 100644 --- a/tests/Core/Baseline/BaselineSetTest.php +++ b/tests/Core/Baseline/BaselineSetTest.php @@ -18,6 +18,8 @@ */ class BaselineSetTest extends TestCase { + + /** * @covers ::addEntry * @covers ::contains @@ -28,7 +30,9 @@ public function testSetContainsEntryWithoutMethodName() $set->addEntry(new ViolationBaseline('sniff', 'foobar')); static::assertTrue($set->contains('sniff', 'foobar')); - } + + }//end testSetContainsEntryWithoutMethodName() + /** * @covers ::addEntry @@ -43,7 +47,9 @@ public function testShouldFindEntryForIdenticalRules() static::assertTrue($set->contains('sniff', 'foo')); static::assertTrue($set->contains('sniff', 'bar')); static::assertFalse($set->contains('sniff', 'unknown')); - } + + }//end testShouldFindEntryForIdenticalRules() + /** * @covers ::addEntry @@ -55,5 +61,8 @@ public function testShouldNotFindEntryForNonExistingRule() $set->addEntry(new ViolationBaseline('sniff', 'foo')); static::assertFalse($set->contains('unknown', 'foo')); - } -} + + }//end testShouldNotFindEntryForNonExistingRule() + + +}//end class diff --git a/tests/Core/Baseline/ViolationBaselineTest.php b/tests/Core/Baseline/ViolationBaselineTest.php index 92a71478e2..216363259d 100644 --- a/tests/Core/Baseline/ViolationBaselineTest.php +++ b/tests/Core/Baseline/ViolationBaselineTest.php @@ -17,6 +17,8 @@ */ class ViolationBaselineTest extends TestCase { + + /** * @covers ::__construct * @covers ::getSniffName @@ -25,7 +27,9 @@ public function testGetSniffName() { $violation = new ViolationBaseline('sniff', 'foobar'); static::assertSame('sniff', $violation->getSniffName()); - } + + }//end testGetSniffName() + /** * @covers ::__construct @@ -37,5 +41,8 @@ public function testMatches() static::assertTrue($violation->matches('foobar.txt')); static::assertTrue($violation->matches('/test/foobar.txt')); static::assertFalse($violation->matches('foo.txt')); - } -} + + }//end testMatches() + + +}//end class diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index 98e7f09f59..dd965410ec 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -19,13 +19,19 @@ */ class BaselineTest extends TestCase { - /** @var File|MockObject */ + + /** + * @var File|MockObject + */ private $file; + protected function setup() { $this->file = $this->createMock('PHP_CodeSniffer\Files\File'); - } + + }//end setup() + /** * @covers ::generateFileReport @@ -34,7 +40,9 @@ public function testGenerateFileReportEmptyShouldReturnFalse() { $report = new Baseline(); static::assertFalse($report->generateFileReport(['errors' => 0, 'warnings' => 0], $this->file)); - } + + }//end testGenerateFileReportEmptyShouldReturnFalse() + /** * @covers ::generateFileReport @@ -45,29 +53,34 @@ public function testGenerateFileReportShouldPrintReport() 'filename' => '/test/foobar.txt', 'errors' => 1, 'warnings' => 0, - 'messages' => [[[['sniff' => 'MySniff']]]] + 'messages' => [[[['sniff' => 'MySniff']]]], ]; $report = new Baseline(); ob_start(); static::assertTrue($report->generateFileReport($reportData, $this->file)); $result = ob_get_clean(); - static::assertSame('' . "\n", $result); - } + static::assertSame(''."\n", $result); + + }//end testGenerateFileReportShouldPrintReport() + /** * @covers ::generate */ public function testGenerate() { - $expected = "" . PHP_EOL; - $expected .= "" . PHP_EOL; - $expected .= "" . PHP_EOL; + $expected = "".PHP_EOL; + $expected .= "".PHP_EOL; + $expected .= "".PHP_EOL; $report = new Baseline(); ob_start(); $report->generate('', 1, 1, 0, 1); $result = ob_get_clean(); static::assertSame($expected, $result); - } -} + + }//end testGenerate() + + +}//end class From 2e23a74bfe587bb11ae2d1342da4f13a9144a65d Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 12:55:05 +0200 Subject: [PATCH 07/22] Added phpcbf fixes --- .../Core/Baseline/BaselineSetFactoryTest.php | 20 +++++++++++++++++++ tests/Core/Baseline/BaselineSetTest.php | 12 +++++++++-- tests/Core/Baseline/ViolationBaselineTest.php | 6 ++++++ tests/Core/Reports/BaselineTest.php | 13 ++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/tests/Core/Baseline/BaselineSetFactoryTest.php b/tests/Core/Baseline/BaselineSetFactoryTest.php index 4d33920d3c..60c577f4f1 100644 --- a/tests/Core/Baseline/BaselineSetFactoryTest.php +++ b/tests/Core/Baseline/BaselineSetFactoryTest.php @@ -13,6 +13,8 @@ use PHPUnit\Framework\TestCase; /** + * Testcases for the reading the baseline set from file + * * @coversDefaultClass \PHP_CodeSniffer\Baseline\BaselineSetFactory */ class BaselineSetFactoryTest extends TestCase @@ -20,7 +22,10 @@ class BaselineSetFactoryTest extends TestCase /** + * Read the baseline from a file + * * @covers ::fromFile + * @return void */ public function testFromFileShouldSucceed() { @@ -33,7 +38,10 @@ public function testFromFileShouldSucceed() /** + * Read the baseline from a file with different slashes + * * @covers ::fromFile + * @return void */ public function testFromFileShouldSucceedWithBackAndForwardSlashes() { @@ -46,7 +54,10 @@ public function testFromFileShouldSucceedWithBackAndForwardSlashes() /** + * Test that reading absent file returns null + * * @covers ::fromFile + * @return void */ public function testFromFileShouldReturnNullIfAbsent() { @@ -56,7 +67,10 @@ public function testFromFileShouldReturnNullIfAbsent() /** + * Test that reading invalid xml throws exception + * * @covers ::fromFile + * @return void */ public function testFromFileShouldThrowExceptionForOnInvalidXML() { @@ -68,7 +82,10 @@ public function testFromFileShouldThrowExceptionForOnInvalidXML() /** + * Test that missing attributes throws exception + * * @covers ::fromFile + * @return void */ public function testFromFileViolationMissingRuleShouldThrowException() { @@ -80,7 +97,10 @@ public function testFromFileViolationMissingRuleShouldThrowException() /** + * Test that missing attributes throws exception + * * @covers ::fromFile + * @return void */ public function testFromFileViolationMissingFileShouldThrowException() { diff --git a/tests/Core/Baseline/BaselineSetTest.php b/tests/Core/Baseline/BaselineSetTest.php index ba76717851..a6cd8f122c 100644 --- a/tests/Core/Baseline/BaselineSetTest.php +++ b/tests/Core/Baseline/BaselineSetTest.php @@ -14,6 +14,8 @@ use PHPUnit\Framework\TestCase; /** + * Test the logic of the baseline set + * * @coversDefaultClass \PHP_CodeSniffer\Baseline\BaselineSet */ class BaselineSetTest extends TestCase @@ -21,20 +23,24 @@ class BaselineSetTest extends TestCase /** + * Test that contains find the correct sniff + * * @covers ::addEntry * @covers ::contains */ - public function testSetContainsEntryWithoutMethodName() + public function testSetContainsEntry() { $set = new BaselineSet(); $set->addEntry(new ViolationBaseline('sniff', 'foobar')); static::assertTrue($set->contains('sniff', 'foobar')); - }//end testSetContainsEntryWithoutMethodName() + }//end testSetContainsEntry() /** + * Test that contains differentiates between types + * * @covers ::addEntry * @covers ::contains */ @@ -52,6 +58,8 @@ public function testShouldFindEntryForIdenticalRules() /** + * Test that unknown sniffs are not found + * * @covers ::addEntry * @covers ::contains */ diff --git a/tests/Core/Baseline/ViolationBaselineTest.php b/tests/Core/Baseline/ViolationBaselineTest.php index 216363259d..834c253b4f 100644 --- a/tests/Core/Baseline/ViolationBaselineTest.php +++ b/tests/Core/Baseline/ViolationBaselineTest.php @@ -13,6 +13,8 @@ use PHPUnit\Framework\TestCase; /** + * Test the violation baseline data model + * * @coversDefaultClass \PHP_CodeSniffer\Baseline\ViolationBaseline */ class ViolationBaselineTest extends TestCase @@ -20,6 +22,8 @@ class ViolationBaselineTest extends TestCase /** + * Test the sniff name is returned + * * @covers ::__construct * @covers ::getSniffName */ @@ -32,6 +36,8 @@ public function testGetSniffName() /** + * Test the give file matches the baseline correctly + * * @covers ::__construct * @covers ::matches */ diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index dd965410ec..699b915ff6 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -15,12 +15,16 @@ use PHPUnit\Framework\TestCase; /** + * Testcases for the baseline report output file + * * @coversDefaultClass \PHP_CodeSniffer\Reports\Baseline */ class BaselineTest extends TestCase { /** + * The mock file object + * * @var File|MockObject */ private $file; @@ -34,7 +38,10 @@ protected function setup() /** + * Test that generation is skipped when there are no errors + * * @covers ::generateFileReport + * @return void */ public function testGenerateFileReportEmptyShouldReturnFalse() { @@ -45,7 +52,10 @@ public function testGenerateFileReportEmptyShouldReturnFalse() /** + * Test the generation of a single error message + * * @covers ::generateFileReport + * @return void */ public function testGenerateFileReportShouldPrintReport() { @@ -66,7 +76,10 @@ public function testGenerateFileReportShouldPrintReport() /** + * Test the generate of the complete file + * * @covers ::generate + * @return void */ public function testGenerate() { From 57e089d8ea7564946039b83e6f64f00d825f5486 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 13:02:48 +0200 Subject: [PATCH 08/22] Added phpcbf fixes --- src/Baseline/BaselineSet.php | 13 ++++++++++-- src/Baseline/BaselineSetFactory.php | 2 +- src/Baseline/ViolationBaseline.php | 20 ++++++++++++++----- src/Config.php | 2 +- src/Files/File.php | 4 ++-- tests/Core/Baseline/BaselineSetTest.php | 3 +++ tests/Core/Baseline/ViolationBaselineTest.php | 2 ++ tests/Core/Reports/BaselineTest.php | 5 +++++ 8 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/Baseline/BaselineSet.php b/src/Baseline/BaselineSet.php index 0d005235eb..dc7284199a 100644 --- a/src/Baseline/BaselineSet.php +++ b/src/Baseline/BaselineSet.php @@ -15,11 +15,18 @@ class BaselineSet { /** + * A collection of a baselined violations + * * @var array */ private $violations = []; + /** + * Add a single entry to the baseline set + * + * @param ViolationBaseline $entry the entry to add to the collection + */ public function addEntry(ViolationBaseline $entry) { $this->violations[$entry->getSniffName()][] = $entry; @@ -28,8 +35,10 @@ public function addEntry(ViolationBaseline $entry) /** - * @param string $sniffName - * @param string $fileName + * Test if the given sniff and filename is in the baseline collection + * + * @param string $sniffName the name of the sniff to search for + * @param string $fileName the full filename of the file to match * * @return bool */ diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php index 724037c949..0a4474a89d 100644 --- a/src/Baseline/BaselineSetFactory.php +++ b/src/Baseline/BaselineSetFactory.php @@ -52,7 +52,7 @@ public static function fromFile($fileName) throw new RuntimeException('Missing `file` attribute in `violation` in '.$fileName); } - // normalize filepath (if needed) + // Normalize filepath (if needed). $filePath = '/'.ltrim(str_replace('\\', '/', (string) $node['file']), '/'); $baselineSet->addEntry(new ViolationBaseline((string) $node['sniff'], $filePath)); diff --git a/src/Baseline/ViolationBaseline.php b/src/Baseline/ViolationBaseline.php index f155bcdeed..b2b2ce858f 100644 --- a/src/Baseline/ViolationBaseline.php +++ b/src/Baseline/ViolationBaseline.php @@ -15,28 +15,36 @@ class ViolationBaseline { /** + * The name of the sniff + * * @var string */ private $sniffName; /** + * The relative file path + * * @var string */ private $fileName; /** + * The length of the filename to improve comparison performance + * * @var integer */ private $fileNameLength; /** - * @param string $ruleName - * @param string $fileName + * Initialize the violation baseline + * + * @param string $sniffName The name of the sniff that's baselined. + * @param string $fileName The relative file path. */ - public function __construct($ruleName, $fileName) + public function __construct($sniffName, $fileName) { - $this->sniffName = $ruleName; + $this->sniffName = $sniffName; $this->fileName = $fileName; $this->fileNameLength = strlen($fileName); @@ -44,6 +52,8 @@ public function __construct($ruleName, $fileName) /** + * Get the sniff name that was baselined + * * @return string */ public function getSniffName() @@ -56,7 +66,7 @@ public function getSniffName() /** * Test if the given filepath matches the relative filename in the baseline * - * @param string $filepath + * @param string $filepath the full filepath to match against * * @return bool */ diff --git a/src/Config.php b/src/Config.php index 7c4fe11705..6ff5a2acce 100644 --- a/src/Config.php +++ b/src/Config.php @@ -376,7 +376,7 @@ public function __construct(array $cliArgs=[], $dieOnUnknownArg=true) } while ($currentDir !== '.' && $currentDir !== $lastDir && @is_readable($currentDir) === true); }//end if - // load baseline file (if any) + // Load baseline file (if any). $this->baseline = BaselineSetFactory::fromFile($this->baselineFile); if (defined('STDIN') === false diff --git a/src/Files/File.php b/src/Files/File.php index 28c8099c8b..cc1a3b791a 100644 --- a/src/Files/File.php +++ b/src/Files/File.php @@ -1031,8 +1031,8 @@ protected function addMessage($error, $message, $line, $column, $code, $data, $s return false; } - // The message is part of the baselined violations - if ($this->config->baseline !== null && $this->config->baseline->contains($sniffCode, $this->path)) { + // The message is part of the baselined violations. + if ($this->config->baseline !== null && $this->config->baseline->contains($sniffCode, $this->path) === true) { return false; } diff --git a/tests/Core/Baseline/BaselineSetTest.php b/tests/Core/Baseline/BaselineSetTest.php index a6cd8f122c..9d7405b0fb 100644 --- a/tests/Core/Baseline/BaselineSetTest.php +++ b/tests/Core/Baseline/BaselineSetTest.php @@ -27,6 +27,7 @@ class BaselineSetTest extends TestCase * * @covers ::addEntry * @covers ::contains + * @return void */ public function testSetContainsEntry() { @@ -43,6 +44,7 @@ public function testSetContainsEntry() * * @covers ::addEntry * @covers ::contains + * @return void */ public function testShouldFindEntryForIdenticalRules() { @@ -62,6 +64,7 @@ public function testShouldFindEntryForIdenticalRules() * * @covers ::addEntry * @covers ::contains + * @return void */ public function testShouldNotFindEntryForNonExistingRule() { diff --git a/tests/Core/Baseline/ViolationBaselineTest.php b/tests/Core/Baseline/ViolationBaselineTest.php index 834c253b4f..c8a77680a3 100644 --- a/tests/Core/Baseline/ViolationBaselineTest.php +++ b/tests/Core/Baseline/ViolationBaselineTest.php @@ -26,6 +26,7 @@ class ViolationBaselineTest extends TestCase * * @covers ::__construct * @covers ::getSniffName + * @return void */ public function testGetSniffName() { @@ -40,6 +41,7 @@ public function testGetSniffName() * * @covers ::__construct * @covers ::matches + * @return void */ public function testMatches() { diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index 699b915ff6..de69e4caaa 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -30,6 +30,11 @@ class BaselineTest extends TestCase private $file; + /** + * Setup the test mock object + * + * @return void + */ protected function setup() { $this->file = $this->createMock('PHP_CodeSniffer\Files\File'); From 8da5a12cc174d07d88f093fe79f2a49954161743 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 13:03:42 +0200 Subject: [PATCH 09/22] Added phpcbf fixes --- src/Baseline/BaselineSet.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Baseline/BaselineSet.php b/src/Baseline/BaselineSet.php index dc7284199a..e62b64c12a 100644 --- a/src/Baseline/BaselineSet.php +++ b/src/Baseline/BaselineSet.php @@ -25,7 +25,8 @@ class BaselineSet /** * Add a single entry to the baseline set * - * @param ViolationBaseline $entry the entry to add to the collection + * @param ViolationBaseline $entry the entry to add to the collection + * @return void */ public function addEntry(ViolationBaseline $entry) { @@ -48,11 +49,11 @@ public function contains($sniffName, $fileName) return false; } - // normalize slashes in file name + // Normalize slashes in file name. $fileName = str_replace('\\', '/', $fileName); foreach ($this->violations[$sniffName] as $baseline) { - if ($baseline->matches($fileName)) { + if ($baseline->matches($fileName) === true) { return true; } } From fae3721706a7651f115da51835f57ace396ed07b Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 13:04:45 +0200 Subject: [PATCH 10/22] Added phpcbf fixes --- src/Baseline/BaselineSet.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Baseline/BaselineSet.php b/src/Baseline/BaselineSet.php index e62b64c12a..b2ecd7b9ce 100644 --- a/src/Baseline/BaselineSet.php +++ b/src/Baseline/BaselineSet.php @@ -25,7 +25,8 @@ class BaselineSet /** * Add a single entry to the baseline set * - * @param ViolationBaseline $entry the entry to add to the collection + * @param ViolationBaseline $entry the entry to add to the collection + * * @return void */ public function addEntry(ViolationBaseline $entry) From 0d7d69b36b39110088b7c07fe534fb779ad45d00 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 13:09:55 +0200 Subject: [PATCH 11/22] Added phpcbf fixes --- tests/Core/Reports/BaselineTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index de69e4caaa..93d9f7d568 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -7,7 +7,7 @@ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ -namespace PHP_CodeSniffer\Tests\Core\Baseline; +namespace PHP_CodeSniffer\Tests\Core\Reports; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Reports\Baseline; From 3c29275daaae4ac37063d78ae14defa760ca6dab Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 13:16:08 +0200 Subject: [PATCH 12/22] Added `baselineFile` to the docblocks --- src/Config.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Config.php b/src/Config.php index 6ff5a2acce..1127543800 100644 --- a/src/Config.php +++ b/src/Config.php @@ -1372,9 +1372,10 @@ public function printPHPCSUsage() echo 'Usage: phpcs [-nwlsaepqvi] [-d key[=value]] [--colors] [--no-colors]'.PHP_EOL; echo ' [--cache[=]] [--no-cache] [--tab-width=]'.PHP_EOL; echo ' [--report=] [--report-file=] [--report-=]'.PHP_EOL; - echo ' [--report-width=] [--basepath=] [--bootstrap=]'.PHP_EOL; - echo ' [--severity=] [--error-severity=] [--warning-severity=]'.PHP_EOL; - echo ' [--runtime-set key value] [--config-set key value] [--config-delete key] [--config-show]'.PHP_EOL; + echo ' [--report-width=] [--basepath=] [--baselineFile=]'.PHP_EOL; + echo ' [--bootstrap=] [--severity=] [--error-severity=]'.PHP_EOL; + echo ' [--warning-severity=] [--runtime-set key value]'.PHP_EOL; + echo ' [--config-set key value] [--config-delete key] [--config-show]'.PHP_EOL; echo ' [--standard=] [--sniffs=] [--exclude=]'.PHP_EOL; echo ' [--encoding=] [--parallel=] [--generator=]'.PHP_EOL; echo ' [--extensions=] [--ignore=] [--ignore-annotations]'.PHP_EOL; @@ -1407,6 +1408,7 @@ public function printPHPCSUsage() echo PHP_EOL; echo ' Use a specific file for caching (uses a temporary file by default)'.PHP_EOL; echo ' A path to strip from the front of file paths inside reports'.PHP_EOL; + echo ' The path to the file with the baselined violations'.PHP_EOL; echo ' A comma separated list of files to run before processing begins'.PHP_EOL; echo ' The encoding of the files being checked (default is utf-8)'.PHP_EOL; echo ' A comma separated list of file extensions to check'.PHP_EOL; From 54a4c522db5f1424abab71c52e48ad89f39981c3 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 13:24:12 +0200 Subject: [PATCH 13/22] Update file doc block --- src/Baseline/BaselineSet.php | 6 ++---- src/Baseline/BaselineSetFactory.php | 6 ++---- src/Baseline/ViolationBaseline.php | 6 ++---- tests/Core/Baseline/BaselineSetFactoryTest.php | 4 ++-- tests/Core/Baseline/BaselineSetTest.php | 4 ++-- tests/Core/Baseline/ViolationBaselineTest.php | 4 ++-- tests/Core/Reports/BaselineTest.php | 4 ++-- 7 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Baseline/BaselineSet.php b/src/Baseline/BaselineSet.php index b2ecd7b9ce..7028b928ab 100644 --- a/src/Baseline/BaselineSet.php +++ b/src/Baseline/BaselineSet.php @@ -1,10 +1,8 @@ + * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php index 0a4474a89d..ad518d40b2 100644 --- a/src/Baseline/BaselineSetFactory.php +++ b/src/Baseline/BaselineSetFactory.php @@ -1,10 +1,8 @@ + * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ diff --git a/src/Baseline/ViolationBaseline.php b/src/Baseline/ViolationBaseline.php index b2b2ce858f..87a9190282 100644 --- a/src/Baseline/ViolationBaseline.php +++ b/src/Baseline/ViolationBaseline.php @@ -1,10 +1,8 @@ + * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ diff --git a/tests/Core/Baseline/BaselineSetFactoryTest.php b/tests/Core/Baseline/BaselineSetFactoryTest.php index 60c577f4f1..4bce734783 100644 --- a/tests/Core/Baseline/BaselineSetFactoryTest.php +++ b/tests/Core/Baseline/BaselineSetFactoryTest.php @@ -1,8 +1,8 @@ + * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ diff --git a/tests/Core/Baseline/BaselineSetTest.php b/tests/Core/Baseline/BaselineSetTest.php index 9d7405b0fb..16f2ed6c19 100644 --- a/tests/Core/Baseline/BaselineSetTest.php +++ b/tests/Core/Baseline/BaselineSetTest.php @@ -1,8 +1,8 @@ + * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ diff --git a/tests/Core/Baseline/ViolationBaselineTest.php b/tests/Core/Baseline/ViolationBaselineTest.php index c8a77680a3..f264e6159e 100644 --- a/tests/Core/Baseline/ViolationBaselineTest.php +++ b/tests/Core/Baseline/ViolationBaselineTest.php @@ -1,8 +1,8 @@ + * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index 93d9f7d568..2e3715c6b3 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -1,8 +1,8 @@ + * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ From 689a9e242598408c9a84efa0f82150385e91f1ad Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 15:06:24 +0200 Subject: [PATCH 14/22] Bugfix, property should be source --- src/Reports/Baseline.php | 2 +- tests/Core/Reports/BaselineTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php index 610d425584..fa6223d1ad 100644 --- a/src/Reports/Baseline.php +++ b/src/Reports/Baseline.php @@ -48,7 +48,7 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, foreach ($colErrors as $error) { $out->startElement('violation'); $out->writeAttribute('file', $report['filename']); - $out->writeAttribute('sniff', $error['sniff']); + $out->writeAttribute('sniff', $error['source']); $out->endElement(); } diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index 2e3715c6b3..3c3d016e15 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -68,7 +68,7 @@ public function testGenerateFileReportShouldPrintReport() 'filename' => '/test/foobar.txt', 'errors' => 1, 'warnings' => 0, - 'messages' => [[[['sniff' => 'MySniff']]]], + 'messages' => [[[['source' => 'MySniff']]]], ]; $report = new Baseline(); From 2fa845290e71384f04cc910734c498a10a85e7ea Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 15:18:32 +0200 Subject: [PATCH 15/22] Update file doc block --- src/Reports/Baseline.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php index fa6223d1ad..5f2d2daf43 100644 --- a/src/Reports/Baseline.php +++ b/src/Reports/Baseline.php @@ -1,8 +1,8 @@ + * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ From c998baf143fa834b59b0ebbe2d85864033af78c8 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 17:37:25 +0200 Subject: [PATCH 16/22] Ensure baseline report only outputs unique violations. --- src/Reports/Baseline.php | 16 +++++++++++----- tests/Core/Reports/BaselineTest.php | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php index 5f2d2daf43..4b9ba62d64 100644 --- a/src/Reports/Baseline.php +++ b/src/Reports/Baseline.php @@ -59,11 +59,8 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, // add that manually later. We only have it in here to // properly set the encoding. $content = $out->flush(); - if (strpos($content, PHP_EOL) !== false) { - $content = substr($content, (strpos($content, PHP_EOL) + strlen(PHP_EOL))); - } else if (strpos($content, "\n") !== false) { - $content = substr($content, (strpos($content, "\n") + 1)); - } + $content = preg_replace("/[\n\r]/", PHP_EOL, $content); + $content = substr($content, (strpos($content, PHP_EOL) + strlen(PHP_EOL))); echo $content; @@ -101,6 +98,15 @@ public function generate( ) { echo ''.PHP_EOL; echo ''.PHP_EOL; + + // Split violations on line-ending, make them unique and sort them. + if ($cachedData !== "") { + $lines = explode(PHP_EOL, $cachedData); + $lines = array_unique($lines); + sort($lines); + $cachedData = implode(PHP_EOL, $lines); + } + echo $cachedData; echo ''.PHP_EOL; diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index 3c3d016e15..fb67416536 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -75,7 +75,7 @@ public function testGenerateFileReportShouldPrintReport() ob_start(); static::assertTrue($report->generateFileReport($reportData, $this->file)); $result = ob_get_clean(); - static::assertSame(''."\n", $result); + static::assertSame(''.PHP_EOL, $result); }//end testGenerateFileReportShouldPrintReport() From 2e7fe27204b85afa0a998059267886de64f3ea38 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 11 Jul 2021 17:38:52 +0200 Subject: [PATCH 17/22] Ensure baseline report only outputs unique violations. --- tests/Core/Reports/BaselineTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index fb67416536..e8e310e176 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -9,6 +9,7 @@ namespace PHP_CodeSniffer\Tests\Core\Reports; +use PHP_CodeSniffer\Config; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Reports\Baseline; use PHPUnit\Framework\MockObject\MockObject; @@ -89,7 +90,7 @@ public function testGenerateFileReportShouldPrintReport() public function testGenerate() { $expected = "".PHP_EOL; - $expected .= "".PHP_EOL; + $expected .= "".PHP_EOL; $expected .= "".PHP_EOL; $report = new Baseline(); From 66cba31ec2b3a1b9569e1635479faee765e8c3c5 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sat, 31 Jul 2021 23:38:01 +0200 Subject: [PATCH 18/22] Add code signature --- src/Config.php | 6 ++- src/Reports/Baseline.php | 10 ++-- src/Util/Signature.php | 48 +++++++++++++++++ tests/Core/Util/SignatureTest.php | 89 +++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 src/Util/Signature.php create mode 100644 tests/Core/Util/SignatureTest.php diff --git a/src/Config.php b/src/Config.php index 1127543800..547d6893ad 100644 --- a/src/Config.php +++ b/src/Config.php @@ -376,8 +376,10 @@ public function __construct(array $cliArgs=[], $dieOnUnknownArg=true) } while ($currentDir !== '.' && $currentDir !== $lastDir && @is_readable($currentDir) === true); }//end if - // Load baseline file (if any). - $this->baseline = BaselineSetFactory::fromFile($this->baselineFile); + // Load baseline file, only if no baseline should be created. + if (isset($this->settings['reports']['baseline']) === false) { + $this->baseline = BaselineSetFactory::fromFile($this->baselineFile); + } if (defined('STDIN') === false || strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php index 4b9ba62d64..10e6e7104f 100644 --- a/src/Reports/Baseline.php +++ b/src/Reports/Baseline.php @@ -11,6 +11,7 @@ use PHP_CodeSniffer\Config; use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; use XMLWriter; class Baseline implements Report @@ -43,12 +44,15 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, return false; } - foreach ($report['messages'] as $lineErrors) { + foreach ($report['messages'] as $lineNr => $lineErrors) { + $signature = Util\Signature::createSignature($phpcsFile->getTokens(), $lineNr); + foreach ($lineErrors as $colErrors) { foreach ($colErrors as $error) { $out->startElement('violation'); $out->writeAttribute('file', $report['filename']); $out->writeAttribute('sniff', $error['source']); + $out->writeAttribute('signature', $signature); $out->endElement(); } @@ -97,7 +101,7 @@ public function generate( $toScreen=true ) { echo ''.PHP_EOL; - echo ''.PHP_EOL; + echo ''; // Split violations on line-ending, make them unique and sort them. if ($cachedData !== "") { @@ -108,7 +112,7 @@ public function generate( } echo $cachedData; - echo ''.PHP_EOL; + echo PHP_EOL.''.PHP_EOL; }//end generate() diff --git a/src/Util/Signature.php b/src/Util/Signature.php new file mode 100644 index 0000000000..fb99258bf3 --- /dev/null +++ b/src/Util/Signature.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +class Signature +{ + + + /** + * Generate the sha1 code signature for the tokens around the given line. + * + * @param array $tokens All tokens of a given file. + * @param int $lineNr The lineNr to search for tokens. + * + * @return string The sha1 hash of the tokens around the given line + */ + public static function createSignature(array $tokens, $lineNr) + { + // get all tokens one line before and after + $start = ($lineNr - 1); + $end = ($lineNr + 1); + + $line = ''; + foreach ($tokens as $token) { + if ($token['line'] > $end) { + break; + } + + if ($token['line'] >= $start) { + // concat content excluding line endings. + $line .= isset($token['content']) ? trim($token['content'], "\r\n") : ''; + } + } + + // generate hash + return hash('sha1', $line); + + }//end createSignature() + + +}//end class diff --git a/tests/Core/Util/SignatureTest.php b/tests/Core/Util/SignatureTest.php new file mode 100644 index 0000000000..9a1d24ddcc --- /dev/null +++ b/tests/Core/Util/SignatureTest.php @@ -0,0 +1,89 @@ + 'line1', + 'line' => 1, + ], + [ + 'content' => 'line2', + 'line' => 2, + ], + [ + 'content' => 'line3', + 'line' => 3, + ], + [ + 'content' => "\r\n", + 'line' => 3, + ], + [ + 'content' => 'line4', + 'line' => 4, + ], + [ + 'content' => 'line5', + 'line' => 5, + ], + ]; + + $signature = Signature::createSignature($tokens, $lineNr); + static::assertSame($expected, $signature); + + }//end testCreateSignature() + + + /** + * @return array> + */ + public function dataProvider() + { + return [ + 'first line of file' => [ + 1, + hash('sha1', 'line1line2'), + ], + 'middle line of file' => [ + 3, + hash('sha1', 'line2line3line4'), + ], + 'last line of file' => [ + 5, + hash('sha1', 'line4line5'), + ] + ]; + + }//end dataProvider() + + +}//end class From 688605f6558e3bf257e3987cdf69523c2fa78fd0 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sat, 31 Jul 2021 23:59:47 +0200 Subject: [PATCH 19/22] Add code signature --- phpcs.baseline.xml | 4 ++++ src/Baseline/BaselineSet.php | 5 +++-- src/Baseline/BaselineSetFactory.php | 8 ++++++-- src/Baseline/ViolationBaseline.php | 18 ++++++++++++++---- src/Files/File.php | 7 +++++-- src/Reports/Baseline.php | 2 +- src/Util/{Signature.php => CodeSignature.php} | 16 ++++++++-------- ...SignatureTest.php => CodeSignatureTest.php} | 18 ++++++++++++------ 8 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 phpcs.baseline.xml rename src/Util/{Signature.php => CodeSignature.php} (72%) rename tests/Core/Util/{SignatureTest.php => CodeSignatureTest.php} (81%) diff --git a/phpcs.baseline.xml b/phpcs.baseline.xml new file mode 100644 index 0000000000..23d32f2671 --- /dev/null +++ b/phpcs.baseline.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/Baseline/BaselineSet.php b/src/Baseline/BaselineSet.php index 7028b928ab..958411b853 100644 --- a/src/Baseline/BaselineSet.php +++ b/src/Baseline/BaselineSet.php @@ -39,10 +39,11 @@ public function addEntry(ViolationBaseline $entry) * * @param string $sniffName the name of the sniff to search for * @param string $fileName the full filename of the file to match + * @param string $signature the code signature of the violation * * @return bool */ - public function contains($sniffName, $fileName) + public function contains($sniffName, $fileName, $signature) { if (isset($this->violations[$sniffName]) === false) { return false; @@ -52,7 +53,7 @@ public function contains($sniffName, $fileName) $fileName = str_replace('\\', '/', $fileName); foreach ($this->violations[$sniffName] as $baseline) { - if ($baseline->matches($fileName) === true) { + if ($baseline->matches($fileName, $signature) === true) { return true; } } diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php index ad518d40b2..d57c2925b6 100644 --- a/src/Baseline/BaselineSetFactory.php +++ b/src/Baseline/BaselineSetFactory.php @@ -50,11 +50,15 @@ public static function fromFile($fileName) throw new RuntimeException('Missing `file` attribute in `violation` in '.$fileName); } + if (isset($node['signature']) === false) { + throw new RuntimeException('Missing `signature` attribute in `violation` in '.$fileName); + } + // Normalize filepath (if needed). $filePath = '/'.ltrim(str_replace('\\', '/', (string) $node['file']), '/'); - $baselineSet->addEntry(new ViolationBaseline((string) $node['sniff'], $filePath)); - } + $baselineSet->addEntry(new ViolationBaseline((string) $node['sniff'], $filePath, $node['signature'])); + }//end foreach return $baselineSet; diff --git a/src/Baseline/ViolationBaseline.php b/src/Baseline/ViolationBaseline.php index 87a9190282..ebc4db2172 100644 --- a/src/Baseline/ViolationBaseline.php +++ b/src/Baseline/ViolationBaseline.php @@ -33,18 +33,27 @@ class ViolationBaseline */ private $fileNameLength; + /** + * The code signature for the baseline + * + * @var string + */ + private $signature; + /** * Initialize the violation baseline * * @param string $sniffName The name of the sniff that's baselined. * @param string $fileName The relative file path. + * @param string $signature The code signature for the baseline. */ - public function __construct($sniffName, $fileName) + public function __construct($sniffName, $fileName, $signature) { $this->sniffName = $sniffName; $this->fileName = $fileName; $this->fileNameLength = strlen($fileName); + $this->signature = $signature; }//end __construct() @@ -64,13 +73,14 @@ public function getSniffName() /** * Test if the given filepath matches the relative filename in the baseline * - * @param string $filepath the full filepath to match against + * @param string $filepath the full filepath to match against + * @param string $signature the code signature of the violation * * @return bool */ - public function matches($filepath) + public function matches($filepath, $signature) { - return substr($filepath, -$this->fileNameLength) === $this->fileName; + return $this->signature === $signature && substr($filepath, -$this->fileNameLength) === $this->fileName; }//end matches() diff --git a/src/Files/File.php b/src/Files/File.php index cc1a3b791a..ee4f05933e 100644 --- a/src/Files/File.php +++ b/src/Files/File.php @@ -1032,8 +1032,11 @@ protected function addMessage($error, $message, $line, $column, $code, $data, $s } // The message is part of the baselined violations. - if ($this->config->baseline !== null && $this->config->baseline->contains($sniffCode, $this->path) === true) { - return false; + if ($this->config->baseline !== null) { + $signature = Util\CodeSignature::createSignature($this->getTokens(), $line); + if ($this->config->baseline->contains($sniffCode, $this->path, $signature) === true) { + return false; + } } $messageCount++; diff --git a/src/Reports/Baseline.php b/src/Reports/Baseline.php index 10e6e7104f..e5e965fe78 100644 --- a/src/Reports/Baseline.php +++ b/src/Reports/Baseline.php @@ -45,7 +45,7 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, } foreach ($report['messages'] as $lineNr => $lineErrors) { - $signature = Util\Signature::createSignature($phpcsFile->getTokens(), $lineNr); + $signature = Util\CodeSignature::createSignature($phpcsFile->getTokens(), $lineNr); foreach ($lineErrors as $colErrors) { foreach ($colErrors as $error) { diff --git a/src/Util/Signature.php b/src/Util/CodeSignature.php similarity index 72% rename from src/Util/Signature.php rename to src/Util/CodeSignature.php index fb99258bf3..5c3cf7cc4d 100644 --- a/src/Util/Signature.php +++ b/src/Util/CodeSignature.php @@ -9,7 +9,7 @@ namespace PHP_CodeSniffer\Util; -class Signature +class CodeSignature { @@ -23,24 +23,24 @@ class Signature */ public static function createSignature(array $tokens, $lineNr) { - // get all tokens one line before and after + // Get all tokens one line before and after. $start = ($lineNr - 1); $end = ($lineNr + 1); - $line = ''; + $content = ''; foreach ($tokens as $token) { if ($token['line'] > $end) { break; } - if ($token['line'] >= $start) { - // concat content excluding line endings. - $line .= isset($token['content']) ? trim($token['content'], "\r\n") : ''; + // Concat content excluding line endings. + if ($token['line'] >= $start && isset($token['content']) === true) { + $content .= trim($token['content'], "\r\n"); } } - // generate hash - return hash('sha1', $line); + // Generate sha1 hash. + return hash('sha1', $content); }//end createSignature() diff --git a/tests/Core/Util/SignatureTest.php b/tests/Core/Util/CodeSignatureTest.php similarity index 81% rename from tests/Core/Util/SignatureTest.php rename to tests/Core/Util/CodeSignatureTest.php index 9a1d24ddcc..8da0bb6a59 100644 --- a/tests/Core/Util/SignatureTest.php +++ b/tests/Core/Util/CodeSignatureTest.php @@ -2,20 +2,22 @@ /** * Tests the generation of code signature based on tokens * - * @author Frank Dekker * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ namespace PHP_CodeSniffer\Tests\Core\Util; -use PHP_CodeSniffer\Util\Signature; +use PHP_CodeSniffer\Util\CodeSignature; use PHPUnit\Framework\TestCase; /** - * @coversDefaultClass \PHP_CodeSniffer\Util\Signature + * Tests the generation of code signature based on tokens + * + * @coversDefaultClass \PHP_CodeSniffer\Util\CodeSignature */ -class SignatureTest extends TestCase +class CodeSignatureTest extends TestCase { @@ -25,6 +27,8 @@ class SignatureTest extends TestCase * @param int $lineNr the line nr within the file * @param string $expected the expected signature * + * @return void + * * @covers ::createSignature * @dataProvider dataProvider */ @@ -57,13 +61,15 @@ public function testCreateSignature($lineNr, $expected) ], ]; - $signature = Signature::createSignature($tokens, $lineNr); + $signature = CodeSignature::createSignature($tokens, $lineNr); static::assertSame($expected, $signature); }//end testCreateSignature() /** + * Provide edge case scenario's for the code signature + * * @return array> */ public function dataProvider() @@ -80,7 +86,7 @@ public function dataProvider() 'last line of file' => [ 5, hash('sha1', 'line4line5'), - ] + ], ]; }//end dataProvider() From c19a4d7d98df92f4076caf16da327837063ee762 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 1 Aug 2021 00:19:51 +0200 Subject: [PATCH 20/22] Update unit tests to solve coverage --- phpcs.baseline.xml | 4 ---- src/Baseline/BaselineSetFactory.php | 2 +- .../Core/Baseline/BaselineSetFactoryTest.php | 23 +++++++++++++++---- tests/Core/Baseline/BaselineSetTest.php | 19 +++++++-------- tests/Core/Baseline/TestFiles/baseline.xml | 2 +- .../TestFiles/missing-file-baseline.xml | 2 +- .../TestFiles/missing-signature-baseline.xml | 4 ++++ .../TestFiles/missing-sniff-baseline.xml | 2 +- tests/Core/Baseline/ViolationBaselineTest.php | 11 +++++---- tests/Core/Reports/BaselineTest.php | 21 +++++++++++++---- 10 files changed, 59 insertions(+), 31 deletions(-) delete mode 100644 phpcs.baseline.xml create mode 100644 tests/Core/Baseline/TestFiles/missing-signature-baseline.xml diff --git a/phpcs.baseline.xml b/phpcs.baseline.xml deleted file mode 100644 index 23d32f2671..0000000000 --- a/phpcs.baseline.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php index d57c2925b6..ce6c72fb37 100644 --- a/src/Baseline/BaselineSetFactory.php +++ b/src/Baseline/BaselineSetFactory.php @@ -57,7 +57,7 @@ public static function fromFile($fileName) // Normalize filepath (if needed). $filePath = '/'.ltrim(str_replace('\\', '/', (string) $node['file']), '/'); - $baselineSet->addEntry(new ViolationBaseline((string) $node['sniff'], $filePath, $node['signature'])); + $baselineSet->addEntry(new ViolationBaseline((string) $node['sniff'], $filePath, (string) $node['signature'])); }//end foreach return $baselineSet; diff --git a/tests/Core/Baseline/BaselineSetFactoryTest.php b/tests/Core/Baseline/BaselineSetFactoryTest.php index 4bce734783..3de5487a3a 100644 --- a/tests/Core/Baseline/BaselineSetFactoryTest.php +++ b/tests/Core/Baseline/BaselineSetFactoryTest.php @@ -32,7 +32,7 @@ public function testFromFileShouldSucceed() $filename = __DIR__.'/TestFiles/baseline.xml'; $set = BaselineSetFactory::fromFile($filename); - static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test/src/foo/bar')); + static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test/src/foo/bar', 'foobar')); }//end testFromFileShouldSucceed() @@ -48,7 +48,7 @@ public function testFromFileShouldSucceedWithBackAndForwardSlashes() $filename = __DIR__.'/TestFiles/baseline.xml'; $set = BaselineSetFactory::fromFile($filename); - static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test\\src\\foo/bar')); + static::assertTrue($set->contains('Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen', '/test\\src\\foo/bar', 'foobar')); }//end testFromFileShouldSucceedWithBackAndForwardSlashes() @@ -87,13 +87,28 @@ public function testFromFileShouldThrowExceptionForOnInvalidXML() * @covers ::fromFile * @return void */ - public function testFromFileViolationMissingRuleShouldThrowException() + public function testFromFileViolationMissingSniffShouldThrowException() { $this->expectException('PHP_CodeSniffer\Exceptions\RuntimeException'); $this->expectExceptionMessage('Missing `sniff` attribute in `violation`'); BaselineSetFactory::fromFile(__DIR__.'/TestFiles/missing-sniff-baseline.xml'); - }//end testFromFileViolationMissingRuleShouldThrowException() + }//end testFromFileViolationMissingSniffShouldThrowException() + + + /** + * Test that missing signature attribute throws exception + * + * @covers ::fromFile + * @return void + */ + public function testFromFileViolationMissingSignatureShouldThrowException() + { + $this->expectException('PHP_CodeSniffer\Exceptions\RuntimeException'); + $this->expectExceptionMessage('Missing `signature` attribute in `violation` in'); + BaselineSetFactory::fromFile(__DIR__.'/TestFiles/missing-signature-baseline.xml'); + + }//end testFromFileViolationMissingSignatureShouldThrowException() /** diff --git a/tests/Core/Baseline/BaselineSetTest.php b/tests/Core/Baseline/BaselineSetTest.php index 16f2ed6c19..588ee47925 100644 --- a/tests/Core/Baseline/BaselineSetTest.php +++ b/tests/Core/Baseline/BaselineSetTest.php @@ -32,9 +32,9 @@ class BaselineSetTest extends TestCase public function testSetContainsEntry() { $set = new BaselineSet(); - $set->addEntry(new ViolationBaseline('sniff', 'foobar')); + $set->addEntry(new ViolationBaseline('sniff', 'foobar', 'signature')); - static::assertTrue($set->contains('sniff', 'foobar')); + static::assertTrue($set->contains('sniff', 'foobar', 'signature')); }//end testSetContainsEntry() @@ -49,12 +49,13 @@ public function testSetContainsEntry() public function testShouldFindEntryForIdenticalRules() { $set = new BaselineSet(); - $set->addEntry(new ViolationBaseline('sniff', 'foo')); - $set->addEntry(new ViolationBaseline('sniff', 'bar')); + $set->addEntry(new ViolationBaseline('sniff', 'foo', 'signA')); + $set->addEntry(new ViolationBaseline('sniff', 'bar', 'signB')); - static::assertTrue($set->contains('sniff', 'foo')); - static::assertTrue($set->contains('sniff', 'bar')); - static::assertFalse($set->contains('sniff', 'unknown')); + static::assertTrue($set->contains('sniff', 'foo', 'signA')); + static::assertTrue($set->contains('sniff', 'bar', 'signB')); + static::assertFalse($set->contains('sniff', 'unknown', 'signA')); + static::assertFalse($set->contains('sniff', 'foo', 'signB')); }//end testShouldFindEntryForIdenticalRules() @@ -69,9 +70,9 @@ public function testShouldFindEntryForIdenticalRules() public function testShouldNotFindEntryForNonExistingRule() { $set = new BaselineSet(); - $set->addEntry(new ViolationBaseline('sniff', 'foo')); + $set->addEntry(new ViolationBaseline('sniff', 'foo', 'signature')); - static::assertFalse($set->contains('unknown', 'foo')); + static::assertFalse($set->contains('unknown', 'foo', 'signature')); }//end testShouldNotFindEntryForNonExistingRule() diff --git a/tests/Core/Baseline/TestFiles/baseline.xml b/tests/Core/Baseline/TestFiles/baseline.xml index 2ea6dd6606..e9467b0291 100644 --- a/tests/Core/Baseline/TestFiles/baseline.xml +++ b/tests/Core/Baseline/TestFiles/baseline.xml @@ -1,5 +1,5 @@ - + diff --git a/tests/Core/Baseline/TestFiles/missing-file-baseline.xml b/tests/Core/Baseline/TestFiles/missing-file-baseline.xml index cfac035c95..51f024cebe 100644 --- a/tests/Core/Baseline/TestFiles/missing-file-baseline.xml +++ b/tests/Core/Baseline/TestFiles/missing-file-baseline.xml @@ -1,4 +1,4 @@ - + diff --git a/tests/Core/Baseline/TestFiles/missing-signature-baseline.xml b/tests/Core/Baseline/TestFiles/missing-signature-baseline.xml new file mode 100644 index 0000000000..af4d2c870b --- /dev/null +++ b/tests/Core/Baseline/TestFiles/missing-signature-baseline.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/Core/Baseline/TestFiles/missing-sniff-baseline.xml b/tests/Core/Baseline/TestFiles/missing-sniff-baseline.xml index c120ec0c23..bc50c10973 100644 --- a/tests/Core/Baseline/TestFiles/missing-sniff-baseline.xml +++ b/tests/Core/Baseline/TestFiles/missing-sniff-baseline.xml @@ -1,4 +1,4 @@ - + diff --git a/tests/Core/Baseline/ViolationBaselineTest.php b/tests/Core/Baseline/ViolationBaselineTest.php index f264e6159e..e0682628d8 100644 --- a/tests/Core/Baseline/ViolationBaselineTest.php +++ b/tests/Core/Baseline/ViolationBaselineTest.php @@ -30,7 +30,7 @@ class ViolationBaselineTest extends TestCase */ public function testGetSniffName() { - $violation = new ViolationBaseline('sniff', 'foobar'); + $violation = new ViolationBaseline('sniff', 'foobar', 'signature'); static::assertSame('sniff', $violation->getSniffName()); }//end testGetSniffName() @@ -45,10 +45,11 @@ public function testGetSniffName() */ public function testMatches() { - $violation = new ViolationBaseline('sniff', 'foobar.txt'); - static::assertTrue($violation->matches('foobar.txt')); - static::assertTrue($violation->matches('/test/foobar.txt')); - static::assertFalse($violation->matches('foo.txt')); + $violation = new ViolationBaseline('sniff', 'foobar.txt', 'signature'); + static::assertTrue($violation->matches('foobar.txt', 'signature')); + static::assertTrue($violation->matches('/test/foobar.txt', 'signature')); + static::assertFalse($violation->matches('foo.txt', 'signature')); + static::assertFalse($violation->matches('foobar.txt', 'bad-signature')); }//end testMatches() diff --git a/tests/Core/Reports/BaselineTest.php b/tests/Core/Reports/BaselineTest.php index e8e310e176..e398593885 100644 --- a/tests/Core/Reports/BaselineTest.php +++ b/tests/Core/Reports/BaselineTest.php @@ -12,6 +12,7 @@ use PHP_CodeSniffer\Config; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Reports\Baseline; +use PHP_CodeSniffer\Util; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -69,20 +70,29 @@ public function testGenerateFileReportShouldPrintReport() 'filename' => '/test/foobar.txt', 'errors' => 1, 'warnings' => 0, - 'messages' => [[[['source' => 'MySniff']]]], + 'messages' => [5 => [[['source' => 'MySniff']]]], ]; + $tokens = [ + [ + 'content' => 'foobar', + 'line' => 5, + ], + ]; + $signature = Util\CodeSignature::createSignature($tokens, 5); + $this->file->method('getTokens')->willReturn($tokens); + $report = new Baseline(); ob_start(); static::assertTrue($report->generateFileReport($reportData, $this->file)); $result = ob_get_clean(); - static::assertSame(''.PHP_EOL, $result); + static::assertSame(''.PHP_EOL, $result); }//end testGenerateFileReportShouldPrintReport() /** - * Test the generate of the complete file + * Test the generation of the complete file * * @covers ::generate * @return void @@ -90,8 +100,9 @@ public function testGenerateFileReportShouldPrintReport() public function testGenerate() { $expected = "".PHP_EOL; - $expected .= "".PHP_EOL; - $expected .= "".PHP_EOL; + $expected .= ""; + $expected .= "".PHP_EOL; + $expected .= "".PHP_EOL; $report = new Baseline(); ob_start(); From 62adaa9e3c5e5ac3b62ef790f5410fecaecf18b3 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 1 Aug 2021 11:06:05 +0200 Subject: [PATCH 21/22] Improve performance at checking existence of sniff and signature --- src/Baseline/BaselineSet.php | 8 ++++---- src/Baseline/ViolationBaseline.php | 19 +++++++++++++++---- tests/Core/Baseline/ViolationBaselineTest.php | 15 ++++++++------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/Baseline/BaselineSet.php b/src/Baseline/BaselineSet.php index 958411b853..7370f9bdae 100644 --- a/src/Baseline/BaselineSet.php +++ b/src/Baseline/BaselineSet.php @@ -29,7 +29,7 @@ class BaselineSet */ public function addEntry(ViolationBaseline $entry) { - $this->violations[$entry->getSniffName()][] = $entry; + $this->violations[$entry->getSniffName()][$entry->getSignature()][] = $entry; }//end addEntry() @@ -45,15 +45,15 @@ public function addEntry(ViolationBaseline $entry) */ public function contains($sniffName, $fileName, $signature) { - if (isset($this->violations[$sniffName]) === false) { + if (isset($this->violations[$sniffName][$signature]) === false) { return false; } // Normalize slashes in file name. $fileName = str_replace('\\', '/', $fileName); - foreach ($this->violations[$sniffName] as $baseline) { - if ($baseline->matches($fileName, $signature) === true) { + foreach ($this->violations[$sniffName][$signature] as $baseline) { + if ($baseline->matches($fileName) === true) { return true; } } diff --git a/src/Baseline/ViolationBaseline.php b/src/Baseline/ViolationBaseline.php index ebc4db2172..ecba0101ea 100644 --- a/src/Baseline/ViolationBaseline.php +++ b/src/Baseline/ViolationBaseline.php @@ -70,17 +70,28 @@ public function getSniffName() }//end getSniffName() + /** + * Get the code signature for this baseline + * + * @return string + */ + public function getSignature() + { + return $this->signature; + + }//end getSignature() + + /** * Test if the given filepath matches the relative filename in the baseline * - * @param string $filepath the full filepath to match against - * @param string $signature the code signature of the violation + * @param string $filepath the full filepath to match against * * @return bool */ - public function matches($filepath, $signature) + public function matches($filepath) { - return $this->signature === $signature && substr($filepath, -$this->fileNameLength) === $this->fileName; + return substr($filepath, -$this->fileNameLength) === $this->fileName; }//end matches() diff --git a/tests/Core/Baseline/ViolationBaselineTest.php b/tests/Core/Baseline/ViolationBaselineTest.php index e0682628d8..14c256ba9a 100644 --- a/tests/Core/Baseline/ViolationBaselineTest.php +++ b/tests/Core/Baseline/ViolationBaselineTest.php @@ -22,18 +22,20 @@ class ViolationBaselineTest extends TestCase /** - * Test the sniff name is returned + * Test the sniff name and signature is returned * * @covers ::__construct * @covers ::getSniffName + * @covers ::getSignature * @return void */ - public function testGetSniffName() + public function testAccessors() { $violation = new ViolationBaseline('sniff', 'foobar', 'signature'); static::assertSame('sniff', $violation->getSniffName()); + static::assertSame('signature', $violation->getSignature()); - }//end testGetSniffName() + }//end testAccessors() /** @@ -46,10 +48,9 @@ public function testGetSniffName() public function testMatches() { $violation = new ViolationBaseline('sniff', 'foobar.txt', 'signature'); - static::assertTrue($violation->matches('foobar.txt', 'signature')); - static::assertTrue($violation->matches('/test/foobar.txt', 'signature')); - static::assertFalse($violation->matches('foo.txt', 'signature')); - static::assertFalse($violation->matches('foobar.txt', 'bad-signature')); + static::assertTrue($violation->matches('foobar.txt')); + static::assertTrue($violation->matches('/test/foobar.txt')); + static::assertFalse($violation->matches('foo.txt')); }//end testMatches() From 7c83e83524085a3b9e5780f2b1255798b39fe8cc Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sun, 1 Aug 2021 11:09:30 +0200 Subject: [PATCH 22/22] Method explanation docblock fix --- src/Baseline/BaselineSetFactory.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Baseline/BaselineSetFactory.php b/src/Baseline/BaselineSetFactory.php index ce6c72fb37..cbe45195cb 100644 --- a/src/Baseline/BaselineSetFactory.php +++ b/src/Baseline/BaselineSetFactory.php @@ -16,8 +16,7 @@ class BaselineSetFactory /** - * Read the baseline violations from the given filename path. Append the baseDir to all the file paths within - * the baseline file. + * Read the baseline violations from the given filename path. * * @param string $fileName the baseline file to import *