diff --git a/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/BleedingEdgeIncludePurifierTest.php b/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/BleedingEdgeIncludePurifierTest.php new file mode 100644 index 00000000000..9e6bc033d57 --- /dev/null +++ b/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/BleedingEdgeIncludePurifierTest.php @@ -0,0 +1,43 @@ +boot(); + + $this->bleedingEdgeIncludePurifier = $this->getService(BleedingEdgeIncludePurifier::class); + } + + public function testNothing(): void + { + $purifiedConfigFilePath = $this->bleedingEdgeIncludePurifier->purifyConfigFile( + __DIR__ . '/Fixture/no_bleeding_edge.neon' + ); + $this->assertNull($purifiedConfigFilePath); + } + + public function test(): void + { + $purifiedConfigFilePath = $this->bleedingEdgeIncludePurifier->purifyConfigFile( + __DIR__ . '/Fixture/some_file_including.neon' + ); + + $this->assertNotNull($purifiedConfigFilePath); + + $this->assertFileEquals(__DIR__ . '/Expected/some_file_including.neon', $purifiedConfigFilePath); + + // cleanup after yourself :) + FileSystem::delete($purifiedConfigFilePath); + } +} diff --git a/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Expected/some_file_including.neon b/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Expected/some_file_including.neon new file mode 100644 index 00000000000..70f5d904b66 --- /dev/null +++ b/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Expected/some_file_including.neon @@ -0,0 +1,4 @@ +includes: + +parameters: + one: two diff --git a/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Fixture/no_bleeding_edge.neon b/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Fixture/no_bleeding_edge.neon new file mode 100644 index 00000000000..db65a72428c --- /dev/null +++ b/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Fixture/no_bleeding_edge.neon @@ -0,0 +1,2 @@ +parameters: + one: two diff --git a/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Fixture/some_file_including.neon b/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Fixture/some_file_including.neon new file mode 100644 index 00000000000..1e38d87fcb2 --- /dev/null +++ b/packages-tests/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier/Fixture/some_file_including.neon @@ -0,0 +1,5 @@ +includes: + - %rootDir%/conf/bleedingEdge.neon + +parameters: + one: two diff --git a/packages-tests/NodeTypeResolver/DependencyInjection/PHPStanServiceFactoryTest.php b/packages-tests/NodeTypeResolver/DependencyInjection/PHPStanServiceFactoryTest.php new file mode 100644 index 00000000000..dc815860a66 --- /dev/null +++ b/packages-tests/NodeTypeResolver/DependencyInjection/PHPStanServiceFactoryTest.php @@ -0,0 +1,27 @@ +boot(); + + $this->phpStanServicesFactory = $this->getService(PHPStanServicesFactory::class); + } + + public function test(): void + { + $phpstanParser = $this->phpStanServicesFactory->createPHPStanParser(); + $this->assertInstanceOf(Parser::class, $phpstanParser); + } +} diff --git a/packages/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier.php b/packages/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier.php new file mode 100644 index 00000000000..721e293eabb --- /dev/null +++ b/packages/NodeTypeResolver/DependencyInjection/BleedingEdgeIncludePurifier.php @@ -0,0 +1,58 @@ +createTemporaryFilePath($filePath); + + $clearedFileContents = Strings::replace($fileContents, self::BLEEDING_EDGE_REGEX); + FileSystem::write($temporaryFilePath, $clearedFileContents); + + return $temporaryFilePath; + } + + private function createTemporaryFilePath(string $filePath): string + { + $fileDirectory = dirname($filePath); + $baseFileName = pathinfo($filePath, PATHINFO_BASENAME); + + return $fileDirectory . '/temp_' . $baseFileName; + } +} diff --git a/packages/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.php b/packages/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.php index c9be504d5b1..5522bdf6e85 100644 --- a/packages/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.php +++ b/packages/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.php @@ -17,36 +17,44 @@ use Rector\Core\Configuration\Option; use Rector\Core\Configuration\Parameter\ParameterProvider; use Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocatorProvider\DynamicSourceLocatorProvider; +use Symfony\Component\Filesystem\Filesystem; /** * Factory so Symfony app can use services from PHPStan container + * + * @see \Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory */ final class PHPStanServicesFactory { private readonly Container $container; public function __construct( - ParameterProvider $parameterProvider, - PHPStanExtensionsConfigResolver $phpStanExtensionsConfigResolver, + private readonly ParameterProvider $parameterProvider, + private readonly PHPStanExtensionsConfigResolver $phpStanExtensionsConfigResolver, + BleedingEdgeIncludePurifier $bleedingEdgeIncludePurifier, ) { - $containerFactory = new ContainerFactory(getcwd()); + $additionalConfigFiles = $this->resolveAdditionalConfigFiles(); - $additionalConfigFiles = []; + $purifiedConfigFiles = []; - if ($parameterProvider->hasParameter(Option::PHPSTAN_FOR_RECTOR_PATH)) { - $additionalConfigFiles[] = $parameterProvider->provideStringParameter(Option::PHPSTAN_FOR_RECTOR_PATH); - } + foreach ($additionalConfigFiles as $key => $additionalConfigFile) { + $purifiedConfigFile = $bleedingEdgeIncludePurifier->purifyConfigFile($additionalConfigFile); - $additionalConfigFiles[] = __DIR__ . '/../../../config/phpstan/static-reflection.neon'; - $additionalConfigFiles[] = __DIR__ . '/../../../config/phpstan/better-infer.neon'; - $additionalConfigFiles[] = __DIR__ . '/../../../config/phpstan/parser.neon'; + // nothing was changed + if ($purifiedConfigFile === null) { + continue; + } - $extensionConfigFiles = $phpStanExtensionsConfigResolver->resolve(); - $additionalConfigFiles = array_merge($additionalConfigFiles, $extensionConfigFiles); + $additionalConfigFiles[$key] = $purifiedConfigFile; + $purifiedConfigFiles[] = $purifiedConfigFile; + } - $existingAdditionalConfigFiles = array_filter($additionalConfigFiles, 'file_exists'); + $containerFactory = new ContainerFactory(getcwd()); + $this->container = $containerFactory->create(sys_get_temp_dir(), $additionalConfigFiles, []); - $this->container = $containerFactory->create(sys_get_temp_dir(), $existingAdditionalConfigFiles, []); + // clear temporary files, after container is created + $filesystem = new Filesystem(); + $filesystem->remove($purifiedConfigFiles); } /** @@ -120,4 +128,27 @@ public function createDynamicSourceLocatorProvider(): DynamicSourceLocatorProvid { return $this->container->getByType(DynamicSourceLocatorProvider::class); } + + /** + * @return string[] + */ + private function resolveAdditionalConfigFiles(): array + { + $additionalConfigFiles = []; + + if ($this->parameterProvider->hasParameter(Option::PHPSTAN_FOR_RECTOR_PATH)) { + $additionalConfigFiles[] = $this->parameterProvider->provideStringParameter( + Option::PHPSTAN_FOR_RECTOR_PATH + ); + } + + $additionalConfigFiles[] = __DIR__ . '/../../../config/phpstan/static-reflection.neon'; + $additionalConfigFiles[] = __DIR__ . '/../../../config/phpstan/better-infer.neon'; + $additionalConfigFiles[] = __DIR__ . '/../../../config/phpstan/parser.neon'; + + $extensionConfigFiles = $this->phpStanExtensionsConfigResolver->resolve(); + $additionalConfigFiles = array_merge($additionalConfigFiles, $extensionConfigFiles); + + return array_filter($additionalConfigFiles, 'file_exists'); + } }