Skip to content

Commit d3fbcc7

Browse files
committed
Fix namespace and trait imports - Close #34
1 parent ca2a80e commit d3fbcc7

File tree

5 files changed

+179
-5
lines changed

5 files changed

+179
-5
lines changed

src/Builder/ClassBuilder.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ public function generate(Parser $parser): array
398398
$visitors[] = new ClassNamespace($this->namespace);
399399
}
400400
if ($this->namespaceImports) {
401-
$visitors[] = new NamespaceUse(...$this->namespaceImports);
401+
$visitors[] = new NamespaceUse(...\array_reverse($this->namespaceImports));
402402
}
403403

404404
$visitors[] = new ClassFile($this->classGenerator());
@@ -410,7 +410,7 @@ public function generate(Parser $parser): array
410410
$visitors[] = new ClassImplements(...$this->implements);
411411
}
412412
if ($this->traits) {
413-
$visitors[] = new ClassUseTrait(...$this->traits);
413+
$visitors[] = new ClassUseTrait(...\array_reverse($this->traits));
414414
}
415415

416416
if (\count($this->constants) > 0) {

src/NodeVisitor/ClassUseTrait.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ public function afterTraverse(array $nodes): ?array
4242

4343
if ($node instanceof Stmt\Class_) {
4444
foreach ($traits as $trait) {
45-
$node->stmts[] = new Stmt\TraitUse([new Name($trait)]);
45+
\array_unshift($node->stmts, new Stmt\TraitUse([new Name($trait)]));
4646
}
4747
}
4848

4949
if ($node instanceof Namespace_) {
5050
foreach ($node->stmts as $stmt) {
5151
if ($stmt instanceof Stmt\Class_) {
5252
foreach ($traits as $trait) {
53-
$stmt->stmts[] = new Stmt\TraitUse([new Name($trait)]);
53+
\array_unshift($stmt->stmts, new Stmt\TraitUse([new Name($trait)]));
5454
}
5555
}
5656
}

src/NodeVisitor/NamespaceUse.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ public function afterTraverse(array $nodes): ?array
4747
$newNodes[] = $node;
4848

4949
if ($node instanceof Stmt\Namespace_) {
50+
$stmts = $node->stmts;
5051
foreach ($imports as $import) {
5152
if (\is_array($import)) {
5253
$useNamespace = $this->builderFactory->use($import[0]);
5354
$useNamespace->as($import[1]);
5455
} else {
5556
$useNamespace = $this->builderFactory->use($import);
5657
}
57-
$node->stmts[] = $useNamespace->getNode(); // @phpstan-ignore-line
58+
\array_unshift($stmts, $useNamespace->getNode());
5859
}
60+
$node->stmts = $stmts; // @phpstan-ignore-line
5961
}
6062
}
6163

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
/**
4+
* @see https://github.com/open-code-modeling/php-code-ast for the canonical source repository
5+
* @copyright https://github.com/open-code-modeling/php-code-ast/blob/master/COPYRIGHT.md
6+
* @license https://github.com/open-code-modeling/php-code-ast/blob/master/LICENSE.md MIT License
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace OpenCodeModelingTest\CodeAst\NodeVisitor;
12+
13+
use OpenCodeModeling\CodeAst\NodeVisitor\ClassUseTrait;
14+
use PhpParser\NodeTraverser;
15+
use PhpParser\Parser;
16+
use PhpParser\ParserFactory;
17+
use PhpParser\PrettyPrinter\Standard;
18+
use PHPUnit\Framework\TestCase;
19+
20+
final class ClassUseTraitTest extends TestCase
21+
{
22+
/**
23+
* @var Parser
24+
*/
25+
private $parser;
26+
27+
/**
28+
* @var Standard
29+
*/
30+
private $printer;
31+
32+
public function setUp(): void
33+
{
34+
$this->parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
35+
$this->printer = new Standard(['shortArraySyntax' => true]);
36+
}
37+
38+
/**
39+
* @test
40+
*/
41+
public function it_add_namespace_imports_in_correct_order(): void
42+
{
43+
$ast = $this->parser->parse($this->classCode());
44+
45+
$nodeTraverser = new NodeTraverser();
46+
$nodeTraverser->addVisitor(new ClassUseTrait('MyService\Foo', 'MyService\Bar'));
47+
48+
$this->assertSame($this->expectedClassCode(), $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
49+
}
50+
51+
private function classCode(): string
52+
{
53+
return <<<'EOF'
54+
<?php
55+
56+
declare(strict_types=1);
57+
58+
namespace My\Awesome\Service;
59+
60+
class TestClass
61+
{
62+
use MyService\Foo;
63+
64+
public function testMethod()
65+
{
66+
}
67+
}
68+
EOF;
69+
}
70+
71+
private function expectedClassCode(): string
72+
{
73+
return <<<'EOF'
74+
<?php
75+
76+
declare (strict_types=1);
77+
namespace My\Awesome\Service;
78+
79+
class TestClass
80+
{
81+
use MyService\Bar;
82+
use MyService\Foo;
83+
public function testMethod()
84+
{
85+
}
86+
}
87+
EOF;
88+
}
89+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
/**
4+
* @see https://github.com/open-code-modeling/php-code-ast for the canonical source repository
5+
* @copyright https://github.com/open-code-modeling/php-code-ast/blob/master/COPYRIGHT.md
6+
* @license https://github.com/open-code-modeling/php-code-ast/blob/master/LICENSE.md MIT License
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace OpenCodeModelingTest\CodeAst\NodeVisitor;
12+
13+
use OpenCodeModeling\CodeAst\NodeVisitor\NamespaceUse;
14+
use PhpParser\NodeTraverser;
15+
use PhpParser\Parser;
16+
use PhpParser\ParserFactory;
17+
use PhpParser\PrettyPrinter\Standard;
18+
use PHPUnit\Framework\TestCase;
19+
20+
final class NamespaceUseTest extends TestCase
21+
{
22+
/**
23+
* @var Parser
24+
*/
25+
private $parser;
26+
27+
/**
28+
* @var Standard
29+
*/
30+
private $printer;
31+
32+
public function setUp(): void
33+
{
34+
$this->parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
35+
$this->printer = new Standard(['shortArraySyntax' => true]);
36+
}
37+
38+
/**
39+
* @test
40+
*/
41+
public function it_add_namespace_imports_in_correct_order(): void
42+
{
43+
$ast = $this->parser->parse($this->classCode());
44+
45+
$nodeTraverser = new NodeTraverser();
46+
$nodeTraverser->addVisitor(new NamespaceUse('MyService\Foo', 'MyService\Bar'));
47+
48+
$this->assertSame($this->expectedClassCode(), $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
49+
}
50+
51+
private function classCode(): string
52+
{
53+
return <<<'EOF'
54+
<?php
55+
56+
declare(strict_types=1);
57+
58+
namespace My\Awesome\Service;
59+
60+
use MyService\Foo;
61+
62+
class TestClass
63+
{
64+
}
65+
EOF;
66+
}
67+
68+
private function expectedClassCode(): string
69+
{
70+
return <<<'EOF'
71+
<?php
72+
73+
declare (strict_types=1);
74+
namespace My\Awesome\Service;
75+
76+
use MyService\Bar;
77+
use MyService\Foo;
78+
class TestClass
79+
{
80+
}
81+
EOF;
82+
}
83+
}

0 commit comments

Comments
 (0)