ParserTest.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. namespace PhpParser;
  3. use PhpParser\Comment;
  4. require_once __DIR__ . '/CodeTestAbstract.php';
  5. class ParserTest extends CodeTestAbstract
  6. {
  7. /**
  8. * @dataProvider provideTestParse
  9. */
  10. public function testParse($name, $code, $expected) {
  11. $lexer = new Lexer\Emulative(array('usedAttributes' => array(
  12. 'startLine', 'endLine', 'startFilePos', 'endFilePos'
  13. )));
  14. $parser = new Parser($lexer, array(
  15. 'throwOnError' => false,
  16. ));
  17. $stmts = $parser->parse($code);
  18. $errors = $parser->getErrors();
  19. $output = '';
  20. foreach ($errors as $error) {
  21. $output .= $this->formatErrorMessage($error, $code) . "\n";
  22. }
  23. if (null !== $stmts) {
  24. $dumper = new NodeDumper;
  25. $output .= $dumper->dump($stmts);
  26. }
  27. $this->assertSame($this->canonicalize($expected), $this->canonicalize($output), $name);
  28. }
  29. public function provideTestParse() {
  30. return $this->getTests(__DIR__ . '/../code/parser', 'test');
  31. }
  32. private function formatErrorMessage(Error $e, $code) {
  33. if ($e->hasColumnInfo()) {
  34. return $e->getRawMessage() . ' from ' . $e->getStartLine() . ':' . $e->getStartColumn($code)
  35. . ' to ' . $e->getEndLine() . ':' . $e->getEndColumn($code);
  36. } else {
  37. return $e->getMessage();
  38. }
  39. }
  40. /**
  41. * @expectedException \PhpParser\Error
  42. * @expectedExceptionMessage Syntax error, unexpected EOF on line 1
  43. */
  44. public function testParserThrowsSyntaxError() {
  45. $parser = new Parser(new Lexer());
  46. $parser->parse('<?php foo');
  47. }
  48. /**
  49. * @expectedException \PhpParser\Error
  50. * @expectedExceptionMessage Cannot use foo as self because 'self' is a special class name on line 1
  51. */
  52. public function testParserThrowsSpecialError() {
  53. $parser = new Parser(new Lexer());
  54. $parser->parse('<?php use foo as self;');
  55. }
  56. public function testAttributeAssignment() {
  57. $lexer = new Lexer(array(
  58. 'usedAttributes' => array(
  59. 'comments', 'startLine', 'endLine',
  60. 'startTokenPos', 'endTokenPos',
  61. )
  62. ));
  63. $code = <<<'EOC'
  64. <?php
  65. /** Doc comment */
  66. function test($a) {
  67. // Line
  68. // Comments
  69. echo $a;
  70. }
  71. EOC;
  72. $code = $this->canonicalize($code);
  73. $parser = new Parser($lexer);
  74. $stmts = $parser->parse($code);
  75. /** @var \PhpParser\Node\Stmt\Function_ $fn */
  76. $fn = $stmts[0];
  77. $this->assertInstanceOf('PhpParser\Node\Stmt\Function_', $fn);
  78. $this->assertEquals(array(
  79. 'comments' => array(
  80. new Comment\Doc('/** Doc comment */', 2),
  81. ),
  82. 'startLine' => 3,
  83. 'endLine' => 7,
  84. 'startTokenPos' => 3,
  85. 'endTokenPos' => 21,
  86. ), $fn->getAttributes());
  87. $param = $fn->params[0];
  88. $this->assertInstanceOf('PhpParser\Node\Param', $param);
  89. $this->assertEquals(array(
  90. 'startLine' => 3,
  91. 'endLine' => 3,
  92. 'startTokenPos' => 7,
  93. 'endTokenPos' => 7,
  94. ), $param->getAttributes());
  95. /** @var \PhpParser\Node\Stmt\Echo_ $echo */
  96. $echo = $fn->stmts[0];
  97. $this->assertInstanceOf('PhpParser\Node\Stmt\Echo_', $echo);
  98. $this->assertEquals(array(
  99. 'comments' => array(
  100. new Comment("// Line\n", 4),
  101. new Comment("// Comments\n", 5),
  102. ),
  103. 'startLine' => 6,
  104. 'endLine' => 6,
  105. 'startTokenPos' => 16,
  106. 'endTokenPos' => 19,
  107. ), $echo->getAttributes());
  108. /** @var \PhpParser\Node\Expr\Variable $var */
  109. $var = $echo->exprs[0];
  110. $this->assertInstanceOf('PhpParser\Node\Expr\Variable', $var);
  111. $this->assertEquals(array(
  112. 'startLine' => 6,
  113. 'endLine' => 6,
  114. 'startTokenPos' => 18,
  115. 'endTokenPos' => 18,
  116. ), $var->getAttributes());
  117. }
  118. /**
  119. * @expectedException \RangeException
  120. * @expectedExceptionMessage The lexer returned an invalid token (id=999, value=foobar)
  121. */
  122. public function testInvalidToken() {
  123. $lexer = new InvalidTokenLexer;
  124. $parser = new Parser($lexer);
  125. $parser->parse('dummy');
  126. }
  127. }
  128. class InvalidTokenLexer extends Lexer {
  129. public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
  130. $value = 'foobar';
  131. return 999;
  132. }
  133. }