Skip to content

Commit

Permalink
Report nonexistent classes and functions based on @since and `@remo…
Browse files Browse the repository at this point in the history
…ved` in phpstorm-stubs while respecting `phpVersion` parameter
  • Loading branch information
ondrejmirtes committed Oct 6, 2020
1 parent aa92b5b commit 4eecc4f
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 18 deletions.
2 changes: 1 addition & 1 deletion build/baseline-7.4.neon
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@ parameters:
count: 1
path: ../src/Reflection/ReflectionProvider/SetterReflectionProviderProvider.php
-
message: "#^Class class@anonymous/src/Testing/TestCase\\.php\\:257 has an uninitialized property \\$reflectionProvider\\. Give it default value or assign it in the constructor\\.$#"
message: "#^Class class@anonymous/src/Testing/TestCase\\.php\\:258 has an uninitialized property \\$reflectionProvider\\. Give it default value or assign it in the constructor\\.$#"
count: 1
path: ../src/Testing/TestCase.php
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"nette/utils": "^3.1.3",
"nikic/php-parser": "4.10.2",
"ondram/ci-detector": "^3.4.0",
"ondrejmirtes/better-reflection": "4.3.33",
"ondrejmirtes/better-reflection": "4.3.34",
"phpdocumentor/reflection-docblock": "4.3.4",
"phpstan/php-8-stubs": "^0.1.2",
"phpstan/phpdoc-parser": "^0.4.9",
Expand Down
16 changes: 8 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use PHPStan\Reflection\BetterReflection\SourceLocator\ComposerJsonAndInstalledJsonSourceLocatorMaker;
use PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedDirectorySourceLocatorRepository;
use PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocatorRepository;
use PHPStan\Reflection\BetterReflection\SourceLocator\PhpVersionBlacklistSourceLocator;
use PHPStan\Reflection\BetterReflection\SourceLocator\SkipClassAliasSourceLocator;
use Roave\BetterReflection\Reflector\FunctionReflector;
use Roave\BetterReflection\SourceLocator\Ast\Locator;
Expand Down Expand Up @@ -174,8 +175,8 @@ public function create(): SourceLocator
$locators[] = $locator;
}
$locators[] = new ClassWhitelistSourceLocator($this->autoloadSourceLocator, $this->staticReflectionClassNamePatterns);
$locators[] = new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber);
$locators[] = new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber);
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);

return new MemoizingSourceLocator(new AggregateSourceLocator($locators));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php declare(strict_types = 1);

namespace PHPStan\Reflection\BetterReflection\SourceLocator;

use Roave\BetterReflection\Identifier\Identifier;
use Roave\BetterReflection\Identifier\IdentifierType;
use Roave\BetterReflection\Reflection\Reflection;
use Roave\BetterReflection\Reflector\Reflector;
use Roave\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;

class PhpVersionBlacklistSourceLocator implements SourceLocator
{

private SourceLocator $sourceLocator;

private PhpStormStubsSourceStubber $phpStormStubsSourceStubber;

public function __construct(
SourceLocator $sourceLocator,
PhpStormStubsSourceStubber $phpStormStubsSourceStubber
)
{
$this->sourceLocator = $sourceLocator;
$this->phpStormStubsSourceStubber = $phpStormStubsSourceStubber;
}

public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection
{
if ($identifier->isClass()) {
if ($this->phpStormStubsSourceStubber->isPresentClass($identifier->getName()) === false) {
return null;
}
}

if ($identifier->isFunction()) {
if ($this->phpStormStubsSourceStubber->isPresentFunction($identifier->getName()) === false) {
return null;
}
}

return $this->sourceLocator->locateIdentifier($reflector, $identifier);
}

public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
{
return $this->sourceLocator->locateIdentifiersByType($reflector, $identifierType);
}

}
13 changes: 11 additions & 2 deletions src/Reflection/Runtime/RuntimeReflectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Type;
use ReflectionClass;
use Roave\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;

