Skip to content

Commit a5e179b

Browse files
authored
AttributeVersionRequirementHelper: Improve error messages
1 parent 2297f6c commit a5e179b

5 files changed

Lines changed: 64 additions & 28 deletions

File tree

.github/workflows/e2e-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ jobs:
3030
composer install
3131
OUTPUT=$(../bashunit -a exit_code "1" "vendor/bin/phpstan analyze test.php --error-format=raw")
3232
echo "$OUTPUT"
33-
../bashunit -a contains 'test.php:12:Version requirement will always evaluate to false.' "$OUTPUT"
34-
../bashunit -a contains 'test.php:32:Version requirement will always evaluate to false.' "$OUTPUT"
33+
../bashunit -a contains 'test.php:12:Version requirement <=8.0.0 does not match 8.1.0...8.5.99.' "$OUTPUT"
34+
../bashunit -a contains 'test.php:32:Version requirement ^11.0.0 does not match 12.5.0...12.5.99.' "$OUTPUT"
3535
3636
steps:
3737
- name: Harden the runner (Audit all outbound calls)

src/Rules/PHPUnit/AttributeVersionRequirementHelper.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use PHPStan\Php\PhpMinorVersionIterator;
1212
use PHPStan\Rules\IdentifierRuleError;
1313
use PHPStan\Rules\RuleErrorBuilder;
14+
use PHPStan\ShouldNotHappenException;
1415
use function count;
1516
use function is_numeric;
1617
use function preg_match;
@@ -77,7 +78,7 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
7778

7879
if ($this->warnAboutIncompleteVersion($versionRequirement)) {
7980
$errors[] = RuleErrorBuilder::message(
80-
sprintf('Version requirement is incomplete.'),
81+
sprintf('Version requirement %s is incomplete. Expect a version composed of major, minor and patch.', $versionRequirement),
8182
)
8283
->identifier('phpunit.attributeRequiresPhpVersion')
8384
->build();
@@ -129,9 +130,25 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
129130
}
130131
}
131132

133+
if (count($pharIoVersions) < 2) {
134+
throw new ShouldNotHappenException();
135+
}
136+
137+
if (strpos($attr->getName(), 'RequiresPhpunit') !== false) {
138+
$tip = 'PHPUnit version inferred from composer.json requirements.';
139+
} else {
140+
$tip = 'PHP version for analysis inferred from NEON config phpVersion or composer.json requirements. Invoke PHPStan with -vvv to get more details.';
141+
}
142+
132143
$errors[] = RuleErrorBuilder::message(
133-
sprintf('Version requirement will always evaluate to false.'),
144+
sprintf(
145+
'Version requirement %s does not match %s...%s.',
146+
$versionRequirement,
147+
$pharIoVersions[0]->getVersionString(),
148+
$pharIoVersions[count($pharIoVersions) - 1]->getVersionString(),
149+
),
134150
)
151+
->tip($tip)
135152
->identifier('phpunit.attributeRequiresPhpVersion')
136153
->build();
137154

@@ -140,7 +157,7 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
140157

141158
if ($this->PHPUnitVersion->requiresPhpversionAttributeWithOperator()->yes()) {
142159
$errors[] = RuleErrorBuilder::message(
143-
sprintf('Version requirement is missing operator.'),
160+
sprintf('Version requirement %s is missing operator.', $versionRequirement),
144161
)
145162
->identifier('phpunit.attributeRequiresPhpVersion')
146163
->build();
@@ -149,7 +166,7 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
149166
&& $this->PHPUnitVersion->deprecatesPhpversionAttributeWithoutOperator()->yes()
150167
) {
151168
$errors[] = RuleErrorBuilder::message(
152-
sprintf('Version requirement without operator is deprecated.'),
169+
sprintf('Version requirement %s without operator is deprecated.', $versionRequirement),
153170
)
154171
->identifier('phpunit.attributeRequiresPhpVersion')
155172
->build();
@@ -159,7 +176,7 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
159176
}
160177

