1 <?php declare(strict_types=1);
3 namespace PhpParser\Lexer;
5 use PhpParser\ErrorHandler;
6 use PhpParser\LexerTest;
7 use PhpParser\Parser\Tokens;
9 require_once __DIR__ . '/../LexerTest.php';
11 class EmulativeTest extends LexerTest
13 protected function getLexer(array $options = []) {
14 return new Emulative($options);
18 * @dataProvider provideTestReplaceKeywords
20 public function testReplaceKeywords($keyword, $expectedToken) {
21 $lexer = $this->getLexer();
22 $lexer->startLexing('<?php ' . $keyword);
24 $this->assertSame($expectedToken, $lexer->getNextToken());
25 $this->assertSame(0, $lexer->getNextToken());
29 * @dataProvider provideTestReplaceKeywords
31 public function testNoReplaceKeywordsAfterObjectOperator($keyword) {
32 $lexer = $this->getLexer();
33 $lexer->startLexing('<?php ->' . $keyword);
35 $this->assertSame(Tokens::T_OBJECT_OPERATOR, $lexer->getNextToken());
36 $this->assertSame(Tokens::T_STRING, $lexer->getNextToken());
37 $this->assertSame(0, $lexer->getNextToken());
40 public function provideTestReplaceKeywords() {
43 ['finally', Tokens::T_FINALLY],
44 ['yield', Tokens::T_YIELD],
47 ['callable', Tokens::T_CALLABLE],
48 ['insteadof', Tokens::T_INSTEADOF],
49 ['trait', Tokens::T_TRAIT],
50 ['__TRAIT__', Tokens::T_TRAIT_C],
53 ['__DIR__', Tokens::T_DIR],
54 ['goto', Tokens::T_GOTO],
55 ['namespace', Tokens::T_NAMESPACE],
56 ['__NAMESPACE__', Tokens::T_NS_C],
61 * @dataProvider provideTestLexNewFeatures
63 public function testLexNewFeatures($code, array $expectedTokens) {
64 $lexer = $this->getLexer();
65 $lexer->startLexing('<?php ' . $code);
68 while (0 !== $token = $lexer->getNextToken($text)) {
69 $tokens[] = [$token, $text];
71 $this->assertSame($expectedTokens, $tokens);
75 * @dataProvider provideTestLexNewFeatures
77 public function testLeaveStuffAloneInStrings($code) {
78 $stringifiedToken = '"' . addcslashes($code, '"\\') . '"';
80 $lexer = $this->getLexer();
81 $lexer->startLexing('<?php ' . $stringifiedToken);
83 $this->assertSame(Tokens::T_CONSTANT_ENCAPSED_STRING, $lexer->getNextToken($text));
84 $this->assertSame($stringifiedToken, $text);
85 $this->assertSame(0, $lexer->getNextToken());
89 * @dataProvider provideTestLexNewFeatures
91 public function testErrorAfterEmulation($code) {
92 $errorHandler = new ErrorHandler\Collecting;
93 $lexer = $this->getLexer([]);
94 $lexer->startLexing('<?php ' . $code . "\0", $errorHandler);
96 $errors = $errorHandler->getErrors();
97 $this->assertCount(1, $errors);
100 $this->assertSame('Unexpected null byte', $error->getRawMessage());
102 $attrs = $error->getAttributes();
103 $expPos = strlen('<?php ' . $code);
104 $expLine = 1 + substr_count('<?php ' . $code, "\n");
105 $this->assertSame($expPos, $attrs['startFilePos']);
106 $this->assertSame($expPos, $attrs['endFilePos']);
107 $this->assertSame($expLine, $attrs['startLine']);
108 $this->assertSame($expLine, $attrs['endLine']);
111 public function provideTestLexNewFeatures() {
114 [Tokens::T_YIELD_FROM, 'yield from'],
117 [Tokens::T_YIELD_FROM, "yield\r\nfrom"],
120 [Tokens::T_ELLIPSIS, '...'],
123 [Tokens::T_POW, '**'],
126 [Tokens::T_POW_EQUAL, '**='],
129 [Tokens::T_COALESCE, '??'],
132 [Tokens::T_SPACESHIP, '<=>'],
135 [Tokens::T_LNUMBER, '0b1010110'],
137 ['0b1011010101001010110101010010101011010101010101101011001110111100', [
138 [Tokens::T_DNUMBER, '0b1011010101001010110101010010101011010101010101101011001110111100'],
141 [Tokens::T_NS_SEPARATOR, '\\'],
143 ["<<<'NOWDOC'\nNOWDOC;\n", [
144 [Tokens::T_START_HEREDOC, "<<<'NOWDOC'\n"],
145 [Tokens::T_END_HEREDOC, 'NOWDOC'],
148 ["<<<'NOWDOC'\nFoobar\nNOWDOC;\n", [
149 [Tokens::T_START_HEREDOC, "<<<'NOWDOC'\n"],
150 [Tokens::T_ENCAPSED_AND_WHITESPACE, "Foobar\n"],
151 [Tokens::T_END_HEREDOC, 'NOWDOC'],
155 // Flexible heredoc/nowdoc
156 ["<<<LABEL\nLABEL,", [
157 [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
158 [Tokens::T_END_HEREDOC, "LABEL"],
161 ["<<<LABEL\n LABEL,", [
162 [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
163 [Tokens::T_END_HEREDOC, " LABEL"],
166 ["<<<LABEL\n Foo\n LABEL;", [
167 [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
168 [Tokens::T_ENCAPSED_AND_WHITESPACE, " Foo\n"],
169 [Tokens::T_END_HEREDOC, " LABEL"],
172 ["<<<A\n A,<<<A\n A,", [
173 [Tokens::T_START_HEREDOC, "<<<A\n"],
174 [Tokens::T_END_HEREDOC, " A"],
176 [Tokens::T_START_HEREDOC, "<<<A\n"],
177 [Tokens::T_END_HEREDOC, " A"],
180 ["<<<LABEL\nLABELNOPE\nLABEL\n", [
181 [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
182 [Tokens::T_ENCAPSED_AND_WHITESPACE, "LABELNOPE\n"],
183 [Tokens::T_END_HEREDOC, "LABEL"],
185 // Interpretation changed
186 ["<<<LABEL\n LABEL\nLABEL\n", [
187 [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
188 [Tokens::T_END_HEREDOC, " LABEL"],
189 [Tokens::T_STRING, "LABEL"],