2019-10-13 05:59:52 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
2018-08-06 10:31:17 +00:00
|
|
|
|
|
|
|
namespace Rector\NodeTypeResolver\DependencyInjection;
|
|
|
|
|
2020-01-03 20:35:16 +00:00
|
|
|
use Nette\Utils\FileSystem;
|
|
|
|
use Nette\Utils\Strings;
|
2018-08-06 10:31:17 +00:00
|
|
|
use PHPStan\Analyser\NodeScopeResolver;
|
|
|
|
use PHPStan\Analyser\ScopeFactory;
|
|
|
|
use PHPStan\Analyser\TypeSpecifier;
|
2019-12-08 21:00:38 +00:00
|
|
|
use PHPStan\DependencyInjection\Container;
|
2018-08-06 10:31:17 +00:00
|
|
|
use PHPStan\DependencyInjection\ContainerFactory;
|
2020-01-06 12:22:18 +00:00
|
|
|
use PHPStan\DependencyInjection\Type\DynamicReturnTypeExtensionRegistryProvider;
|
|
|
|
use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider;
|
2020-01-13 13:34:18 +00:00
|
|
|
use PHPStan\Reflection\ReflectionProvider;
|
2018-08-06 10:31:17 +00:00
|
|
|
|
|
|
|
final class PHPStanServicesFactory
|
|
|
|
{
|
2020-01-03 20:35:16 +00:00
|
|
|
/**
|
|
|
|
* @see https://regex101.com/r/CWADBe/2
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private const BLEEDING_EDGE_PATTERN = '#\n\s+-(.*?)bleedingEdge\.neon[\'|"]?#';
|
|
|
|
|
2018-08-06 10:31:17 +00:00
|
|
|
/**
|
|
|
|
* @var Container
|
|
|
|
*/
|
|
|
|
private $container;
|
|
|
|
|
|
|
|
public function __construct()
|
|
|
|
{
|
2019-10-19 17:53:56 +00:00
|
|
|
$currentWorkingDirectory = getcwd();
|
|
|
|
|
|
|
|
$containerFactory = new ContainerFactory($currentWorkingDirectory);
|
2019-07-28 13:46:37 +00:00
|
|
|
$additionalConfigFiles = [];
|
|
|
|
|
|
|
|
// possible path collision for Docker
|
2019-10-19 17:53:56 +00:00
|
|
|
$phpstanPhpunitExtensionConfig = $currentWorkingDirectory . '/vendor/phpstan/phpstan-phpunit/extension.neon';
|
2019-08-05 16:14:49 +00:00
|
|
|
if (file_exists($phpstanPhpunitExtensionConfig) && class_exists('PHPUnit\\Framework\\TestCase')) {
|
2019-07-28 13:46:37 +00:00
|
|
|
$additionalConfigFiles[] = $phpstanPhpunitExtensionConfig;
|
|
|
|
}
|
|
|
|
|
2020-01-03 20:35:16 +00:00
|
|
|
$temporaryPhpstanNeon = null;
|
|
|
|
|
2019-10-19 18:20:07 +00:00
|
|
|
$currentProjectConfigFile = $currentWorkingDirectory . '/phpstan.neon';
|
2019-10-19 17:53:56 +00:00
|
|
|
if (file_exists($currentProjectConfigFile)) {
|
2020-01-03 20:35:16 +00:00
|
|
|
$phpstanNeonContent = FileSystem::read($currentProjectConfigFile);
|
|
|
|
|
|
|
|
// bleeding edge clean out, see https://github.com/rectorphp/rector/issues/2431
|
|
|
|
if (Strings::match($phpstanNeonContent, self::BLEEDING_EDGE_PATTERN)) {
|
|
|
|
$temporaryPhpstanNeon = $currentWorkingDirectory . '/rector-temp-phpstan.neon';
|
|
|
|
$clearedPhpstanNeonContent = Strings::replace($phpstanNeonContent, self::BLEEDING_EDGE_PATTERN);
|
|
|
|
FileSystem::write($temporaryPhpstanNeon, $clearedPhpstanNeonContent);
|
|
|
|
|
|
|
|
$additionalConfigFiles[] = $temporaryPhpstanNeon;
|
|
|
|
} else {
|
|
|
|
$additionalConfigFiles[] = $currentProjectConfigFile;
|
|
|
|
}
|
2019-10-19 17:53:56 +00:00
|
|
|
}
|
|
|
|
|
2019-08-18 12:15:39 +00:00
|
|
|
$additionalConfigFiles[] = __DIR__ . '/../../config/phpstan/type-extensions.neon';
|
2020-01-03 22:44:40 +00:00
|
|
|
|
|
|
|
// enable type inferring from constructor
|
|
|
|
$additionalConfigFiles[] = __DIR__ . '/../../config/phpstan/better-infer.neon';
|
|
|
|
|
2019-07-28 13:46:37 +00:00
|
|
|
$this->container = $containerFactory->create(sys_get_temp_dir(), $additionalConfigFiles, []);
|
2020-01-03 20:35:16 +00:00
|
|
|
|
|
|
|
// clear bleeding edge fallback
|
|
|
|
if ($temporaryPhpstanNeon !== null) {
|
|
|
|
FileSystem::delete($temporaryPhpstanNeon);
|
|
|
|
}
|
2018-08-06 10:31:17 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 13:34:18 +00:00
|
|
|
public function createReflectionProvider(): ReflectionProvider
|
2018-08-06 10:31:17 +00:00
|
|
|
{
|
2020-01-13 13:34:18 +00:00
|
|
|
return $this->container->getByType(ReflectionProvider::class);
|
2018-08-06 10:31:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function createNodeScopeResolver(): NodeScopeResolver
|
|
|
|
{
|
|
|
|
return $this->container->getByType(NodeScopeResolver::class);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function createTypeSpecifier(): TypeSpecifier
|
|
|
|
{
|
|
|
|
return $this->container->getByType(TypeSpecifier::class);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function createScopeFactory(): ScopeFactory
|
|
|
|
{
|
|
|
|
return $this->container->getByType(ScopeFactory::class);
|
|
|
|
}
|
2020-01-06 08:43:51 +00:00
|
|
|
|
2020-01-06 12:22:18 +00:00
|
|
|
public function createDynamicReturnTypeExtensionRegistryProvider(): DynamicReturnTypeExtensionRegistryProvider
|
2020-01-06 08:43:51 +00:00
|
|
|
{
|
2020-01-06 12:22:18 +00:00
|
|
|
return $this->container->getByType(DynamicReturnTypeExtensionRegistryProvider::class);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function createOperatorTypeSpecifyingExtensionRegistryProvider(): OperatorTypeSpecifyingExtensionRegistryProvider
|
|
|
|
{
|
|
|
|
return $this->container->getByType(OperatorTypeSpecifyingExtensionRegistryProvider::class);
|
2020-01-06 08:43:51 +00:00
|
|
|
}
|
2018-08-06 10:31:17 +00:00
|
|
|
}
|