Skip to content

Commit 780e527

Browse files
committed
Always put properties / constants before methods when no one exists - #75
1 parent 7673930 commit 780e527

File tree

5 files changed

+159
-8
lines changed

5 files changed

+159
-8
lines changed

src/NodeVisitor/ClassConstant.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function afterTraverse(array $nodes): ?array
4545
}
4646
\array_splice(
4747
$stmt->stmts,
48-
$this->findInsertPositionForType($stmt->stmts, Node\Stmt\ClassConst::class),
48+
$this->findInsertPositionForType($stmt->stmts, Node\Stmt\ClassConst::class, [Node\Stmt\ClassMethod::class]),
4949
0,
5050
$this->lineGenerator->generate()
5151
);
@@ -57,7 +57,7 @@ public function afterTraverse(array $nodes): ?array
5757
}
5858
\array_splice(
5959
$node->stmts,
60-
$this->findInsertPositionForType($node->stmts, Node\Stmt\ClassConst::class),
60+
$this->findInsertPositionForType($node->stmts, Node\Stmt\ClassConst::class, [Node\Stmt\ClassMethod::class]),
6161
0,
6262
$this->lineGenerator->generate()
6363
);

src/NodeVisitor/FindInsertPositionForType.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,35 @@ trait FindInsertPositionForType
1717
/**
1818
* @param Stmt[] $stmts
1919
* @param string $type
20+
* @param array $decTypes List of types (FQCN) where position should be decremented
21+
* @param array $incTypes List of types (FQCN) where position should be incremented
2022
* @return int
2123
*/
22-
private function findInsertPositionForType(array $stmts, string $type): int
23-
{
24-
$pos = 0;
24+
private function findInsertPositionForType(
25+
array $stmts,
26+
string $type,
27+
array $decTypes = [],
28+
array $incTypes = []
29+
): int {
30+
$pos = -1;
2531
$length = 0;
2632

2733
foreach ($stmts as $key => $stmt) {
34+
$class = \get_class($stmt);
35+
2836
if ($stmt instanceof $type) {
2937
$pos = (int) $key;
3038
}
3139
$length++;
40+
41+
if (true === \in_array($class, $decTypes, true)) {
42+
$length--;
43+
}
44+
if (true === \in_array($class, $incTypes, true)) {
45+
$length++;
46+
}
3247
}
3348

34-
return $pos === 0 ? ++$length : ++$pos;
49+
return $pos === -1 ? $length : ++$pos;
3550
}
3651
}

src/NodeVisitor/Property.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function afterTraverse(array $nodes): ?array
4646
}
4747
\array_splice(
4848
$stmt->stmts,
49-
$this->findInsertPositionForType($stmt->stmts, Node\Stmt\Property::class),
49+
$this->findInsertPositionForType($stmt->stmts, Node\Stmt\Property::class, [Node\Stmt\ClassMethod::class]),
5050
0,
5151
[$this->propertyGenerator->generate()]
5252
);
@@ -58,7 +58,7 @@ public function afterTraverse(array $nodes): ?array
5858
}
5959
\array_splice(
6060
$node->stmts,
61-
$this->findInsertPositionForType($node->stmts, Node\Stmt\Property::class),
61+
$this->findInsertPositionForType($node->stmts, Node\Stmt\Property::class, [Node\Stmt\ClassMethod::class]),
6262
0,
6363
[$this->propertyGenerator->generate()]
6464
);

tests/Builder/ClassBuilderTest.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,74 @@ public function test() : void
228228
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
229229
}
230230

231+
/**
232+
* @test
233+
*/
234+
public function it_supports_adding_of_class_constants_before_methods_with_doc_blocks(): void
235+
{
236+
$code = <<<'EOF'
237+
<?php
238+
239+
declare (strict_types=1);
240+
namespace My\Awesome\Service;
241+
242+
final class TestClass
243+
{
244+
/**
245+
* Define aggregate names using constants
246+
*
247+
* @example
248+
*
249+
* const USER = 'User';
250+
*/
251+
252+
253+
/**
254+
* @param EventEngine $eventEngine
255+
*/
256+
public static function describe(EventEngine $eventEngine): void
257+
{
258+
}
259+
}
260+
EOF;
261+
262+
$ast = $this->parser->parse($code);
263+
264+
$classFactory = ClassBuilder::fromScratch('TestClass', 'My\Awesome\Service');
265+
$classFactory->addConstant(ClassConstBuilder::fromScratch('FIRST', 1));
266+
$classFactory->addConstant(ClassConstBuilder::fromScratch('PUB', 'public'));
267+
268+
$expected = <<<'EOF'
269+
<?php
270+
271+
declare (strict_types=1);
272+
namespace My\Awesome\Service;
273+
274+
final class TestClass
275+
{
276+
public const FIRST = 1;
277+
public const PUB = 'public';
278+
/**
279+
* Define aggregate names using constants
280+
*
281+
* @example
282+
*
283+
* const USER = 'User';
284+
*/
285+
/**
286+
* @param EventEngine $eventEngine
287+
*/
288+
public static function describe(EventEngine $eventEngine) : void
289+
{
290+
}
291+
}
292+
EOF;
293+
$nodeTraverser = new NodeTraverser();
294+
$classFactory->injectVisitors($nodeTraverser, $this->parser);
295+
296+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
297+
}
298+
231299
/**
232300
* @test
233301
*/

tests/Builder/ClassPropertyBuilderTest.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,74 @@ class TestClass
166166
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
167167
}
168168

169+
/**
170+
* @test
171+
*/
172+
public function it_supports_adding_of_properties_before_methods_with_doc_blocks(): void
173+
{
174+
$code = <<<'EOF'
175+
<?php
176+
177+
declare (strict_types=1);
178+
namespace My\Awesome\Service;
179+
180+
final class TestClass
181+
{
182+
/**
183+
* Define aggregate names using constants
184+
*
185+
* @example
186+
*
187+
* const USER = 'User';
188+
*/
189+
190+
191+
/**
192+
* @param EventEngine $eventEngine
193+
*/
194+
public static function describe(EventEngine $eventEngine): void
195+
{
196+
}
197+
}
198+
EOF;
199+
200+
$ast = $this->parser->parse($code);
201+
202+
$classFactory = ClassBuilder::fromScratch('TestClass', 'My\Awesome\Service');
203+
$classFactory->addProperty(ClassPropertyBuilder::fromScratch('first', 'string'));
204+
$classFactory->addProperty(ClassPropertyBuilder::fromScratch('pub', 'array'));
205+
206+
$expected = <<<'EOF'
207+
<?php
208+
209+
declare (strict_types=1);
210+
namespace My\Awesome\Service;
211+
212+
final class TestClass
213+
{
214+
private string $first;
215+
private array $pub;
216+
/**
217+
* Define aggregate names using constants
218+
*
219+
* @example
220+
*
221+
* const USER = 'User';
222+
*/
223+
/**
224+
* @param EventEngine $eventEngine
225+
*/
226+
public static function describe(EventEngine $eventEngine) : void
227+
{
228+
}
229+
}
230+
EOF;
231+
$nodeTraverser = new NodeTraverser();
232+
$classFactory->injectVisitors($nodeTraverser, $this->parser);
233+
234+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast)));
235+
}
236+
169237
/**
170238
* @test
171239
*/

0 commit comments

Comments
 (0)