DivisionByOne::pass()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
nc 6
nop 2
dl 0
loc 22
ccs 0
cts 13
cp 0
crap 20
rs 9.568
c 0
b 0
f 0
1
<?php
2
3
namespace PHPSA\Analyzer\Pass\Expression;
4
5
use PhpParser\Node\Expr;
6
use PHPSA\Analyzer\Helper\DefaultMetadataPassTrait;
7
use PHPSA\Analyzer\Pass\AnalyzerPassInterface;
8
use PHPSA\Context;
9
10
class DivisionByOne implements AnalyzerPassInterface
11
{
12
    use DefaultMetadataPassTrait;
13
14
    const DESCRIPTION = 'Checks for division by 1. For example: `$x/1`, `$x%true`';
15
16
    /**
17
     * @param Expr $expr
18
     * @param Context $context
19
     * @return bool
20
     */
21
    public function pass(Expr $expr, Context $context)
22
    {
23
        $compiler = $context->getExpressionCompiler();
24
25
        if ($expr instanceof Expr\AssignOp) {
26
            $right = $compiler->compile($expr->expr);
27
        } elseif ($expr instanceof Expr\BinaryOp) {
28
            $right = $compiler->compile($expr->right);
29
        }
30
31
        if ($right->getValue() == 1) {
0 ignored issues
show
Bug introduced by
The variable $right does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
32
            $context->notice(
33
                'division_by_one',
34
                "You are trying to divide by one",
35
                $expr
36
            );
37
38
            return true;
39
        }
40
        
41
        return false;
42
    }
43
44
    /**
45
     * @return array
46
     */
47
    public function getRegister()
48
    {
49
        return [
50
            Expr\BinaryOp\Div::class,
51
            Expr\BinaryOp\Mod::class,
52
            Expr\AssignOp\Div::class,
53
            Expr\AssignOp\Mod::class,
54
        ];
55
    }
56
}
57