Completed
Pull Request — master (#139)
by Kévin
03:44
created

ArrayIllegalOffsetType::getConfiguration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 9
ccs 0
cts 5
cp 0
crap 2
rs 9.6666
c 1
b 0
f 0
1
<?php
2
/**
3
 * @author Kévin Gomez https://github.com/K-Phoen <[email protected]>
4
 */
5
6
namespace PHPSA\Analyzer\Pass\Expression;
7
8
use PhpParser\Node\Expr;
9
use PHPSA\Analyzer\Helper\DefaultMetadataPassTrait;
10
use PHPSA\Analyzer\Pass\AnalyzerPassInterface;
11
use PHPSA\Context;
12
13
class ArrayIllegalOffsetType implements AnalyzerPassInterface
14
{
15
    use DefaultMetadataPassTrait;
16
17
    /**
18
     * @param Expr\Array_|Expr\Assign $expr
19
     * @param Context $context
20
     * @return bool
21
     */
22 35
    public function pass(Expr $expr, Context $context)
23
    {
24 35
        if ($expr instanceof Expr\Array_) {
25 26
            return $this->analyzeArray($expr, $context);
26 12
        } elseif ($expr instanceof Expr\Assign && $expr->var instanceof Expr\ArrayDimFetch) {
27 1
            return $this->analyzeDimensionFetch($expr->var, $context);
28
        }
29 12
    }
30
31
    /**
32
     * @param Expr\ArrayDimFetch $expr
33
     * @param Context $context
34
     *
35
     * @return bool
36
     */
37 1
    private function analyzeDimensionFetch(Expr\ArrayDimFetch $expr, Context $context)
38
    {
39
        // $array[]
40 1
        if ($expr->dim === null) {
41 1
            return false;
42
        }
43
44
        // $array[…]
45 1
        return $this->analyzeExpression($expr->dim, $context);
46
    }
47
48
    /**
49
     * @param Expr\Array_ $expr
50
     * @param Context $context
51
     *
52
     * @return bool
53
     */
54 26
    private function analyzeArray(Expr\Array_ $expr, Context $context)
55
    {
56 26
        $result = false;
57
58
        /** @var Expr\ArrayItem $item */
59 26
        foreach ($expr->items as $item) {
60 10
            if ($item->key === null) {
61 7
                continue;
62
            }
63
64 3
            $result = $this->analyzeExpression($item->key, $context) || $result;
65 26
        }
66
67 26
        return $result;
68
    }
69
70 3
    private function analyzeExpression(Expr $expr, Context $context)
71
    {
72 3
        $compiledKey = $context->getExpressionCompiler()->compile($expr);
73 3
        if (!$compiledKey->isTypeKnown() || $compiledKey->isScalar()) {
74 3
            return false;
75
        }
76
77 1
        $keyType = $compiledKey->getTypeName();
78 1
        if ($compiledKey->isObject() && $compiledKey->getValue()) {
79 1
            $keyType = get_class($compiledKey->getValue());
80 1
        }
81
82 1
        if ($expr instanceof Expr\Variable) {
83 1
            $message = sprintf('Illegal array offset type %s for key %s.', $keyType, '$'.$expr->name);
84 1
        } else {
85 1
            $message = sprintf('Illegal array offset type %s.', $keyType);
86
        }
87
88 1
        $context->notice('array.illegal_offset_type', $message, $expr);
89
90 1
        return true;
91
    }
92
93
    /**
94
     * @return array
95
     */
96 1
    public function getRegister()
97
    {
98
        return [
99 1
            Expr\Array_::class,
100 1
            Expr\Assign::class,
101 1
        ];
102
    }
103
}
104