Skip to content

Commit 0344d37

Browse files
committed
Always put properties before methods - close #75
1 parent e041151 commit 0344d37

File tree

6 files changed

+133
-4
lines changed

6 files changed

+133
-4
lines changed

src/Builder/ClassPropertyBuilder.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,15 @@ public function getType(): ?string
144144
return $this->type;
145145
}
146146

147+
public function setType(string $type): self
148+
{
149+
$this->type = $type;
150+
151+
$this->propertyGenerator->setType($type);
152+
153+
return $this;
154+
}
155+
147156
public function setTyped(bool $typed): self
148157
{
149158
$this->typed = $typed;

src/NodeVisitor/ClassConstant.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
final class ClassConstant extends NodeVisitorAbstract
2020
{
21+
use FindInsertPositionForType;
22+
2123
/**
2224
* @var IdentifierGenerator
2325
*/
@@ -41,8 +43,10 @@ public function afterTraverse(array $nodes): ?array
4143
if ($this->checkConstantExists($stmt)) {
4244
return null;
4345
}
44-
$stmt->stmts = \array_merge(
46+
\array_splice(
4547
$stmt->stmts,
48+
$this->findInsertPositionForType($stmt->stmts, Node\Stmt\ClassConst::class),
49+
0,
4650
$this->lineGenerator->generate()
4751
);
4852
}
@@ -51,8 +55,10 @@ public function afterTraverse(array $nodes): ?array
5155
if ($this->checkConstantExists($node)) {
5256
return null;
5357
}
54-
$node->stmts = \array_merge(
58+
\array_splice(
5559
$node->stmts,
60+
$this->findInsertPositionForType($node->stmts, Node\Stmt\ClassConst::class),
61+
0,
5662
$this->lineGenerator->generate()
5763
);
5864
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 OpenCodeModeling\CodeAst\NodeVisitor;
12+
13+
use PhpParser\Node\Stmt;
14+
15+
trait FindInsertPositionForType
16+
{
17+
/**
18+
* @param Stmt[] $stmts
19+
* @param string $type
20+
* @return int
21+
*/
22+
private function findInsertPositionForType(array $stmts, string $type): int
23+
{
24+
$pos = 0;
25+
$length = 0;
26+
27+
foreach ($stmts as $key => $stmt) {
28+
if ($stmt instanceof $type) {
29+
$pos = (int) $key;
30+
}
31+
$length++;
32+
}
33+
34+
return $pos === 0 ? ++$length : ++$pos;
35+
}
36+
}

src/NodeVisitor/Property.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
final class Property extends NodeVisitorAbstract
2121
{
22+
use FindInsertPositionForType;
23+
2224
/**
2325
* @var PropertyGenerator
2426
**/
@@ -42,14 +44,24 @@ public function afterTraverse(array $nodes): ?array
4244
if ($this->checkPropertyExists($stmt)) {
4345
return null;
4446
}
45-
$stmt->stmts[] = $this->propertyGenerator->generate();
47+
\array_splice(
48+
$stmt->stmts,
49+
$this->findInsertPositionForType($stmt->stmts, Node\Stmt\Property::class),
50+
0,
51+
[$this->propertyGenerator->generate()]
52+
);
4653
}
4754
}
4855
} elseif ($node instanceof Stmt\Class_) {
4956
if ($this->checkPropertyExists($node)) {
5057
return null;
5158
}
52-
$node->stmts[] = $this->propertyGenerator->generate();
59+
\array_splice(
60+
$node->stmts,
61+
$this->findInsertPositionForType($node->stmts, Node\Stmt\Property::class),
62+
0,
63+
[$this->propertyGenerator->generate()]
64+
);
5365
}
5466
}
5567

tests/Builder/ClassBuilderTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,57 @@ final class TestClass
177177
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
178178
}
179179

180+
/**
181+
* @test
182+
*/
183+
public function it_supports_adding_of_class_constants_before_property(): void
184+
{
185+
$code = <<<'EOF'
186+
<?php
187+
188+
declare (strict_types=1);
189+
namespace My\Awesome\Service;
190+
191+
final class TestClass
192+
{
193+
use TestTrait;
194+
protected $property;
195+
196+
public function test(): void
197+
{
198+
}
199+
}
200+
EOF;
201+
202+
$ast = $this->parser->parse($code);
203+
204+
$classFactory = ClassBuilder::fromNodes(...$ast);
205+
$classFactory->addConstant(ClassConstBuilder::fromScratch('FIRST', 1));
206+
$classFactory->addConstant(ClassConstBuilder::fromScratch('PUB', 'public'));
207+
208+
$expected = <<<'EOF'
209+
<?php
210+
211+
declare (strict_types=1);
212+
namespace My\Awesome\Service;
213+
214+
final class TestClass
215+
{
216+
use TestTrait;
217+
public const FIRST = 1;
218+
public const PUB = 'public';
219+
protected $property;
220+
public function test() : void
221+
{
222+
}
223+
}
224+
EOF;
225+
$nodeTraverser = new NodeTraverser();
226+
$classFactory->injectVisitors($nodeTraverser, $this->parser);
227+
228+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
229+
}
230+
180231
/**
181232
* @test
182233
*/
@@ -191,6 +242,10 @@ public function it_supports_adding_of_class_constants(): void
191242
final class TestClass
192243
{
193244
protected const PROT = 'protected';
245+
246+
public function test(): void
247+
{
248+
}
194249
}
195250
EOF;
196251

@@ -211,6 +266,9 @@ final class TestClass
211266
protected const PROT = 'protected';
212267
public const FIRST = 1;
213268
public const PUB = 'public';
269+
public function test() : void
270+
{
271+
}
214272
}
215273
EOF;
216274
$nodeTraverser = new NodeTraverser();

tests/Builder/ClassPropertyBuilderTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,11 @@ public function it_supports_adding_of_class_properties(): void
179179
180180
class TestClass
181181
{
182+
public const TEST = 1;
182183
private $a;
184+
public function test(): void
185+
{
186+
}
183187
}
184188
EOF;
185189

@@ -199,10 +203,14 @@ class TestClass
199203
200204
class TestClass
201205
{
206+
public const TEST = 1;
202207
private string $a;
203208
private string $b;
204209
private string $c;
205210
private string $d;
211+
public function test() : void
212+
{
213+
}
206214
}
207215
EOF;
208216

0 commit comments

Comments
 (0)