Removed modules/contrib/media module to allow update to the core media module
[yaffs-website] / vendor / nikic / php-parser / test / PhpParser / ParserTest.php
1 <?php declare(strict_types=1);
2
3 namespace PhpParser;
4
5 use PhpParser\Node\Expr;
6 use PhpParser\Node\Scalar;
7 use PhpParser\Node\Scalar\String_;
8 use PhpParser\Node\Stmt;
9 use PHPUnit\Framework\TestCase;
10
11 abstract class ParserTest extends TestCase
12 {
13     /** @returns Parser */
14     abstract protected function getParser(Lexer $lexer);
15
16     /**
17      * @expectedException \PhpParser\Error
18      * @expectedExceptionMessage Syntax error, unexpected EOF on line 1
19      */
20     public function testParserThrowsSyntaxError() {
21         $parser = $this->getParser(new Lexer());
22         $parser->parse('<?php foo');
23     }
24
25     /**
26      * @expectedException \PhpParser\Error
27      * @expectedExceptionMessage Cannot use foo as self because 'self' is a special class name on line 1
28      */
29     public function testParserThrowsSpecialError() {
30         $parser = $this->getParser(new Lexer());
31         $parser->parse('<?php use foo as self;');
32     }
33
34     /**
35      * @expectedException \PhpParser\Error
36      * @expectedExceptionMessage Unterminated comment on line 1
37      */
38     public function testParserThrowsLexerError() {
39         $parser = $this->getParser(new Lexer());
40         $parser->parse('<?php /*');
41     }
42
43     public function testAttributeAssignment() {
44         $lexer = new Lexer([
45             'usedAttributes' => [
46                 'comments', 'startLine', 'endLine',
47                 'startTokenPos', 'endTokenPos',
48             ]
49         ]);
50
51         $code = <<<'EOC'
52 <?php
53 /** Doc comment */
54 function test($a) {
55     // Line
56     // Comments
57     echo $a;
58 }
59 EOC;
60         $code = canonicalize($code);
61
62         $parser = $this->getParser($lexer);
63         $stmts = $parser->parse($code);
64
65         /** @var Stmt\Function_ $fn */
66         $fn = $stmts[0];
67         $this->assertInstanceOf(Stmt\Function_::class, $fn);
68         $this->assertEquals([
69             'comments' => [
70                 new Comment\Doc('/** Doc comment */', 2, 6, 1),
71             ],
72             'startLine' => 3,
73             'endLine' => 7,
74             'startTokenPos' => 3,
75             'endTokenPos' => 21,
76         ], $fn->getAttributes());
77
78         $param = $fn->params[0];
79         $this->assertInstanceOf(Node\Param::class, $param);
80         $this->assertEquals([
81             'startLine' => 3,
82             'endLine' => 3,
83             'startTokenPos' => 7,
84             'endTokenPos' => 7,
85         ], $param->getAttributes());
86
87         /** @var Stmt\Echo_ $echo */
88         $echo = $fn->stmts[0];
89         $this->assertInstanceOf(Stmt\Echo_::class, $echo);
90         $this->assertEquals([
91             'comments' => [
92                 new Comment("// Line\n", 4, 49, 12),
93                 new Comment("// Comments\n", 5, 61, 14),
94             ],
95             'startLine' => 6,
96             'endLine' => 6,
97             'startTokenPos' => 16,
98             'endTokenPos' => 19,
99         ], $echo->getAttributes());
100
101         /** @var \PhpParser\Node\Expr\Variable $var */
102         $var = $echo->exprs[0];
103         $this->assertInstanceOf(Expr\Variable::class, $var);
104         $this->assertEquals([
105             'startLine' => 6,
106             'endLine' => 6,
107             'startTokenPos' => 18,
108             'endTokenPos' => 18,
109         ], $var->getAttributes());
110     }
111
112     /**
113      * @expectedException \RangeException
114      * @expectedExceptionMessage The lexer returned an invalid token (id=999, value=foobar)
115      */
116     public function testInvalidToken() {
117         $lexer = new InvalidTokenLexer;
118         $parser = $this->getParser($lexer);
119         $parser->parse('dummy');
120     }
121
122     /**
123      * @dataProvider provideTestExtraAttributes
124      */
125     public function testExtraAttributes($code, $expectedAttributes) {
126         $parser = $this->getParser(new Lexer);
127         $stmts = $parser->parse("<?php $code;");
128         $node = $stmts[0] instanceof Stmt\Expression ? $stmts[0]->expr : $stmts[0];
129         $attributes = $node->getAttributes();
130         foreach ($expectedAttributes as $name => $value) {
131             $this->assertSame($value, $attributes[$name]);
132         }
133     }
134
135     public function provideTestExtraAttributes() {
136         return [
137             ['0', ['kind' => Scalar\LNumber::KIND_DEC]],
138             ['9', ['kind' => Scalar\LNumber::KIND_DEC]],
139             ['07', ['kind' => Scalar\LNumber::KIND_OCT]],
140             ['0xf', ['kind' => Scalar\LNumber::KIND_HEX]],
141             ['0XF', ['kind' => Scalar\LNumber::KIND_HEX]],
142             ['0b1', ['kind' => Scalar\LNumber::KIND_BIN]],
143             ['0B1', ['kind' => Scalar\LNumber::KIND_BIN]],
144             ['[]', ['kind' => Expr\Array_::KIND_SHORT]],
145             ['array()', ['kind' => Expr\Array_::KIND_LONG]],
146             ["'foo'", ['kind' => String_::KIND_SINGLE_QUOTED]],
147             ["b'foo'", ['kind' => String_::KIND_SINGLE_QUOTED]],
148             ["B'foo'", ['kind' => String_::KIND_SINGLE_QUOTED]],
149             ['"foo"', ['kind' => String_::KIND_DOUBLE_QUOTED]],
150             ['b"foo"', ['kind' => String_::KIND_DOUBLE_QUOTED]],
151             ['B"foo"', ['kind' => String_::KIND_DOUBLE_QUOTED]],
152             ['"foo$bar"', ['kind' => String_::KIND_DOUBLE_QUOTED]],
153             ['b"foo$bar"', ['kind' => String_::KIND_DOUBLE_QUOTED]],
154             ['B"foo$bar"', ['kind' => String_::KIND_DOUBLE_QUOTED]],
155             ["<<<'STR'\nSTR\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']],
156             ["<<<STR\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']],
157             ["<<<\"STR\"\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']],
158             ["b<<<'STR'\nSTR\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']],
159             ["B<<<'STR'\nSTR\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']],
160             ["<<< \t 'STR'\nSTR\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']],
161             ["<<<'\xff'\n\xff\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => "\xff"]],
162             ["<<<\"STR\"\n\$a\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']],
163             ["b<<<\"STR\"\n\$a\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']],
164             ["B<<<\"STR\"\n\$a\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']],
165             ["<<< \t \"STR\"\n\$a\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']],
166             ["die", ['kind' => Expr\Exit_::KIND_DIE]],
167             ["die('done')", ['kind' => Expr\Exit_::KIND_DIE]],
168             ["exit", ['kind' => Expr\Exit_::KIND_EXIT]],
169             ["exit(1)", ['kind' => Expr\Exit_::KIND_EXIT]],
170             ["?>Foo", ['hasLeadingNewline' => false]],
171             ["?>\nFoo", ['hasLeadingNewline' => true]],
172             ["namespace Foo;", ['kind' => Stmt\Namespace_::KIND_SEMICOLON]],
173             ["namespace Foo {}", ['kind' => Stmt\Namespace_::KIND_BRACED]],
174             ["namespace {}", ['kind' => Stmt\Namespace_::KIND_BRACED]],
175         ];
176     }
177 }
178
179 class InvalidTokenLexer extends Lexer
180 {
181     public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int {
182         $value = 'foobar';
183         return 999;
184     }
185 }