Test Setup Failed
Push — master ( 4f8726...d71f12 )
by Matthew
04:36
created

IncDecExpressionAnalyzer::analyze()   F

Complexity

Conditions 18
Paths 28

Size

Total Lines 96

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
nc 28
nop 3
dl 0
loc 96
rs 3.9806
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace Psalm\Internal\Analyzer\Statements\Expression;
3
4
use PhpParser;
5
use PhpParser\Node\Expr\{PostInc, PostDec, PreInc, PreDec};
6
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
7
use Psalm\Internal\Analyzer\StatementsAnalyzer;
8
use Psalm\CodeLocation;
9
use Psalm\Context;
10
use Psalm\Issue\ImpurePropertyAssignment;
11
use Psalm\IssueBuffer;
12
use Psalm\Type;
13
use function strpos;
14
15
class IncDecExpressionAnalyzer
16
{
17
    /**
18
     * @param PostInc|PostDec|PreInc|PreDec $stmt
19
     */
20
    public static function analyze(
21
        StatementsAnalyzer $statements_analyzer,
22
        PhpParser\Node\Expr $stmt,
23
        Context $context
24
    ) : bool {
25
        $was_inside_assignment = $context->inside_assignment;
26
        $context->inside_assignment = true;
27
28
        if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === false) {
29
            if (!$was_inside_assignment) {
30
                $context->inside_assignment = false;
31
            }
32
            return false;
33
        }
34
35
        if (!$was_inside_assignment) {
36
            $context->inside_assignment = false;
37
        }
38
39
        if ($stmt_var_type = $statements_analyzer->node_data->getType($stmt->var)) {
40
            $return_type = null;
41
42
            $fake_right_expr = new PhpParser\Node\Scalar\LNumber(1, $stmt->getAttributes());
43
            $statements_analyzer->node_data->setType($fake_right_expr, Type::getInt());
44
45
            BinaryOp\NonDivArithmeticOpAnalyzer::analyze(
46
                $statements_analyzer,
47
                $statements_analyzer->node_data,
48
                $stmt->var,
49
                $fake_right_expr,
50
                $stmt,
51
                $return_type,
52
                $context
53
            );
54
55
            $stmt_type = clone $stmt_var_type;
56
57
            $statements_analyzer->node_data->setType($stmt, $stmt_type);
58
            $stmt_type->from_calculation = true;
59
60
            foreach ($stmt_type->getAtomicTypes() as $atomic_type) {
61
                if ($atomic_type instanceof Type\Atomic\TLiteralInt) {
62
                    $stmt_type->addType(new Type\Atomic\TInt);
63
                } elseif ($atomic_type instanceof Type\Atomic\TLiteralFloat) {
64
                    $stmt_type->addType(new Type\Atomic\TFloat);
65
                }
66
            }
67
68
            $var_id = ExpressionIdentifier::getArrayVarId($stmt->var, null);
69
70
            if ($var_id && $context->mutation_free && strpos($var_id, '->')) {
71
                if (IssueBuffer::accepts(
72
                    new ImpurePropertyAssignment(
73
                        'Cannot assign to a property from a mutation-free context',
74
                        new CodeLocation($statements_analyzer, $stmt->var)
75
                    ),
76
                    $statements_analyzer->getSuppressedIssues()
77
                )) {
78
                    // fall through
79
                }
80
            }
81
82
            $codebase = $statements_analyzer->getCodebase();
83
84
            if ($var_id && isset($context->vars_in_scope[$var_id])) {
85
                $context->vars_in_scope[$var_id] = $stmt_type;
86
87
                if ($codebase->find_unused_variables && $stmt->var instanceof PhpParser\Node\Expr\Variable) {
88
                    $location = new CodeLocation($statements_analyzer, $stmt->var);
89
                    $context->assigned_var_ids[$var_id] = true;
90
                    $context->possibly_assigned_var_ids[$var_id] = true;
91
92
                    if (!$context->inside_isset || !$context->inside_loop) {
93
                        $statements_analyzer->registerVariableAssignment(
94
                            $var_id,
95
                            $location
96
                        );
97
98
                        $context->unreferenced_vars[$var_id] = [$location->getHash() => $location];
99
                    }
100
                }
101
102
                // removes dependent vars from $context
103
                $context->removeDescendents(
104
                    $var_id,
105
                    $context->vars_in_scope[$var_id],
106
                    $return_type,
107
                    $statements_analyzer
108
                );
109
            }
110
        } else {
111
            $statements_analyzer->node_data->setType($stmt, Type::getMixed());
112
        }
113
114
        return true;
115
    }
116
}
117