Completed
Push — master ( 05fb7c...b72046 )
by Povilas
10s
created

DetectorVisitor::isNumber()   B

Complexity

Conditions 6
Paths 14

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
rs 8.8571
cc 6
eloc 8
nc 14
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\Extension;
17
use Povils\PHPMND\Extension\FunctionAwareExtension;
18
use Povils\PHPMND\FileReport;
19
20
/**
21
 * Class DetectorVisitor
22
 *
23
 * @package Povils\PHPMND
24
 */
25
class DetectorVisitor extends NodeVisitorAbstract
26
{
27
    /**
28
     * @var FileReport
29
     */
30
    private $fileReport;
31
32
    /**
33
     * @var Option
34
     */
35
    private $option;
36
37
    /**
38
     * @param FileReport $fileReport
39
     * @param Option $option
40
     */
41
    public function __construct(FileReport $fileReport, Option $option)
42
    {
43
        $this->fileReport = $fileReport;
44
        $this->option = $option;
45
    }
46
47
    /**
48
     * @inheritdoc
49
     */
50
    public function enterNode(Node $node)
51
    {
52
        if ($node instanceof Const_) {
53
            return NodeTraverser::DONT_TRAVERSE_CHILDREN;
54
        }
55
56
        if ($this->isNumber($node) || $this->isString($node)) {
57
            /** @var LNumber|DNumber|String_ $scalar */
58
            $scalar = $node;
59
            if ($this->hasSign($node)) {
60
                $node = $node->getAttribute('parent');
61
                if ($this->isMinus($node)) {
62
                    $scalar->value = -$scalar->value;
63
                }
64
            }
65
            foreach ($this->option->getExtensions() as $extension) {
66
                if ($extension->extend($node) && false === $this->ignoreFunc($node, $extension)) {
67
                    $this->fileReport->addEntry($scalar->getLine(), $scalar->value);
68
69
                    return null;
70
                }
71
            }
72
        }
73
74
        return null;
75
    }
76
77
    /**
78
     * @param Node $node
79
     *
80
     * @return bool
81
     */
82
    private function isNumber(Node $node)
83
    {
84
        $isNumber = (
85
            $node instanceof LNumber ||
86
            $node instanceof DNumber ||
87
            (
88
                $this->option->getNumericStrings() &&
89
                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...
90
                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...
91
            )
92
        );
93
94
        return $isNumber && false === $this->ignoreNumber($node);
95
    }
96
97
    /**
98
     * @param Node $node
99
     *
100
     * @return bool
101
     */
102
    private function isString(Node $node)
103
    {
104
        return $this->option->includeStrings() && $node instanceof String_ && false === $this->ignoreString($node);
105
    }
106
107
    /**
108
     * @param LNumber|DNumber|Node $node
109
     *
110
     * @return bool
111
     */
112
    private function ignoreNumber(Node $node)
113
    {
114
        return in_array($node->value, $this->option->getIgnoreNumbers(), true);
115
    }
116
117
    /**
118
     * @param String_|Node $node
119
     *
120
     * @return bool
121
     */
122
    private function ignoreString(Node $node)
123
    {
124
        return in_array($node->value, $this->option->getIgnoreStrings(), true);
125
    }
126
127
    /**
128
     * @param Node $node
129
     *
130
     * @return bool
131
     */
132
    private function hasSign(Node $node)
133
    {
134
        return $node->getAttribute('parent') instanceof UnaryMinus || $node->getAttribute('parent') instanceof UnaryPlus;
135
    }
136
137
    /**
138
     * @param Node $node
139
     *
140
     * @return bool
141
     */
142
    private function isMinus(Node $node)
143
    {
144
        return $node instanceof UnaryMinus;
145
    }
146
147
    /**
148
     * @param Node $node
149
     * @param Extension $extension
150
     *
151
     * @return bool
152
     */
153
    private function ignoreFunc(Node $node, Extension $extension)
154
    {
155
        if ($extension instanceof FunctionAwareExtension) {
156
            return $extension->ignoreFunc($node, $this->option->getIgnoreFuncs());
157
        }
158
159
        return false;
160
    }
161
}
162