Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of Psy Shell.
5
 *
200 lars 6
 * (c) 2012-2023 Justin Hileman
148 lars 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;
16
use PhpParser\Node\Expr\Array_;
17
use PhpParser\Node\Expr\ArrayDimFetch;
18
use PhpParser\Node\Expr\ArrayItem;
19
use PhpParser\Node\Expr\Assign;
20
use PhpParser\Node\Expr\FuncCall;
21
use PhpParser\Node\Expr\List_;
22
use PhpParser\Node\Expr\MethodCall;
23
use PhpParser\Node\Expr\PropertyFetch;
24
use PhpParser\Node\Expr\Variable;
25
use Psy\Exception\ParseErrorException;
26
 
27
/**
28
 * Validate that the list assignment.
29
 */
30
class ListPass extends CodeCleanerPass
31
{
32
    private $atLeastPhp71;
33
 
34
    public function __construct()
35
    {
36
        $this->atLeastPhp71 = \version_compare(\PHP_VERSION, '7.1', '>=');
37
    }
38
 
39
    /**
40
     * Validate use of list assignment.
41
     *
42
     * @throws ParseErrorException if the user used empty with anything but a variable
43
     *
44
     * @param Node $node
45
     *
46
     * @return int|Node|null Replacement node (or special return value)
47
     */
48
    public function enterNode(Node $node)
49
    {
50
        if (!$node instanceof Assign) {
51
            return;
52
        }
53
 
54
        if (!$node->var instanceof Array_ && !$node->var instanceof List_) {
55
            return;
56
        }
57
 
58
        if (!$this->atLeastPhp71 && $node->var instanceof Array_) {
59
            $msg = "syntax error, unexpected '='";
60
            throw new ParseErrorException($msg, $node->expr->getLine());
61
        }
62
 
63
        // Polyfill for PHP-Parser 2.x
64
        $items = isset($node->var->items) ? $node->var->items : $node->var->vars;
65
 
66
        if ($items === [] || $items === [null]) {
67
            throw new ParseErrorException('Cannot use empty list', $node->var->getLine());
68
        }
69
 
70
        $itemFound = false;
71
        foreach ($items as $item) {
72
            if ($item === null) {
73
                continue;
74
            }
75
 
76
            $itemFound = true;
77
 
78
            // List_->$vars in PHP-Parser 2.x is Variable instead of ArrayItem.
79
            if (!$this->atLeastPhp71 && $item instanceof ArrayItem && $item->key !== null) {
80
                $msg = 'Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting \',\' or \')\'';
81
                throw new ParseErrorException($msg, $item->key->getLine());
82
            }
83
 
84
            if (!self::isValidArrayItem($item)) {
85
                $msg = 'Assignments can only happen to writable values';
86
                throw new ParseErrorException($msg, $item->getLine());
87
            }
88
        }
89
 
90
        if (!$itemFound) {
91
            throw new ParseErrorException('Cannot use empty list');
92
        }
93
    }
94
 
95
    /**
96
     * Validate whether a given item in an array is valid for short assignment.
97
     *
98
     * @param Expr $item
99
     */
100
    private static function isValidArrayItem(Expr $item): bool
101
    {
102
        $value = ($item instanceof ArrayItem) ? $item->value : $item;
103
 
104
        while ($value instanceof ArrayDimFetch || $value instanceof PropertyFetch) {
105
            $value = $value->var;
106
        }
107
 
108
        // We just kind of give up if it's a method call. We can't tell if it's
109
        // valid via static analysis.
110
        return $value instanceof Variable || $value instanceof MethodCall || $value instanceof FuncCall;
111
    }
112
}