Skip to content

Commit 5b4fcc0

Browse files
committed
Allow sort of constants, properties, methods, traits and namespace imports in ClassBuilder - Close #20
1 parent 4108f14 commit 5b4fcc0

File tree

5 files changed

+360
-1
lines changed

5 files changed

+360
-1
lines changed

src/Builder/ClassBuilder.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,71 @@ public function getMethods(): array
247247
return $this->methods;
248248
}
249249

250+
/**
251+
* Uses usort internally
252+
*
253+
* @param callable $sort (ClassConstBuilder $a, ClassConstBuilder $b)
254+
* @return $this
255+
*/
256+
public function sortConstants(callable $sort): self
257+
{
258+
\usort($this->constants, $sort);
259+
260+
return $this;
261+
}
262+
263+
/**
264+
* Uses usort internally
265+
*
266+
* @param callable $sort (ClassPropertyBuilder $a, ClassPropertyBuilder $b)
267+
* @return $this
268+
*/
269+
public function sortProperties(callable $sort): self
270+
{
271+
\usort($this->properties, $sort);
272+
273+
return $this;
274+
}
275+
276+
/**
277+
* Uses usort internally
278+
*
279+
* @param callable $sort (ClassMethodBuilder $a, ClassMethodBuilder $b)
280+
* @return $this
281+
*/
282+
public function sortMethods(callable $sort): self
283+
{
284+
\usort($this->methods, $sort);
285+
286+
return $this;
287+
}
288+
289+
/**
290+
* Uses usort internally
291+
*
292+
* @param callable $sort (string $a, string $b)
293+
* @return $this
294+
*/
295+
public function sortTraits(callable $sort): self
296+
{
297+
\usort($this->traits, $sort);
298+
299+
return $this;
300+
}
301+
302+
/**
303+
* Uses usort internally
304+
*
305+
* @param callable $sort (string $a, string $b)
306+
* @return $this
307+
*/
308+
public function sortNamespaceUse(callable $sort): self
309+
{
310+
\usort($this->namespaceUse, $sort);
311+
312+
return $this;
313+
}
314+
250315
/**
251316
* @param Parser $parser
252317
* @return NodeVisitor[]

src/Builder/ClassPropertyBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static function fromNode(Node\Stmt\Property $node): self
6262

6363
$self->name = $node->props[0]->name->name;
6464
$self->defaultValue = $node->props[0]->default;
65-
$self->type = $node->type->toString();
65+
$self->type = $node->type ? $node->type->toString() : null;
6666
$self->visibility = $node->flags;
6767

6868
if ($self->type !== null) {

tests/Builder/ClassBuilderTest.php

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,170 @@ final class TestClass extends BaseClass implements \Iterator, Bar
110110

111111
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
112112
}
113+
114+
/**
115+
* @test
116+
*/
117+
public function it_supports_sort_of_class_constants(): void
118+
{
119+
$code = <<<'EOF'
120+
<?php
121+
122+
declare (strict_types=1);
123+
namespace My\Awesome\Service;
124+
125+
final class TestClass
126+
{
127+
protected const PROT = 'protected';
128+
private const PRIV = 'private';
129+
public const PUB = 'public';
130+
const FIRST = 1;
131+
}
132+
EOF;
133+
134+
$ast = $this->parser->parse($code);
135+
136+
$classFactory = ClassBuilder::fromNodes(...$ast);
137+
138+
$classFactory->sortConstants(function (ClassConstBuilder $a, ClassConstBuilder $b) {
139+
return $a->getName() <=> $b->getName();
140+
});
141+
142+
$constants = $classFactory->getConstants();
143+
$this->assertCount(4, $constants);
144+
$this->assertSame('FIRST', $constants[0]->getName());
145+
$this->assertSame('PRIV', $constants[1]->getName());
146+
$this->assertSame('PROT', $constants[2]->getName());
147+
$this->assertSame('PUB', $constants[3]->getName());
148+
149+
$expected = <<<'EOF'
150+
<?php
151+
152+
declare (strict_types=1);
153+
namespace My\Awesome\Service;
154+
155+
final class TestClass
156+
{
157+
const FIRST = 1;
158+
private const PRIV = 'private';
159+
protected const PROT = 'protected';
160+
public const PUB = 'public';
161+
}
162+
EOF;
163+
$nodeTraverser = new NodeTraverser();
164+
$classFactory->injectVisitors($nodeTraverser, $this->parser);
165+
166+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
167+
}
168+
169+
/**
170+
* @test
171+
*/
172+
public function it_supports_sort_of_namespace_use(): void
173+
{
174+
$code = <<<'EOF'
175+
<?php
176+
177+
declare (strict_types=1);
178+
namespace My\Awesome\Service;
179+
180+
use My\D;
181+
use My\A;
182+
use My\C;
183+
use My\B;
184+
185+
final class TestClass
186+
{
187+
}
188+
EOF;
189+
190+
$ast = $this->parser->parse($code);
191+
192+
$classFactory = ClassBuilder::fromNodes(...$ast);
193+
194+
$classFactory->sortNamespaceUse(function (string $a, string $b) {
195+
return $a <=> $b;
196+
});
197+
198+
$namespaceUse = $classFactory->getNamespaceUse();
199+
$this->assertCount(4, $namespaceUse);
200+
$this->assertSame('My\\A', $namespaceUse[0]);
201+
$this->assertSame('My\\B', $namespaceUse[1]);
202+
$this->assertSame('My\\C', $namespaceUse[2]);
203+
$this->assertSame('My\\D', $namespaceUse[3]);
204+
205+
$expected = <<<'EOF'
206+
<?php
207+
208+
declare (strict_types=1);
209+
namespace My\Awesome\Service;
210+
211+
use My\A;
212+
use My\B;
213+
use My\C;
214+
use My\D;
215+
final class TestClass
216+
{
217+
}
218+
EOF;
219+
$nodeTraverser = new NodeTraverser();
220+
$classFactory->injectVisitors($nodeTraverser, $this->parser);
221+
222+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
223+
}
224+
225+
/**
226+
* @test
227+
*/
228+
public function it_supports_sort_of_traits(): void
229+
{
230+
$code = <<<'EOF'
231+
<?php
232+
233+
declare (strict_types=1);
234+
namespace My\Awesome\Service;
235+
236+
final class TestClass
237+
{
238+
use My\D;
239+
use My\A;
240+
use My\C;
241+
use My\B;
242+
}
243+
EOF;
244+
245+
$ast = $this->parser->parse($code);
246+
247+
$classFactory = ClassBuilder::fromNodes(...$ast);
248+
249+
$classFactory->sortTraits(function (string $a, string $b) {
250+
return $a <=> $b;
251+
});
252+
253+
$useTrait = $classFactory->getUseTrait();
254+
$this->assertCount(4, $useTrait);
255+
$this->assertSame('My\\A', $useTrait[0]);
256+
$this->assertSame('My\\B', $useTrait[1]);
257+
$this->assertSame('My\\C', $useTrait[2]);
258+
$this->assertSame('My\\D', $useTrait[3]);
259+
260+
$expected = <<<'EOF'
261+
<?php
262+
263+
declare (strict_types=1);
264+
namespace My\Awesome\Service;
265+
266+
final class TestClass
267+
{
268+
use My\A;
269+
use My\B;
270+
use My\C;
271+
use My\D;
272+
}
273+
EOF;
274+
$nodeTraverser = new NodeTraverser();
275+
$classFactory->injectVisitors($nodeTraverser, $this->parser);
276+
277+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
278+
}
113279
}

