Skip to content

Commit 513800d

Browse files
authored
Simplify TraverserFactory (#653)
1 parent da5866b commit 513800d

File tree

9 files changed

+165
-150
lines changed

9 files changed

+165
-150
lines changed

src/PhpParser/NodeTraverser.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
use PhpParser\Node\Stmt\Namespace_;
2424
use PhpParser\Node\Stmt\Use_;
2525
use PhpParser\Node\Stmt\UseUse;
26-
use PhpParser\NodeTraverser as PhpParserNodeTraverser;
26+
use PhpParser\NodeTraverserInterface;
27+
use PhpParser\NodeVisitor;
2728
use function array_map;
2829
use function array_slice;
2930
use function array_splice;
@@ -34,14 +35,31 @@
3435
/**
3536
* @private
3637
*/
37-
final class NodeTraverser extends PhpParserNodeTraverser
38+
final class NodeTraverser implements NodeTraverserInterface
3839
{
40+
private NodeTraverserInterface $decoratedTraverser;
41+
42+
public function __construct(NodeTraverserInterface $decoratedTraverser)
43+
{
44+
$this->decoratedTraverser = $decoratedTraverser;
45+
}
46+
47+
public function addVisitor(NodeVisitor $visitor): void
48+
{
49+
$this->decoratedTraverser->addVisitor($visitor);
50+
}
51+
52+
public function removeVisitor(NodeVisitor $visitor): void
53+
{
54+
$this->decoratedTraverser->removeVisitor($visitor);
55+
}
56+
3957
public function traverse(array $nodes): array
4058
{
4159
$nodes = $this->wrapInNamespace($nodes);
4260
$nodes = $this->replaceGroupUseStatements($nodes);
4361

44-
return parent::traverse($nodes);
62+
return $this->decoratedTraverser->traverse($nodes);
4563
}
4664

4765
/**

src/PhpParser/TraverserFactory.php

Lines changed: 102 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Humbug\PhpScoper\Scoper\PhpScoper;
2121
use Humbug\PhpScoper\Symbol\EnrichedReflector;
2222
use Humbug\PhpScoper\Symbol\SymbolsRegistry;
23+
use PhpParser\NodeTraverser as PhpParserNodeTraverser;
2324
use PhpParser\NodeTraverserInterface;
2425
use PhpParser\NodeVisitor as PhpParserNodeVisitor;
2526
use PhpParser\NodeVisitor\NameResolver;
@@ -30,20 +31,57 @@
3031
class TraverserFactory
3132
{
3233
private EnrichedReflector $reflector;
34+
private string $prefix;
35+
private SymbolsRegistry $symbolsRegistry;
3336

34-
public function __construct(EnrichedReflector $reflector)
35-
{
37+
public function __construct(
38+
EnrichedReflector $reflector,
39+
string $prefix,
40+
SymbolsRegistry $symbolsRegistry
41+
) {
3642
$this->reflector = $reflector;
43+
$this->prefix = $prefix;
44+
$this->symbolsRegistry = $symbolsRegistry;
3745
}
3846

39-
public function create(
40-
PhpScoper $scoper,
47+
public function create(PhpScoper $scoper): NodeTraverserInterface
48+
{
49+
return self::createTraverser(
50+
self::createNodeVisitors(
51+
$this->prefix,
52+
$this->reflector,
53+
$scoper,
54+
$this->symbolsRegistry,
55+
)
56+
);
57+
}
58+
59+
/**
60+
* @param PhpParserNodeVisitor[] $nodeVisitors
61+
*/
62+
private static function createTraverser(array $nodeVisitors): NodeTraverserInterface
63+
{
64+
$traverser = new NodeTraverser(
65+
new PhpParserNodeTraverser(),
66+
);
67+
68+
foreach ($nodeVisitors as $nodeVisitor) {
69+
$traverser->addVisitor($nodeVisitor);
70+
}
71+
72+
return $traverser;
73+
}
74+
75+
/**
76+
* @return PhpParserNodeVisitor[]
77+
*/
78+
private static function createNodeVisitors(
4179
string $prefix,
80+
EnrichedReflector $reflector,
81+
PhpScoper $scoper,
4282
SymbolsRegistry $symbolsRegistry
43-
): NodeTraverserInterface
83+
): array
4484
{
45-
$traverser = new NodeTraverser();
46-
4785
$namespaceStatements = new NamespaceStmtCollection();
4886
$useStatements = new UseStmtCollection();
4987

@@ -53,80 +91,62 @@ public function create(
5391
);
5492
$identifierResolver = new IdentifierResolver($nameResolver);
5593
$stringNodePrefixer = new StringNodePrefixer($scoper);
56-
57-
self::addVisitors(
58-
$traverser,
59-
[
60-
$nameResolver,
61-
new NodeVisitor\ParentNodeAppender(),
62-
new NodeVisitor\IdentifierNameAppender($identifierResolver),
63-
64-
new NodeVisitor\NamespaceStmt\NamespaceStmtPrefixer(
65-
$prefix,
66-
$this->reflector,
67-
$namespaceStatements,
68-
),
69-
70-
new NodeVisitor\UseStmt\UseStmtCollector(
71-
$namespaceStatements,
72-
$useStatements,
73-
),
74-
new NodeVisitor\UseStmt\UseStmtPrefixer(
75-
$prefix,
76-
$this->reflector,
77-
),
78-
79-
new NodeVisitor\NamespaceStmt\FunctionIdentifierRecorder(
80-
$prefix,
81-
$identifierResolver,
82-
$symbolsRegistry,
83-
$this->reflector,
84-
),
85-
new NodeVisitor\ClassIdentifierRecorder(
86-
$prefix,
87-
$identifierResolver,
88-
$symbolsRegistry,
89-
$this->reflector,
90-
),
91-
new NodeVisitor\NameStmtPrefixer(
92-
$prefix,
93-
$namespaceStatements,
94-
$useStatements,
95-
$this->reflector,
96-
),
97-
new NodeVisitor\StringScalarPrefixer(
98-
$prefix,
99-
$this->reflector,
100-
),
101-
new NodeVisitor\NewdocPrefixer($stringNodePrefixer),
102-
new NodeVisitor\EvalPrefixer($stringNodePrefixer),
103-
104-
new NodeVisitor\ClassAliasStmtAppender(
105-
$prefix,
106-
$this->reflector,
107-
$identifierResolver,
108-
),
109-
new NodeVisitor\MultiConstStmtReplacer(),
110-
new NodeVisitor\ConstStmtReplacer(
111-
$identifierResolver,
112-
$this->reflector,
113-
),
114-
],
115-
);
116-
117-
return $traverser;
118-
}
119-
120-
/**
121-
* @param PhpParserNodeVisitor[] $nodeVisitors
122-
*/
123-
private static function addVisitors(
124-
NodeTraverserInterface $nodeTraverser,
125-
array $nodeVisitors
126-
): void
127-
{
128-
foreach ($nodeVisitors as $nodeVisitor) {
129-
$nodeTraverser->addVisitor($nodeVisitor);
130-
}
94+
95+
return [
96+
$nameResolver,
97+
new NodeVisitor\ParentNodeAppender(),
98+
new NodeVisitor\IdentifierNameAppender($identifierResolver),
99+
100+
new NodeVisitor\NamespaceStmt\NamespaceStmtPrefixer(
101+
$prefix,
102+
$reflector,
103+
$namespaceStatements,
104+
),
105+
106+
new NodeVisitor\UseStmt\UseStmtCollector(
107+
$namespaceStatements,
108+
$useStatements,
109+
),
110+
new NodeVisitor\UseStmt\UseStmtPrefixer(
111+
$prefix,
112+
$reflector,
113+
),
114+
115+
new NodeVisitor\NamespaceStmt\FunctionIdentifierRecorder(
116+
$prefix,
117+
$identifierResolver,
118+
$symbolsRegistry,
119+
$reflector,
120+
),
121+
new NodeVisitor\ClassIdentifierRecorder(
122+
$prefix,
123+
$identifierResolver,
124+
$symbolsRegistry,
125+
$reflector,
126+
),
127+
new NodeVisitor\NameStmtPrefixer(
128+
$prefix,
129+
$namespaceStatements,
130+
$useStatements,
131+
$reflector,
132+
),
133+
new NodeVisitor\StringScalarPrefixer(
134+
$prefix,
135+
$reflector,
136+
),
137+
new NodeVisitor\NewdocPrefixer($stringNodePrefixer),
138+
new NodeVisitor\EvalPrefixer($stringNodePrefixer),
139+
140+
new NodeVisitor\ClassAliasStmtAppender(
141+
$prefix,
142+
$reflector,
143+
$identifierResolver,
144+
),
145+
new NodeVisitor\MultiConstStmtReplacer(),
146+
new NodeVisitor\ConstStmtReplacer(
147+
$identifierResolver,
148+
$reflector,
149+
),
150+
];
131151
}
132152
}

