annotate vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php @ 5:12f9dff5fda9 tip

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:34:47 +0100
parents c75dbcec494b
children
rev   line source
Chris@0 1 <?php declare(strict_types=1);
Chris@0 2
Chris@0 3 namespace PhpParser;
Chris@0 4
Chris@0 5 class JsonDecoder
Chris@0 6 {
Chris@0 7 /** @var \ReflectionClass[] Node type to reflection class map */
Chris@0 8 private $reflectionClassCache;
Chris@0 9
Chris@0 10 public function decode(string $json) {
Chris@0 11 $value = json_decode($json, true);
Chris@0 12 if (json_last_error()) {
Chris@0 13 throw new \RuntimeException('JSON decoding error: ' . json_last_error_msg());
Chris@0 14 }
Chris@0 15
Chris@0 16 return $this->decodeRecursive($value);
Chris@0 17 }
Chris@0 18
Chris@0 19 private function decodeRecursive($value) {
Chris@0 20 if (\is_array($value)) {
Chris@0 21 if (isset($value['nodeType'])) {
Chris@0 22 if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') {
Chris@0 23 return $this->decodeComment($value);
Chris@0 24 }
Chris@0 25 return $this->decodeNode($value);
Chris@0 26 }
Chris@0 27 return $this->decodeArray($value);
Chris@0 28 }
Chris@0 29 return $value;
Chris@0 30 }
Chris@0 31
Chris@0 32 private function decodeArray(array $array) : array {
Chris@0 33 $decodedArray = [];
Chris@0 34 foreach ($array as $key => $value) {
Chris@0 35 $decodedArray[$key] = $this->decodeRecursive($value);
Chris@0 36 }
Chris@0 37 return $decodedArray;
Chris@0 38 }
Chris@0 39
Chris@0 40 private function decodeNode(array $value) : Node {
Chris@0 41 $nodeType = $value['nodeType'];
Chris@0 42 if (!\is_string($nodeType)) {
Chris@0 43 throw new \RuntimeException('Node type must be a string');
Chris@0 44 }
Chris@0 45
Chris@0 46 $reflectionClass = $this->reflectionClassFromNodeType($nodeType);
Chris@0 47 /** @var Node $node */
Chris@0 48 $node = $reflectionClass->newInstanceWithoutConstructor();
Chris@0 49
Chris@0 50 if (isset($value['attributes'])) {
Chris@0 51 if (!\is_array($value['attributes'])) {
Chris@0 52 throw new \RuntimeException('Attributes must be an array');
Chris@0 53 }
Chris@0 54
Chris@0 55 $node->setAttributes($this->decodeArray($value['attributes']));
Chris@0 56 }
Chris@0 57
Chris@0 58 foreach ($value as $name => $subNode) {
Chris@0 59 if ($name === 'nodeType' || $name === 'attributes') {
Chris@0 60 continue;
Chris@0 61 }
Chris@0 62
Chris@0 63 $node->$name = $this->decodeRecursive($subNode);
Chris@0 64 }
Chris@0 65
Chris@0 66 return $node;
Chris@0 67 }
Chris@0 68
Chris@0 69 private function decodeComment(array $value) : Comment {
Chris@0 70 $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
Chris@0 71 if (!isset($value['text'])) {
Chris@0 72 throw new \RuntimeException('Comment must have text');
Chris@0 73 }
Chris@0 74
Chris@0 75 return new $className(
Chris@0 76 $value['text'], $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1
Chris@0 77 );
Chris@0 78 }
Chris@0 79
Chris@0 80 private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass {
Chris@0 81 if (!isset($this->reflectionClassCache[$nodeType])) {
Chris@0 82 $className = $this->classNameFromNodeType($nodeType);
Chris@0 83 $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className);
Chris@0 84 }
Chris@0 85 return $this->reflectionClassCache[$nodeType];
Chris@0 86 }
Chris@0 87
Chris@0 88 private function classNameFromNodeType(string $nodeType) : string {
Chris@0 89 $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\');
Chris@0 90 if (class_exists($className)) {
Chris@0 91 return $className;
Chris@0 92 }
Chris@0 93
Chris@0 94 $className .= '_';
Chris@0 95 if (class_exists($className)) {
Chris@0 96 return $className;
Chris@0 97 }
Chris@0 98
Chris@0 99 throw new \RuntimeException("Unknown node type \"$nodeType\"");
Chris@0 100 }
Chris@0 101 }