public static function isEqual(\PhpParser\Node $nodeA, \PhpParser\Node $nodeB) { if ($nodeA->getType() !== $nodeB->getType()) { return false; } $subNodesA = $nodeA->getSubNodeNames(); $subNodesB = $nodeB->getSubNodeNames(); if ($subNodesA !== $subNodesB) { return false; } foreach ($subNodesA as $key) { $valueA = $nodeA->{$key}; $valueB = $nodeB->{$key}; $result = true; if ($valueA instanceof \PhpParser\Node && $valueB instanceof \PhpParser\Node) { $result = self::isEqual($valueA, $valueB); } else { $result = $valueA === $valueB; } if (!$result) { return false; } } return true; }
function node_props(Node $node) { $props = []; foreach ($node->getSubNodeNames() as $prop) { $props[$prop] = $node->{$prop}; } return $props; }
/** * Checks and goes through each list of sub nodes a given Node has, * and triggers the callback for each of those sub nodes (Node[]) * * @param Node $node * @param callable $callback */ protected function foreachSubNodes(Node $node, callable $callback) { foreach ($node->getSubNodeNames() as $subNodeName) { $subNodeList = $node->{$subNodeName}; $subNodeList = $this->harmonizeNodes($subNodeList); if (!is_array($subNodeList)) { continue; } // Node[] $subNodeList $callback($subNodeList); } }
/** * @param string $file * @param \PhpParser\Node $node * @param string $prefix */ private function processNode($file, \PhpParser\Node $node, $prefix = '') { if ($node instanceof \PhpParser\Node\Stmt\Const_ && $node->consts) { $this->require[$file] = true; } else { if ($node instanceof \PhpParser\Node\Stmt\Function_) { $this->require[$file] = true; } else { if ($node instanceof \PhpParser\Node\Expr\FuncCall) { // Try to catch constants defined with define() if ($node->name instanceof \PhpParser\Node\Name && $node->name->parts === ['define']) { $this->require[$file] = true; } } else { if ($node instanceof \PhpParser\Node\Stmt\ClassLike) { $this->map[$prefix . $node->name] = $file; } } } } if ($node instanceof \PhpParser\Node\Stmt\Namespace_) { /** @var \PhpParser\Node\Name|null $name */ $name = $node->name; if ($name && $name->parts) { $prefix2 = join('\\', $name->parts) . '\\'; } else { $prefix2 = ''; } foreach ($node->stmts as $node2) { $this->processNode($file, $node2, $prefix . $prefix2); } } else { // Cheating a little. I really just want to traverse the tree // recursively without needing to write code specifically for // each kind of node. This seems to be what \PhpParser\NodeTraverser // does anyway. foreach ($node->getSubNodeNames() as $name) { $var = $node->{$name}; if ($var instanceof \PhpParser\Node) { $this->processNode($file, $var, $prefix); } else { if (is_array($var)) { foreach ($var as $var2) { if ($var2 instanceof \PhpParser\Node) { $this->processNode($file, $var2, $prefix); } } } } } } }
/** * For the code above * Я атеист, но когда я начинал это писать, только Бог и я понимали, что я делаю * Сейчас остался только Бог * * @param Node $node * @return \Generator * * @todo After move to PHP 7.0+ use yield from */ protected function traverseNode(Node $node) { foreach ($node->getSubNodeNames() as $name) { $subNode =& $node->{$name}; if (is_array($subNode)) { foreach ($this->traverseArray($subNode) as $rNode) { (yield $rNode); } } elseif ($subNode instanceof Node) { (yield $subNode); foreach ($this->traverseNode($subNode) as $rNode) { (yield $rNode); } } } }
/** * @param \PhpParser\Node[]|\PhpParser\Node $node * @return string[] */ private function getUsedVariables($node) : array { $variableNames = []; if ($node instanceof Node) { if ($node instanceof Node\Expr\Variable && is_string($node->name) && $node->name !== 'this') { return [$node->name]; } foreach ($node->getSubNodeNames() as $subNodeName) { $subNode = $node->{$subNodeName}; $variableNames = array_merge($variableNames, $this->getUsedVariables($subNode)); } } elseif (is_array($node)) { foreach ($node as $subNode) { $variableNames = array_merge($variableNames, $this->getUsedVariables($subNode)); } } return $variableNames; }
public static function getSubNodes(Node $node) { $subnodes = []; foreach ($node->getSubNodeNames() as $name) { $subnodes[] = $node->{$name}; } return $subnodes; }
/** * @param Node $node * @param string $prefix */ private function processNode(Node $node, $prefix) { if ($node instanceof Node\Stmt\Const_ && $node->consts) { foreach ($node->consts as $const) { $this->constants[] = $prefix . $const->name; } } else { if ($node instanceof Node\Stmt\Function_) { $this->functions[] = $prefix . $node->name; } else { if ($node instanceof Node\Expr\FuncCall) { // Try to catch constants defined with define() if ($node->name instanceof Node\Name && $node->name->parts === array('define') && $node->args) { $arg = $node->args[0]->value; if ($arg instanceof Node\Scalar\String_) { // Constants defined with define() don't use the current namespace $this->constants[] = $arg->value; } } } else { if ($node instanceof Node\Stmt\ClassLike) { $this->classes[] = $prefix . $node->name; } } } } if ($node instanceof Node\Stmt\Namespace_) { /** @var Node\Name|null $name */ $name = $node->name; if ($name && $name->parts) { $prefix = join('\\', $name->parts) . '\\'; } else { $prefix = ''; } } foreach ($node->getSubNodeNames() as $name) { $var = $node->{$name}; if ($var instanceof Node) { $this->processNode($var, $prefix); } else { if (\is_array($var)) { foreach ($var as $var2) { if ($var2 instanceof Node) { $this->processNode($var2, $prefix); } } } } } }
/** * 给定一个节点,返回该节点对应string name * @param Node $node * @return base node name string */ public static function getNodeStringName($node) { if (!$node instanceof Node) { return null; } $type = $node->getType(); switch ($type) { case "Expr_Variable": case "Scalar_String": case "Scalar_LNumber": case "Scalar_DNumber": if ($node->name) { return $node->name; } $names = $node->getSubNodeNames(); foreach ($names as $name) { return $node->{$name}; } break; //负数 //负数 case "Expr_UnaryMinus": $names = $node->getSubNodeNames(); //print_r($node->getSubNodeNames()); foreach ($names as $name) { return "-" . NodeUtils::getNodeStringName($node->{$name}); } break; //arg name //arg name case "Arg": return NodeUtils::getNodeStringName($node->value); break; //param name //param name case "Param": return $node->name; break; case "Name": $names = $node->getSubNodeNames(); //print_r($node->getSubNodeNames()); foreach ($names as $name) { foreach ($node->{$name} as $parts) { return $parts; } } break; //$a[],$[a]$a[]][] //$a[],$[a]$a[]][] case "Expr_ArrayDimFetch": //处理GLOBALS if ($node->var->name == "GLOBALS") { return $node->dim->value; } //不处理_GET _POST等 $userInput = Sources::getUserInput(); if (in_array($node->var->name, $userInput)) { return $node->var->name; } $names = $node->getSubNodeNames(); $temp = ""; foreach ($names as $name) { if ($name == "dim") { if ($node->{$name}) { $temp .= "[" . NodeUtils::getNodeStringName($node->{$name}) . "]"; } else { $temp .= "[]"; } } else { $temp .= NodeUtils::getNodeStringName($node->{$name}); } } return $temp; break; //数组dim //数组dim case "Expr_ConstFetch": $names = $node->getSubNodeNames(); //print_r($names); foreach ($names as $name) { return NodeUtils::getNodeStringName($node->{$name}); } break; //$this->property对象属性 //$this->property对象属性 case "Expr_PropertyFetch": $names = $node->getSubNodeNames(); $ret = ''; foreach ($names as $name) { $ret .= NodeUtils::getNodeStringName($node->{$name}) . ":"; } $ret .= $node->name; return $ret; break; default: break; } return ""; }
protected function resolveValue(NodeInterface $nodeValue) { if ($nodeValue instanceof MagicConst) { return $nodeValue->getName(); } $subModules = $nodeValue->getSubNodeNames(); if (!is_array($subModules) || empty($subModules)) { return; } $subModule = reset($subModules); $value = $nodeValue->{$subModule}; if (is_object($value) && method_exists($value, 'toString')) { $value = $value->toString(); } elseif (is_object($value) && property_exists($value, 'value')) { $value = $value->value; } if (is_array($value)) { $newValues = []; foreach ($value as $key => $node) { $newValues[$this->resolveValue($node->key)] = $this->resolveValue($node->value); } return $newValues; } if ($value === 'true') { return true; } elseif ($value === 'false') { return false; } elseif ($value === 'null') { return; } return $value; }