annotate vendor/psy/psysh/src/CodeCleaner/CalledClassPass.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@13 1 <?php
Chris@13 2
Chris@13 3 /*
Chris@13 4 * This file is part of Psy Shell.
Chris@13 5 *
Chris@13 6 * (c) 2012-2018 Justin Hileman
Chris@13 7 *
Chris@13 8 * For the full copyright and license information, please view the LICENSE
Chris@13 9 * file that was distributed with this source code.
Chris@13 10 */
Chris@13 11
Chris@13 12 namespace Psy\CodeCleaner;
Chris@13 13
Chris@13 14 use PhpParser\Node;
Chris@13 15 use PhpParser\Node\Expr\ConstFetch;
Chris@13 16 use PhpParser\Node\Expr\FuncCall;
Chris@13 17 use PhpParser\Node\Name;
Chris@13 18 use PhpParser\Node\Stmt\Class_;
Chris@13 19 use PhpParser\Node\Stmt\Trait_;
Chris@13 20 use Psy\Exception\ErrorException;
Chris@13 21
Chris@13 22 /**
Chris@13 23 * The called class pass throws warnings for get_class() and get_called_class()
Chris@13 24 * outside a class context.
Chris@13 25 */
Chris@13 26 class CalledClassPass extends CodeCleanerPass
Chris@13 27 {
Chris@13 28 private $inClass;
Chris@13 29
Chris@13 30 /**
Chris@13 31 * @param array $nodes
Chris@13 32 */
Chris@13 33 public function beforeTraverse(array $nodes)
Chris@13 34 {
Chris@13 35 $this->inClass = false;
Chris@13 36 }
Chris@13 37
Chris@13 38 /**
Chris@13 39 * @throws ErrorException if get_class or get_called_class is called without an object from outside a class
Chris@13 40 *
Chris@13 41 * @param Node $node
Chris@13 42 */
Chris@13 43 public function enterNode(Node $node)
Chris@13 44 {
Chris@13 45 if ($node instanceof Class_ || $node instanceof Trait_) {
Chris@13 46 $this->inClass = true;
Chris@13 47 } elseif ($node instanceof FuncCall && !$this->inClass) {
Chris@13 48 // We'll give any args at all (besides null) a pass.
Chris@13 49 // Technically we should be checking whether the args are objects, but this will do for now.
Chris@13 50 //
Chris@13 51 // @todo switch this to actually validate args when we get context-aware code cleaner passes.
Chris@13 52 if (!empty($node->args) && !$this->isNull($node->args[0])) {
Chris@13 53 return;
Chris@13 54 }
Chris@13 55
Chris@13 56 // We'll ignore name expressions as well (things like `$foo()`)
Chris@13 57 if (!($node->name instanceof Name)) {
Chris@13 58 return;
Chris@13 59 }
Chris@13 60
Chris@17 61 $name = \strtolower($node->name);
Chris@17 62 if (\in_array($name, ['get_class', 'get_called_class'])) {
Chris@17 63 $msg = \sprintf('%s() called without object from outside a class', $name);
Chris@13 64 throw new ErrorException($msg, 0, E_USER_WARNING, null, $node->getLine());
Chris@13 65 }
Chris@13 66 }
Chris@13 67 }
Chris@13 68
Chris@13 69 /**
Chris@13 70 * @param Node $node
Chris@13 71 */
Chris@13 72 public function leaveNode(Node $node)
Chris@13 73 {
Chris@13 74 if ($node instanceof Class_) {
Chris@13 75 $this->inClass = false;
Chris@13 76 }
Chris@13 77 }
Chris@13 78
Chris@13 79 private function isNull(Node $node)
Chris@13 80 {
Chris@17 81 return $node->value instanceof ConstFetch && \strtolower($node->value->name) === 'null';
Chris@13 82 }
Chris@13 83 }