Skip to content

Commit f8a592c

Browse files
committed
Use content instead of line number for the fingerprint
1 parent 13fdf71 commit f8a592c

File tree

14 files changed

+134
-127
lines changed

14 files changed

+134
-127
lines changed

phpcs.xml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515

1616
<file>src</file>
1717
<file>tests</file>
18+
<exclude-pattern>tests/_files/*</exclude-pattern>
1819
</ruleset>

phpstan.neon.dist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@ parameters:
44
paths:
55
- src
66
- tests
7+
excludePaths:
8+
- tests/_files/
79
scanDirectories:
810
- vendor/squizlabs/php_codesniffer

phpunit.xml.dist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
colors="true"
88
forceCoversAnnotation="true"
99
>
10+
<php>
11+
<const name="PHP_CODESNIFFER_IN_TESTS" value="true"/>
12+
<const name="PHP_CODESNIFFER_CBF" value="false"/>
13+
<const name="PHP_CODESNIFFER_VERBOSITY" value="0"/>
14+
</php>
15+
1016
<testsuites>
1117
<testsuite name="Project Test Suite">
1218
<directory>tests</directory>

src/Report/Gitlab.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111

1212
use PHP_CodeSniffer\Files\File;
1313
use PHP_CodeSniffer\Reports\Report;
14+
use SplFileObject;
1415

16+
use function is_string;
1517
use function md5;
18+
use function preg_replace;
1619
use function rtrim;
1720
use function str_replace;
1821

@@ -26,15 +29,25 @@ class Gitlab implements Report
2629
public function generateFileReport($report, File $phpcsFile, $showSources = false, $width = 80)
2730
{
2831
$hasOutput = false;
32+
$fingerprints = [];
2933

3034
foreach ($report['messages'] as $line => $lineErrors) {
31-
foreach ($lineErrors as $column => $colErrors) {
35+
$lineContent = $this->getContentOfLine($phpcsFile->getFilename(), $line);
36+
37+
foreach ($lineErrors as $colErrors) {
3238
foreach ($colErrors as $error) {
39+
$fingerprint = md5($report['filename'] . $lineContent . $error['source']);
40+
if (isset($fingerprints[$fingerprint])) {
41+
++$fingerprints[$fingerprint];
42+
} else {
43+
$fingerprints[$fingerprint] = 1;
44+
}
45+
3346
$issue = [
3447
'type' => 'issue',
3548
'categories' => ['Style'],
3649
'check_name' => $error['source'],
37-
'fingerprint' => md5($report['filename'] . $error['message'] . $line . $column),
50+
'fingerprint' => $fingerprint . '-' . $fingerprints[$fingerprint],
3851
'severity' => $error['type'] === 'ERROR' ? 'major' : 'minor',
3952
'description' => str_replace(["\n", "\r", "\t"], ['\n', '\r', '\t'], $error['message']),
4053
'location' => [
@@ -68,4 +81,25 @@ public function generate(
6881
) {
6982
echo '[' . rtrim($cachedData, ',') . ']' . PHP_EOL;
7083
}
84+
85+
/**
86+
* @param string $filename
87+
* @param int $line
88+
* @return string
89+
*/
90+
private function getContentOfLine($filename, $line)
91+
{
92+
$file = new SplFileObject($filename);
93+
94+
if (!$file->eof()) {
95+
$file->seek($line - 1);
96+
$contents = $file->current();
97+
98+
if (is_string($contents)) {
99+
return (string) preg_replace('/\s+/', '', $contents);
100+
}
101+
}
102+
103+
return '';
104+
}
71105
}

tests/Fixtures/MixedViolations.php

Lines changed: 0 additions & 52 deletions
This file was deleted.

tests/Fixtures/ReportFixture.php

Lines changed: 0 additions & 20 deletions
This file was deleted.

tests/Fixtures/SingleViolation.php

Lines changed: 0 additions & 41 deletions
This file was deleted.

tests/Report/GitlabTest.php

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,39 @@
1010
namespace MichehTest\PhpCodeSniffer\Report;
1111

