Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ jobs:
composer install
OUTPUT=$(../bashunit -a exit_code "1" "vendor/bin/phpstan analyze test.php --error-format=raw")
echo "$OUTPUT"
../bashunit -a contains 'test.php:12:Version requirement will always evaluate to false.' "$OUTPUT"
../bashunit -a contains 'test.php:32:Version requirement will always evaluate to false.' "$OUTPUT"
../bashunit -a contains 'test.php:12:Version requirement <=8.0.0 does not match 8.1.0...8.5.99.' "$OUTPUT"
../bashunit -a contains 'test.php:32:Version requirement ^11.0.0 does not match 12.5.0...12.5.99.' "$OUTPUT"
steps:
- name: Harden the runner (Audit all outbound calls)
Expand Down
27 changes: 22 additions & 5 deletions src/Rules/PHPUnit/AttributeVersionRequirementHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use PHPStan\Php\PhpMinorVersionIterator;
use PHPStan\Rules\IdentifierRuleError;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\ShouldNotHappenException;
use function count;
use function is_numeric;
use function preg_match;
Expand Down Expand Up @@ -77,7 +78,7 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array

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

if (count($pharIoVersions) < 2) {
throw new ShouldNotHappenException();
}

if (strpos($attr->getName(), 'RequiresPhpunit') !== false) {
$tip = 'PHPUnit version inferred from composer.json requirements.';
} else {
$tip = 'PHP version for analysis inferred from NEON config phpVersion or composer.json requirements. Invoke PHPStan with -vvv to get more details.';
}

$errors[] = RuleErrorBuilder::message(
sprintf('Version requirement will always evaluate to false.'),
sprintf(
'Version requirement %s does not match %s...%s.',
$versionRequirement,
$pharIoVersions[0]->getVersionString(),
$pharIoVersions[count($pharIoVersions) - 1]->getVersionString(),
),
)
->tip($tip)
->identifier('phpunit.attributeRequiresPhpVersion')
->build();

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

if ($this->PHPUnitVersion->requiresPhpversionAttributeWithOperator()->yes()) {
$errors[] = RuleErrorBuilder::message(
sprintf('Version requirement is missing operator.'),
sprintf('Version requirement %s is missing operator.', $versionRequirement),
)
->identifier('phpunit.attributeRequiresPhpVersion')
->build();
Expand All @@ -149,7 +166,7 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
&& $this->PHPUnitVersion->deprecatesPhpversionAttributeWithoutOperator()->yes()
) {
$errors[] = RuleErrorBuilder::message(
sprintf('Version requirement without operator is deprecated.'),
sprintf('Version requirement %s without operator is deprecated.', $versionRequirement),
)
->identifier('phpunit.attributeRequiresPhpVersion')
->build();
Expand All @@ -159,7 +176,7 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
}

/**
* @return Version[]
* @return list<Version>
*/
private function getAnalyzedPhpVersions(): array
{
Expand Down
17 changes: 12 additions & 5 deletions tests/Rules/PHPUnit/AttributeRequiresPhpVersionRangeRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,33 @@ final class AttributeRequiresPhpVersionRangeRuleTest extends RuleTestCase

public function testPhpVersionMismatch(): void
{
$tip = 'PHP version for analysis inferred from NEON config phpVersion or composer.json requirements. Invoke PHPStan with -vvv to get more details.';

$this->analyse([__DIR__ . '/data/requires-php-version-mismatch.php'], [
[
'Version requirement will always evaluate to false.',
'Version requirement < 7.0 does not match 8.2.0...8.4.0.',

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using a version range notation which github.com is also using. so I think it should be familiar to devs

20,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement ^5.0 does not match 8.2.0...8.4.0.',
28,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement ~5.0 does not match 8.2.0...8.4.0.',
36,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement 5.* does not match 8.2.0...8.4.0.',
44,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement 8.5.* does not match 8.2.0...8.4.0.',
76,
$tip,
],
]);
}
Expand Down
35 changes: 22 additions & 13 deletions tests/Rules/PHPUnit/AttributeRequiresPhpVersionRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function testRuleOnPHPUnit124DeprecationsOn(): void

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

$this->analyse([__DIR__ . '/data/requires-php-version.php'], [
[
'Version requirement is missing operator.',
'Version requirement 8.0 is missing operator.',
12,
],
]);
Expand All @@ -87,40 +87,49 @@ public function testPhpVersionMismatch(): void
$this->phpunitMinorVersion = 4;
$this->deprecationRulesInstalled = false;

$tip = 'PHP version for analysis inferred from NEON config phpVersion or composer.json requirements. Invoke PHPStan with -vvv to get more details.';
$this->analyse([__DIR__ . '/data/requires-php-version-mismatch.php'], [
[
// errors because https://github.com/sebastianbergmann/phpunit/issues/6451
// the test assumes PHP_VERSION_ID 80500 and the constraint only has 2 digits
'Version requirement will always evaluate to false.',
'Version requirement <= 8.5 does not match 8.5.0...8.5.99.',
12,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement < 7.0 does not match 8.5.0...8.5.99.',
20,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement ^5.0 does not match 8.5.0...8.5.99.',
28,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement ~5.0 does not match 8.5.0...8.5.99.',
36,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement 5.* does not match 8.5.0...8.5.99.',
44,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement <= 8.4 does not match 8.5.0...8.5.99.',
52,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement <= 8.5 does not match 8.5.0...8.5.99.',
60,
$tip,
],
[
'Version requirement will always evaluate to false.',
'Version requirement 8.3.* does not match 8.5.0...8.5.99.',
68,
$tip,
],
]);
}
Expand Down Expand Up @@ -158,11 +167,11 @@ public function testWarnAboutIncompleteVersion(): void

$this->analyse([__DIR__ . '/data/requires-php-version.php'], [
[
'Version requirement is incomplete.',
'Version requirement 8.0 is incomplete. Expect a version composed of major, minor and patch.',
12,
],
[
'Version requirement is incomplete.',
'Version requirement >=8.0 is incomplete. Expect a version composed of major, minor and patch.',
20,
],
]);
Expand All @@ -177,7 +186,7 @@ public function testWarnAboutIncompletePhpunitVersion(): void

$this->analyse([__DIR__ . '/data/requires-phpunit-version.php'], [
[
'Version requirement is incomplete.',
'Version requirement 11.0 is incomplete. Expect a version composed of major, minor and patch.',
12,
],
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ public function testWarnAboutIncompleteVersion(): void
$this->phpunitMinorVersion = 5;
$this->warnAboutIncompleteVersion = true;

$tip = 'PHP version for analysis inferred from NEON config phpVersion or composer.json requirements. Invoke PHPStan with -vvv to get more details.';

$this->analyse([__DIR__ . '/data/requires-php-version-on-class.php'], [
[
'Version requirement will always evaluate to false.',
'Version requirement < 7.0 does not match 8.5.0...8.5.99.',
10,
$tip,
],
[
'Version requirement is incomplete.',
'Version requirement < 7.0 is incomplete. Expect a version composed of major, minor and patch.',
10,
],
]);
Expand All @@ -44,7 +47,7 @@ public function testWarnAboutIncompletePhpunitVersion(): void

$this->analyse([__DIR__ . '/data/requires-phpunit-version.php'], [
[
'Version requirement is incomplete.',
'Version requirement >=11.0 is incomplete. Expect a version composed of major, minor and patch.',
18,
],
]);
Expand Down
Loading