Skip to content

Commit 24b428b

Browse files
authored
Check if single level use statement is an aliased namespace, not simply a global namespace class (#50)
* Add failing test for aliased one-level NS * Add new visitor * CS fix * Add new visitor to Scoper after move
1 parent eeb07dd commit 24b428b

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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\NodeVisitor;
16+
17+
use PhpParser\Node;
18+
use PhpParser\Node\Name;
19+
use PhpParser\Node\Stmt\GroupUse;
20+
use PhpParser\Node\Stmt\UseUse;
21+
use PhpParser\NodeVisitorAbstract;
22+
23+
final class SingleLevelUseAliasVisitor extends NodeVisitorAbstract
24+
{
25+
/**
26+
* @var string
27+
*/
28+
private $prefix;
29+
30+
/**
31+
* @var array
32+
*/
33+
private $aliases;
34+
35+
public function __construct(string $prefix)
36+
{
37+
$this->prefix = $prefix;
38+
}
39+
40+
/**
41+
* @inheritdoc
42+
*/
43+
public function beforeTraverse(array $nodes)
44+
{
45+
$this->aliases = [];
46+
}
47+
48+
/**
49+
* @inheritdoc
50+
*/
51+
public function enterNode(Node $node)
52+
{
53+
/* Collate all single level aliases */
54+
if ($node instanceof UseUse
55+
&& (!$node->hasAttribute('parent')
56+
|| false === ($node->getAttribute('parent') instanceof GroupUse))
57+
&& $this->prefix !== $node->name->getFirst()
58+
&& 1 === count($node->name->parts)
59+
&& $node->alias !== $node->name->getFirst()
60+
) {
61+
$this->aliases[$node->alias] = $node;
62+
63+
return;
64+
}
65+
66+
$this->scopeUseStmtIfUsedInAnyNameAsAliasedNamespace($node);
67+
}
68+
69+
/**
70+
* @param Node $node
71+
*/
72+
private function scopeUseStmtIfUsedInAnyNameAsAliasedNamespace(Node $node)
73+
{
74+
if ($node instanceof Name
75+
&& 1 < count($node->parts)
76+
&& in_array($node->getFirst(), array_keys($this->aliases))
77+
) {
78+
$nodeToPrefix = $this->aliases[$node->getFirst()];
79+
$nodeToPrefix->name = Name::concat($this->prefix, $nodeToPrefix->name);
80+
unset($this->aliases[$node->getFirst()]);
81+
}
82+
}
83+
}

src/Scoper/PhpScoper.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Humbug\PhpScoper\NodeVisitor\IgnoreNamespaceScoperNodeVisitor;
2020
use Humbug\PhpScoper\NodeVisitor\NamespaceScoperNodeVisitor;
2121
use Humbug\PhpScoper\NodeVisitor\ParentNodeVisitor;
22+
use Humbug\PhpScoper\NodeVisitor\SingleLevelUseAliasVisitor;
2223
use Humbug\PhpScoper\NodeVisitor\UseNamespaceScoperNodeVisitor;
2324
use Humbug\PhpScoper\Scoper;
2425
use PhpParser\Error as PhpParserError;
@@ -71,6 +72,7 @@ private function createTraverser(string $prefix): NodeTraverserInterface
7172
$traverser = new NodeTraverser();
7273

7374
$traverser->addVisitor(new ParentNodeVisitor());
75+
$traverser->addVisitor(new SingleLevelUseAliasVisitor($prefix));
7476
$traverser->addVisitor(new IgnoreNamespaceScoperNodeVisitor());
7577
$traverser->addVisitor(new GroupUseNamespaceScoperNodeVisitor($prefix));
7678
$traverser->addVisitor(new NamespaceScoperNodeVisitor($prefix));

tests/Scoper/PhpScoperTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,25 @@ function foo($bar) : Closure
781781
{
782782
}
783783

784+
PHP
785+
];
786+
787+
yield '[Single part global namespace reference] an aliased root namespace' => [
788+
<<<'PHP'
789+
<?php
790+
791+
use Foo as Bar;
792+
new Bar\Baz();
793+
794+
PHP
795+
,
796+
'Humbug',
797+
<<<'PHP'
798+
<?php
799+
800+
use Humbug\Foo as Bar;
801+
new Bar\Baz();
802+
784803
PHP
785804
];
786805
}

0 commit comments

Comments
 (0)