1212
use Micheh\PhpCodeSniffer\Report\Gitlab;
13-
use MichehTest\PhpCodeSniffer\Fixtures\MixedViolations;
14-
use MichehTest\PhpCodeSniffer\Fixtures\ReportFixture;
15-
use MichehTest\PhpCodeSniffer\Fixtures\SingleViolation;
13+
use PHP_CodeSniffer\Config;
1614
use PHP_CodeSniffer\Files\File;
15+
use PHP_CodeSniffer\Files\LocalFile;
16+
use PHP_CodeSniffer\Reporter;
17+
use PHP_CodeSniffer\Ruleset;
18+
use PHP_CodeSniffer\Util\Tokens;
1719
use PHPUnit\Framework\TestCase;
1820

21+
use function file_get_contents;
22+
1923
class GitlabTest extends TestCase
2024
{
2125
/**
2226
* @var Gitlab
2327
*/
2428
private $report;
2529

30+
/**
31+
* @var Config
32+
*/
33+
private $config;
34+
2635

2736
protected function setUp(): void
2837
{
2938
$this->report = new Gitlab();
39+
40+
$this->config = new Config();
41+
$this->config->basepath = __DIR__ . '/../'; // @phpstan-ignore property.notFound
42+
$this->config->standards = ['PSR12']; // @phpstan-ignore property.notFound
43+
44+
// Autoload PHP_CodeSniffer-specific token type constants
45+
$tokens = new Tokens();
3046
}
3147

3248
/**
@@ -48,27 +64,49 @@ public function testGenerateWithEmpty(): void
4864
}
4965

5066
/**
51-
* @return array<string, array<class-string<ReportFixture>>>
67+
* @return array<string, array<string>>
5268
*/
5369
public function violations(): array
5470
{
5571
return [
56-
'single' => [SingleViolation::class],
57-
'mixed' => [MixedViolations::class],
72+
'single' => ['Single'],
73+
'mixed' => ['Mixed'],
74+
'multiple' => ['Multiple'],
5875
];
5976
}
6077

6178
/**
62-
* @param class-string<ReportFixture> $class
6379
* @covers \Micheh\PhpCodeSniffer\Report\Gitlab::generateFileReport
6480
* @dataProvider violations
6581
*/
66-
public function testGenerateFileReport(string $class): void
82+
public function testGenerateFileReport(string $fileName): void
6783
{
68-
$fixture = new $class();
69-
self::assertInstanceOf(ReportFixture::class, $fixture);
84+
$phpPath = __DIR__ . '/../_files/' . $fileName . '.php';
85+
self::assertFileExists($phpPath);
86+
87+
$outputPath = __DIR__ . '/../_files/' . $fileName . '.json';
88+
self::assertFileExists($outputPath);
7089

71-
$this->expectOutputString($fixture->getExpectedOutput());
72-
$this->report->generateFileReport($fixture->getReportData(), $this->createMock(File::class));
90+
$file = $this->createFile($phpPath);
91+
92+
$this->expectOutputString((string) file_get_contents($outputPath));
93+
$this->report->generateFileReport($this->getReportData($file), $file);
94+
}
95+
96+
private function createFile(string $path): File
97+
{
98+
$file = new LocalFile($path, new Ruleset($this->config), $this->config);
99+
$file->process();
100+
101+
return $file;
102+
}
103+
104+
/**
105+
* @return array{filename: string, errors: int, warnings: int, fixable: int, messages: array<mixed>}
106+
*/
107+
private function getReportData(File $file): array
108+
{
109+
$reporter = new Reporter($this->config);
110+
return $reporter->prepareFileReport($file); // @phpstan-ignore return.type
73111
}
74112
}

tests/_files/Mixed.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"type":"issue","categories":["Style"],"check_name":"Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine","fingerprint":"0da49d5a2f6b30f151e4abef2fccd4e2-1","severity":"major","description":"Opening brace should be on a new line","location":{"path":"_files/Mixed.php","lines":{"begin":7,"end":7}}},{"type":"issue","categories":["Style"],"check_name":"Generic.Files.LineLength.TooLong","fingerprint":"0be4b9620fcab36dcef7ba50bd3ac097-1","severity":"minor","description":"Line exceeds 120 characters; contains 143 characters","location":{"path":"_files/Mixed.php","lines":{"begin":8,"end":8}}},

tests/_files/Mixed.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace DoNotUse;
4+
5+
class Mixed
6+
{
7+
public function __invoke(): string {
8+
return 'mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed mixed';
9+
}
10+
}

0 commit comments

Comments
 (0)