Skip to content

Commit 2297f6c

Browse files
authored
Fix PHPVersion based checks (#315)
1 parent f5dc20f commit 2297f6c

14 files changed

Lines changed: 194 additions & 41 deletions

.github/workflows/e2e-tests.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
2+
3+
name: "E2E Tests"
4+
5+
on:
6+
pull_request:
7+
push:
8+
branches:
9+
- "2.0.x"
10+
11+
concurrency:
12+
group: e2e-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches
13+
cancel-in-progress: true
14+
15+
permissions:
16+
contents: read
17+
18+
jobs:
19+
e2e-tests:
20+
name: "E2E tests"
21+
runs-on: "ubuntu-latest"
22+
timeout-minutes: 60
23+
24+
strategy:
25+
fail-fast: false
26+
matrix:
27+
include:
28+
- script: |
29+
cd e2e/composer-version
30+
composer install
31+
OUTPUT=$(../bashunit -a exit_code "1" "vendor/bin/phpstan analyze test.php --error-format=raw")
32+
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"
35+
36+
steps:
37+
- name: Harden the runner (Audit all outbound calls)
38+
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
39+
with:
40+
egress-policy: audit
41+
42+
- name: "Checkout"
43+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
44+
45+
- name: "Install PHP"
46+
uses: "shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc" # v2.37.1
47+
with:
48+
coverage: "none"
49+
php-version: "8.3"
50+
51+
- uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
52+
53+
- name: "Install bashunit"
54+
uses: "TypedDevs/bashunit@ffa9c79e71ecbb9990e777348bc9ba12314b62d0" # 0.39.1
55+
with:
56+
directory: "e2e"
57+
58+
- name: "Test"
59+
run: ${{ matrix.script }}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"require": {
1010
"php": "^7.4 || ^8.0",
1111
"phar-io/version": "^3.2",
12-
"phpstan/phpstan": "^2.2.3"
12+
"phpstan/phpstan": "^2.2.6"
1313
},
1414
"conflict": {
1515
"phpunit/phpunit": "<7.0"

e2e/composer-version/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/vendor
2+
composer.lock

e2e/composer-version/composer.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"require": {
3+
"php": "^8.1",
4+
"phpstan/phpstan": "@dev",
5+
"phpstan/phpstan-phpunit": "@dev",
6+
"phpunit/phpunit": "^12.5",
7+
"phpstan/extension-installer": "^1.4"
8+
},
9+
"repositories": [
10+
{
11+
"type": "path",
12+
"url": "../../"
13+
}
14+
],
15+
"config": {
16+
"allow-plugins": {
17+
"phpstan/extension-installer": true
18+
}
19+
}
20+
}

e2e/composer-version/phpstan.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
includes:
2+
- phar://phpstan.phar/conf/bleedingEdge.neon
3+
4+
parameters:
5+
level: 5

e2e/composer-version/test.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
use PHPUnit\Framework\Attributes\RequiresPhp;
4+
use PHPUnit\Framework\Attributes\RequiresPhpunit;
5+
6+
class A extends \PHPUnit\Framework\TestCase {
7+
#[RequiresPhp('<=8.2.0')]
8+
public function testFoo() {}
9+
}
10+
11+
class B extends \PHPUnit\Framework\TestCase {
12+
#[RequiresPhp('<=8.0.0')]
13+
public function testFoo() {}
14+
}
15+
16+
class C extends \PHPUnit\Framework\TestCase {
17+
#[RequiresPhp('^8.0.0')]
18+
public function testFoo() {}
19+
}
20+
21+
class D extends \PHPUnit\Framework\TestCase {
22+
#[RequiresPhp('^8.1.0')]
23+
public function testFoo() {}
24+
}
25+
26+
class E extends \PHPUnit\Framework\TestCase {
27+
#[RequiresPhpunit('^12.0.0')]
28+
public function testFoo() {}
29+
}
30+
31+
class F extends \PHPUnit\Framework\TestCase {
32+
#[RequiresPhpunit('^11.0.0')]
33+
public function testFoo() {}
34+
}

src/Rules/PHPUnit/AttributeVersionRequirementHelper.php

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@
77
use PharIo\Version\VersionConstraintParser;
88
use PHPStan\Analyser\Scope;
99
use PHPStan\BetterReflection\Reflection\ReflectionAttribute;
10+
use PHPStan\Php\ConfiguredPhpVersionRangeHelper;
1011
use PHPStan\Php\PhpMinorVersionIterator;
11-
use PHPStan\Php\PhpVersion;
1212
use PHPStan\Rules\IdentifierRuleError;
1313
use PHPStan\Rules\RuleErrorBuilder;
14-
use PHPStan\Type\Constant\ConstantIntegerType;
15-
use PHPStan\Type\IntegerRangeType;
1614
use function count;
1715
use function is_numeric;
1816
use function preg_match;
@@ -28,8 +26,6 @@ final class AttributeVersionRequirementHelper
2826

2927
private PHPUnitVersion $PHPUnitVersion;
3028

31-
private PhpVersion $fallbackPhpVersion;
32-
3329
/**
3430
* When phpstan-deprecation-rules is installed, rule reports deprecated usages.
3531
*/
@@ -42,19 +38,21 @@ final class AttributeVersionRequirementHelper
4238

4339
private bool $bleedingEdge;
4440

41+
private ConfiguredPhpVersionRangeHelper $phpVersionRangeHelper;
42+
4543
public function __construct(
4644
PHPUnitVersion $PHPUnitVersion,
47-
PhpVersion $phpVersion,
45+
ConfiguredPhpVersionRangeHelper $phpVersionRangeHelper,
4846
bool $deprecationRulesInstalled = false,
4947
bool $bleedingEdge = false,
5048
bool $warnAboutIncompleteVersion = true
5149
)
5250
{
5351
$this->PHPUnitVersion = $PHPUnitVersion;
5452
$this->deprecationRulesInstalled = $deprecationRulesInstalled;
55-
$this->fallbackPhpVersion = $phpVersion;
5653
$this->warnAboutIncompleteVersion = $warnAboutIncompleteVersion;
5754
$this->bleedingEdge = $bleedingEdge;
55+
$this->phpVersionRangeHelper = $phpVersionRangeHelper;
5856
}
5957

6058
/**
@@ -64,11 +62,6 @@ public function __construct(
6462
*/
6563
public function checkVersionRequirement(array $attributes, Scope $scope): array
6664
{
67-
$phpstanPharIoVersions = $this->getAnalyzedPhpVersions($scope);
68-
if ($phpstanPharIoVersions === []) {
69-
return [];
70-
}
71-
7265
$errors = [];
7366
$parser = new VersionConstraintParser();
7467
foreach ($attributes as $attr) {
@@ -99,7 +92,7 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
9992

10093
$pharIoVersions = strpos($attr->getName(), 'RequiresPhpunit') !== false
10194
? $this->PHPUnitVersion->getPharIoVersions()
102-
: $phpstanPharIoVersions;
95+
: $this->getAnalyzedPhpVersions();
10396
if ($pharIoVersions === []) {
10497
continue;
10598
}
@@ -168,29 +161,23 @@ public function checkVersionRequirement(array $attributes, Scope $scope): array
168161
/**
169162
* @return Version[]
170163
*/
171-
private function getAnalyzedPhpVersions(Scope $scope): array
164+
private function getAnalyzedPhpVersions(): array
172165
{
173-
$scopePhpVersion = $scope->getPhpVersion()->getType();
174-
if ($scopePhpVersion instanceof ConstantIntegerType) {
175-
$v = new PhpVersion($scopePhpVersion->getValue());
176-
return [new Version($v->getVersionString())];
177-
} elseif ($scopePhpVersion instanceof IntegerRangeType) {
178-
if ($scopePhpVersion->getMin() === null || $scopePhpVersion->getMax() === null) {
179-
return [];
180-
}
181-
166+
// @phpstan-ignore phpstanApi.method
167+
[$minVersion, $maxVersion] = $this->phpVersionRangeHelper->getVersionRange();
168+
if ($minVersion !== null && $maxVersion !== null) {
182169
$versions = [];
183170
$minorVersionIterator = new PhpMinorVersionIterator(
184-
new PhpVersion($scopePhpVersion->getMin()),
185-
new PhpVersion($scopePhpVersion->getMax()),
171+
$minVersion,
172+
$maxVersion,
186173
);
187174
foreach ($minorVersionIterator as $phpstanVersion) {
188175
$versions[] = new Version($phpstanVersion->getVersionString());
189176
}
190177
return $versions;
191178
}
192179

193-
return [new Version($this->fallbackPhpVersion->getVersionString())];
180+
return [];
194181
}
195182

196183
// see https://github.com/sebastianbergmann/phpunit/issues/6451

tests/Rules/PHPUnit/AttributeRequiresPhpVersionRangeRuleTest.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace PHPStan\Rules\PHPUnit;
44

5-
use PHPStan\Php\PhpVersion;
5+
use PHPStan\Php\ConfiguredPhpVersionRangeHelper;
66
use PHPStan\Rules\Rule;
77
use PHPStan\Testing\RuleTestCase;
88
use PHPStan\Type\FileTypeMapper;
@@ -13,8 +13,6 @@
1313
final class AttributeRequiresPhpVersionRangeRuleTest extends RuleTestCase
1414
{
1515

16-
private int $phpVersion = 80500;
17-
1816
public function testPhpVersionMismatch(): void
1917
{
2018
$this->analyse([__DIR__ . '/data/requires-php-version-mismatch.php'], [
@@ -52,7 +50,7 @@ protected function getRule(): Rule
5250
),
5351
new AttributeVersionRequirementHelper(
5452
$phpunitVersion,
55-
new PhpVersion($this->phpVersion),
53+
self::getContainer()->getByType(ConfiguredPhpVersionRangeHelper::class), // @phpstan-ignore phpstanApi.classConstant
5654
false,
5755
true,
5856
),
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
parameters:
2-
phpVersion: 80500
2+
phpVersion:
3+
min: 80500
4+
max: 80599

tests/Rules/PHPUnit/AttributeRequiresPhpVersionRuleTest.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace PHPStan\Rules\PHPUnit;
44

5-
use PHPStan\Php\PhpVersion;
5+
use PHPStan\Php\ConfiguredPhpVersionRangeHelper;
66
use PHPStan\Rules\Rule;
77
use PHPStan\Testing\RuleTestCase;
88
use PHPStan\Type\FileTypeMapper;
@@ -13,8 +13,6 @@
1313
final class AttributeRequiresPhpVersionRuleTest extends RuleTestCase
1414
{
1515

16-
private int $phpVersion = 80500;
17-
1816
private ?int $phpunitMajorVersion;
1917

2018
private ?int $phpunitMinorVersion;
@@ -196,7 +194,7 @@ protected function getRule(): Rule
196194
),
197195
new AttributeVersionRequirementHelper(
198196
$phpunitVersion,
199-
new PhpVersion($this->phpVersion),
197+
self::getContainer()->getByType(ConfiguredPhpVersionRangeHelper::class), // @phpstan-ignore phpstanApi.classConstant
200198
$this->deprecationRulesInstalled,
201199
true,
202200
$this->warnAboutIncompleteVersion,

0 commit comments

Comments
 (0)