Skip to content

Commit 790ab70

Browse files
authored
Leverage SymbolRegistry in Reflector (#602)
1 parent a6702a1 commit 790ab70

File tree

6 files changed

+258
-58
lines changed

6 files changed

+258
-58
lines changed

phpstan.neon.dist

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ parameters:
1010
path: 'src/Patcher/SymfonyPatcher.php'
1111
- message: '#Parameter \#1 \$nodes of method PhpParser\\NodeTraverserInterface::traverse\(\) expects array\<PhpParser\\Node\>, array\<PhpParser\\Node\\Stmt\>\|null given\.#'
1212
path: 'src/Scoper/PhpScoper.php'
13-
- message: '#Reflector::createSymbolList\(\)#'
14-
path: 'src/Reflector.php'
1513
- message: '#UseStmtName::getUseStmtAliasAndType\(\) should return#'
1614
path: 'src/PhpParser/UseStmtName.php'
1715
- message: '#UseStmtManipulator::getOriginalName\(\) should return#'

src/Reflector.php

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616

1717
namespace Humbug\PhpScoper;
1818

19+
use Humbug\PhpScoper\Symbol\SymbolRegistry;
1920
use JetBrains\PHPStormStub\PhpStormStubsMap;
20-
use function array_fill_keys;
2121
use function array_keys;
2222
use function array_merge;
23-
use function strtolower;
2423

2524
/**
2625
* @private
@@ -88,20 +87,9 @@ final class Reflector
8887
'T_READONLY',
8988
];
9089

91-
/**
92-
* @var array<string,true>
93-
*/
94-
private array $classes;
95-
96-
/**
97-
* @var array<string,true>
98-
*/
99-
private array $functions;
100-
101-
/**
102-
* @var array<string,true>
103-
*/
104-
private array $constants;
90+
private SymbolRegistry $classes;
91+
private SymbolRegistry $functions;
92+
private SymbolRegistry $constants;
10593

10694
public static function createWithPhpStormStubs(): self
10795
{
@@ -114,7 +102,7 @@ public static function createWithPhpStormStubs(): self
114102
array_keys(PhpStormStubsMap::FUNCTIONS),
115103
self::MISSING_FUNCTIONS,
116104
),
117-
self::createSymbolList(
105+
self::createConstantSymbolList(
118106
array_keys(PhpStormStubsMap::CONSTANTS),
119107
self::MISSING_CONSTANTS,
120108
),
@@ -123,73 +111,73 @@ public static function createWithPhpStormStubs(): self
123111

124112
public static function createEmpty(): self
125113
{
126-
return new self([], [], []);
114+
return new self(
115+
SymbolRegistry::create(),
116+
SymbolRegistry::create(),
117+
SymbolRegistry::createForConstants(),
118+
);
127119
}
128120

129-
/**
130-
* @param array<string, true> $classes
131-
* @param array<string, true> $functions
132-
* @param array<string, true> $constants
133-
*/
134-
public function __construct(array $classes, array $functions, array $constants)
135-
{
121+
private function __construct(
122+
SymbolRegistry $classes,
123+
SymbolRegistry $functions,
124+
SymbolRegistry $constants
125+
) {
136126
$this->classes = $classes;
137127
$this->functions = $functions;
138128
$this->constants = $constants;
139129
}
140130

141131
/**
142-
* @param string[] $classes
143-
* @param string[] $functions
144-
* @param string[] $constants
132+
* @param string[] $classNames
133+
* @param string[] $functionNames
134+
* @param string[] $constantNames
145135
*/
146136
public function withSymbols(
147-
array $classes,
148-
array $functions,
149-
array $constants
137+
array $classNames,
138+
array $functionNames,
139+
array $constantNames
150140
): self
151141
{
152142
return new self(
153-
self::createSymbolList(
154-
array_keys($this->classes),
155-
$classes,
156-
),
157-
self::createSymbolList(
158-
array_keys($this->functions),
159-
$functions,
160-
),
161-
self::createSymbolList(
162-
array_keys($this->constants),
163-
$constants,
164-
),
143+
$this->classes->withAdditionalSymbols($classNames),
144+
$this->functions->withAdditionalSymbols($functionNames),
145+
$this->constants->withAdditionalSymbols($constantNames),
165146
);
166147
}
167148

168149
public function isClassInternal(string $name): bool
169150
{
170-
return isset($this->classes[$name]);
151+
return $this->classes->matches($name);
171152
}
172153

173154
public function isFunctionInternal(string $name): bool
174155
{
175-
return isset($this->functions[strtolower($name)]);
156+
return $this->functions->matches($name);
176157
}
177158

178159
public function isConstantInternal(string $name): bool
179160
{
180-
return isset($this->constants[$name]);
161+
return $this->constants->matches($name);
162+
}
163+
164+
/**
165+
* @param string[] $sources
166+
*/
167+
private static function createSymbolList(array ...$sources): SymbolRegistry
168+
{
169+
return SymbolRegistry::create(
170+
array_merge(...$sources),
171+
);
181172
}
182173

183174
/**
184-
* @param string[][] $sources
185-
*
186-
* @return array<string, true>
175+
* @param string[] $sources
187176
*/
188-
private static function createSymbolList(array ...$sources): array
177+
private static function createConstantSymbolList(array ...$sources): SymbolRegistry
189178
{
190-
return array_fill_keys(
179+
return SymbolRegistry::createForConstants(
191180
array_merge(...$sources),
192-
true
193181
);
194182
}
195183
}

src/Symbol/SymbolRegistry.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,28 @@ public function matches(string $symbol): bool
109109
return false;
110110
}
111111

112+
/**
113+
* @param string[] $names
114+
* @param string[] $regexes
115+
*/
116+
public function withAdditionalSymbols(array $names = [], array $regexes = []): self
117+
{
118+
$args = [
119+
[
120+
...$this->getNames(),
121+
...$names,
122+
],
123+
[
124+
...$this->getRegexes(),
125+
...$regexes,
126+
],
127+
];
128+
129+
return $this->constants
130+
? self::createForConstants(...$args)
131+
: self::create(...$args);
132+
}
133+
112134
/**
113135
* @internal
114136
*

tests/EmptyReflectorTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the humbug/php-scoper package.
7+
*
8+
* Copyright (c) 2017 Théo FIDRY <[email protected]>,
9+
* Pádraic Brady <[email protected]>
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
namespace Humbug\PhpScoper;
16+
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* @covers \Humbug\PhpScoper\Reflector
21+
*/
22+
class EmptyReflectorTest extends TestCase
23+
{
24+
private Reflector $reflector;
25+
26+
protected function setUp(): void
27+
{
28+
$this->reflector = Reflector::createEmpty();
29+
}
30+
31+
/**
32+
* @dataProvider \Humbug\PhpScoper\PhpStormStubsReflectorTest::provideClasses
33+
*/
34+
public function test_it_can_identify_internal_classes(string $class): void
35+
{
36+
$actual = $this->reflector->isClassInternal($class);
37+
38+
self::assertFalse($actual);
39+
}
40+
41+
/**
42+
* @dataProvider \Humbug\PhpScoper\PhpStormStubsReflectorTest::provideFunctions
43+
*/
44+
public function test_it_can_identify_internal_functions(string $class, bool $expected): void
45+
{
46+
$actual = $this->reflector->isFunctionInternal($class);
47+
48+
self::assertFalse($actual);
49+
}
50+
51+
/**
52+
* @dataProvider \Humbug\PhpScoper\PhpStormStubsReflectorTest::provideConstants
53+
*/
54+
public function test_it_can_identify_internal_constants(string $class, bool $expected): void
55+
{
56+
$actual = $this->reflector->isConstantInternal($class);
57+
58+
self::assertFalse($actual);
59+
}
60+
}

tests/ReflectorTest.php renamed to tests/PhpStormStubsReflectorTest.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,21 @@
1919
/**
2020
* @covers \Humbug\PhpScoper\Reflector
2121
*/
22-
class ReflectorTest extends TestCase
22+
class PhpStormStubsReflectorTest extends TestCase
2323
{
24+
private Reflector $reflector;
25+
26+
protected function setUp(): void
27+
{
28+
$this->reflector = Reflector::createWithPhpStormStubs();
29+
}
30+
2431
/**
2532
* @dataProvider provideClasses
2633
*/
2734
public function test_it_can_identify_internal_classes(string $class, bool $expected): void
2835
{
29-
$actual = (Reflector::createWithPhpStormStubs())->isClassInternal($class);
36+
$actual = $this->reflector->isClassInternal($class);
3037

3138
self::assertSame($expected, $actual);
3239
}
@@ -36,7 +43,7 @@ public function test_it_can_identify_internal_classes(string $class, bool $expec
3643
*/
3744
public function test_it_can_identify_internal_functions(string $class, bool $expected): void
3845
{
39-
$actual = (Reflector::createWithPhpStormStubs())->isFunctionInternal($class);
46+
$actual = $this->reflector->isFunctionInternal($class);
4047

4148
self::assertSame($expected, $actual);
4249
}
@@ -46,7 +53,7 @@ public function test_it_can_identify_internal_functions(string $class, bool $exp
4653
*/
4754
public function test_it_can_identify_internal_constants(string $class, bool $expected): void
4855
{
49-
$actual = (Reflector::createWithPhpStormStubs())->isConstantInternal($class);
56+
$actual = $this->reflector->isConstantInternal($class);
5057

5158
self::assertSame($expected, $actual);
5259
}
@@ -58,6 +65,11 @@ public static function provideClasses(): iterable
5865
true,
5966
];
6067

68+
yield 'FQ PHP internal class' => [
69+
'\DateTime',
70+
true,
71+
];
72+
6173
yield 'PHP unknown user-defined class' => [
6274
'Foo',
6375
false,
@@ -88,6 +100,11 @@ public static function provideFunctions(): iterable
88100
true,
89101
];
90102

103+
yield 'FQ PHP internal function' => [
104+
'\class_exists',
105+
true,
106+
];
107+
91108
yield 'PHP internal function with the wrong case' => [
92109
'CLASS_EXISTS',
93110
true,
@@ -132,6 +149,11 @@ public static function provideConstants(): iterable
132149
true,
133150
];
134151

152+
yield '\PHP internal constant' => [
153+
'PHP_VERSION',
154+
true,
155+
];
156+
135157
yield 'PHP unknown user-defined constant' => [
136158
'UNKNOWN',
137159
false,

0 commit comments

Comments
 (0)