Dashboard sipadu mbip
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

EmulativeTest.php 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php declare(strict_types=1);
  2. namespace PhpParser\Lexer;
  3. use PhpParser\ErrorHandler;
  4. use PhpParser\LexerTest;
  5. use PhpParser\Parser\Tokens;
  6. class EmulativeTest extends LexerTest
  7. {
  8. protected function getLexer(array $options = []) {
  9. return new Emulative($options);
  10. }
  11. /**
  12. * @dataProvider provideTestReplaceKeywords
  13. */
  14. public function testReplaceKeywords($keyword, $expectedToken) {
  15. $lexer = $this->getLexer();
  16. $lexer->startLexing('<?php ' . $keyword);
  17. $this->assertSame($expectedToken, $lexer->getNextToken());
  18. $this->assertSame(0, $lexer->getNextToken());
  19. }
  20. /**
  21. * @dataProvider provideTestReplaceKeywords
  22. */
  23. public function testNoReplaceKeywordsAfterObjectOperator(string $keyword) {
  24. $lexer = $this->getLexer();
  25. $lexer->startLexing('<?php ->' . $keyword);
  26. $this->assertSame(Tokens::T_OBJECT_OPERATOR, $lexer->getNextToken());
  27. $this->assertSame(Tokens::T_STRING, $lexer->getNextToken());
  28. $this->assertSame(0, $lexer->getNextToken());
  29. }
  30. /**
  31. * @dataProvider provideTestReplaceKeywords
  32. */
  33. public function testNoReplaceKeywordsAfterObjectOperatorWithSpaces(string $keyword) {
  34. $lexer = $this->getLexer();
  35. $lexer->startLexing('<?php -> ' . $keyword);
  36. $this->assertSame(Tokens::T_OBJECT_OPERATOR, $lexer->getNextToken());
  37. $this->assertSame(Tokens::T_STRING, $lexer->getNextToken());
  38. $this->assertSame(0, $lexer->getNextToken());
  39. }
  40. public function provideTestReplaceKeywords() {
  41. return [
  42. // PHP 7.4
  43. ['fn', Tokens::T_FN],
  44. // PHP 5.5
  45. ['finally', Tokens::T_FINALLY],
  46. ['yield', Tokens::T_YIELD],
  47. // PHP 5.4
  48. ['callable', Tokens::T_CALLABLE],
  49. ['insteadof', Tokens::T_INSTEADOF],
  50. ['trait', Tokens::T_TRAIT],
  51. ['__TRAIT__', Tokens::T_TRAIT_C],
  52. // PHP 5.3
  53. ['__DIR__', Tokens::T_DIR],
  54. ['goto', Tokens::T_GOTO],
  55. ['namespace', Tokens::T_NAMESPACE],
  56. ['__NAMESPACE__', Tokens::T_NS_C],
  57. ];
  58. }
  59. /**
  60. * @dataProvider provideTestLexNewFeatures
  61. */
  62. public function testLexNewFeatures($code, array $expectedTokens) {
  63. $lexer = $this->getLexer();
  64. $lexer->startLexing('<?php ' . $code);
  65. $tokens = [];
  66. while (0 !== $token = $lexer->getNextToken($text)) {
  67. $tokens[] = [$token, $text];
  68. }
  69. $this->assertSame($expectedTokens, $tokens);
  70. }
  71. /**
  72. * @dataProvider provideTestLexNewFeatures
  73. */
  74. public function testLeaveStuffAloneInStrings($code) {
  75. $stringifiedToken = '"' . addcslashes($code, '"\\') . '"';
  76. $lexer = $this->getLexer();
  77. $lexer->startLexing('<?php ' . $stringifiedToken);
  78. $this->assertSame(Tokens::T_CONSTANT_ENCAPSED_STRING, $lexer->getNextToken($text));
  79. $this->assertSame($stringifiedToken, $text);
  80. $this->assertSame(0, $lexer->getNextToken());
  81. }
  82. /**
  83. * @dataProvider provideTestLexNewFeatures
  84. */
  85. public function testErrorAfterEmulation($code) {
  86. $errorHandler = new ErrorHandler\Collecting;
  87. $lexer = $this->getLexer();
  88. $lexer->startLexing('<?php ' . $code . "\0", $errorHandler);
  89. $errors = $errorHandler->getErrors();
  90. $this->assertCount(1, $errors);
  91. $error = $errors[0];
  92. $this->assertSame('Unexpected null byte', $error->getRawMessage());
  93. $attrs = $error->getAttributes();
  94. $expPos = strlen('<?php ' . $code);
  95. $expLine = 1 + substr_count('<?php ' . $code, "\n");
  96. $this->assertSame($expPos, $attrs['startFilePos']);
  97. $this->assertSame($expPos, $attrs['endFilePos']);
  98. $this->assertSame($expLine, $attrs['startLine']);
  99. $this->assertSame($expLine, $attrs['endLine']);
  100. }
  101. public function provideTestLexNewFeatures() {
  102. return [
  103. ['yield from', [
  104. [Tokens::T_YIELD_FROM, 'yield from'],
  105. ]],
  106. ["yield\r\nfrom", [
  107. [Tokens::T_YIELD_FROM, "yield\r\nfrom"],
  108. ]],
  109. ['...', [
  110. [Tokens::T_ELLIPSIS, '...'],
  111. ]],
  112. ['**', [
  113. [Tokens::T_POW, '**'],
  114. ]],
  115. ['**=', [
  116. [Tokens::T_POW_EQUAL, '**='],
  117. ]],
  118. ['??', [
  119. [Tokens::T_COALESCE, '??'],
  120. ]],
  121. ['<=>', [
  122. [Tokens::T_SPACESHIP, '<=>'],
  123. ]],
  124. ['0b1010110', [
  125. [Tokens::T_LNUMBER, '0b1010110'],
  126. ]],
  127. ['0b1011010101001010110101010010101011010101010101101011001110111100', [
  128. [Tokens::T_DNUMBER, '0b1011010101001010110101010010101011010101010101101011001110111100'],
  129. ]],
  130. ['\\', [
  131. [Tokens::T_NS_SEPARATOR, '\\'],
  132. ]],
  133. ["<<<'NOWDOC'\nNOWDOC;\n", [
  134. [Tokens::T_START_HEREDOC, "<<<'NOWDOC'\n"],
  135. [Tokens::T_END_HEREDOC, 'NOWDOC'],
  136. [ord(';'), ';'],
  137. ]],
  138. ["<<<'NOWDOC'\nFoobar\nNOWDOC;\n", [
  139. [Tokens::T_START_HEREDOC, "<<<'NOWDOC'\n"],
  140. [Tokens::T_ENCAPSED_AND_WHITESPACE, "Foobar\n"],
  141. [Tokens::T_END_HEREDOC, 'NOWDOC'],
  142. [ord(';'), ';'],
  143. ]],
  144. // PHP 7.3: Flexible heredoc/nowdoc
  145. ["<<<LABEL\nLABEL,", [
  146. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  147. [Tokens::T_END_HEREDOC, "LABEL"],
  148. [ord(','), ','],
  149. ]],
  150. ["<<<LABEL\n LABEL,", [
  151. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  152. [Tokens::T_END_HEREDOC, " LABEL"],
  153. [ord(','), ','],
  154. ]],
  155. ["<<<LABEL\n Foo\n LABEL;", [
  156. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  157. [Tokens::T_ENCAPSED_AND_WHITESPACE, " Foo\n"],
  158. [Tokens::T_END_HEREDOC, " LABEL"],
  159. [ord(';'), ';'],
  160. ]],
  161. ["<<<A\n A,<<<A\n A,", [
  162. [Tokens::T_START_HEREDOC, "<<<A\n"],
  163. [Tokens::T_END_HEREDOC, " A"],
  164. [ord(','), ','],
  165. [Tokens::T_START_HEREDOC, "<<<A\n"],
  166. [Tokens::T_END_HEREDOC, " A"],
  167. [ord(','), ','],
  168. ]],
  169. ["<<<LABEL\nLABELNOPE\nLABEL\n", [
  170. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  171. [Tokens::T_ENCAPSED_AND_WHITESPACE, "LABELNOPE\n"],
  172. [Tokens::T_END_HEREDOC, "LABEL"],
  173. ]],
  174. // Interpretation changed
  175. ["<<<LABEL\n LABEL\nLABEL\n", [
  176. [Tokens::T_START_HEREDOC, "<<<LABEL\n"],
  177. [Tokens::T_END_HEREDOC, " LABEL"],
  178. [Tokens::T_STRING, "LABEL"],
  179. ]],
  180. // PHP 7.4: Null coalesce equal
  181. ['??=', [
  182. [Tokens::T_COALESCE_EQUAL, '??='],
  183. ]],
  184. // PHP 7.4: Number literal separator
  185. ['1_000', [
  186. [Tokens::T_LNUMBER, '1_000'],
  187. ]],
  188. ['0xCAFE_F00D', [
  189. [Tokens::T_LNUMBER, '0xCAFE_F00D'],
  190. ]],
  191. ['0b0101_1111', [
  192. [Tokens::T_LNUMBER, '0b0101_1111'],
  193. ]],
  194. ['0137_041', [
  195. [Tokens::T_LNUMBER, '0137_041'],
  196. ]],
  197. ['1_000.0', [
  198. [Tokens::T_DNUMBER, '1_000.0'],
  199. ]],
  200. ['1_0.0', [
  201. [Tokens::T_DNUMBER, '1_0.0']
  202. ]],
  203. ['1_000_000_000.0', [
  204. [Tokens::T_DNUMBER, '1_000_000_000.0']
  205. ]],
  206. ['0e1_0', [
  207. [Tokens::T_DNUMBER, '0e1_0']
  208. ]],
  209. ['1_0e+10', [
  210. [Tokens::T_DNUMBER, '1_0e+10']
  211. ]],
  212. ['1_0e-10', [
  213. [Tokens::T_DNUMBER, '1_0e-10']
  214. ]],
  215. ['0b1011010101001010_110101010010_10101101010101_0101101011001_110111100', [
  216. [Tokens::T_DNUMBER, '0b1011010101001010_110101010010_10101101010101_0101101011001_110111100'],
  217. ]],
  218. ['0xFFFF_FFFF_FFFF_FFFF', [
  219. [Tokens::T_DNUMBER, '0xFFFF_FFFF_FFFF_FFFF'],
  220. ]],
  221. ['1_000+1', [
  222. [Tokens::T_LNUMBER, '1_000'],
  223. [ord('+'), '+'],
  224. [Tokens::T_LNUMBER, '1'],
  225. ]],
  226. ['1_0abc', [
  227. [Tokens::T_LNUMBER, '1_0'],
  228. [Tokens::T_STRING, 'abc'],
  229. ]],
  230. ];
  231. }
  232. }