Skip to content

Commit 48228ed

Browse files
authored
[config] include bootstrap files of extensions, to let rector know about types as well (rectorphp#3380)
* [config] include bootstrap files of extensions, to let rector know about types as well * tidy * make fixtures unique to easier find
1 parent dffddb2 commit 48228ed

File tree

15 files changed

+220
-142
lines changed

15 files changed

+220
-142
lines changed

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"composer/xdebug-handler": "^3.0.3",
1515
"doctrine/inflector": "^2.0.6",
1616
"fidry/cpu-core-counter": "^0.5.1",
17+
"nette/neon": "^3.4",
1718
"nette/utils": "^3.2.9",
1819
"nikic/php-parser": "^4.15.3",
1920
"ondram/ci-detector": "^4.1",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\NodeTypeResolver\DependencyInjection;
6+
7+
use Rector\NodeTypeResolver\DependencyInjection\PHPStanExtensionsConfigResolver;
8+
use Rector\Testing\PHPUnit\AbstractTestCase;
9+
10+
final class PHPStanExtensionsConfigResolverTest extends AbstractTestCase
11+
{
12+
private PHPStanExtensionsConfigResolver $phpStanExtensionsConfigResolver;
13+
14+
protected function setUp(): void
15+
{
16+
$this->boot();
17+
18+
$this->phpStanExtensionsConfigResolver = $this->getService(PHPStanExtensionsConfigResolver::class);
19+
}
20+
21+
public function test(): void
22+
{
23+
// these configs are required by this package, so must be in there
24+
25+
$phpunitExtensionFilePath = realpath(__DIR__ . '/../../../vendor/phpstan/phpstan-phpunit/extension.neon');
26+
27+
$assertExtensionFilePath = realpath(
28+
__DIR__ . '/../../../vendor/phpstan/phpstan-webmozart-assert/extension.neon'
29+
);
30+
31+
$extensionConfigFiles = $this->phpStanExtensionsConfigResolver->resolve();
32+
33+
$this->assertContains($phpunitExtensionFilePath, $extensionConfigFiles);
34+
$this->assertContains($assertExtensionFilePath, $extensionConfigFiles);
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\NodeTypeResolver\DependencyInjection;
6+
7+
use PHPStan\ExtensionInstaller\GeneratedConfig;
8+
use Rector\Core\Exception\ShouldNotHappenException;
9+
use ReflectionClass;
10+
11+
/**
12+
* @see \Rector\Tests\NodeTypeResolver\DependencyInjection\PHPStanExtensionsConfigResolverTest
13+
*/
14+
final class PHPStanExtensionsConfigResolver
15+
{
16+
/**
17+
* @var string[]
18+
*/
19+
private array $cachedExtensionConfigFiles = [];
20+
21+
/**
22+
* @return string[]
23+
*/
24+
public function resolve(): array
25+
{
26+
// same logic as in PHPStan for extension installed - https://github.com/phpstan/phpstan-src/blob/5956ec4f6cd09c8d7db9466ed4e7f25706f37a43/src/Command/CommandHelper.php#L195-L222
27+
if (! class_exists(GeneratedConfig::class)) {
28+
return [];
29+
}
30+
31+
if ($this->cachedExtensionConfigFiles !== []) {
32+
return $this->cachedExtensionConfigFiles;
33+
}
34+
35+
$reflectionClass = new ReflectionClass(GeneratedConfig::class);
36+
$generatedConfigClassFileName = $reflectionClass->getFileName();
37+
if ($generatedConfigClassFileName === false) {
38+
throw new ShouldNotHappenException();
39+
}
40+
41+
$generatedConfigDirectory = dirname($generatedConfigClassFileName);
42+
43+
$extensionConfigFiles = [];
44+
45+
foreach (GeneratedConfig::EXTENSIONS as $extension) {
46+
$fileNames = $extension['extra']['includes'] ?? [];
47+
foreach ($fileNames as $fileName) {
48+
$configFilePath = $generatedConfigDirectory . '/' . $extension['relative_install_path'] . '/' . $fileName;
49+
50+
$absoluteConfigFilePath = realpath($configFilePath);
51+
if (! is_string($absoluteConfigFilePath)) {
52+
continue;
53+
}
54+
55+
$extensionConfigFiles[] = $absoluteConfigFilePath;
56+
}
57+
}
58+
59+
$this->cachedExtensionConfigFiles = $extensionConfigFiles;
60+
61+
return $extensionConfigFiles;
62+
}
63+
}

packages/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.php

+5-41
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,13 @@
1010
use PHPStan\Dependency\DependencyResolver;
1111
use PHPStan\DependencyInjection\Container;
1212
use PHPStan\DependencyInjection\ContainerFactory;
13-
use PHPStan\ExtensionInstaller\GeneratedConfig;
1413
use PHPStan\File\FileHelper;
1514
use PHPStan\Parser\Parser;
1615
use PHPStan\PhpDoc\TypeNodeResolver;
1716
use PHPStan\Reflection\ReflectionProvider;
1817
use Rector\Core\Configuration\Option;
1918
use Rector\Core\Configuration\Parameter\ParameterProvider;
20-
use Rector\Core\Exception\ShouldNotHappenException;
2119
use Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocatorProvider\DynamicSourceLocatorProvider;
22-
use ReflectionClass;
2320

2421
/**
2522
* Factory so Symfony app can use services from PHPStan container
@@ -28,8 +25,10 @@ final class PHPStanServicesFactory
2825
{
2926
private readonly Container $container;
3027

31-
public function __construct(ParameterProvider $parameterProvider)
32-
{
28+
public function __construct(
29+
ParameterProvider $parameterProvider,
30+
PHPStanExtensionsConfigResolver $phpStanExtensionsConfigResolver,
31+
) {
3332
$containerFactory = new ContainerFactory(getcwd());
3433

3534
$additionalConfigFiles = [];
@@ -42,7 +41,7 @@ public function __construct(ParameterProvider $parameterProvider)
4241
$additionalConfigFiles[] = __DIR__ . '/../../../config/phpstan/better-infer.neon';
4342
$additionalConfigFiles[] = __DIR__ . '/../../../config/phpstan/parser.neon';
4443

45-
$extensionConfigFiles = $this->resolveExtensionConfigs();
44+
$extensionConfigFiles = $phpStanExtensionsConfigResolver->resolve();
4645
$additionalConfigFiles = array_merge($additionalConfigFiles, $extensionConfigFiles);
4746

4847
$existingAdditionalConfigFiles = array_filter($additionalConfigFiles, 'file_exists');
@@ -121,39 +120,4 @@ public function createDynamicSourceLocatorProvider(): DynamicSourceLocatorProvid
121120
{
122121
return $this->container->getByType(DynamicSourceLocatorProvider::class);
123122
}
124-
125-
/**
126-
* @return string[]
127-
*/
128-
private function resolveExtensionConfigs(): array
129-
{
130-
// same logic as in PHPStan for extension installed - https://github.com/phpstan/phpstan-src/blob/5956ec4f6cd09c8d7db9466ed4e7f25706f37a43/src/Command/CommandHelper.php#L195-L222
131-
if (! class_exists(GeneratedConfig::class)) {
132-
return [];
133-
}
134-
135-
$reflectionClass = new ReflectionClass(GeneratedConfig::class);
136-
$generatedConfigClassFileName = $reflectionClass->getFileName();
137-
if ($generatedConfigClassFileName === false) {
138-
throw new ShouldNotHappenException();
139-
}
140-
141-
$generatedConfigDirectory = dirname($generatedConfigClassFileName);
142-
143-
$extensionConfigFiles = [];
144-
145-
foreach (GeneratedConfig::EXTENSIONS as $extension) {
146-
$fileNames = $extension['extra']['includes'] ?? [];
147-
foreach ($fileNames as $fileName) {
148-
$configFilePath = $generatedConfigDirectory . '/' . $extension['relative_install_path'] . '/' . $fileName;
149-
if (! file_exists($configFilePath)) {
150-
continue;
151-
}
152-
153-
$extensionConfigFiles[] = $configFilePath;
154-
}
155-
}
156-
157-
return $extensionConfigFiles;
158-
}
159123
}

packages/Testing/PHPUnit/AbstractRectorTestCase.php

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ protected function setUp(): void
6767
/** @var BootstrapFilesIncluder $bootstrapFilesIncluder */
6868
$bootstrapFilesIncluder = $this->getService(BootstrapFilesIncluder::class);
6969
$bootstrapFilesIncluder->includeBootstrapFiles();
70+
$bootstrapFilesIncluder->includePHPStanExtensionsBoostrapFiles();
7071
}
7172

7273
protected function tearDown(): void

phpstan.neon

+3-5
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,6 @@ parameters:
9999
# known value
100100
- '#Property PhpParser\\Node\\Stmt\\Foreach_\:\:\$valueVar \(PhpParser\\Node\\Expr\) does not accept PhpParser\\Node\\Expr\|null#'
101101

102-
- '#Parameter \#1 \$variable of class Rector\\Php70\\ValueObject\\VariableAssignPair constructor expects PhpParser\\Node\\Expr\\ArrayDimFetch\|PhpParser\\Node\\Expr\\PropertyFetch\|PhpParser\\Node\\Expr\\StaticPropertyFetch\|PhpParser\\Node\\Expr\\Variable, PhpParser\\Node\\Expr given#'
103-
104102
# is nested expr
105103
- '#Access to an undefined property PhpParser\\Node\\Expr\:\:\$expr#'
106104

@@ -432,9 +430,9 @@ parameters:
432430
paths:
433431
# autoload check in bin file
434432
- bin/rector.php
435-
- src/Bootstrap/ExtensionConfigResolver.php
433+
- packages/NodeTypeResolver/DependencyInjection/PHPStanExtensionsConfigResolver.php
436434
# for config class reflection
437-
- packages/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.php
435+
- src/Bootstrap/ExtensionConfigResolver.php
438436
- src/DependencyInjection/CompilerPass/AutowireArrayParameterCompilerPass.php
439437
- src/DependencyInjection/Skipper/ParameterSkipper.php
440438
- src/DependencyInjection/DefinitionFinder.php
@@ -691,8 +689,8 @@ parameters:
691689
-
692690
message: '#Offset (.*?)includes(.*?) always exists and is not nullable#'
693691
paths:
694-
- packages/NodeTypeResolver/DependencyInjection/PHPStanServicesFactory.php
695692
- src/Bootstrap/ExtensionConfigResolver.php
693+
- packages/NodeTypeResolver/DependencyInjection/PHPStanExtensionsConfigResolver.php
696694

697695
# returns bool for notifications
698696
- '#Method "renamePropertyPromotion\(\)" returns bool type, so the name should start with is/has/was#'

rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/AutoImportTest.php

-28
This file was deleted.

rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/FixtureAutoImport/do_not_import_iterable.php.inc

-32
This file was deleted.

rules-tests/Php80/Rector/FunctionLike/UnionTypesRector/config/configured_rule_auto_import.php

-14
This file was deleted.

rules-tests/Renaming/Rector/Name/RenameClassRector/Fixture/array_static.php.inc

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class ArrayStatic extends \DateTime
1414

1515
public function __construct(DateTime $dateTime)
1616
{
17-
$this->dateTime = rand(0,1)
17+
$this->dateTime = rand(0, 15)
1818
? [$dateTime]
1919
: null;
2020
}
@@ -38,7 +38,7 @@ class ArrayStatic extends \DateTime
3838

3939
public function __construct(\DateTimeInterface $dateTime)
4040
{
41-
$this->dateTime = rand(0,1)
41+
$this->dateTime = rand(0, 15)
4242
? [$dateTime]
4343
: null;
4444
}

rules-tests/Renaming/Rector/Name/RenameClassRector/Fixture/var_static_in_nullable2.php.inc

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
55
use DateTime;
66
use DateTimeInterface;
77

8-
class VarStaticInNullable extends \DateTime
8+
class VarStaticInNullable2 extends \DateTime
99
{
1010
/**
1111
* @var ?static
@@ -14,7 +14,7 @@ class VarStaticInNullable extends \DateTime
1414

1515
public function __construct(DateTime $dateTime)
1616
{
17-
$this->dateTime = rand(0,1)
17+
$this->dateTime = rand(0,45)
1818
? $dateTime
1919
: null;
2020
}
@@ -29,7 +29,7 @@ namespace Rector\Tests\Renaming\Rector\Name\RenameClassRector\Fixture;
2929
use DateTime;
3030
use DateTimeInterface;
3131

32-
class VarStaticInNullable extends \DateTime
32+
class VarStaticInNullable2 extends \DateTime
3333
{
3434
/**
3535
* @var ?static
@@ -38,7 +38,7 @@ class VarStaticInNullable extends \DateTime
3838

3939
public function __construct(\DateTimeInterface $dateTime)
4040
{
41-
$this->dateTime = rand(0,1)
41+
$this->dateTime = rand(0,45)
4242
? $dateTime
4343
: null;
4444
}

rules-tests/Renaming/Rector/Name/RenameClassRector/Fixture/var_static_in_union.php.inc

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class VarStaticInUnion extends \DateTime
1414

1515
public function __construct(DateTime $dateTime)
1616
{
17-
$this->dateTime = rand(0,1)
17+
$this->dateTime = rand(0,30)
1818
? $dateTime
1919
: null;
2020
}
@@ -38,7 +38,7 @@ class VarStaticInUnion extends \DateTime
3838

3939
public function __construct(\DateTimeInterface $dateTime)
4040
{
41-
$this->dateTime = rand(0,1)
41+
$this->dateTime = rand(0,30)
4242
? $dateTime
4343
: null;
4444
}

0 commit comments

Comments
 (0)