Skip to content

Commit

Permalink
[BCB] PHPStanTestCase - TypeSpecifier extensions can no longer be pro…
Browse files Browse the repository at this point in the history
…vided by overriding methods from PHPStanTestCase. Use getAdditionalConfigFiles() instead.
  • Loading branch information
ondrejmirtes committed Sep 15, 2021
1 parent f8ecb19 commit 239291a
Show file tree
Hide file tree
Showing 7 changed files with 10 additions and 180 deletions.
113 changes: 4 additions & 109 deletions src/Testing/PHPStanTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,23 @@

namespace PHPStan\Testing;

use Composer\Autoload\ClassLoader;
use PhpParser\PrettyPrinter\Standard;
use PHPStan\Analyser\DirectScopeFactory;
use PHPStan\Analyser\MutatingScope;
use PHPStan\Analyser\NodeScopeResolver;
use PHPStan\Analyser\ScopeFactory;
use PHPStan\Analyser\TypeSpecifier;
use PHPStan\Analyser\TypeSpecifierFactory;
use PHPStan\BetterReflection\Reflector\ClassReflector;
use PHPStan\BetterReflection\Reflector\ConstantReflector;
use PHPStan\BetterReflection\Reflector\FunctionReflector;
use PHPStan\BetterReflection\SourceLocator\Ast\Locator;
use PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
use PHPStan\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber;
use PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\EvaledCodeSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
use PHPStan\DependencyInjection\Container;
use PHPStan\DependencyInjection\ContainerFactory;
use PHPStan\DependencyInjection\Reflection\ClassReflectionExtensionRegistryProvider;
use PHPStan\DependencyInjection\Type\DynamicReturnTypeExtensionRegistryProvider;
use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider;
use PHPStan\File\FileHelper;
use PHPStan\Parser\CachedParser;
use PHPStan\Parser\PhpParserDecorator;
use PHPStan\PhpDoc\TypeNodeResolver;
use PHPStan\PhpDoc\TypeStringResolver;
use PHPStan\Reflection\BetterReflection\Reflector\MemoizingClassReflector;
use PHPStan\Reflection\BetterReflection\Reflector\MemoizingConstantReflector;
use PHPStan\Reflection\BetterReflection\Reflector\MemoizingFunctionReflector;
use PHPStan\Reflection\BetterReflection\SourceLocator\AutoloadSourceLocator;
use PHPStan\Reflection\BetterReflection\SourceLocator\ComposerJsonAndInstalledJsonSourceLocatorMaker;
use PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Properties\PropertyReflectionFinder;
use PHPStan\Type\TypeAliasResolver;
Expand All @@ -50,12 +33,6 @@ abstract class PHPStanTestCase extends \PHPUnit\Framework\TestCase
/** @var array<string, Container> */
private static array $containers = [];

/** @var array{ClassReflector, FunctionReflector, ConstantReflector}|null */
private static $reflectors;

/** @var PhpStormStubsSourceStubber|null */
private static $phpStormStubsSourceStubber;

/** @api */
public static function getContainer(): Container
{
Expand Down Expand Up @@ -118,74 +95,16 @@ public function createReflectionProvider(): ReflectionProvider
return self::getContainer()->getByType(ReflectionProvider::class);
}

private static function getPhpStormStubsSourceStubber(): PhpStormStubsSourceStubber
{
if (self::$phpStormStubsSourceStubber === null) {
self::$phpStormStubsSourceStubber = self::getContainer()->getByType(PhpStormStubsSourceStubber::class);
}

return self::$phpStormStubsSourceStubber;
}

/**
* @return array{ClassReflector, FunctionReflector, ConstantReflector}
*/
public static function getReflectors(): array
{
if (self::$reflectors !== null) {
return self::$reflectors;
}

if (!class_exists(ClassLoader::class)) {
self::fail('Composer ClassLoader is unknown');
}

$classLoaderReflection = new \ReflectionClass(ClassLoader::class);
if ($classLoaderReflection->getFileName() === false) {
self::fail('Unknown ClassLoader filename');
}

$composerProjectPath = dirname($classLoaderReflection->getFileName(), 3);
if (!is_file($composerProjectPath . '/composer.json')) {
self::fail(sprintf('composer.json not found in directory %s', $composerProjectPath));
}

$composerJsonAndInstalledJsonSourceLocatorMaker = self::getContainer()->getByType(ComposerJsonAndInstalledJsonSourceLocatorMaker::class);
$composerSourceLocator = $composerJsonAndInstalledJsonSourceLocatorMaker->create($composerProjectPath);
if ($composerSourceLocator === null) {
self::fail('Could not create composer source locator');
}

// these need to be synced with TestCase-staticReflection.neon file and TestCaseSourceLocatorFactory

$locators = [
$composerSourceLocator,
return [
self::getContainer()->getService('betterReflectionClassReflector'),
self::getContainer()->getService('betterReflectionFunctionReflector'),
self::getContainer()->getService('betterReflectionConstantReflector'),
];

$phpParser = new PhpParserDecorator(self::getContainer()->getByType(CachedParser::class));

/** @var FunctionReflector $functionReflector */
$functionReflector = null;
$astLocator = new Locator($phpParser, static function () use (&$functionReflector): FunctionReflector {
return $functionReflector;
});
$astPhp8Locator = new Locator(self::getContainer()->getService('php8PhpParser'), static function () use (&$functionReflector): FunctionReflector {
return $functionReflector;
});
$reflectionSourceStubber = new ReflectionSourceStubber();
$locators[] = new PhpInternalSourceLocator($astPhp8Locator, self::getPhpStormStubsSourceStubber());
$locators[] = new AutoloadSourceLocator(self::getContainer()->getByType(FileNodesFetcher::class));
$locators[] = new PhpInternalSourceLocator($astLocator, $reflectionSourceStubber);
$locators[] = new EvaledCodeSourceLocator($astLocator, $reflectionSourceStubber);
$sourceLocator = new MemoizingSourceLocator(new AggregateSourceLocator($locators));

$classReflector = new MemoizingClassReflector($sourceLocator);
$functionReflector = new MemoizingFunctionReflector($sourceLocator, $classReflector);
$constantReflector = new MemoizingConstantReflector($sourceLocator, $classReflector);

self::$reflectors = [$classReflector, $functionReflector, $constantReflector];

return self::$reflectors;
}

public function getClassReflectionExtensionRegistryProvider(): ClassReflectionExtensionRegistryProvider
Expand Down Expand Up @@ -233,30 +152,6 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool
return true;
}

