Skip to content

Commit c538b10

Browse files
Jean85goetas
authored andcommitted
Require doctrine/lexer
1 parent c9cb427 commit c538b10

File tree

7 files changed

+253
-0
lines changed

7 files changed

+253
-0
lines changed

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"jms/metadata": "^2.0",
2121
"doctrine/annotations": "^1.0",
2222
"doctrine/instantiator": "^1.0.3",
23+
"doctrine/lexer": "^1.2",
2324
"hoa/compiler": "^3.17.08.08"
2425
},
2526
"suggest": {

src/Type/InnerParser.php

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
/**
1414
* @internal
1515
*
16+
* @deprecated This class is no longer in use and will be removed in the next major version,
17+
* @see https://github.com/schmittjoh/serializer/issues/1182
1618
* @generated Use regenerate-parser.php to refresh this class.
1719
*/
1820
final class InnerParser extends Parser

src/Type/Lexer.php

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace JMS\Serializer\Type;
4+
5+
use Doctrine\Common\Lexer\AbstractLexer;
6+
use Hoa\Exception\Exception;
7+
use JMS\Serializer\Type\Exception\SyntaxError;
8+
9+
class Lexer extends AbstractLexer implements ParserInterface
10+
{
11+
public function parse(string $type): array
12+
{
13+
try {
14+
return $this->getType($type);
15+
} catch (Exception $e) {
16+
throw new SyntaxError($e->getMessage(), 0, $e);
17+
}
18+
}
19+
20+
protected function getCatchablePatterns(): array
21+
{
22+
return [
23+
'(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*', // name
24+
'(\+|\-)?(0|[1-9]\d*)(\.\d+)?', // number
25+
'null',
26+
'""|\'\'', // empty string
27+
'"[^"]+"', // quoted string
28+
"'[^']+'", // apostrophed string
29+
];
30+
}
31+
32+
protected function getNonCatchablePatterns(): array
33+
{
34+
return [
35+
// TODO: Implement getNonCatchablePatterns() method.
36+
];
37+
}
38+
39+
protected function getType(&$value)
40+
{
41+
// TODO: Implement getType() method.
42+
}
43+
}

src/Type/Parser.php

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use Hoa\Visitor\Visit;
99
use JMS\Serializer\Type\Exception\SyntaxError;
1010

11+
@trigger_error(sprintf('Class "%s" is deprecated and will be removed in the next major version, use %s instead.', TypeVisitor::class, Lexer::class), E_USER_DEPRECATED);
12+
1113
final class Parser implements ParserInterface
1214
{
1315
/** @var InnerParser */

src/Type/TypeVisitor.php

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
use JMS\Serializer\Type\Exception\InvalidNode;
1111
use function strpos;
1212

13+
@trigger_error(sprintf('Class "%s" is deprecated and will be removed in the next major version, use %s instead.', TypeVisitor::class, ''), E_USER_DEPRECATED);
14+
15+
/**
16+
* @deprecated This class is no longer in use and will be removed in the next major version,
17+
* @see https://github.com/schmittjoh/serializer/issues/1182
18+
*/
1319
final class TypeVisitor implements Visit
1420
{
1521
/**

src/Type/regenerate-parser.php

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
use Hoa\Compiler\Llk\Llk;
77
use Hoa\File\Read;
88

9+
@trigger_error(sprintf('This script, "%s" is deprecated and will be removed in the next major version.', __FILE__), E_USER_DEPRECATED);
10+
911
require __DIR__ . '/../../vendor/autoload.php';
1012

1113
$compiler = Llk::load(new Read(__DIR__ . '/grammar.pp'));

tests/Serializer/Type/LexerTest.php

+197
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace JMS\Serializer\Tests\Serializer\Type;
6+
7+
use JMS\Serializer\Type\Exception\SyntaxError;
8+
use JMS\Serializer\Type\Lexer;
9+
use JMS\Serializer\Type\Parser;
10+
use JMS\Serializer\Type\ParserInterface;
11+
use PHPUnit\Framework\TestCase;
12+
13+
class LexerTest extends TestCase
14+
{
15+
/** @var ParserInterface */
16+
private $lexer;
17+
18+
protected function setUp(): void
19+
{
20+
$this->lexer = new Lexer();
21+
}
22+
23+
/**
24+
* @dataProvider validTypesProvider
25+
*/
26+
public function testParse(string $sourceType, array $expectedType): void
27+
{
28+
self::assertSame(
29+
$expectedType,
30+
$this->lexer->parse($sourceType)
31+
);
32+
}
33+
34+
/**
35+
* @return mixed[][]
36+
*/
37+
public function validTypesProvider(): iterable
38+
{
39+
$type = static function (string $name, array $params = []): array {
40+
return ['name' => $name, 'params' => $params];
41+
};
42+
43+
yield [
44+
'string',
45+
$type('string'),
46+
];
47+
yield [
48+
'array<Foo>',
49+
$type('array', [['name' => 'Foo', 'params' => []]]),
50+
];
51+
yield [
52+
'Foo<\'a\'>',
53+
$type('Foo', ['a']),
54+
];
55+
yield [
56+
'Foo<5>',
57+
$type('Foo', [5]),
58+
];
59+
yield [
60+
'Foo<5.5>',
61+
$type('Foo', [5.5]),
62+
];
63+
yield [
64+
'Foo<null>',
65+
$type('Foo', [null]),
66+
];
67+
yield [
68+
'Foo<\'a\',\'b\',\'c\'>',
69+
$type('Foo', ['a', 'b', 'c']),
70+
];
71+
yield [
72+
'Foo<\'a\',\'\'>',
73+
$type('Foo', ['a', '']),
74+
];
75+
yield [
76+
'array<Foo,Bar>',
77+
$type('array', [['name' => 'Foo', 'params' => []], ['name' => 'Bar', 'params' => []]]),
78+
];
79+
yield [
80+
'array<Foo\Bar, Baz\Boo>',
81+
$type('array', [['name' => 'Foo\Bar', 'params' => []], ['name' => 'Baz\Boo', 'params' => []]]),
82+
];
83+
yield [
84+
'a<b<c,d>,e>',
85+
$type('a', [['name' => 'b', 'params' => [['name' => 'c', 'params' => []], ['name' => 'd', 'params' => []]]], ['name' => 'e', 'params' => []]]),
86+
87+
];
88+
yield [
89+
'Foo',
90+
$type('Foo'),
91+
];
92+
yield [
93+
'Foo\Bar',
94+
$type('Foo\Bar'),
95+
];
96+
yield [
97+
'Foo<"asdf asdf">',
98+
$type('Foo', ['asdf asdf']),
99+
];
100+
yield [
101+
'Foo<[]>',
102+
$type('Foo', [[]]),
103+
];
104+
yield [
105+
'Foo<[[]]>',
106+
$type('Foo', [[[]]]),
107+
];
108+
yield [
109+
'Foo<[123]>',
110+
$type('Foo', [[123]]),
111+
];
112+
yield [
113+
'Foo<[123, 456]>',
114+
$type('Foo', [[123, 456]]),
115+
];
116+
yield [
117+
'Foo<[[123], 456, "bar"]>',
118+
$type('Foo', [[[123], 456, 'bar']]),
119+
];
120+
yield [
121+
'DateTime<null, null, [\'Y-m-d\TH:i:s\', \'Y-m-d\TH:i:sP\']>',
122+
$type('DateTime', [null, null, ['Y-m-d\TH:i:s', 'Y-m-d\TH:i:sP']]),
123+
];
124+
}
125+
126+
public function testEmptyString(): void
127+
{
128+
$this->expectException(SyntaxError::class);
129+
$this->expectExceptionMessage(
130+
"Unexpected token \"EOF\" (EOF) at line 1 and column 1:\n"
131+
. "\n"
132+
. ''
133+
);
134+
135+
$this->lexer->parse('');
136+
}
137+
138+
public function testParamTypeMustEndWithBracket(): void
139+
{
140+
$this->expectException(SyntaxError::class);
141+
$this->expectExceptionMessage(
142+
"Unexpected token \"EOF\" (EOF) at line 1 and column 8:\n"
143+
. "Foo<bar\n"
144+
. ''
145+
);
146+
147+
$this->lexer->parse('Foo<bar');
148+
}
149+
150+
public function testMustStartWithName(): void
151+
{
152+
$this->expectException(SyntaxError::class);
153+
$this->expectExceptionMessage(
154+
"Unexpected token \",\" (comma) at line 1 and column 1:\n"
155+
. ",\n"
156+
. ''
157+
);
158+
159+
$this->lexer->parse(',');
160+
}
161+
162+
public function testEmptyParams(): void
163+
{
164+
$this->expectException(SyntaxError::class);
165+
$this->expectExceptionMessage(
166+
"Unexpected token \">\" (_parenthesis) at line 1 and column 5:\n"
167+
. "Foo<>\n"
168+
. ''
169+
);
170+
171+
$this->lexer->parse('Foo<>');
172+
}
173+
174+
public function testNoTrailingComma(): void
175+
{
176+
$this->expectException(SyntaxError::class);
177+
$this->expectExceptionMessage(
178+
"Unexpected token \",\" (comma) at line 1 and column 7:\n"
179+
. "Foo<aa,>\n"
180+
. ''
181+
);
182+
183+
$this->lexer->parse('Foo<aa,>');
184+
}
185+
186+
public function testLeadingBackslash(): void
187+
{
188+
$this->expectException(SyntaxError::class);
189+
$this->expectExceptionMessage(
190+
"Unrecognized token \"\\\" at line 1 and column 5:\n"
191+
. "Foo<\Bar>\n"
192+
. ''
193+
);
194+
195+
$this->lexer->parse('Foo<\Bar>');
196+
}
197+
}

0 commit comments

Comments
 (0)