Skip to content

Commit 39c2533

Browse files
committed
Fix TypeOffsetAccessNode serialization logic and a little more improvements
1 parent e9172d7 commit 39c2533

21 files changed

+111
-84
lines changed

resources/.meta-storm.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<meta-storm xmlns="meta-storm">
3+
<definitions>
4+
5+
<classConstructor class="\TypeLang\Parser\ParserInterface"
6+
argument="1">
7+
<languageInjection language="InjectablePHP" />
8+
</classConstructor>
9+
10+
<classConstructor class="\TypeLang\Parser\Parser"
11+
argument="1">
12+
<languageInjection language="InjectablePHP" />
13+
</classConstructor>
14+
15+
<classConstructor class="\TypeLang\Parser\InMemoryCachedParser"
16+
argument="1">
17+
<languageInjection language="InjectablePHP" />
18+
</classConstructor>
19+
20+
</definitions>
21+
</meta-storm>

src/Builder.php

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/InMemoryCachedParser.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace TypeLang\Parser;
66

7-
use JetBrains\PhpStorm\Language;
87
use Phplrt\Contracts\Source\SourceExceptionInterface;
98
use Phplrt\Contracts\Source\SourceFactoryInterface;
109
use Phplrt\Source\SourceFactory;
@@ -28,7 +27,7 @@ public function __construct(
2827
* @throws SourceExceptionInterface
2928
* @throws \Throwable
3029
*/
31-
public function parse(#[Language('PHP')] mixed $source): TypeStatement
30+
public function parse(mixed $source): TypeStatement
3231
{
3332
$instance = $this->sources->create($source);
3433

src/Node/Stmt/GenericTypeNode.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TypeLang\Parser\Node\Stmt;
6+
7+
/**
8+
* @template T of TypeStatement = TypeStatement
9+
* @template-extends GenericTypeStmt<T>
10+
*/
11+
abstract class GenericTypeNode extends GenericTypeStmt {}

src/Node/Stmt/GenericTypeStmt.php

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

77
/**
88
* @template T of TypeStatement = TypeStatement
9+
*
10+
* @deprecated Since 1.4.3, please use {@see GenericTypeNode} instead.
911
*/
1012
abstract class GenericTypeStmt extends TypeStatement
1113
{
@@ -15,30 +17,4 @@ abstract class GenericTypeStmt extends TypeStatement
1517
public function __construct(
1618
public TypeStatement $type,
1719
) {}
18-
19-
/**
20-
* @return array{int<0, max>, T}
21-
*/
22-
public function __serialize(): array
23-
{
24-
return [$this->offset, $this->type];
25-
}
26-
27-
/**
28-
* @param array{0?: int<0, max>, 1?: T} $data
29-
*
30-
* @throws \UnexpectedValueException
31-
*/
32-
public function __unserialize(array $data): void
33-
{
34-
$this->offset = $data[0] ?? throw new \UnexpectedValueException(\sprintf(
35-
'Unable to unserialize %s offset',
36-
static::class,
37-
));
38-
39-
$this->type = $data[1] ?? throw new \UnexpectedValueException(\sprintf(
40-
'Unable to unserialize %s type',
41-
static::class,
42-
));
43-
}
4420
}

src/Node/Stmt/NullableTypeNode.php

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

77
/**
88
* @template T of TypeStatement = TypeStatement
9-
* @template-extends GenericTypeStmt<TypeStatement>
9+
* @template-extends GenericTypeNode<TypeStatement>
1010
*/
11-
class NullableTypeNode extends GenericTypeStmt {}
11+
class NullableTypeNode extends GenericTypeNode {}

src/Node/Stmt/TypeOffsetAccessNode.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
/**
88
* @template T of TypeStatement = TypeStatement
9-
* @template-extends GenericTypeStmt<T>
9+
* @template-extends GenericTypeNode<T>
1010
*/
11-
class TypeOffsetAccessNode extends GenericTypeStmt
11+
class TypeOffsetAccessNode extends GenericTypeNode
1212
{
1313
public function __construct(
1414
TypeStatement $type,

src/Node/Stmt/TypesListNode.php

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

77
/**
88
* @template T of TypeStatement = TypeStatement
9-
* @template-extends GenericTypeStmt<T>
9+
* @template-extends GenericTypeNode<T>
1010
*/
11-
class TypesListNode extends GenericTypeStmt {}
11+
class TypesListNode extends GenericTypeNode {}

src/Parser.php

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace TypeLang\Parser;
66

7-
use JetBrains\PhpStorm\Language;
87
use Phplrt\Contracts\Lexer\LexerInterface;
98
use Phplrt\Contracts\Lexer\TokenInterface;
109
use Phplrt\Contracts\Parser\ParserRuntimeExceptionInterface;
@@ -128,11 +127,41 @@ public function __construct(
128127
$this->stringPool = new \WeakMap();
129128
$this->integerPool = new \WeakMap();
130129

131-
$this->builder = new Builder($grammar['reducers']);
130+
$this->builder = $this->createBuilder($grammar['reducers']);
132131
$this->lexer = $this->createLexer($grammar);
133132
$this->parser = $this->createParser($this->lexer, $grammar);
134133
}
135134

135+
/**
136+
* @param array<int<0, max>|non-empty-string, callable(Context, mixed):mixed> $reducers
137+
*/
138+
private function createBuilder(array $reducers): BuilderInterface
139+
{
140+
return new class($reducers) implements BuilderInterface {
141+
/**
142+
* @param array<int<0, max>|non-empty-string, callable(Context, mixed):mixed> $reducers
143+
*/
144+
public function __construct(
145+
private readonly array $reducers,
146+
) {}
147+
148+
public function build(Context $context, mixed $result): mixed
149+
{
150+
if (!isset($this->reducers[$context->state])) {
151+
return $result;
152+
}
153+
154+
$result = ($this->reducers[$context->state])($context, $result);
155+
156+
if ($result instanceof Node && $result->offset === 0) {
157+
$result->offset = $context->lastProcessedToken->getOffset();
158+
}
159+
160+
return $result;
161+
}
162+
};
163+
}
164+
136165
/**
137166
* @phpstan-param GrammarConfigArray $grammar
138167
*
@@ -164,7 +193,7 @@ private function createLexer(array $grammar): Lexer
164193
);
165194
}
166195

167-
public function parse(#[Language('PHP')] mixed $source): TypeStatement
196+
public function parse(mixed $source): TypeStatement
168197
{
169198
$this->lastProcessedTokenOffset = 0;
170199

src/ParserInterface.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace TypeLang\Parser;
66

7-
use JetBrains\PhpStorm\Language;
87
use TypeLang\Parser\Exception\ParserExceptionInterface;
98
use TypeLang\Parser\Node\Stmt\TypeStatement;
109

@@ -19,5 +18,5 @@ interface ParserInterface
1918
* @throws ParserExceptionInterface in case of parsing exception occurs
2019
* @throws \Throwable in case of internal error occurs
2120
*/
22-
public function parse(#[Language('PHP')] mixed $source): TypeStatement;
21+
public function parse(mixed $source): TypeStatement;
2322
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
O:56:"TypeLang\Parser\Node\Stmt\Callable\CallableParameterNode":7:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}s:4:"name";N;s:6:"output";b:0;s:8:"variadic";b:0;s:8:"optional";b:0;s:10:"attributes";N;}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
O:61:"TypeLang\Parser\Node\Stmt\Callable\CallableParametersListNode":2:{s:6:"offset";i:0;s:5:"items";a:1:{i:0;O:56:"TypeLang\Parser\Node\Stmt\Callable\CallableParameterNode":7:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}s:4:"name";N;s:6:"output";b:0;s:8:"variadic";b:0;s:8:"optional";b:0;s:10:"attributes";N;}}}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
O:53:"TypeLang\Parser\Node\Stmt\Callable\ParametersListNode":2:{s:6:"offset";i:0;s:5:"items";a:1:{i:0;O:48:"TypeLang\Parser\Node\Stmt\Callable\ParameterNode":7:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}s:4:"name";N;s:6:"output";b:0;s:8:"variadic";b:0;s:8:"optional";b:0;s:10:"attributes";N;}}}
1+
O:53:"TypeLang\Parser\Node\Stmt\Callable\ParametersListNode":2:{s:6:"offset";i:0;s:5:"items";a:1:{i:0;O:56:"TypeLang\Parser\Node\Stmt\Callable\CallableParameterNode":7:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}s:4:"name";N;s:6:"output";b:0;s:8:"variadic";b:0;s:8:"optional";b:0;s:10:"attributes";N;}}}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
O:42:"TypeLang\Parser\Node\Stmt\CallableTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"foo";}}}s:10:"parameters";O:53:"TypeLang\Parser\Node\Stmt\Callable\ParametersListNode":2:{s:6:"offset";i:0;s:5:"items";a:1:{i:0;O:48:"TypeLang\Parser\Node\Stmt\Callable\ParameterNode":7:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}s:4:"name";N;s:6:"output";b:0;s:8:"variadic";b:0;s:8:"optional";b:0;s:10:"attributes";N;}}}s:4:"type";N;}
1+
O:42:"TypeLang\Parser\Node\Stmt\CallableTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"foo";}}}s:10:"parameters";O:61:"TypeLang\Parser\Node\Stmt\Callable\CallableParametersListNode":2:{s:6:"offset";i:0;s:5:"items";a:1:{i:0;O:56:"TypeLang\Parser\Node\Stmt\Callable\CallableParameterNode":7:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}s:4:"name";N;s:6:"output";b:0;s:8:"variadic";b:0;s:8:"optional";b:0;s:10:"attributes";N;}}}s:4:"type";N;}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
O:42:"TypeLang\Parser\Node\Stmt\CallableTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"foo";}}}s:10:"parameters";O:53:"TypeLang\Parser\Node\Stmt\Callable\ParametersListNode":2:{s:6:"offset";i:0;s:5:"items";a:1:{i:0;O:48:"TypeLang\Parser\Node\Stmt\Callable\ParameterNode":7:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}s:4:"name";N;s:6:"output";b:0;s:8:"variadic";b:0;s:8:"optional";b:0;s:10:"attributes";N;}}}s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:4:"void";}}}s:9:"arguments";N;s:6:"fields";N;}}
1+
O:42:"TypeLang\Parser\Node\Stmt\CallableTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"foo";}}}s:10:"parameters";O:61:"TypeLang\Parser\Node\Stmt\Callable\CallableParametersListNode":2:{s:6:"offset";i:0;s:5:"items";a:1:{i:0;O:56:"TypeLang\Parser\Node\Stmt\Callable\CallableParameterNode":7:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}s:4:"name";N;s:6:"output";b:0;s:8:"variadic";b:0;s:8:"optional";b:0;s:10:"attributes";N;}}}s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:4:"void";}}}s:9:"arguments";N;s:6:"fields";N;}}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
O:42:"TypeLang\Parser\Node\Stmt\NullableTypeNode":2:{i:0;i:0;i:1;O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}}
1+
O:42:"TypeLang\Parser\Node\Stmt\NullableTypeNode":2:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
O:46:"TypeLang\Parser\Node\Stmt\TypeOffsetAccessNode":3:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:5:"array";}}}s:9:"arguments";N;s:6:"fields";N;}s:6:"access";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:5:"mixed";}}}s:9:"arguments";N;s:6:"fields";N;}}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
O:39:"TypeLang\Parser\Node\Stmt\TypesListNode":2:{i:0;i:0;i:1;O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}}
1+
O:39:"TypeLang\Parser\Node\Stmt\TypesListNode":2:{s:6:"offset";i:0;s:4:"type";O:39:"TypeLang\Parser\Node\Stmt\NamedTypeNode":4:{s:6:"offset";i:0;s:4:"name";O:25:"TypeLang\Parser\Node\Name":2:{i:0;i:0;i:1;a:1:{i:0;O:31:"TypeLang\Parser\Node\Identifier":2:{i:0;i:0;i:1;s:3:"int";}}}s:9:"arguments";N;s:6:"fields";N;}}

