Skip to content

Commit a4eb800

Browse files
committed
Enum: value can be expression
1 parent d003c62 commit a4eb800

File tree

8 files changed

+53
-19
lines changed

8 files changed

+53
-19
lines changed

src/PhpGenerator/EnumCase.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@ final class EnumCase
2222
use Traits\CommentAware;
2323
use Traits\AttributeAware;
2424

25-
private string|int|null $value = null;
25+
private string|int|Literal|null $value = null;
2626

2727

28-
public function setValue(string|int|null $val): static
28+
public function setValue(string|int|Literal|null $val): static
2929
{
3030
$this->value = $val;
3131
return $this;
3232
}
3333

3434

35-
public function getValue(): string|int|null
35+
public function getValue(): string|int|Literal|null
3636
{
3737
return $this->value;
3838
}

src/PhpGenerator/EnumType.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ final class EnumType extends ClassLike
2626

2727
/** @var array<string, EnumCase> */
2828
private array $cases = [];
29+
private ?string $type = null;
30+
31+
32+
public function setType(?string $type): static
33+
{
34+
$this->type = $type;
35+
return $this;
36+
}
37+
38+
39+
public function getType(): ?string
40+
{
41+
return $this->type;
42+
}
2943

3044

3145
/**
@@ -85,7 +99,7 @@ public function getCases(): array
8599

86100

87101
/** Adds case to enum */
88-
public function addCase(string $name, string|int|null $value = null): EnumCase
102+
public function addCase(string $name, string|int|Literal|null $value = null): EnumCase
89103
{
90104
if (isset($this->cases[$name])) {
91105
throw new Nette\InvalidStateException("Cannot add cases '$name', because it already exists.");

src/PhpGenerator/Extractor.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ private function addTraitToFile(PhpFile $phpFile, Node\Stmt\Trait_ $node): Trait
275275
private function addEnumToFile(PhpFile $phpFile, Node\Stmt\Enum_ $node): EnumType
276276
{
277277
$enum = $phpFile->addEnum($node->namespacedName->toString());
278+
$enum->setType($node->scalarType?->toString());
278279
foreach ($node->implements as $item) {
279280
$enum->addImplement($item->toString());
280281
}
@@ -362,7 +363,12 @@ private function addConstantToClass(ClassLike $class, Node\Stmt\ClassConst $node
362363

363364
private function addEnumCaseToClass(EnumType $class, Node\Stmt\EnumCase $node): void
364365
{
365-
$case = $class->addCase($node->name->toString(), $node->expr?->value);
366+
$value = match (true) {
367+
$node->expr === null => null,
368+
$node->expr instanceof Node\Scalar\LNumber, $node->expr instanceof Node\Scalar\String_ => $node->expr->value,
369+
default => new Literal($this->getReformattedContents([$node->expr], 1)),
370+
};
371+
$case = $class->addCase($node->name->toString(), $value);
366372
$this->addCommentAndAttributes($case, $node);
367373
}
368374

src/PhpGenerator/Printer.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,11 @@ public function printClass(ClassLike $class, ?PhpNamespace $namespace = null): s
147147
}
148148

149149
$cases = [];
150+
$enumType = null;
150151
if ($class instanceof EnumType) {
152+
$enumType = $class->getType();
151153
foreach ($class->getCases() as $case) {
154+
$enumType ??= is_scalar($case->getValue()) ? get_debug_type($case->getValue()) : null;
152155
$cases[] = Helpers::formatDocComment((string) $case->getComment())
153156
. self::printAttributes($case->getAttributes())
154157
. 'case ' . $case->getName()
@@ -157,10 +160,6 @@ public function printClass(ClassLike $class, ?PhpNamespace $namespace = null): s
157160
}
158161
}
159162

160-
$enumType = isset($case) && $case->getValue() !== null
161-
? $this->returnTypeColon . get_debug_type($case->getValue())
162-
: '';
163-
164163
$consts = [];
165164
$methods = [];
166165
if (
@@ -209,8 +208,8 @@ public function printClass(ClassLike $class, ?PhpNamespace $namespace = null): s
209208

210209
$members = array_filter([
211210
implode('', $traits),
212-
$this->joinProperties($cases),
213211
$this->joinProperties($consts),
212+
$this->joinProperties($cases),
214213
$this->joinProperties($properties),
215214
($methods && $properties ? str_repeat("\n", $this->linesBetweenMethods - 1) : '')
216215
. implode(str_repeat("\n", $this->linesBetweenMethods), $methods),
@@ -228,7 +227,7 @@ public function printClass(ClassLike $class, ?PhpNamespace $namespace = null): s
228227
. self::printAttributes($class->getAttributes())
229228
. ($class instanceof ClassType && $class->isAbstract() ? 'abstract ' : '')
230229
. ($class instanceof ClassType && $class->isFinal() ? 'final ' : '')
231-
. ($class->getName() ? $type . ' ' . $class->getName() . $enumType . ' ' : '')
230+
. ($class->getName() ? $type . ' ' . $class->getName() . ($enumType ? $this->returnTypeColon . $enumType : '') . ' ' : '')
232231
. (($class instanceof ClassType || $class instanceof InterfaceType) && $class->getExtends()
233232
? 'extends ' . implode(', ', array_map($resolver, (array) $class->getExtends())) . ' '
234233
: '')

tests/PhpGenerator/expected/ClassType.enum.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ enum Suit
77
{
88
use ObjectTrait;
99

10+
public const ACTIVE = false;
11+
1012
/** ♣ */
1113
#[ValueAttribute]
1214
case Clubs;
@@ -16,8 +18,6 @@ enum Suit
1618
case Hearts;
1719
case Spades;
1820

19-
public const ACTIVE = false;
20-
2121
public function foo()
2222
{
2323
return 10;

tests/PhpGenerator/expected/ClassType.from.enum.expect

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
#[\ExampleAttribute]
55
enum Enum1
66
{
7+
public const FOO = 123;
8+
public const BAR = \Abc\Enum1::Clubs;
9+
710
/** Commented */
811
case Clubs;
912

@@ -12,9 +15,6 @@ enum Enum1
1215
case Hearts;
1316
case Spades;
1417

15-
public const FOO = 123;
16-
public const BAR = \Abc\Enum1::Clubs;
17-
1818
public function foo($x = self::Diamonds)
1919
{
2020
}

tests/PhpGenerator/expected/Extractor.enum.expect

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ namespace Abc;
1010
#[\ExampleAttribute]
1111
enum Enum1
1212
{
13+
public const FOO = 123;
14+
public const BAR = self::Clubs;
15+
1316
/** Commented */
1417
case Clubs;
1518

@@ -18,9 +21,6 @@ enum Enum1
1821
case Hearts;
1922
case Spades;
2023

21-
public const FOO = 123;
22-
public const BAR = self::Clubs;
23-
2424
public function foo($x = self::Diamonds)
2525
{
2626
}
@@ -35,3 +35,11 @@ enum Enum2: string implements \Countable
3535
{
3636
}
3737
}
38+
39+
enum Enum3: int
40+
{
41+
public const FOO = 123;
42+
43+
case A = self::FOO;
44+
case B = 20 + 5;
45+
}

tests/PhpGenerator/fixtures/enum.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,10 @@ function count(): int
3535
{
3636
}
3737
}
38+
39+
enum Enum3: int
40+
{
41+
const FOO = 123;
42+
case A = self::FOO;
43+
case B = 20 + 5;
44+
}

0 commit comments

Comments
 (0)