class RuntimeReflectionProvider implements ReflectionProvider
{
Expand All @@ -37,6 +38,8 @@ class RuntimeReflectionProvider implements ReflectionProvider

private StubPhpDocProvider $stubPhpDocProvider;

private PhpStormStubsSourceStubber $phpStormStubsSourceStubber;

/** @var \PHPStan\Reflection\FunctionReflection[] */
private array $functionReflections = [];

Expand All @@ -55,7 +58,8 @@ public function __construct(
FunctionReflectionFactory $functionReflectionFactory,
FileTypeMapper $fileTypeMapper,
NativeFunctionReflectionProvider $nativeFunctionReflectionProvider,
StubPhpDocProvider $stubPhpDocProvider
StubPhpDocProvider $stubPhpDocProvider,
PhpStormStubsSourceStubber $phpStormStubsSourceStubber
)
{
$this->reflectionProviderProvider = $reflectionProviderProvider;
Expand All @@ -64,6 +68,7 @@ public function __construct(
$this->fileTypeMapper = $fileTypeMapper;
$this->nativeFunctionReflectionProvider = $nativeFunctionReflectionProvider;
$this->stubPhpDocProvider = $stubPhpDocProvider;
$this->phpStormStubsSourceStubber = $phpStormStubsSourceStubber;
}

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

public function resolveFunctionName(\PhpParser\Node\Name $nameNode, ?Scope $scope): ?string
{
return $this->resolveName($nameNode, static function (string $name): bool {
return $this->resolveName($nameNode, function (string $name): bool {
$exists = function_exists($name);
if ($exists) {
if ($this->phpStormStubsSourceStubber->isPresentFunction($name) === false) {
return false;
}

return true;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Testing/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ private function createRuntimeReflectionProvider(ReflectionProvider $actualRefle
$functionReflectionFactory,
$fileTypeMapper,
self::getContainer()->getByType(NativeFunctionReflectionProvider::class),
self::getContainer()->getByType(StubPhpDocProvider::class)
self::getContainer()->getByType(StubPhpDocProvider::class),
self::getContainer()->getByType(PhpStormStubsSourceStubber::class)
),
self::getPhpStormStubsSourceStubber(),
[
Expand Down
5 changes: 3 additions & 2 deletions src/Testing/TestCaseSourceLocatorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use PHPStan\DependencyInjection\Container;
use PHPStan\Reflection\BetterReflection\SourceLocator\AutoloadSourceLocator;
use PHPStan\Reflection\BetterReflection\SourceLocator\ComposerJsonAndInstalledJsonSourceLocatorMaker;
use PHPStan\Reflection\BetterReflection\SourceLocator\PhpVersionBlacklistSourceLocator;
use Roave\BetterReflection\Reflector\FunctionReflector;
use Roave\BetterReflection\SourceLocator\Ast\Locator;
use Roave\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
Expand Down Expand Up @@ -74,8 +75,8 @@ public function create(): SourceLocator

$locators[] = new PhpInternalSourceLocator($astLocator, $this->phpstormStubsSourceStubber);
$locators[] = $this->autoloadSourceLocator;
$locators[] = new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber);
$locators[] = new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber);
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);

return new MemoizingSourceLocator(new AggregateSourceLocator($locators));
}
Expand Down
38 changes: 38 additions & 0 deletions tests/PHPStan/Analyser/AnalyserPhp74IntegrationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

class AnalyserPhp74IntegrationTest extends \PHPStan\Testing\TestCase
{

public function testErrors(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/removedOnPhp80.php');
$this->assertCount(0, $errors);
}

/**
* @return string[]
*/
public static function getAdditionalConfigFiles(): array
{
return [
__DIR__ . '/php74.neon',
];
}


/**
* @param string $file
* @return \PHPStan\Analyser\Error[]
*/
private function runAnalyse(string $file): array
{
$file = $this->getFileHelper()->normalizePath($file);
/** @var \PHPStan\Analyser\Analyser $analyser */
$analyser = self::getContainer()->getByType(Analyser::class);

return $analyser->analyse([$file])->getErrors();
}

}
38 changes: 38 additions & 0 deletions tests/PHPStan/Analyser/AnalyserPhp80IntegrationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

class AnalyserPhp80IntegrationTest extends \PHPStan\Testing\TestCase
{

public function testErrors(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/removedOnPhp80.php');
$this->assertCount(2, $errors);
}

/**
* @return string[]
*/
public static function getAdditionalConfigFiles(): array
{
return [
__DIR__ . '/php80.neon',
];
}


/**
* @param string $file
* @return \PHPStan\Analyser\Error[]
*/
private function runAnalyse(string $file): array
{
$file = $this->getFileHelper()->normalizePath($file);
/** @var \PHPStan\Analyser\Analyser $analyser */
$analyser = self::getContainer()->getByType(Analyser::class);

return $analyser->analyse([$file])->getErrors();
}

}
7 changes: 7 additions & 0 deletions tests/PHPStan/Analyser/data/removedOnPhp80.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

function (): void {
gmp_random();

new DOMImplementationSource();
};
2 changes: 2 additions & 0 deletions tests/PHPStan/Analyser/php74.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parameters:
phpVersion: 70400
2 changes: 2 additions & 0 deletions tests/PHPStan/Analyser/php80.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parameters:
phpVersion: 80000
4 changes: 3 additions & 1 deletion tests/PHPStan/Broker/BrokerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use PHPStan\Reflection\Runtime\RuntimeReflectionProvider;
use PHPStan\Reflection\SignatureMap\NativeFunctionReflectionProvider;
use PHPStan\Type\FileTypeMapper;
use Roave\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;

class BrokerTest extends \PHPStan\Testing\TestCase
{
Expand Down Expand Up @@ -46,7 +47,8 @@ protected function setUp(): void
$this->createMock(FunctionReflectionFactory::class),
new FileTypeMapper($setterReflectionProviderProvider, $this->getParser(), $phpDocStringResolver, $phpDocNodeResolver, $this->createMock(Cache::class), $anonymousClassNameHelper),
self::getContainer()->getByType(NativeFunctionReflectionProvider::class),
self::getContainer()->getByType(StubPhpDocProvider::class)
self::getContainer()->getByType(StubPhpDocProvider::class),
self::getContainer()->getByType(PhpStormStubsSourceStubber::class)
);
$setterReflectionProviderProvider->setReflectionProvider($reflectionProvider);
$this->broker = new Broker(
Expand Down

0 comments on commit 4eecc4f

Please sign in to comment.