Completed
Push — master ( aa6461...70d9a0 )
by Povilas
01:48
created

DetectorVisitor::isIgnoreableConst()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
namespace Povils\PHPMND\Visitor;
4
5
use PhpParser\Node;
6
use PhpParser\Node\Const_;
7
use PhpParser\Node\Expr\UnaryMinus;
8
use PhpParser\Node\Expr\UnaryPlus;
9
use PhpParser\Node\Scalar;
10
use PhpParser\Node\Scalar\DNumber;
11
use PhpParser\Node\Scalar\LNumber;
12
use PhpParser\Node\Scalar\String_;
13
use PhpParser\NodeTraverser;
14
use PhpParser\NodeVisitorAbstract;
15
use Povils\PHPMND\Console\Option;
16
use Povils\PHPMND\Extension\ArrayAwareExtension;
17
use Povils\PHPMND\Extension\Extension;
18
use Povils\PHPMND\Extension\FunctionAwareExtension;
19
use Povils\PHPMND\FileReport;
20
21
/**
22
 * Class DetectorVisitor
23
 *
24
 * @package Povils\PHPMND
25
 */
26
class DetectorVisitor extends NodeVisitorAbstract
27
{
28
    /**
29
     * @var FileReport
30
     */
31
    private $fileReport;
32
33
    /**
34
     * @var Option
35
     */
36
    private $option;
37
38
    public function __construct(FileReport $fileReport, Option $option)
39
    {
40
        $this->fileReport = $fileReport;
41
        $this->option = $option;
42
    }
43
44
    public function enterNode(Node $node): ?int
45
    {
46
        if ($this->isIgnoreableConst($node)) {
47
            return NodeTraverser::DONT_TRAVERSE_CHILDREN;
48
        }
49
50
        if ($this->isNumber($node) || $this->isString($node)) {
51
            /** @var LNumber|DNumber|String_ $scalar */
52
            $scalar = $node;
53
            if ($this->hasSign($node)) {
54
                $node = $node->getAttribute('parent');
55
                if ($this->isMinus($node)) {
56
                    $scalar->value = -$scalar->value;
57
                }
58
            }
59
            foreach ($this->option->getExtensions() as $extension) {
60
                $extension->setOption($this->option);
61
                if ($extension->extend($node)) {
62
                    $this->fileReport->addEntry($scalar->getLine(), $scalar->value);
63
64
                    return null;
65
                }
66
            }
67
        }
68
69
        return null;
70
    }
71
72
    private function isIgnoreableConst(Node $node): bool
73
    {
74
        return $node instanceof Const_ &&
75
            ($this->isNumber($node->value) || $this->isString($node->value));
76
    }
77
78
    private function isNumber(Node $node): bool
79
    {
80
        $isNumber = (
81
            $node instanceof LNumber ||
82
            $node instanceof DNumber ||
83
            $this->isValidNumeric($node)
84
        );
85
86
        return $isNumber && false === $this->ignoreNumber($node);
87
    }
88
89
    private function isString(Node $node): bool
90
    {
91
        return $this->option->includeStrings() && $node instanceof String_ && false === $this->ignoreString($node);
92
    }
93
94
    private function ignoreNumber(Node $node): bool
95
    {
96
        return in_array($node->value, $this->option->getIgnoreNumbers(), true);
97
    }
98
99
    private function ignoreString(Node $node): bool
100
    {
101
        return in_array($node->value, $this->option->getIgnoreStrings(), true);
102
    }
103
104
    private function hasSign(Node $node): bool
105
    {
106
        return $node->getAttribute('parent') instanceof UnaryMinus
107
            || $node->getAttribute('parent') instanceof UnaryPlus;
108
    }
109
110
    private function isMinus(Node $node): bool
111
    {
112
        return $node instanceof UnaryMinus;
113
    }
114
115
    private function isValidNumeric(Node $node): bool
116
    {
117
        return $this->option->includeNumericStrings() &&
118
        isset($node->value) &&
0 ignored issues
show
Bug introduced by
Accessing value on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
119
        is_numeric($node->value) &&
0 ignored issues
show
Bug introduced by
Accessing value on the interface PhpParser\Node suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
120
        false === $this->ignoreString($node);
121
    }
122
}
123