Skip to content

Commit d8e259e

Browse files
authored
Make PHPStan DI-Container available in bootstrap files (#8190)
1 parent 2084662 commit d8e259e

12 files changed

Lines changed: 64 additions & 5 deletions

File tree

.github/workflows/e2e.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ jobs:
4444
- 'e2e/parallel-reflection-resolver'
4545
- 'e2e/parallel with space'
4646
- 'e2e/print-new-node'
47+
- 'e2e/phpstan-container-bootstrap'
4748

4849
name: End to end test - ${{ matrix.directory }}
4950

bin/rector.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
use Rector\Bootstrap\AutoloadFileParameterResolver;
77
use Rector\Bootstrap\RectorConfigsResolver;
88
use Rector\ChangesReporting\Output\JsonOutputFormatter;
9+
use Rector\Config\RectorConfig;
910
use Rector\Configuration\Option;
1011
use Rector\Console\Style\SymfonyStyleFactory;
1112
use Rector\DependencyInjection\LazyContainerFactory;
1213
use Rector\DependencyInjection\RectorContainerFactory;
14+
use Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory;
1315
use Rector\Util\Reflection\PrivatesAccessor;
1416
use Symfony\Component\Console\Application;
1517
use Symfony\Component\Console\Command\Command;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
if (!isset($container)) {
4+
echo 'missing global $container variable';
5+
} elseif (get_class($container) === 'PHPStan\DependencyInjection\MemoizingContainer') {
6+
echo "working as expected\n";
7+
exit(0);
8+
} else {
9+
echo '$container has wrong class ' . get_class($container);
10+
}
11+
12+
exit(1);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"require": {
3+
"php": "^8.1"
4+
},
5+
"minimum-stability": "dev",
6+
"prefer-stable": true
7+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
use Rector\Config\RectorConfig;
4+
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
5+
6+
return static function (RectorConfig $rectorConfig): void {
7+
$rectorConfig->paths([__DIR__ . '/src']);
8+
9+
$rectorConfig->bootstrapFiles(['bootstrap.php']);
10+
11+
$rectorConfig->rule(AddParamBasedOnParentClassMethodRector::class);
12+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
echo "hello world";

phpstan.neon

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,13 @@ parameters:
379379
identifier: offsetAccess.nonArray
380380
path: src/PhpParser/NodeTraverser/RectorNodeTraverser.php
381381

382+
# variable is expected in included/required file
383+
-
384+
identifier: closure.unusedUse
385+
message: '#Anonymous function has an unused use \$container#'
386+
paths:
387+
- src/Autoloading/BootstrapFilesIncluder.php
388+
382389
# false positive
383390
-
384391
message: '#Method (.*?)refactor\(\) (never returns|should return) (.*?)#'

src/Autoloading/BootstrapFilesIncluder.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use RecursiveIteratorIterator;
1212
use SplFileInfo;
1313
use Webmozart\Assert\Assert;
14+
use PHPStan\DependencyInjection\Container;
1415

1516
/**
1617
* @see \Rector\Tests\Autoloading\BootstrapFilesIncluderTest
@@ -21,7 +22,7 @@ final class BootstrapFilesIncluder
2122
* Inspired by
2223
* @see https://github.com/phpstan/phpstan-src/commit/aad1bf888ab7b5808898ee5fe2228bb8bb4e4cf1
2324
*/
24-
public function includeBootstrapFiles(): void
25+
public function includeBootstrapFiles(Container $container): void
2526
{
2627
$bootstrapFiles = SimpleParameterProvider::provideArrayParameter(Option::BOOTSTRAP_FILES);
2728

@@ -33,7 +34,10 @@ public function includeBootstrapFiles(): void
3334
throw new ShouldNotHappenException(sprintf('Bootstrap file "%s" does not exist.', $bootstrapFile));
3435
}
3536

36-
require $bootstrapFile;
37+
// mimic PHPStan bootstrap file inclusion (bootstrap files have access to the global $container variable)
38+
(static function (string $file) use ($container): void {
39+
require $file;
40+
})($bootstrapFile);
3741
}
3842

3943
$this->requireRectorStubs();

src/DependencyInjection/RectorContainerFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Rector\Autoloading\BootstrapFilesIncluder;
88
use Rector\Caching\Detector\ChangedFilesDetector;
99
use Rector\Config\RectorConfig;
10+
use Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory;
1011
use Rector\ValueObject\Bootstrap\BootstrapConfigs;
1112

1213
final class RectorContainerFactory
@@ -25,7 +26,7 @@ public function createFromBootstrapConfigs(BootstrapConfigs $bootstrapConfigs):
2526

2627
/** @var BootstrapFilesIncluder $bootstrapFilesIncluder */
2728
$bootstrapFilesIncluder = $rectorConfig->get(BootstrapFilesIncluder::class);
28-
$bootstrapFilesIncluder->includeBootstrapFiles();
29+
$bootstrapFilesIncluder->includeBootstrapFiles($rectorConfig->get(PHPStanServicesFactory::class)->getContainer());
2930

3031
return $rectorConfig;
3132
}

src/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@ public function createDynamicSourceLocatorProvider(): DynamicSourceLocatorProvid
144144
return $this->container->getByType(DynamicSourceLocatorProvider::class);
145145
}
146146

147+
/**
148+
* @api
149+
*/
150+
public function getContainer(): Container
151+
{
152+
return $this->container;
153+
}
154+
147155
/**
148156
* @return string[]
149157
*/

0 commit comments

Comments
 (0)