Skip to content

Commit 4eecc4f

Browse files
committed
Report nonexistent classes and functions based on @since and @removed in phpstorm-stubs while respecting phpVersion parameter
1 parent aa92b5b commit 4eecc4f

14 files changed

+169
-18
lines changed

build/baseline-7.4.neon

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,6 @@ parameters:
8989
count: 1
9090
path: ../src/Reflection/ReflectionProvider/SetterReflectionProviderProvider.php
9191
-
92-
message: "#^Class class@anonymous/src/Testing/TestCase\\.php\\:257 has an uninitialized property \\$reflectionProvider\\. Give it default value or assign it in the constructor\\.$#"
92+
message: "#^Class class@anonymous/src/Testing/TestCase\\.php\\:258 has an uninitialized property \\$reflectionProvider\\. Give it default value or assign it in the constructor\\.$#"
9393
count: 1
9494
path: ../src/Testing/TestCase.php

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"nette/utils": "^3.1.3",
2424
"nikic/php-parser": "4.10.2",
2525
"ondram/ci-detector": "^3.4.0",
26-
"ondrejmirtes/better-reflection": "4.3.33",
26+
"ondrejmirtes/better-reflection": "4.3.34",
2727
"phpdocumentor/reflection-docblock": "4.3.4",
2828
"phpstan/php-8-stubs": "^0.1.2",
2929
"phpstan/phpdoc-parser": "^0.4.9",

composer.lock

+8-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Reflection/BetterReflection/BetterReflectionSourceLocatorFactory.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PHPStan\Reflection\BetterReflection\SourceLocator\ComposerJsonAndInstalledJsonSourceLocatorMaker;
1111
use PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocatorRepository;
1212
use PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocatorRepository;
13+
use PHPStan\Reflection\BetterReflection\SourceLocator\PhpVersionBlacklistSourceLocator;
1314
use PHPStan\Reflection\BetterReflection\SourceLocator\SkipClassAliasSourceLocator;
1415
use Roave\BetterReflection\Reflector\FunctionReflector;
1516
use Roave\BetterReflection\SourceLocator\Ast\Locator;
@@ -174,8 +175,8 @@ public function create(): SourceLocator
174175
$locators[] = $locator;
175176
}
176177
$locators[] = new ClassWhitelistSourceLocator($this->autoloadSourceLocator, $this->staticReflectionClassNamePatterns);
177-
$locators[] = new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber);
178-
$locators[] = new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber);
178+
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
179+
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
179180

180181
return new MemoizingSourceLocator(new AggregateSourceLocator($locators));
181182
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Reflection\BetterReflection\SourceLocator;
4+
5+
use Roave\BetterReflection\Identifier\Identifier;
6+
use Roave\BetterReflection\Identifier\IdentifierType;
7+
use Roave\BetterReflection\Reflection\Reflection;
8+
use Roave\BetterReflection\Reflector\Reflector;
9+
use Roave\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
10+
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;
11+
12+
class PhpVersionBlacklistSourceLocator implements SourceLocator
13+
{
14+
15+
private SourceLocator $sourceLocator;
16+
17+
private PhpStormStubsSourceStubber $phpStormStubsSourceStubber;
18+
19+
public function __construct(
20+
SourceLocator $sourceLocator,
21+
PhpStormStubsSourceStubber $phpStormStubsSourceStubber
22+
)
23+
{
24+
$this->sourceLocator = $sourceLocator;
25+
$this->phpStormStubsSourceStubber = $phpStormStubsSourceStubber;
26+
}
27+
28+
public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection
29+
{
30+
if ($identifier->isClass()) {
31+
if ($this->phpStormStubsSourceStubber->isPresentClass($identifier->getName()) === false) {
32+
return null;
33+
}
34+
}
35+
36+
if ($identifier->isFunction()) {
37+
if ($this->phpStormStubsSourceStubber->isPresentFunction($identifier->getName()) === false) {
38+
return null;
39+
}
40+
}
41+
42+
return $this->sourceLocator->locateIdentifier($reflector, $identifier);
43+
}
44+
45+
public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
46+
{
47+
return $this->sourceLocator->locateIdentifiersByType($reflector, $identifierType);
48+
}
49+
50+
}

