Skip to content

Commit 016ddc2

Browse files
committed
Add counter to fingerprint
1 parent beb79ba commit 016ddc2

File tree

16 files changed

+134
-146
lines changed

16 files changed

+134
-146
lines changed

.github/workflows/main.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ jobs:
2121
with:
2222
php-version: ${{ matrix.php-versions }}
2323
coverage: none
24-
if: matrix.php-versions != '7.4' || matrix.dependencies != 'highest'
24+
if: matrix.php-versions != '8.4' || matrix.dependencies != 'highest'
2525

2626
- uses: shivammathur/setup-php@2.31.1
2727
with:
2828
php-version: ${{ matrix.php-versions }}
2929
coverage: pcov
30-
if: matrix.php-versions == '7.4' && matrix.dependencies == 'highest'
30+
if: matrix.php-versions == '8.4' && matrix.dependencies == 'highest'
3131

3232
- name: Setup problem matcher for PHPUnit
3333
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
@@ -42,17 +42,17 @@ jobs:
4242

4343
- name: Run PHPUnit
4444
run: vendor/bin/phpunit
45-
if: matrix.php-versions != '7.4' || matrix.dependencies != 'highest'
45+
if: matrix.php-versions != '8.4' || matrix.dependencies != 'highest'
4646

4747
- name: Run PHPUnit with coverage
4848
run: vendor/bin/phpunit --coverage-clover=coverage.xml
49-
if: matrix.php-versions == '7.4' && matrix.dependencies == 'highest'
49+
if: matrix.php-versions == '8.4' && matrix.dependencies == 'highest'
5050

5151
- name: Upload coverage to Codecov
5252
uses: codecov/codecov-action@v5.1.2
5353
with:
5454
token: ${{ secrets.CODECOV_TOKEN }}
55-
if: matrix.php-versions == '7.4' && matrix.dependencies == 'highest'
55+
if: matrix.php-versions == '8.4' && matrix.dependencies == 'highest'
5656

5757
phpcs:
5858
runs-on: ubuntu-latest

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"require-dev": {
2525
"phpstan/phpstan": "^2.0",
2626
"phpunit/phpunit": "^8.5.14 || ^9.0",
27-
"squizlabs/php_codesniffer": "^3.3.1"
27+
"squizlabs/php_codesniffer": "^3.5.0"
2828
},
2929
"autoload": {
3030
"psr-4": {

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: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
use PHP_CodeSniffer\Reports\Report;
1414
use SplFileObject;
1515

16+
use function is_string;
1617
use function md5;
18+
use function preg_replace;
1719
use function rtrim;
1820
use function str_replace;
1921

@@ -27,20 +29,25 @@ class Gitlab implements Report
2729
public function generateFileReport($report, File $phpcsFile, $showSources = false, $width = 80)
2830
{
2931
$hasOutput = false;
32+
$fingerprints = [];
3033

3134
foreach ($report['messages'] as $line => $lineErrors) {
32-
$file = new SplFileObject($phpcsFile->getFilename());
33-
foreach ($lineErrors as $column => $colErrors) {
35+
$lineContent = $this->getContentOfLine($phpcsFile->getFilename(), $line);
36+
37+
foreach ($lineErrors as $colErrors) {
3438
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+
3546
$issue = [
3647
'type' => 'issue',
3748
'categories' => ['Style'],
3849
'check_name' => $error['source'],
39-
'fingerprint' => md5(
40-
$report['filename']
41-
. $error["source"]
42-
. $this->getRelevantSource($file, $line - 1)
43-
),
50+
'fingerprint' => $fingerprint . '-' . $fingerprints[$fingerprint],
4451
'severity' => $error['type'] === 'ERROR' ? 'major' : 'minor',
4552
'description' => str_replace(["\n", "\r", "\t"], ['\n', '\r', '\t'], $error['message']),
4653
'location' => [
@@ -75,14 +82,21 @@ public function generate(
7582
echo '[' . rtrim($cachedData, ',') . ']' . PHP_EOL;
7683
}
7784

78-
private function getRelevantSource(SplFileObject $file, int $line): string
85+
/**
86+
* @param string $filename
87+
* @param int $line
88+
* @return string
89+
*/
90+
private function getContentOfLine($filename, $line)
7991
{
92+
$file = new SplFileObject($filename);
93+
8094
if (!$file->eof()) {
81-
$file->seek($line);
95+
$file->seek($line - 1);
8296
$contents = $file->current();
8397

84-
if (false !== $contents) {
85-
return preg_replace('/\s+/', '', $contents);
98+
if (is_string($contents)) {
99+
return (string) preg_replace('/\s+/', '', $contents);
86100
}
87101
}
88102

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: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +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\Runner;
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 static $config;
34+
35+
36+
public static function setUpBeforeClass(): void
37+
{
38+
self::$config = new Config();
39+
self::$config->basepath = __DIR__ . '/../';
40+
self::$config->standards = ['PSR12'];
41+
42+
$runner = new Runner();
43+
$runner->config = self::$config;
44+
$runner->init();
45+
}
2646

2747
protected function setUp(): void
2848
{
@@ -48,30 +68,49 @@ public function testGenerateWithEmpty(): void
4868
}
4969

5070
/**
51-
* @return array<string, array<class-string<ReportFixture>>>
71+
* @return array<string, array<string>>
5272
*/
5373
public function violations(): array
5474
{
5575
return [
56-
'single' => [SingleViolation::class],
57-
'mixed' => [MixedViolations::class],
76+
'single' => ['Single'],
77+
'mixed' => ['Mixed'],
78+
'multiple' => ['Multiple'],
5879
];
5980
}
6081

6182
/**
62-
* @param class-string<ReportFixture> $class
6383
* @covers \Micheh\PhpCodeSniffer\Report\Gitlab::generateFileReport
6484
* @dataProvider violations
6585
*/
66-
public function testGenerateFileReport(string $class): void
86+
public function testGenerateFileReport(string $fileName): void
87+
{
88+
$phpPath = __DIR__ . '/../_files/' . $fileName . '.php';
89+
self::assertFileExists($phpPath);
90+
91+
$outputPath = __DIR__ . '/../_files/' . $fileName . '.json';
92+
self::assertFileExists($outputPath);
93+
94+
$file = $this->createFile($phpPath);
95+
96+
$this->expectOutputString((string) file_get_contents($outputPath));
97+
$this->report->generateFileReport($this->getReportData($file), $file);
98+
}
99+
100+
private function createFile(string $path): File
101+
{
102+
$file = new LocalFile($path, new Ruleset(self::$config), self::$config);
103+
$file->process();
104+
105+
return $file;
106+
}
107+
108+
/**
109+
* @return array{filename: string, errors: int, warnings: int, fixable: int, messages: array<mixed>}
110+
*/
111+
private function getReportData(File $file): array
67112
{
68-
$fixture = new $class();
69-
self::assertInstanceOf(ReportFixture::class, $fixture);
70-
$fixtureReflection = new \ReflectionClass($class);
71-
$phpcsFile = $this->createMock(File::class);
72-
$phpcsFile->method('getFilename')->willReturn($fixtureReflection->getFileName());
73-
74-
$this->expectOutputString($fixture->getExpectedOutput());
75-
$this->report->generateFileReport($fixture->getReportData(), $phpcsFile);
113+
$reporter = new Reporter(self::$config);
114+
return $reporter->prepareFileReport($file); // @phpstan-ignore return.type
76115
}
77116
}

0 commit comments

Comments
 (0)