tests/Unit/Serialization/SerializationTestCase.php

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use TypeLang\Parser\Node\Literal\StringLiteralNode;
1515
use TypeLang\Parser\Node\Literal\VariableLiteralNode;
1616
use TypeLang\Parser\Node\Name;
17+
use TypeLang\Parser\Node\Stmt\Callable\CallableParameterNode;
18+
use TypeLang\Parser\Node\Stmt\Callable\CallableParametersListNode;
1719
use TypeLang\Parser\Node\Stmt\Callable\ParameterNode;
1820
use TypeLang\Parser\Node\Stmt\Callable\ParametersListNode;
1921
use TypeLang\Parser\Node\Stmt\CallableTypeNode;
@@ -33,6 +35,7 @@
3335
use TypeLang\Parser\Node\Stmt\Template\TemplateArgumentNode;
3436
use TypeLang\Parser\Node\Stmt\Template\TemplateArgumentsListNode;
3537
use TypeLang\Parser\Node\Stmt\TernaryConditionNode;
38+
use TypeLang\Parser\Node\Stmt\TypeOffsetAccessNode;
3639
use TypeLang\Parser\Node\Stmt\TypesListNode;
3740
use TypeLang\Parser\Node\Stmt\UnionTypeNode;
3841
use TypeLang\Parser\Tests\Unit\TestCase;
@@ -266,24 +269,48 @@ class: new Name('Example\Class\Name'),
266269
),
267270
];
268271