/**
* @param \PhpParser\PrettyPrinter\Standard $printer
* @param \PHPStan\Reflection\ReflectionProvider $reflectionProvider
* @param \PHPStan\Type\MethodTypeSpecifyingExtension[] $methodTypeSpecifyingExtensions
* @param \PHPStan\Type\StaticMethodTypeSpecifyingExtension[] $staticMethodTypeSpecifyingExtensions
* @return \PHPStan\Analyser\TypeSpecifier
*/
public function createTypeSpecifier(
Standard $printer,
ReflectionProvider $reflectionProvider,
array $methodTypeSpecifyingExtensions = [],
array $staticMethodTypeSpecifyingExtensions = []
): TypeSpecifier
{
return new TypeSpecifier(
$printer,
$reflectionProvider,
true,
self::getContainer()->getServicesByTag(TypeSpecifierFactory::FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG),
array_merge($methodTypeSpecifyingExtensions, self::getContainer()->getServicesByTag(TypeSpecifierFactory::METHOD_TYPE_SPECIFYING_EXTENSION_TAG)),
array_merge($staticMethodTypeSpecifyingExtensions, self::getContainer()->getServicesByTag(TypeSpecifierFactory::STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG))
);
}

public function getFileHelper(): FileHelper
{
return self::getContainer()->getByType(FileHelper::class);
Expand Down
15 changes: 2 additions & 13 deletions src/Testing/RuleTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,7 @@ abstract protected function getRule(): Rule;

protected function getTypeSpecifier(): TypeSpecifier
{
return $this->createTypeSpecifier(
new \PhpParser\PrettyPrinter\Standard(),
$this->createReflectionProvider(),
$this->getMethodTypeSpecifyingExtensions(),
$this->getStaticMethodTypeSpecifyingExtensions()
);
return self::getContainer()->getService('typeSpecifier');
}

private function getAnalyser(): Analyser
Expand All @@ -50,13 +45,7 @@ private function getAnalyser(): Analyser
]);

$broker = $this->createBroker();
$printer = new \PhpParser\PrettyPrinter\Standard();
$typeSpecifier = $this->createTypeSpecifier(
$printer,
$broker,
$this->getMethodTypeSpecifyingExtensions(),
$this->getStaticMethodTypeSpecifyingExtensions()
);
$typeSpecifier = $this->getTypeSpecifier();
$nodeScopeResolver = new NodeScopeResolver(
$broker,
self::getReflectors()[0],
Expand Down
7 changes: 1 addition & 6 deletions src/Testing/TypeInferenceTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,16 @@ abstract class TypeInferenceTestCase extends \PHPStan\Testing\PHPStanTestCase
/**
* @param string $file
* @param callable(\PhpParser\Node, \PHPStan\Analyser\Scope): void $callback
* @param \PHPStan\Type\MethodTypeSpecifyingExtension[] $methodTypeSpecifyingExtensions
* @param \PHPStan\Type\StaticMethodTypeSpecifyingExtension[] $staticMethodTypeSpecifyingExtensions
* @param string[] $dynamicConstantNames
*/
public function processFile(
string $file,
callable $callback,
array $methodTypeSpecifyingExtensions = [],
array $staticMethodTypeSpecifyingExtensions = [],
array $dynamicConstantNames = []
): void
{
$printer = new \PhpParser\PrettyPrinter\Standard();
$reflectionProvider = $this->createReflectionProvider();
$typeSpecifier = $this->createTypeSpecifier($printer, $reflectionProvider, $methodTypeSpecifyingExtensions, $staticMethodTypeSpecifyingExtensions);
$typeSpecifier = self::getContainer()->getService('typeSpecifier');
$fileHelper = self::getContainer()->getByType(FileHelper::class);
$resolver = new NodeScopeResolver(
$reflectionProvider,
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/AnalyserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ private function createAnalyser(bool $reportUnmatchedIgnoredErrors): \PHPStan\An
$printer = new \PhpParser\PrettyPrinter\Standard();
$fileHelper = $this->getFileHelper();

$typeSpecifier = $this->createTypeSpecifier($printer, $broker);
$typeSpecifier = self::getContainer()->getService('typeSpecifier');
$fileTypeMapper = self::getContainer()->getByType(FileTypeMapper::class);
$phpDocInheritanceResolver = new PhpDocInheritanceResolver($fileTypeMapper);

Expand Down
Loading

0 comments on commit 239291a

Please sign in to comment.