LibraryChanges::prepareNameAndLine()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 7
nc 2
nop 2
crap 2
1
<?php
2
/**
3
 * LibraryChanges.php
4
 *
5
 * MIT LICENSE
6
 *
7
 * LICENSE: This source file is subject to the MIT license.
8
 * A copy of the licenses text was distributed alongside this
9
 * file (usually the repository or package root). The text can also
10
 * be obtained on one of the following sources:
11
 * * http://opensource.org/licenses/MIT
12
 * * https://github.com/suralc/pvra/blob/master/LICENSE
13
 *
14
 * @author     suralc <[email protected]>
15
 * @license    http://opensource.org/licenses/MIT  MIT
16
 */
17
18
namespace Pvra\Analysers;
19
20
21
use PhpParser\Node;
22
use PhpParser\Node\Name;
23
use Pvra\Analyser;
24
use Pvra\AnalyserAwareInterface;
25
use Pvra\InformationProvider\LibraryInformation;
26
use Pvra\InformationProvider\LibraryInformationAwareInterface;
27
use Pvra\InformationProvider\LibraryInformationInterface;
28
use Pvra\Result\Reason;
29
30
/**
31
 * Class LibraryChanges
32
 *
33
 * @package Pvra\Analysers
34
 */
35
class LibraryChanges extends LanguageFeatureAnalyser implements AnalyserAwareInterface, LibraryInformationAwareInterface
36
{
37
    /**
38
     * @var LibraryInformation
39
     */
40
    private $information;
41
42
    /**
43
     * @inheritdoc
44
     * @param array $options
45
     * @param \Pvra\Analyser $analyser
46
     * @param \Pvra\InformationProvider\LibraryInformation $information
47
     */
48 72
    public function __construct(array $options = [], Analyser $analyser = null, LibraryInformation $information = null)
49
    {
50 72
        parent::__construct($options, $analyser);
51
52 72
        if ($information !== null) {
53 24
            $this->information = $information;
54 12
        }
55 72
    }
56
57
    /**
58
     * @param \Pvra\InformationProvider\LibraryInformationInterface $libInfo
59
     * @return $this
60
     */
61 40
    public function setLibraryInformation(LibraryInformationInterface $libInfo)
62
    {
63 40
        $this->information = $libInfo;
64
65 40
        return $this;
66
    }
67
68
    /**
69
     * @param \Pvra\InformationProvider\LibraryInformationInterface $libInfo
70
     * @return $this
71
     */
72 2
    public function addLibraryInformation(LibraryInformationInterface $libInfo)
73
    {
74 2
        $this->getLibraryInformation()->mergeWith($libInfo);
75
76 2
        return $this;
77
    }
78
79
    /**
80
     * @return LibraryInformationInterface
81
     */
82 54
    public function getLibraryInformation()
83
    {
84 54
        if ($this->information === null) {
85 4
            if (($path = $this->getOption('libraryDataPath')) !== null) {
86 2
                return $this->information = LibraryInformation::createFromFile($path);
87
            }
88 2
            $this->information = LibraryInformation::createWithDefaults();
89 1
        }
90
91 54
        return $this->information;
92
    }
93
94
    /**
95
     * Prepare a name
96
     *
97
     * If the first argument is an instance of `PhpParser\Node\Name` its string representation
98
     * will be returned as first element of the result array. The value retrieved via `PhpParser\Node\Name::getLine()`
99
     * will be used as second element.
100
     * If the first parameter is not an instance of `PhpParser\Node\Name` it will be casted to string and returned alongside
101
     * with the value given for the second parameter as line
102
     *
103
     * @param \PhpParser\Node\Name|string $name
104
     * @param int $line Only used if the $name parameter is not an instance of `PhpParser\Node\Name`
105
     * @return array
106
     */
107 50
    private function prepareNameAndLine($name, $line = -1)
108
    {
109 50
        if ($name instanceof Node\Name) {
110 46
            $line = $name->getLine();
111 46
            $name = $name->toString();
112 23
        } else {
113 22
            $name = (string)$name;
114
        }
115
116 50
        return [$name, $line];
117
    }
118
119
    /**
120
     * @param \PhpParser\Node\Name|string $name
121
     * @param int $line
122
     */
123 34 View Code Duplication
    private function handleClassName($name, $line = -1)
124
    {
125 34
        list($name, $line) = $this->prepareNameAndLine($name, $line);
126 34
        $info = $this->getLibraryInformation()->getClassInfo($name);
127 34
        if ($this->mode & self::MODE_ADDITION && $info['addition'] !== null) {
128 20
            $this->getResult()->addArbitraryRequirement(
129 20
                $info['addition'],
130 10
                $line,
131 20
                null,
132 20
                Reason::LIB_CLASS_ADDITION,
133 20
                ['className' => $name]
134 10
            );
135 10
        }
136 34
        if ($this->mode & self::MODE_DEPRECATION && $info['deprecation'] !== null) {
137 4
            $this->getResult()->addArbitraryLimit(
138 4
                $info['deprecation'],
139 2
                $line,
140 4
                null,
141 4
                Reason::LIB_CLASS_DEPRECATION,
142 4
                ['className' => $name]
143 2
            );
144 2
        }
145 34
        if ($this->mode & self::MODE_REMOVAL && $info['removal'] !== null) {
146 4
            $this->getResult()->addArbitraryLimit(
147 4
                $info['removal'],
148 2
                $line,
149 4
                null,
150 4
                Reason::LIB_CLASS_REMOVAL,
151 4
                ['className' => $name]
152 2
            );
153 2
        }
154 34
    }
155
156
    /**
157
     * @param \PhpParser\Node\Name|string $name
158
     * @param int $line
159
     */
160 36 View Code Duplication
    private function handleFunctionName($name, $line = -1)
161
    {
162 36
        list($name, $line) = $this->prepareNameAndLine($name, $line);
163 36
        $info = $this->getLibraryInformation()->getFunctionInfo($name);
164 36
        if ($this->mode & self::MODE_ADDITION && $info['addition'] !== null) {
165 16
            $this->getResult()->addArbitraryRequirement(
166 16
                $info['addition'],
167 8
                $line,
168 16
                null,
169 16
                Reason::LIB_FUNCTION_ADDITION,
170 16
                ['functionName' => $name]
171 8
            );
172 8
        }
173 36
        if ($this->mode & self::MODE_DEPRECATION && $info['deprecation'] !== null) {
174 4
            $this->getResult()->addArbitraryLimit(
175 4
                $info['deprecation'],
176 2
                $line,
177 4
                null,
178 4
                Reason::LIB_FUNCTION_DEPRECATION,
179 4
                ['functionName' => $name]
180 2
            );
181 2
        }
182 36
        if ($this->mode & self::MODE_REMOVAL && $info['removal'] !== null) {
183 2
            $this->getResult()->addArbitraryLimit(
184 2
                $info['removal'],
185 1
                $line,
186 2
                null,
187 2
                Reason::LIB_FUNCTION_REMOVAL,
188 2
                ['functionName' => $name]
189 1
            );
190 1
        }
191 36
    }
192
193
    /**
194
     * @param \PhpParser\Node\Name|string $name
195
     * @param int $line
196
     */
197 24 View Code Duplication
    private function handleConstantName($name, $line = -1)
198
    {
199 24
        list($name, $line) = $this->prepareNameAndLine($name, $line);
200 24
        $info = $this->getLibraryInformation()->getConstantInfo($name);
201 24
        if (($this->mode & self::MODE_ADDITION) && $info['addition'] !== null) {
202 4
            $this->getResult()->addArbitraryRequirement(
203 4
                $info['addition'],
204 2
                $line,
205 4
                null,
206 4
                Reason::LIB_CONSTANT_ADDITION,
207 4
                ['constantName' => $name]
208 2
            );
209 2
        }
210 24
        if (($this->mode & self::MODE_DEPRECATION) && $info['deprecation'] !== null) {
211 4
            $this->getResult()->addArbitraryLimit(
212 4
                $info['deprecation'],
213 2
                $line,
214 4
                null,
215 4
                Reason::LIB_CONSTANT_DEPRECATION,
216 4
                ['constantName' => $name]
217 2
            );
218 2
        }
219 24
        if (($this->mode & self::MODE_REMOVAL) && $info['removal'] !== null) {
220 2
            $this->getResult()->addArbitraryLimit(
221 2
                $info['removal'],
222 1
                $line,
223 2
                null,
224 2
                Reason::LIB_CONSTANT_REMOVAL,
225 2
                ['constantName' => $name]
226 1
            );
227 1
        }
228 24
    }
229
230
    /**
231
     * @inheritdoc
232
     * @param \PhpParser\Node $node
233
     * @return null|\PhpParser\Node|void
234
     */
235 62
    public function enterNode(Node $node)
236
    {
237
        // direct class calls
238 62
        if ($node instanceof Node\Expr\New_ || $node instanceof Node\Expr\StaticCall
239 61
            || $node instanceof Node\Expr\ClassConstFetch || $node instanceof Node\Expr\StaticPropertyFetch
240 31
        ) {
241 34
            if ($node->class instanceof Node\Name) {
242 32
                $this->handleClassName($node->class);
243 16
            }
244 34
            if ($node instanceof Node\Expr\ClassConstFetch) {
245 26
                $this->handleConstantName($node->name, $node->getLine());
246 9
            }
247 33
        } elseif ($node instanceof Node\FunctionLike) {
248 28
            if (!empty($node->getParams())) {
249 28
                foreach ($node->getParams() as $param) {
250 28
                    if (isset($param->type) && !is_string($param->type)) {
251 18
                        $this->handleClassName($param->type);
252 4
                    }
253 14
                }
254 14
            }
255 14
        } elseif ($node instanceof Node\Stmt\Class_
256 56
            || $node instanceof Node\Stmt\Interface_
257 28
        ) {
258 26
            $names = [];
259 26
            if (!empty($node->implements)) {
260 10
                $names += $node->implements;
261 5
            }
262 26
            if (!empty($node->extends)) {
263 10
                if ($node->extends instanceof Name) {
264 10
                    $names[] = $node->extends;
265 5
                } else {
266 8
                    $names += $node->extends;
267
                }
268 5
            }
269
270 26
            foreach ($names as $name) {
271 18
                $this->handleClassName($name);
272 13
            }
273 55
        } elseif ($node instanceof Node\Expr\FuncCall && !($node->name instanceof Node\Expr)) {
274 36
            $this->handleFunctionName($node->name);
275 29
        } elseif ($node instanceof Node\Expr\ConstFetch) {
276 14
            $this->handleConstantName($node->name);
277 7
        }
278 62
    }
279
}
280