tests/Builder/ClassMethodBuilderTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,76 @@ public function setActive(bool $active) : void
179179

180180
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
181181
}
182+
183+
/**
184+
* @test
185+
*/
186+
public function it_supports_sort_of_class_methods(): void
187+
{
188+
$code = <<<'EOF'
189+
<?php
190+
191+
declare (strict_types=1);
192+
namespace My\Awesome\Service;
193+
194+
class TestClass
195+
{
196+
public function b() : void
197+
{
198+
}
199+
public function a() : void
200+
{
201+
}
202+
public function d() : void
203+
{
204+
}
205+
public function c() : void
206+
{
207+
}
208+
}
209+
EOF;
210+
211+
$ast = $this->parser->parse($code);
212+
213+
$classFactory = ClassBuilder::fromNodes(...$ast);
214+
215+
$classFactory->sortMethods(function (ClassMethodBuilder $a, ClassMethodBuilder $b) {
216+
return $a->getName() <=> $b->getName();
217+
});
218+
219+
$methods = $classFactory->getMethods();
220+
$this->assertCount(4, $methods);
221+
$this->assertSame('a', $methods[0]->getName());
222+
$this->assertSame('b', $methods[1]->getName());
223+
$this->assertSame('c', $methods[2]->getName());
224+
$this->assertSame('d', $methods[3]->getName());
225+
226+
$expected = <<<'EOF'
227+
<?php
228+
229+
declare (strict_types=1);
230+
namespace My\Awesome\Service;
231+
232+
class TestClass
233+
{
234+
public function a() : void
235+
{
236+
}
237+
public function b() : void
238+
{
239+
}
240+
public function c() : void
241+
{
242+
}
243+
public function d() : void
244+
{
245+
}
246+
}
247+
EOF;
248+
249+
$nodeTraverser = new NodeTraverser();
250+
$classFactory->injectVisitors($nodeTraverser, $this->parser);
251+
252+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
253+
}
182254
}

tests/Builder/ClassPropertyBuilderTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,60 @@ class TestClass
9797

9898
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
9999
}
100+
101+
/**
102+
* @test
103+
*/
104+
public function it_supports_sort_of_class_properties(): void
105+
{
106+
$code = <<<'EOF'
107+
<?php
108+
109+
declare (strict_types=1);
110+
namespace My\Awesome\Service;
111+
112+
class TestClass
113+
{
114+
private $b;
115+
private $a;
116+
private $d;
117+
private $c;
118+
}
119+
EOF;
120+
121+
$ast = $this->parser->parse($code);
122+
123+
$classFactory = ClassBuilder::fromNodes(...$ast);
124+
125+
$classFactory->sortProperties(function (ClassPropertyBuilder $a, ClassPropertyBuilder $b) {
126+
return $a->getName() <=> $b->getName();
127+
});
128+
129+
$properties = $classFactory->getProperties();
130+
$this->assertCount(4, $properties);
131+
$this->assertSame('a', $properties[0]->getName());
132+
$this->assertSame('b', $properties[1]->getName());
133+
$this->assertSame('c', $properties[2]->getName());
134+
$this->assertSame('d', $properties[3]->getName());
135+
136+
$expected = <<<'EOF'
137+
<?php
138+
139+
declare (strict_types=1);
140+
namespace My\Awesome\Service;
141+
142+
class TestClass
143+
{
144+
private $a;
145+
private $b;
146+
private $c;
147+
private $d;
148+
}
149+
EOF;
150+
151+
$nodeTraverser = new NodeTraverser();
152+
$classFactory->injectVisitors($nodeTraverser, $this->parser);
153+
154+
$this->assertSame($expected, $this->printer->prettyPrintFile($nodeTraverser->traverse($this->parser->parse(''))));
155+
}
100156
}

0 commit comments

Comments
 (0)