Skip to content

Commit f5e0fe4

Browse files
committed
Merge remote-tracking branch 'origin/0.10.x-merge-up-into-0.11.x_naSDI2qg' into 0.11.x
# Conflicts: # CHANGELOG.md # composer.json
2 parents f950039 + fbbda01 commit f5e0fe4

File tree

4 files changed

+259
-14
lines changed

4 files changed

+259
-14
lines changed

CHANGELOG.md

+23-4
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,29 @@ Feature release (minor)
4141

4242
#### enhancement
4343

44-
- [66: Generate code from file collection with current file AST support](https://github.com/open-code-modeling/php-code-ast/issues/66) thanks to @sandrokeil
45-
- [65: Support custom node visitors in class and interface builder](https://github.com/open-code-modeling/php-code-ast/issues/65) thanks to @sandrokeil
46-
- [61: Switch from PHPStan to Psalm](https://github.com/open-code-modeling/php-code-ast/issues/61) thanks to @sandrokeil
47-
- [55: Remove deprecated methods and static node visitor methods in favour of high level API](https://github.com/open-code-modeling/php-code-ast/issues/55) thanks to @sandrokeil
44+
- [66: Generate code from file collection with current file AST support](https://github.com/open-code-modeling/php-code-ast/issues/66) thanks to @sandrokeil
45+
- [65: Support custom node visitors in class and interface builder](https://github.com/open-code-modeling/php-code-ast/issues/65) thanks to @sandrokeil
46+
- [61: Switch from PHPStan to Psalm](https://github.com/open-code-modeling/php-code-ast/issues/61) thanks to @sandrokeil
47+
- [55: Remove deprecated methods and static node visitor methods in favour of high level API](https://github.com/open-code-modeling/php-code-ast/issues/55) thanks to @sandrokeil
48+
49+
## 0.10.4 - 2021-08-27
50+
51+
52+
-----
53+
54+
### Release Notes for [0.10.4](https://github.com/open-code-modeling/php-code-ast/milestone/24)
55+
56+
0.10.x bugfix release (patch)
57+
58+
### 0.10.4
59+
60+
- Total issues resolved: **1**
61+
- Total pull requests resolved: **0**
62+
- Total contributors: **1**
63+
64+
#### bug
65+
66+
- [82: Exists check in NodeVisitor/ClassImplements not working properly](https://github.com/open-code-modeling/php-code-ast/issues/82) thanks to @sandrokeil
4867

4968
## 0.10.3 - 2021-01-29
5069

src/NodeVisitor/ClassImplements.php

+18-9
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,33 @@ public function afterTraverse(array $nodes): ?array
6767

6868
private function filterImplements(array $nodes): array
6969
{
70-
$implements = $this->implements;
71-
7270
foreach ($nodes as $node) {
7371
if ($node instanceof Namespace_) {
7472
foreach ($node->stmts as $stmt) {
7573
if ($stmt instanceof Stmt\Class_) {
76-
foreach ($stmt->implements as $implementName) {
77-
$implements = \array_filter($implements, static function (string $implement) use ($implementName) {
78-
return $implement !== ($implementName instanceof FullyQualified
79-
? '\\' . $implementName->toString()
80-
: (string) $implementName);
81-
});
82-
}
74+
return $this->filterClassImplements($stmt);
8375
}
8476
}
77+
} elseif ($node instanceof Stmt\Class_) {
78+
return $this->filterClassImplements($node);
8579
}
8680
}
8781

82+
return $this->implements;
83+
}
84+
85+
private function filterClassImplements(Stmt\Class_ $node): array
86+
{
87+
$implements = $this->implements;
88+
89+
foreach ($node->implements as $implementName) {
90+
$implements = \array_filter($implements, static function (string $implement) use ($implementName) {
91+
return $implement !== ($implementName instanceof FullyQualified
92+
? '\\' . $implementName->toString()
93+
: (string) $implementName);
94+
});
95+
}
96+
8897
return $implements;
8998
}
9099
}

src/NodeVisitor/NamespaceUse.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function afterTraverse(array $nodes): ?array
5757
}
5858
\array_unshift($stmts, $useNamespace->getNode());
5959
}
60-
$node->stmts = $stmts; // @phpstan-ignore-line
60+
$node->stmts = $stmts;
6161
}
6262
}
6363

+217
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
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 Generator;
14+
use OpenCodeModeling\CodeAst\Code\ClassGenerator;
15+
use OpenCodeModeling\CodeAst\NodeVisitor\ClassFile;
16+
use OpenCodeModeling\CodeAst\NodeVisitor\ClassImplements;
17+
use OpenCodeModeling\CodeAst\NodeVisitor\ClassNamespace;
18+
use PhpParser\NodeTraverser;
19+
use PhpParser\Parser;
20+
use PhpParser\ParserFactory;
21+
use PhpParser\PrettyPrinter\Standard;
22+
use PHPUnit\Framework\TestCase;
23+
24+
final class ClassImplementsTest extends TestCase
25+
{
26+
private Parser $parser;
27+
28+
private Standard $printer;
29+
30+
public function setUp(): void
31+
{
32+
$this->parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
33+
$this->printer = new Standard(['shortArraySyntax' => true]);
34+
}
35+
36+
/**
37+
* Values are: interfaces
38+
*
39+
* @return Generator
40+
*/
41+
public function provideImplements(): Generator
42+
{
43+
yield '\\Awesome\\AcmeClass' => [['\\Awesome\\AcmeClass']];
44+
yield '\\Foo' => [['\\Foo']];
45+
46+
yield '\\Awesome\\AcmeClass, \\My\\OtherInterface' => [['\\Awesome\\AcmeClass', '\\My\\OtherInterface']];
47+
yield '\\Foo, \\Bar' => [['\\Foo', '\\Bar']];
48+
49+
yield 'FirstInterface, SecondInterface, ThirdInterface' => [['FirstInterface', 'SecondInterface', 'ThirdInterface']];
50+
}
51+
52+
/**
53+
* @test
54+
* @dataProvider provideImplements
55+
* @param array $interfaces
56+
*/
57+
public function it_generates_class_implements_for_empty_file(array $interfaces): void
58+
{
59+
$ast = $this->parser->parse('');
60+
61+
$nodeTraverser = new NodeTraverser();
62+
$nodeTraverser->addVisitor(new ClassFile(new ClassGenerator('TestClass')));
63+
$nodeTraverser->addVisitor(new ClassImplements(...$interfaces));
64+
65+
$extends = \implode(', ', $interfaces);
66+
67+
$expected = <<<EOF
68+
<?php
69+
70+
class TestClass implements $extends
71+
{
72+
}
73+
EOF;
74+
75+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
76+
77+
$ast = $this->parser->parse($expected);
78+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
79+
}
80+
81+
/**
82+
* @test
83+
* @dataProvider provideImplements
84+
* @param array $interfaces
85+
*/
86+
public function it_checks_class_implements_for_existing_file(array $interfaces): void
87+
{
88+
$ast = $this->parser->parse('<?php class TestClass {}');
89+
90+
$nodeTraverser = new NodeTraverser();
91+
$nodeTraverser->addVisitor(new ClassFile(new ClassGenerator('TestClass')));
92+
$nodeTraverser->addVisitor(new ClassImplements(...$interfaces));
93+
94+
$extends = \implode(', ', $interfaces);
95+
96+
$expected = <<<EOF
97+
<?php
98+
99+
class TestClass implements $extends
100+
{
101+
}
102+
EOF;
103+
104+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
105+
106+
$ast = $this->parser->parse($expected);
107+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
108+
}
109+
110+
/**
111+
* @test
112+
* @dataProvider provideImplements
113+
* @param array $interfaces
114+
*/
115+
public function it_generates_class_implements_with_namespace_for_empty_file(array $interfaces): void
116+
{
117+
$ast = $this->parser->parse('');
118+
119+
$nodeTraverser = new NodeTraverser();
120+
$nodeTraverser->addVisitor(new ClassNamespace('My\\Awesome\\Service'));
121+
$nodeTraverser->addVisitor(new ClassFile(new ClassGenerator('TestClass')));
122+
$nodeTraverser->addVisitor(new ClassImplements(...$interfaces));
123+
124+
$extends = \implode(', ', $interfaces);
125+
126+
$expected = <<<EOF
127+
<?php
128+
129+
namespace My\Awesome\Service;
130+
131+
class TestClass implements $extends
132+
{
133+
}
134+
EOF;
135+
136+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
137+
138+
$ast = $this->parser->parse($expected);
139+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
140+
}
141+
142+
/**
143+
* @test
144+
* @dataProvider provideImplements
145+
* @param array $interfaces
146+
*/
147+
public function it_generates_class_implements_for_namespace_file(array $interfaces): void
148+
{
149+
$code = <<<EOF
150+
<?php
151+
152+
namespace My\Awesome\Service;
153+
EOF;
154+
155+
$ast = $this->parser->parse($code);
156+
157+
$nodeTraverser = new NodeTraverser();
158+
$nodeTraverser->addVisitor(new ClassFile(new ClassGenerator('TestClass')));
159+
$nodeTraverser->addVisitor(new ClassImplements(...$interfaces));
160+
161+
$extends = \implode(', ', $interfaces);
162+
163+
$expected = <<<EOF
164+
<?php
165+
166+
namespace My\Awesome\Service;
167+
168+
class TestClass implements $extends
169+
{
170+
}
171+
EOF;
172+
173+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
174+
175+
$ast = $this->parser->parse($expected);
176+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
177+
}
178+
179+
/**
180+
* @test
181+
* @dataProvider provideImplements
182+
* @param array $interfaces
183+
*/
184+
public function it_checks_class_implements_with_namespace_for_existing_file(array $interfaces): void
185+
{
186+
$code = <<<EOF
187+
<?php
188+
189+
namespace My\Awesome\Service;
190+
191+
class TestClass {}
192+
EOF;
193+
194+
$ast = $this->parser->parse($code);
195+
196+
$nodeTraverser = new NodeTraverser();
197+
$nodeTraverser->addVisitor(new ClassFile(new ClassGenerator('TestClass')));
198+
$nodeTraverser->addVisitor(new ClassImplements(...$interfaces));
199+
200+
$extends = \implode(', ', $interfaces);
201+
202+
$expected = <<<EOF
203+
<?php
204+
205+
namespace My\Awesome\Service;
206+
207+
class TestClass implements $extends
208+
{
209+
}
210+
EOF;
211+
212+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
213+
214+
$ast = $this->parser->parse($expected);
215+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
216+
}
217+
}

0 commit comments

Comments
 (0)