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