src/Scoper/PhpScoper.php

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,15 @@ final class PhpScoper implements Scoper
3434
private Parser $parser;
3535
private Scoper $decoratedScoper;
3636
private TraverserFactory $traverserFactory;
37-
private string $prefix;
38-
private SymbolsRegistry $symbolsRegistry;
3937

4038
public function __construct(
4139
Parser $parser,
4240
Scoper $decoratedScoper,
43-
TraverserFactory $traverserFactory,
44-
string $prefix,
45-
SymbolsRegistry $symbolsRegistry
41+
TraverserFactory $traverserFactory
4642
) {
4743
$this->parser = $parser;
4844
$this->decoratedScoper = $decoratedScoper;
4945
$this->traverserFactory = $traverserFactory;
50-
$this->prefix = $prefix;
51-
$this->symbolsRegistry = $symbolsRegistry;
5246
}
5347

5448
/**
@@ -69,17 +63,13 @@ public function scopePhp(string $php): string
6963
{
7064
$statements = $this->parser->parse($php);
7165

72-
$statements = $this->traverserFactory
73-
->create(
74-
$this,
75-
$this->prefix,
76-
$this->symbolsRegistry,
77-
)
66+
$scopedStatements = $this->traverserFactory
67+
->create($this)
7868
->traverse($statements);
7969

8070
$prettyPrinter = new Standard();
8171

82-
return $prettyPrinter->prettyPrintFile($statements)."\n";
72+
return $prettyPrinter->prettyPrintFile($scopedStatements)."\n";
8373
}
8474

8575
private static function isPhpFile(string $filePath, string $contents): bool

src/Scoper/ScoperFactory.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,11 @@ public function createScoper(
6666
),
6767
$autoloadPrefixer
6868
),
69-
new TraverserFactory($enrichedReflector),
70-
$prefix,
71-
$symbolsRegistry,
69+
new TraverserFactory(
70+
$enrichedReflector,
71+
$prefix,
72+
$symbolsRegistry,
73+
),
7274
),
7375
$prefix,
7476
$configuration->getPatcher(),

tests/PhpParser/TraverserFactoryTest.php

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ public function test_creates_a_new_traverser_at_each_call(): void
3535
new FakeParser(),
3636
new FakeScoper(),
3737
(new ReflectionClass(TraverserFactory::class))->newInstanceWithoutConstructor(),
38-
$prefix,
39-
new SymbolsRegistry(),
4038
);
4139
$symbolsRegistry = new SymbolsRegistry();
4240

@@ -45,19 +43,13 @@ public function test_creates_a_new_traverser_at_each_call(): void
4543
Reflector::createEmpty(),
4644
SymbolsConfiguration::create(),
4745
),
48-
);
49-
50-
$firstTraverser = $traverserFactory->create(
51-
$phpScoper,
52-
$prefix,
53-
$symbolsRegistry,
54-
);
55-
$secondTraverser = $traverserFactory->create(
56-
$phpScoper,
5746
$prefix,
5847
$symbolsRegistry,
5948
);
6049

50+
$firstTraverser = $traverserFactory->create($phpScoper);
51+
$secondTraverser = $traverserFactory->create($phpScoper);
52+
6153
self::assertNotSame($firstTraverser, $secondTraverser);
6254
}
6355
}

tests/PhpParser/UseStmtNameTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
use Humbug\PhpScoper\PhpParser\NodeVisitor\UseStmt\UseStmtCollection;
1010
use Humbug\PhpScoper\Symbol\EnrichedReflector;
1111
use Humbug\PhpScoper\Symbol\Reflector;
12-
use Humbug\PhpScoper\Whitelist;
1312
use LogicException;
1413
use PhpParser\Node\Name;
1514
use PhpParser\Node\Stmt\Use_;
15+
use PhpParser\NodeTraverser as PhpParserNodeTraverser;
1616
use PHPUnit\Framework\TestCase;
1717
use function Humbug\PhpScoper\create_parser;
1818
use function Safe\sprintf;
@@ -172,7 +172,9 @@ private static function parseUseStmtName(string $php): Name
172172
$namespaceStatements = new NamespaceStmtCollection();
173173
$useStatements = new UseStmtCollection();
174174

175-
$traverser = new NodeTraverser();
175+
$traverser = new NodeTraverser(
176+
new PhpParserNodeTraverser(),
177+
);
176178

177179
$traverser->addVisitor(new NodeVisitor\ParentNodeAppender());
178180
$traverser->addVisitor(

tests/PhpScoperAssertions.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
namespace Humbug\PhpScoper;
66

77
use PHPUnit\Framework\Assert;
8+
use function array_is_list;
9+
use function var_export;
810

911
final class PhpScoperAssertions
1012
{

tests/Scoper/PhpScoperSpecTest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,11 @@ private static function createScoper(
293293
return new PhpScoper(
294294
$phpParser,
295295
new FakeScoper(),
296-
new TraverserFactory($enrichedReflector),
297-
$prefix,
298-
$symbolsRegistry,
296+
new TraverserFactory(
297+
$enrichedReflector,
298+
$prefix,
299+
$symbolsRegistry,
300+
),
299301
);
300302
}
301303

0 commit comments

Comments
 (0)