272+
yield self::className(TypeOffsetAccessNode::class) => [
273+
new TypeOffsetAccessNode(
274+
type: new NamedTypeNode('array'),
275+
access: new NamedTypeNode('mixed')
276+
),
277+
];
278+
269279
// Statements :: Callable
270280
yield self::className(ParameterNode::class) => [$param = new ParameterNode(
271281
type: new NamedTypeNode(new Name('int')),
272282
name: new VariableLiteralNode('$test'),
273-
output: true,
283+
output: false,
274284
variadic: true,
275-
optional: true,
285+
optional: false,
286+
)];
287+
288+
yield self::className(CallableParameterNode::class) => [$param = new CallableParameterNode(
289+
type: new NamedTypeNode(new Name('int')),
290+
name: new VariableLiteralNode('$test'),
291+
output: false,
292+
variadic: true,
293+
optional: false,
276294
)];
277295

278296
yield self::className(ParameterNode::class)
279297
. ' without name' => [$param = new ParameterNode(
280298
type: new NamedTypeNode(new Name('int')),
281299
)];
282300

301+
yield self::className(CallableParameterNode::class)
302+
. ' without name' => [$param = new CallableParameterNode(
303+
type: new NamedTypeNode(new Name('int')),
304+
)];
305+
283306
yield self::className(ParametersListNode::class) => [$paramList = new ParametersListNode(
284307
items: [$param],
285308
)];
286309

310+
yield self::className(CallableParametersListNode::class) => [$paramList = new CallableParametersListNode(
311+
items: [$param],
312+
)];
313+
287314
yield self::className(CallableTypeNode::class) => [new CallableTypeNode(
288315
name: new Name('foo'),
289316
parameters: $paramList,

0 commit comments

Comments
 (0)