Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / vendor / nikic / php-parser / test / PhpParser / CodeParsingTest.php
1 <?php declare(strict_types=1);
2
3 namespace PhpParser;
4
5 use PhpParser\Node\Expr;
6 use PhpParser\Node\Stmt;
7
8 require_once __DIR__ . '/CodeTestAbstract.php';
9
10 class CodeParsingTest extends CodeTestAbstract
11 {
12     /**
13      * @dataProvider provideTestParse
14      */
15     public function testParse($name, $code, $expected, $modeLine) {
16         if (null !== $modeLine) {
17             $modes = array_fill_keys(explode(',', $modeLine), true);
18         } else {
19             $modes = [];
20         }
21
22         list($parser5, $parser7) = $this->createParsers($modes);
23         list($stmts5, $output5) = $this->getParseOutput($parser5, $code, $modes);
24         list($stmts7, $output7) = $this->getParseOutput($parser7, $code, $modes);
25
26         if (isset($modes['php5'])) {
27             $this->assertSame($expected, $output5, $name);
28             $this->assertNotSame($expected, $output7, $name);
29         } elseif (isset($modes['php7'])) {
30             $this->assertNotSame($expected, $output5, $name);
31             $this->assertSame($expected, $output7, $name);
32         } else {
33             $this->assertSame($expected, $output5, $name);
34             $this->assertSame($expected, $output7, $name);
35         }
36
37         $this->checkAttributes($stmts5);
38         $this->checkAttributes($stmts7);
39     }
40
41     public function createParsers(array $modes) {
42         $lexer = new Lexer\Emulative(['usedAttributes' => [
43             'startLine', 'endLine',
44             'startFilePos', 'endFilePos',
45             'startTokenPos', 'endTokenPos',
46             'comments'
47         ]]);
48
49         return [
50             new Parser\Php5($lexer),
51             new Parser\Php7($lexer),
52         ];
53     }
54
55     // Must be public for updateTests.php
56     public function getParseOutput(Parser $parser, $code, array $modes) {
57         $dumpPositions = isset($modes['positions']);
58
59         $errors = new ErrorHandler\Collecting;
60         $stmts = $parser->parse($code, $errors);
61
62         $output = '';
63         foreach ($errors->getErrors() as $error) {
64             $output .= $this->formatErrorMessage($error, $code) . "\n";
65         }
66
67         if (null !== $stmts) {
68             $dumper = new NodeDumper(['dumpComments' => true, 'dumpPositions' => $dumpPositions]);
69             $output .= $dumper->dump($stmts, $code);
70         }
71
72         return [$stmts, canonicalize($output)];
73     }
74
75     public function provideTestParse() {
76         return $this->getTests(__DIR__ . '/../code/parser', 'test');
77     }
78
79     private function formatErrorMessage(Error $e, $code) {
80         if ($e->hasColumnInfo()) {
81             return $e->getMessageWithColumnInfo($code);
82         } else {
83             return $e->getMessage();
84         }
85     }
86
87     private function checkAttributes($stmts) {
88         if ($stmts === null) {
89             return;
90         }
91
92         $traverser = new NodeTraverser();
93         $traverser->addVisitor(new class extends NodeVisitorAbstract {
94             public function enterNode(Node $node) {
95                 $startLine = $node->getStartLine();
96                 $endLine = $node->getEndLine();
97                 $startFilePos = $node->getStartFilePos();
98                 $endFilePos = $node->getEndFilePos();
99                 $startTokenPos = $node->getStartTokenPos();
100                 $endTokenPos = $node->getEndTokenPos();
101                 if ($startLine < 0 || $endLine < 0 ||
102                     $startFilePos < 0 || $endFilePos < 0 ||
103                     $startTokenPos < 0 || $endTokenPos < 0
104                 ) {
105                     throw new \Exception('Missing location information on ' . $node->getType());
106                 }
107
108                 if ($endLine < $startLine ||
109                     $endFilePos < $startFilePos ||
110                     $endTokenPos < $startTokenPos
111                 ) {
112                     // Nops and error can have inverted order, if they are empty
113                     if (!$node instanceof Stmt\Nop && !$node instanceof Expr\Error) {
114                         throw new \Exception('End < start on ' . $node->getType());
115                     }
116                 }
117             }
118         });
119         $traverser->traverse($stmts);
120     }
121 }