Skip to content

Commit d78a07a

Browse files
authored
Merge pull request #11 from PackageFactory/feature/optchain-access
FEATURE: Implement optchain
2 parents 21c6727 + 780b360 commit d78a07a

File tree

5 files changed

+18
-0
lines changed

5 files changed

+18
-0
lines changed

src/Definition/Precedence.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public static function forTokenType(TokenType $tokenType): self
5050
TokenType::BRACKET_ROUND_CLOSE,
5151
TokenType::BRACKET_SQUARE_OPEN,
5252
TokenType::BRACKET_SQUARE_CLOSE,
53+
TokenType::OPTCHAIN,
5354
TokenType::PERIOD => self::ACCESS,
5455

5556
TokenType::OPERATOR_BOOLEAN_NOT => self::UNARY,

src/Parser/Ast/ExpressionNode.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ public static function fromTokens(\Iterator $tokens, Precedence $precedence = Pr
145145
$root = BinaryOperationNode::fromTokens(new self(root: $root), $tokens);
146146
break;
147147
case TokenType::PERIOD:
148+
case TokenType::OPTCHAIN:
148149
$root = AccessNode::fromTokens(new self(root: $root), $tokens);
149150
break;
150151
case TokenType::QUESTIONMARK:

src/Parser/Tokenizer/Tokenizer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ public static function symbol(\Iterator $fragments, ?Buffer $buffer = null): \It
292292
'!==' => $buffer->flush(TokenType::COMPARATOR_NOT_EQUAL),
293293
'->' => $buffer->flush(TokenType::ARROW_SINGLE),
294294
':' => $buffer->flush(TokenType::COLON),
295+
'?.' => $buffer->flush(TokenType::OPTCHAIN),
295296
'.' => $buffer->flush(TokenType::PERIOD),
296297
',' => $buffer->flush(TokenType::COMMA),
297298
'=' => $buffer->flush(TokenType::EQUALS),

src/Target/Php/Transpiler/Access/AccessTranspiler.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
namespace PackageFactory\ComponentEngine\Target\Php\Transpiler\Access;
2424

25+
use PackageFactory\ComponentEngine\Definition\AccessType;
2526
use PackageFactory\ComponentEngine\Parser\Ast\AccessNode;
2627
use PackageFactory\ComponentEngine\Target\Php\Transpiler\Expression\ExpressionTranspiler;
2728
use PackageFactory\ComponentEngine\TypeSystem\Resolver\Expression\ExpressionTypeResolver;
@@ -49,6 +50,8 @@ public function transpile(AccessNode $accessNode): string
4950
foreach ($accessNode->chain->items as $accessChainNode) {
5051
if ($typeOfRoot instanceof EnumStaticType && $isFirstElement) {
5152
$result .= '::';
53+
} elseif ($accessChainNode->accessType === AccessType::OPTIONAL) {
54+
$result .= '?->';
5255
} else {
5356
$result .= '->';
5457
}

test/Unit/Target/Php/Transpiler/Access/AccessTranspilerTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ public function accessExamples(): array
4343
'a.b' => ['a.b', '$this->a->b'],
4444
'a.b.c' => ['a.b.c', '$this->a->b->c'],
4545
'SomeEnum.A' => ['SomeEnum.A', 'SomeEnum::A'],
46+
'someStruct.foo' => ['someStruct.foo', '$this->someStruct->foo'],
47+
'someStruct?.foo' => ['someStruct?.foo', '$this->someStruct?->foo'],
48+
'someStruct.deep?.foo' => ['someStruct.deep?.foo', '$this->someStruct->deep?->foo']
4649
];
4750
}
4851

@@ -66,6 +69,15 @@ public function transpilesAccessNodes(string $accessAsString, string $expectedTr
6669
EnumDeclarationNode::fromString(
6770
'enum SomeEnum { A B C }'
6871
)
72+
),
73+
'someStruct' => StructType::fromStructDeclarationNode(
74+
StructDeclarationNode::fromString(<<<'AFX'
75+
struct SomeStruct {
76+
foo: string
77+
deep: ?SomeStruct
78+
}
79+
AFX
80+
)
6981
)
7082
])
7183
);

0 commit comments

Comments
 (0)