summaryrefslogtreecommitdiff
path: root/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php')
-rw-r--r--vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php103
1 files changed, 103 insertions, 0 deletions
diff --git a/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php b/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php
new file mode 100644
index 000000000..47d2003d4
--- /dev/null
+++ b/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php
@@ -0,0 +1,103 @@
+<?php declare(strict_types=1);
+
+namespace PhpParser;
+
+class JsonDecoder
+{
+ /** @var \ReflectionClass[] Node type to reflection class map */
+ private $reflectionClassCache;
+
+ public function decode(string $json) {
+ $value = json_decode($json, true);
+ if (json_last_error()) {
+ throw new \RuntimeException('JSON decoding error: ' . json_last_error_msg());
+ }
+
+ return $this->decodeRecursive($value);
+ }
+
+ private function decodeRecursive($value) {
+ if (\is_array($value)) {
+ if (isset($value['nodeType'])) {
+ if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') {
+ return $this->decodeComment($value);
+ }
+ return $this->decodeNode($value);
+ }
+ return $this->decodeArray($value);
+ }
+ return $value;
+ }
+
+ private function decodeArray(array $array) : array {
+ $decodedArray = [];
+ foreach ($array as $key => $value) {
+ $decodedArray[$key] = $this->decodeRecursive($value);
+ }
+ return $decodedArray;
+ }
+
+ private function decodeNode(array $value) : Node {
+ $nodeType = $value['nodeType'];
+ if (!\is_string($nodeType)) {
+ throw new \RuntimeException('Node type must be a string');
+ }
+
+ $reflectionClass = $this->reflectionClassFromNodeType($nodeType);
+ /** @var Node $node */
+ $node = $reflectionClass->newInstanceWithoutConstructor();
+
+ if (isset($value['attributes'])) {
+ if (!\is_array($value['attributes'])) {
+ throw new \RuntimeException('Attributes must be an array');
+ }
+
+ $node->setAttributes($this->decodeArray($value['attributes']));
+ }
+
+ foreach ($value as $name => $subNode) {
+ if ($name === 'nodeType' || $name === 'attributes') {
+ continue;
+ }
+
+ $node->$name = $this->decodeRecursive($subNode);
+ }
+
+ return $node;
+ }
+
+ private function decodeComment(array $value) : Comment {
+ $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
+ if (!isset($value['text'])) {
+ throw new \RuntimeException('Comment must have text');
+ }
+
+ return new $className(
+ $value['text'],
+ $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1,
+ $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1
+ );
+ }
+
+ private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass {
+ if (!isset($this->reflectionClassCache[$nodeType])) {
+ $className = $this->classNameFromNodeType($nodeType);
+ $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className);
+ }
+ return $this->reflectionClassCache[$nodeType];
+ }
+
+ private function classNameFromNodeType(string $nodeType) : string {
+ $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\');
+ if (class_exists($className)) {
+ return $className;
+ }
+
+ $className .= '_';
+ if (class_exists($className)) {
+ return $className;
+ }
+
+ throw new \RuntimeException("Unknown node type \"$nodeType\"");
+ }
+}