Completed
Pull Request — master (#254)
by Enrico
14:10 queued 09:31
created

DivisionByOne::pass()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 13
nc 6
nop 2
dl 0
loc 22
ccs 14
cts 14
cp 1
crap 4
rs 8.9197
c 1
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 103
    public function pass(Expr $expr, Context $context)
22
    {
23 103
        $compiler = $context->getExpressionCompiler();
24
25 103
        if ($expr instanceof Expr\AssignOp) {
26 31
            $right = $compiler->compile($expr->expr);
27 103
        } elseif ($expr instanceof Expr\BinaryOp) {
28 74
            $right = $compiler->compile($expr->right);
29 74
        }
30
31 103
        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 42
            $context->notice(
33 42
                'division_by_one',
34 42
                "You are trying to divide by one",
35
                $expr
36 42
            );
37
38 42
            return true;
39
        }
40
        
41 62
        return false;
42
    }
43
44
    /**
45
     * @return array
46
     */
47 1
    public function getRegister()
48
    {
49
        return [
50 1
            Expr\BinaryOp\Div::class,
51 1
            Expr\BinaryOp\Mod::class,
52 1
            Expr\AssignOp\Div::class,
53 1
            Expr\AssignOp\Mod::class,
54 1
        ];
55
    }
56
}
57