src/Reflection/Runtime/RuntimeReflectionProvider.php

+11-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use PHPStan\Type\Generic\TemplateTypeMap;
1919
use PHPStan\Type\Type;
2020
use ReflectionClass;
21+
use Roave\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
2122

2223
class RuntimeReflectionProvider implements ReflectionProvider
2324
{
@@ -37,6 +38,8 @@ class RuntimeReflectionProvider implements ReflectionProvider
3738

3839
private StubPhpDocProvider $stubPhpDocProvider;
3940

41+
private PhpStormStubsSourceStubber $phpStormStubsSourceStubber;
42+
4043
/** @var \PHPStan\Reflection\FunctionReflection[] */
4144
private array $functionReflections = [];
4245

@@ -55,7 +58,8 @@ public function __construct(
5558
FunctionReflectionFactory $functionReflectionFactory,
5659
FileTypeMapper $fileTypeMapper,
5760
NativeFunctionReflectionProvider $nativeFunctionReflectionProvider,
58-
StubPhpDocProvider $stubPhpDocProvider
61+
StubPhpDocProvider $stubPhpDocProvider,
62+
PhpStormStubsSourceStubber $phpStormStubsSourceStubber
5963
)
6064
{
6165
$this->reflectionProviderProvider = $reflectionProviderProvider;
@@ -64,6 +68,7 @@ public function __construct(
6468
$this->fileTypeMapper = $fileTypeMapper;
6569
$this->nativeFunctionReflectionProvider = $nativeFunctionReflectionProvider;
6670
$this->stubPhpDocProvider = $stubPhpDocProvider;
71+
$this->phpStormStubsSourceStubber = $phpStormStubsSourceStubber;
6772
}
6873

6974
public function getClass(string $className): \PHPStan\Reflection\ClassReflection
@@ -287,9 +292,13 @@ private function getCustomFunction(\PhpParser\Node\Name $nameNode, ?Scope $scope
287292

288293
public function resolveFunctionName(\PhpParser\Node\Name $nameNode, ?Scope $scope): ?string
289294
{
290-
return $this->resolveName($nameNode, static function (string $name): bool {
295+
return $this->resolveName($nameNode, function (string $name): bool {
291296
$exists = function_exists($name);
292297
if ($exists) {
298+
if ($this->phpStormStubsSourceStubber->isPresentFunction($name) === false) {
299+
return false;
300+
}
301+
293302
return true;
294303
}
295304

src/Testing/TestCase.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ private function createRuntimeReflectionProvider(ReflectionProvider $actualRefle
221221
$functionReflectionFactory,
222222
$fileTypeMapper,
223223
self::getContainer()->getByType(NativeFunctionReflectionProvider::class),
224-
self::getContainer()->getByType(StubPhpDocProvider::class)
224+
self::getContainer()->getByType(StubPhpDocProvider::class),
225+
self::getContainer()->getByType(PhpStormStubsSourceStubber::class)
225226
),
226227
self::getPhpStormStubsSourceStubber(),
227228
[

src/Testing/TestCaseSourceLocatorFactory.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PHPStan\DependencyInjection\Container;
77
use PHPStan\Reflection\BetterReflection\SourceLocator\AutoloadSourceLocator;
88
use PHPStan\Reflection\BetterReflection\SourceLocator\ComposerJsonAndInstalledJsonSourceLocatorMaker;
9+
use PHPStan\Reflection\BetterReflection\SourceLocator\PhpVersionBlacklistSourceLocator;
910
use Roave\BetterReflection\Reflector\FunctionReflector;
1011
use Roave\BetterReflection\SourceLocator\Ast\Locator;
1112
use Roave\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
@@ -74,8 +75,8 @@ public function create(): SourceLocator
7475

7576
$locators[] = new PhpInternalSourceLocator($astLocator, $this->phpstormStubsSourceStubber);
7677
$locators[] = $this->autoloadSourceLocator;
77-
$locators[] = new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber);
78-
$locators[] = new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber);
78+
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
79+
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
7980

8081
return new MemoizingSourceLocator(new AggregateSourceLocator($locators));
8182
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
class AnalyserPhp74IntegrationTest extends \PHPStan\Testing\TestCase
6+
{
7+
8+
public function testErrors(): void
9+
{
10+
$errors = $this->runAnalyse(__DIR__ . '/data/removedOnPhp80.php');
11+
$this->assertCount(0, $errors);
12+
}
13+
14+
/**
15+
* @return string[]
16+
*/
17+
public static function getAdditionalConfigFiles(): array
18+
{
19+
return [
20+
__DIR__ . '/php74.neon',
21+
];
22+
}
23+
24+
25+
/**
26+
* @param string $file
27+
* @return \PHPStan\Analyser\Error[]
28+
*/
29+
private function runAnalyse(string $file): array
30+
{
31+
$file = $this->getFileHelper()->normalizePath($file);
32+
/** @var \PHPStan\Analyser\Analyser $analyser */
33+
$analyser = self::getContainer()->getByType(Analyser::class);
34+
35+
return $analyser->analyse([$file])->getErrors();
36+
}
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
class AnalyserPhp80IntegrationTest extends \PHPStan\Testing\TestCase
6+
{
7+
8+
public function testErrors(): void
9+
{
10+
$errors = $this->runAnalyse(__DIR__ . '/data/removedOnPhp80.php');
11+
$this->assertCount(2, $errors);
12+
}
13+
14+
/**
15+
* @return string[]
16+
*/
17+
public static function getAdditionalConfigFiles(): array
18+
{
19+
return [
20+
__DIR__ . '/php80.neon',
21+
];
22+
}
23+
24+
25+
/**
26+
* @param string $file
27+
* @return \PHPStan\Analyser\Error[]
28+
*/
29+
private function runAnalyse(string $file): array
30+
{
31+
$file = $this->getFileHelper()->normalizePath($file);
32+
/** @var \PHPStan\Analyser\Analyser $analyser */
33+
$analyser = self::getContainer()->getByType(Analyser::class);
34+
35+
return $analyser->analyse([$file])->getErrors();
36+
}
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
function (): void {
4+
gmp_random();
5+
6+
new DOMImplementationSource();
7+
};

tests/PHPStan/Analyser/php74.neon

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
parameters:
2+
phpVersion: 70400

tests/PHPStan/Analyser/php80.neon

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
parameters:
2+
phpVersion: 80000

tests/PHPStan/Broker/BrokerTest.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use PHPStan\Reflection\Runtime\RuntimeReflectionProvider;
1919
use PHPStan\Reflection\SignatureMap\NativeFunctionReflectionProvider;
2020
use PHPStan\Type\FileTypeMapper;
21+
use Roave\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
2122

2223
class BrokerTest extends \PHPStan\Testing\TestCase
2324
{
@@ -46,7 +47,8 @@ protected function setUp(): void
4647
$this->createMock(FunctionReflectionFactory::class),
4748
new FileTypeMapper($setterReflectionProviderProvider, $this->getParser(), $phpDocStringResolver, $phpDocNodeResolver, $this->createMock(Cache::class), $anonymousClassNameHelper),
4849
self::getContainer()->getByType(NativeFunctionReflectionProvider::class),
49-
self::getContainer()->getByType(StubPhpDocProvider::class)
50+
self::getContainer()->getByType(StubPhpDocProvider::class),
51+
self::getContainer()->getByType(PhpStormStubsSourceStubber::class)
5052
);
5153
$setterReflectionProviderProvider->setReflectionProvider($reflectionProvider);
5254
$this->broker = new Broker(

0 commit comments

Comments
 (0)