161178
/**
162-
* @return Version[]
179+
* @return list<Version>
163180
*/
164181
private function getAnalyzedPhpVersions(): array
165182
{

tests/Rules/PHPUnit/AttributeRequiresPhpVersionRangeRuleTest.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,33 @@ final class AttributeRequiresPhpVersionRangeRuleTest extends RuleTestCase
1515

1616
public function testPhpVersionMismatch(): void
1717
{
18+
$tip = 'PHP version for analysis inferred from NEON config phpVersion or composer.json requirements. Invoke PHPStan with -vvv to get more details.';
19+
1820
$this->analyse([__DIR__ . '/data/requires-php-version-mismatch.php'], [
1921
[
20-
'Version requirement will always evaluate to false.',
22+
'Version requirement < 7.0 does not match 8.2.0...8.4.0.',
2123
20,
24+
$tip,
2225
],
2326
[
24-
'Version requirement will always evaluate to false.',
27+
'Version requirement ^5.0 does not match 8.2.0...8.4.0.',
2528
28,
29+
$tip,
2630
],
2731
[
28-
'Version requirement will always evaluate to false.',
32+
'Version requirement ~5.0 does not match 8.2.0...8.4.0.',
2933
36,
34+
$tip,
3035
],
3136
[
32-
'Version requirement will always evaluate to false.',
37+
'Version requirement 5.* does not match 8.2.0...8.4.0.',
3338
44,
39+
$tip,
3440
],
3541
[
36-
'Version requirement will always evaluate to false.',
42+
'Version requirement 8.5.* does not match 8.2.0...8.4.0.',
3743
76,
44+
$tip,
3845
],
3946
]);
4047
}

tests/Rules/PHPUnit/AttributeRequiresPhpVersionRuleTest.php

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public function testRuleOnPHPUnit124DeprecationsOn(): void
5353

5454
$this->analyse([__DIR__ . '/data/requires-php-version.php'], [
5555
[
56-
'Version requirement without operator is deprecated.',
56+
'Version requirement 8.0 without operator is deprecated.',
5757
12,
5858
],
5959
]);
@@ -75,7 +75,7 @@ public function testRuleOnPHPUnit13(): void
7575

7676
$this->analyse([__DIR__ . '/data/requires-php-version.php'], [
7777
[
78-
'Version requirement is missing operator.',
78+
'Version requirement 8.0 is missing operator.',
7979
12,
8080
],
8181
]);
@@ -87,40 +87,49 @@ public function testPhpVersionMismatch(): void
8787
$this->phpunitMinorVersion = 4;
8888
$this->deprecationRulesInstalled = false;
8989

90+
$tip = 'PHP version for analysis inferred from NEON config phpVersion or composer.json requirements. Invoke PHPStan with -vvv to get more details.';
9091
$this->analyse([__DIR__ . '/data/requires-php-version-mismatch.php'], [
9192
[
9293
// errors because https://github.com/sebastianbergmann/phpunit/issues/6451
9394
// the test assumes PHP_VERSION_ID 80500 and the constraint only has 2 digits
94-
'Version requirement will always evaluate to false.',
95+
'Version requirement <= 8.5 does not match 8.5.0...8.5.99.',
9596
12,
97+
$tip,
9698
],
9799
[
98-
'Version requirement will always evaluate to false.',
100+
'Version requirement < 7.0 does not match 8.5.0...8.5.99.',
99101
20,
102+
$tip,
100103
],
101104
[
102-
'Version requirement will always evaluate to false.',
105+
'Version requirement ^5.0 does not match 8.5.0...8.5.99.',
103106
28,
107+
$tip,
104108
],
105109
[
106-
'Version requirement will always evaluate to false.',
110+
'Version requirement ~5.0 does not match 8.5.0...8.5.99.',
107111
36,
112+
$tip,
108113
],
109114
[
110-
'Version requirement will always evaluate to false.',
115+
'Version requirement 5.* does not match 8.5.0...8.5.99.',
111116
44,
117+
$tip,
112118
],
113119
[
114-
'Version requirement will always evaluate to false.',
120+
'Version requirement <= 8.4 does not match 8.5.0...8.5.99.',
115121
52,
122+
$tip,
116123
],
117124
[
118-
'Version requirement will always evaluate to false.',
125+
'Version requirement <= 8.5 does not match 8.5.0...8.5.99.',
119126
60,
127+
$tip,
120128
],
121129
[
122-
'Version requirement will always evaluate to false.',
130+
'Version requirement 8.3.* does not match 8.5.0...8.5.99.',
123131
68,
132+
$tip,
124133
],
125134
]);
126135
}
@@ -158,11 +167,11 @@ public function testWarnAboutIncompleteVersion(): void
158167

159168
$this->analyse([__DIR__ . '/data/requires-php-version.php'], [
160169
[
161-
'Version requirement is incomplete.',
170+
'Version requirement 8.0 is incomplete. Expect a version composed of major, minor and patch.',
162171
12,
163172
],
164173
[
165-
'Version requirement is incomplete.',
174+
'Version requirement >=8.0 is incomplete. Expect a version composed of major, minor and patch.',
166175
20,
167176
],
168177
]);
@@ -177,7 +186,7 @@ public function testWarnAboutIncompletePhpunitVersion(): void
177186

178187
$this->analyse([__DIR__ . '/data/requires-phpunit-version.php'], [
179188
[
180-
'Version requirement is incomplete.',
189+
'Version requirement 11.0 is incomplete. Expect a version composed of major, minor and patch.',
181190
12,
182191
],
183192
]);

tests/Rules/PHPUnit/ClassAttributeRequiresPhpVersionRuleTest.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ public function testWarnAboutIncompleteVersion(): void
2424
$this->phpunitMinorVersion = 5;
2525
$this->warnAboutIncompleteVersion = true;
2626

27+
$tip = 'PHP version for analysis inferred from NEON config phpVersion or composer.json requirements. Invoke PHPStan with -vvv to get more details.';
28+
2729
$this->analyse([__DIR__ . '/data/requires-php-version-on-class.php'], [
2830
[
29-
'Version requirement will always evaluate to false.',
31+
'Version requirement < 7.0 does not match 8.5.0...8.5.99.',
3032
10,
33+
$tip,
3134
],
3235
[
33-
'Version requirement is incomplete.',
36+
'Version requirement < 7.0 is incomplete. Expect a version composed of major, minor and patch.',
3437
10,
3538
],
3639
]);
@@ -44,7 +47,7 @@ public function testWarnAboutIncompletePhpunitVersion(): void
4447

4548
$this->analyse([__DIR__ . '/data/requires-phpunit-version.php'], [
4649
[
47-
'Version requirement is incomplete.',
50+
'Version requirement >=11.0 is incomplete. Expect a version composed of major, minor and patch.',
4851
18,
4952
],
5053
]);

0 commit comments

Comments
 (0)