EmulativeTest.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php declare(strict_types=1);
  2. namespace PhpParser\Lexer;
  3. use PhpParser\ErrorHandler;
  4. use PhpParser\LexerTest;
  5. use PhpParser\Parser\Tokens;
  6. require_once __DIR__ . '/../LexerTest.php';
  7. class EmulativeTest extends LexerTest
  8. {
  9. protected function getLexer(array $options = []) {
  10. return new Emulative($options);
  11. }
  12. /**
  13. * @dataProvider provideTestReplaceKeywords
  14. */
  15. public function testReplaceKeywords($keyword, $expectedToken) {
  16. $lexer = $this->getLexer();
  17. $lexer->startLexing('<?php ' . $keyword);
  18. $this->assertSame($expectedToken, $lexer->getNextToken());
  19. $this->assertSame(0, $lexer->getNextToken());
  20. }
  21. /**
  22. * @dataProvider provideTestReplaceKeywords
  23. */
  24. public function testNoReplaceKeywordsAfterObjectOperator($keyword) {
  25. $lexer = $this->getLexer();
  26. $lexer->startLexing('<?php ->' . $keyword);
  27. $this->assertSame(Tokens::T_OBJECT_OPERATOR, $lexer->getNextToken());
  28. $this->assertSame(Tokens::T_STRING, $lexer->getNextToken());
  29. $this->assertSame(0, $lexer->getNextToken());
  30. }
  31. public function provideTestReplaceKeywords() {
  32. return [
  33. // PHP 5.5
  34. ['finally', Tokens::T_FINALLY],
  35. ['yield', Tokens::T_YIELD],
  36. // PHP 5.4
  37. ['callable', Tokens::T_CALLABLE],
  38. ['insteadof', Tokens::T_INSTEADOF],
  39. ['trait', Tokens::T_TRAIT],
  40. ['__TRAIT__', Tokens::T_TRAIT_C],
  41. // PHP 5.3
  42. ['__DIR__', Tokens::T_DIR],
  43. ['goto', Tokens::T_GOTO],
  44. ['namespace', Tokens::T_NAMESPACE],
  45. ['__NAMESPACE__', Tokens::T_NS_C],
  46. ];
  47. }
  48. /**
  49. * @dataProvider provideTestLexNewFeatures
  50. */
  51. public function testLexNewFeatures($code, array $expectedTokens) {
  52. $lexer = $this->getLexer();
  53. $lexer->startLexing('<?php ' . $code);
  54. $tokens = [];
  55. while (0 !== $token = $lexer->getNextToken($text)) {
  56. $tokens[] = [$token, $text];
  57. }
  58. $this->assertSame($expectedTokens, $tokens);
  59. }
  60. /**
  61. * @dataProvider provideTestLexNewFeatures
  62. */
  63. public function testLeaveStuffAloneInStrings($code) {
  64. $stringifiedToken = '"' . addcslashes($code, '"\\') . '"';
  65. $lexer = $this->getLexer();
  66. $lexer->startLexing('<?php ' . $stringifiedToken);
  67. $this->assertSame(Tokens::T_CONSTANT_ENCAPSED_STRING, $lexer->getNextToken($text));
  68. $this->assertSame($stringifiedToken, $text);
  69. $this->assertSame(0, $lexer->getNextToken());
  70. }
  71. /**
  72. * @dataProvider provideTestLexNewFeatures
  73. */
  74. public function testErrorAfterEmulation($code) {
  75. $errorHandler = new ErrorHandler\Collecting;
  76. $lexer = $this->getLexer([]);
  77. $lexer->startLexing('<?php ' . $code . "\0", $errorHandler);
  78. $errors = $errorHandler->getErrors();
  79. $this->assertCount(1, $errors);
  80. $error = $errors[0];
  81. $this->assertSame('Unexpected null byte', $error->getRawMessage());
  82. $attrs = $error->getAttributes();
  83. $expPos = strlen('<?php ' . $code);
  84. $expLine = 1 + substr_count('<?php ' . $code, "\n");
  85. $this->assertSame($expPos, $attrs['startFilePos']);
  86. $this->assertSame($expPos, $attrs['endFilePos']);
  87. $this->assertSame($expLine, $attrs['startLine']);
  88. $this->assertSame($expLine, $attrs['endLine']);
  89. }
  90. public function provideTestLexNewFeatures() {
  91. return [
  92. ['yield from', [
  93. [Tokens::T_YIELD_FROM, 'yield from'],
  94. ]],
  95. ["yield\r\nfrom", [
  96. [Tokens::T_YIELD_FROM, "yield\r\nfrom"],
  97. ]],
  98. ['...', [
  99. [Tokens::T_ELLIPSIS, '...'],
  100. ]],
  101. ['**', [
  102. [Tokens::T_POW, '**'],
  103. ]],
  104. ['**=', [
  105. [Tokens::T_POW_EQUAL, '**='],
  106. ]],
  107. ['??', [
  108. [Tokens::T_COALESCE, '??'],
  109. ]],
  110. ['<=>', [
  111. [Tokens::T_SPACESHIP, '<=>'],
  112. ]],
  113. ['0b1010110', [
  114. [Tokens::T_LNUMBER, '0b1010110'],
  115. ]],
  116. ['0b1011010101001010110101010010101011010101010101101011001110111100', [
  117. [Tokens::T_DNUMBER, '0b1011010101001010110101010010101011010101010101101011001110111100'],
  118. ]],
  119. ['\\', [
  120. [Tokens::T_NS_SEPARATOR, '\\'],
  121. ]],
  122. ["<<<'NOWDOC'\nNOWDOC;\n", [
  123. [Tokens::T_START_HEREDOC, "<<<'NOWDOC'\n"],
  124. [Tokens::T_END_HEREDOC, 'NOWDOC'],
  125. [ord(';'), ';'],
  126. ]],
  127. ["<<<'NOWDOC'\nFoobar\nNOWDOC;\n", [
  128. [Tokens::T_START_HEREDOC, "<<<'NOWDOC'\n"],
  129. [Tokens::T_ENCAPSED_AND_WHITESPACE, "Foobar\n"],
  130. [Tokens::T_END_HEREDOC, 'NOWDOC'],
  131. [ord(';'), ';'],
  132. ]],
  133. // Flexible heredoc/nowdoc
  134. ["<<<LABEL\nLABEL,", [
  135. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  136. [Tokens::T_END_HEREDOC, "LABEL"],
  137. [ord(','), ','],
  138. ]],
  139. ["<<<LABEL\n LABEL,", [
  140. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  141. [Tokens::T_END_HEREDOC, " LABEL"],
  142. [ord(','), ','],
  143. ]],
  144. ["<<<LABEL\n Foo\n LABEL;", [
  145. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  146. [Tokens::T_ENCAPSED_AND_WHITESPACE, " Foo\n"],
  147. [Tokens::T_END_HEREDOC, " LABEL"],
  148. [ord(';'), ';'],
  149. ]],
  150. ["<<<A\n A,<<<A\n A,", [
  151. [Tokens::T_START_HEREDOC, "<<<A\n"],
  152. [Tokens::T_END_HEREDOC, " A"],
  153. [ord(','), ','],
  154. [Tokens::T_START_HEREDOC, "<<<A\n"],
  155. [Tokens::T_END_HEREDOC, " A"],
  156. [ord(','), ','],
  157. ]],
  158. ["<<<LABEL\nLABELNOPE\nLABEL\n", [
  159. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  160. [Tokens::T_ENCAPSED_AND_WHITESPACE, "LABELNOPE\n"],
  161. [Tokens::T_END_HEREDOC, "LABEL"],
  162. ]],
  163. // Interpretation changed
  164. ["<<<LABEL\n LABEL\nLABEL\n", [
  165. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  166. [Tokens::T_END_HEREDOC, " LABEL"],
  167. [Tokens::T_STRING, "LABEL"],
  168. ]],
  169. ];
  170. }
  171. }