Removed modules/contrib/media module to allow update to the core media module
[yaffs-website] / vendor / nikic / php-parser / lib / PhpParser / NodeDumper.php
1 <?php declare(strict_types=1);
2
3 namespace PhpParser;
4
5 use PhpParser\Node\Expr\Include_;
6 use PhpParser\Node\Stmt\Class_;
7 use PhpParser\Node\Stmt\GroupUse;
8 use PhpParser\Node\Stmt\Use_;
9 use PhpParser\Node\Stmt\UseUse;
10
11 class NodeDumper
12 {
13     private $dumpComments;
14     private $dumpPositions;
15     private $code;
16
17     /**
18      * Constructs a NodeDumper.
19      *
20      * Supported options:
21      *  * bool dumpComments: Whether comments should be dumped.
22      *  * bool dumpPositions: Whether line/offset information should be dumped. To dump offset
23      *                        information, the code needs to be passed to dump().
24      *
25      * @param array $options Options (see description)
26      */
27     public function __construct(array $options = []) {
28         $this->dumpComments = !empty($options['dumpComments']);
29         $this->dumpPositions = !empty($options['dumpPositions']);
30     }
31
32     /**
33      * Dumps a node or array.
34      *
35      * @param array|Node  $node Node or array to dump
36      * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if
37      *                          the dumpPositions option is enabled and the dumping of node offsets
38      *                          is desired.
39      *
40      * @return string Dumped value
41      */
42     public function dump($node, string $code = null) : string {
43         $this->code = $code;
44         return $this->dumpRecursive($node);
45     }
46
47     protected function dumpRecursive($node) {
48         if ($node instanceof Node) {
49             $r = $node->getType();
50             if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) {
51                 $r .= $p;
52             }
53             $r .= '(';
54
55             foreach ($node->getSubNodeNames() as $key) {
56                 $r .= "\n    " . $key . ': ';
57
58                 $value = $node->$key;
59                 if (null === $value) {
60                     $r .= 'null';
61                 } elseif (false === $value) {
62                     $r .= 'false';
63                 } elseif (true === $value) {
64                     $r .= 'true';
65                 } elseif (is_scalar($value)) {
66                     if ('flags' === $key || 'newModifier' === $key) {
67                         $r .= $this->dumpFlags($value);
68                     } elseif ('type' === $key && $node instanceof Include_) {
69                         $r .= $this->dumpIncludeType($value);
70                     } elseif ('type' === $key
71                             && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) {
72                         $r .= $this->dumpUseType($value);
73                     } else {
74                         $r .= $value;
75                     }
76                 } else {
77                     $r .= str_replace("\n", "\n    ", $this->dumpRecursive($value));
78                 }
79             }
80
81             if ($this->dumpComments && $comments = $node->getComments()) {
82                 $r .= "\n    comments: " . str_replace("\n", "\n    ", $this->dumpRecursive($comments));
83             }
84         } elseif (is_array($node)) {
85             $r = 'array(';
86
87             foreach ($node as $key => $value) {
88                 $r .= "\n    " . $key . ': ';
89
90                 if (null === $value) {
91                     $r .= 'null';
92                 } elseif (false === $value) {
93                     $r .= 'false';
94                 } elseif (true === $value) {
95                     $r .= 'true';
96                 } elseif (is_scalar($value)) {
97                     $r .= $value;
98                 } else {
99                     $r .= str_replace("\n", "\n    ", $this->dumpRecursive($value));
100                 }
101             }
102         } elseif ($node instanceof Comment) {
103             return $node->getReformattedText();
104         } else {
105             throw new \InvalidArgumentException('Can only dump nodes and arrays.');
106         }
107
108         return $r . "\n)";
109     }
110
111     protected function dumpFlags($flags) {
112         $strs = [];
113         if ($flags & Class_::MODIFIER_PUBLIC) {
114             $strs[] = 'MODIFIER_PUBLIC';
115         }
116         if ($flags & Class_::MODIFIER_PROTECTED) {
117             $strs[] = 'MODIFIER_PROTECTED';
118         }
119         if ($flags & Class_::MODIFIER_PRIVATE) {
120             $strs[] = 'MODIFIER_PRIVATE';
121         }
122         if ($flags & Class_::MODIFIER_ABSTRACT) {
123             $strs[] = 'MODIFIER_ABSTRACT';
124         }
125         if ($flags & Class_::MODIFIER_STATIC) {
126             $strs[] = 'MODIFIER_STATIC';
127         }
128         if ($flags & Class_::MODIFIER_FINAL) {
129             $strs[] = 'MODIFIER_FINAL';
130         }
131
132         if ($strs) {
133             return implode(' | ', $strs) . ' (' . $flags . ')';
134         } else {
135             return $flags;
136         }
137     }
138
139     protected function dumpIncludeType($type) {
140         $map = [
141             Include_::TYPE_INCLUDE      => 'TYPE_INCLUDE',
142             Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE',
143             Include_::TYPE_REQUIRE      => 'TYPE_REQUIRE',
144             Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE',
145         ];
146
147         if (!isset($map[$type])) {
148             return $type;
149         }
150         return $map[$type] . ' (' . $type . ')';
151     }
152
153     protected function dumpUseType($type) {
154         $map = [
155             Use_::TYPE_UNKNOWN  => 'TYPE_UNKNOWN',
156             Use_::TYPE_NORMAL   => 'TYPE_NORMAL',
157             Use_::TYPE_FUNCTION => 'TYPE_FUNCTION',
158             Use_::TYPE_CONSTANT => 'TYPE_CONSTANT',
159         ];
160
161         if (!isset($map[$type])) {
162             return $type;
163         }
164         return $map[$type] . ' (' . $type . ')';
165     }
166
167     /**
168      * Dump node position, if possible.
169      *
170      * @param Node $node Node for which to dump position
171      *
172      * @return string|null Dump of position, or null if position information not available
173      */
174     protected function dumpPosition(Node $node) {
175         if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) {
176             return null;
177         }
178
179         $start = $node->getStartLine();
180         $end = $node->getEndLine();
181         if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos')
182             && null !== $this->code
183         ) {
184             $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos());
185             $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos());
186         }
187         return "[$start - $end]";
188     }
189
190     // Copied from Error class
191     private function toColumn($code, $pos) {
192         if ($pos > strlen($code)) {
193             throw new \RuntimeException('Invalid position information');
194         }
195
196         $lineStartPos = strrpos($code, "\n", $pos - strlen($code));
197         if (false === $lineStartPos) {
198             $lineStartPos = -1;
199         }
200
201         return $pos - $lineStartPos;
202     }
203 }