annotate vendor/psy/psysh/src/Psy/Sudo/SudoVisitor.php @ 7:848c88cfe644

More layout
author Chris Cannam
date Fri, 05 Jan 2018 13:59:44 +0000
parents 4c8ae668cc8c
children 7a779792577d
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of Psy Shell.
Chris@0 5 *
Chris@0 6 * (c) 2012-2017 Justin Hileman
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Psy\Sudo;
Chris@0 13
Chris@0 14 use PhpParser\Node;
Chris@0 15 use PhpParser\Node\Arg;
Chris@0 16 use PhpParser\Node\Expr\Assign;
Chris@0 17 use PhpParser\Node\Expr\ClassConstFetch;
Chris@0 18 use PhpParser\Node\Expr\MethodCall;
Chris@0 19 use PhpParser\Node\Expr\PropertyFetch;
Chris@0 20 use PhpParser\Node\Expr\StaticCall;
Chris@0 21 use PhpParser\Node\Expr\StaticPropertyFetch;
Chris@0 22 use PhpParser\Node\Name\FullyQualified as FullyQualifiedName;
Chris@0 23 use PhpParser\Node\Scalar\String_;
Chris@0 24 use PhpParser\NodeVisitorAbstract;
Chris@0 25
Chris@0 26 /**
Chris@0 27 * A PHP Parser node visitor which rewrites property and method access to use
Chris@0 28 * the Psy\Sudo visibility bypass methods.
Chris@0 29 *
Chris@0 30 * @todo handle assigning by reference
Chris@0 31 */
Chris@0 32 class SudoVisitor extends NodeVisitorAbstract
Chris@0 33 {
Chris@0 34 const SUDO_CLASS = 'Psy\Sudo';
Chris@0 35
Chris@0 36 const PROPERTY_FETCH = 'fetchProperty';
Chris@0 37 const PROPERTY_ASSIGN = 'assignProperty';
Chris@0 38 const METHOD_CALL = 'callMethod';
Chris@0 39 const STATIC_PROPERTY_FETCH = 'fetchStaticProperty';
Chris@0 40 const STATIC_PROPERTY_ASSIGN = 'assignStaticProperty';
Chris@0 41 const STATIC_CALL = 'callStatic';
Chris@0 42 const CLASS_CONST_FETCH = 'fetchClassConst';
Chris@0 43
Chris@0 44 /**
Chris@0 45 * {@inheritdoc}
Chris@0 46 */
Chris@0 47 public function enterNode(Node $node)
Chris@0 48 {
Chris@0 49 if ($node instanceof PropertyFetch) {
Chris@0 50 $args = array(
Chris@0 51 $node->var,
Chris@0 52 is_string($node->name) ? new String_($node->name) : $node->name,
Chris@0 53 );
Chris@0 54
Chris@0 55 return $this->prepareCall(self::PROPERTY_FETCH, $args);
Chris@0 56 } elseif ($node instanceof Assign && $node->var instanceof PropertyFetch) {
Chris@0 57 $target = $node->var;
Chris@0 58 $args = array(
Chris@0 59 $target->var,
Chris@0 60 is_string($target->name) ? new String_($target->name) : $target->name,
Chris@0 61 $node->expr,
Chris@0 62 );
Chris@0 63
Chris@0 64 return $this->prepareCall(self::PROPERTY_ASSIGN, $args);
Chris@0 65 } elseif ($node instanceof MethodCall) {
Chris@0 66 $args = $node->args;
Chris@0 67 array_unshift($args, new Arg(is_string($node->name) ? new String_($node->name) : $node->name));
Chris@0 68 array_unshift($args, new Arg($node->var));
Chris@0 69
Chris@0 70 // not using prepareCall because the $node->args we started with are already Arg instances
Chris@0 71 return new StaticCall(new FullyQualifiedName(self::SUDO_CLASS), self::METHOD_CALL, $args);
Chris@0 72 } elseif ($node instanceof StaticPropertyFetch) {
Chris@0 73 $class = $node->class instanceof Name ? (string) $node->class : $node->class;
Chris@0 74 $args = array(
Chris@0 75 is_string($class) ? new String_($class) : $class,
Chris@0 76 is_string($node->name) ? new String_($node->name) : $node->name,
Chris@0 77 );
Chris@0 78
Chris@0 79 return $this->prepareCall(self::STATIC_PROPERTY_FETCH, $args);
Chris@0 80 } elseif ($node instanceof Assign && $node->var instanceof StaticPropertyFetch) {
Chris@0 81 $target = $node->var;
Chris@0 82 $class = $target->class instanceof Name ? (string) $target->class : $target->class;
Chris@0 83 $args = array(
Chris@0 84 is_string($class) ? new String_($class) : $class,
Chris@0 85 is_string($target->name) ? new String_($target->name) : $target->name,
Chris@0 86 $node->expr,
Chris@0 87 );
Chris@0 88
Chris@0 89 return $this->prepareCall(self::STATIC_PROPERTY_ASSIGN, $args);
Chris@0 90 } elseif ($node instanceof StaticCall) {
Chris@0 91 $args = $node->args;
Chris@0 92 $class = $node->class instanceof Name ? (string) $node->class : $node->class;
Chris@0 93 array_unshift($args, new Arg(is_string($node->name) ? new String_($node->name) : $node->name));
Chris@0 94 array_unshift($args, new Arg(is_string($class) ? new String_($class) : $class));
Chris@0 95
Chris@0 96 // not using prepareCall because the $node->args we started with are already Arg instances
Chris@0 97 return new StaticCall(new FullyQualifiedName(self::SUDO_CLASS), self::STATIC_CALL, $args);
Chris@0 98 } elseif ($node instanceof ClassConstFetch) {
Chris@0 99 $class = $node->class instanceof Name ? (string) $node->class : $node->class;
Chris@0 100 $args = array(
Chris@0 101 is_string($class) ? new String_($class) : $class,
Chris@0 102 is_string($node->name) ? new String_($node->name) : $node->name,
Chris@0 103 );
Chris@0 104
Chris@0 105 return $this->prepareCall(self::CLASS_CONST_FETCH, $args);
Chris@0 106 }
Chris@0 107 }
Chris@0 108
Chris@0 109 private function prepareCall($method, $args)
Chris@0 110 {
Chris@0 111 return new StaticCall(new FullyQualifiedName(self::SUDO_CLASS), $method, array_map(function ($arg) {
Chris@0 112 return new Arg($arg);
Chris@0 113 }, $args));
Chris@0 114 }
Chris@0 115 }