Mercurial > hg > isophonics-drupal-site
comparison vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/File.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 /* | |
3 * This file is part of the PHP_CodeCoverage package. | |
4 * | |
5 * (c) Sebastian Bergmann <sebastian@phpunit.de> | |
6 * | |
7 * For the full copyright and license information, please view the LICENSE | |
8 * file that was distributed with this source code. | |
9 */ | |
10 | |
11 /** | |
12 * Represents a file in the code coverage information tree. | |
13 * | |
14 * @since Class available since Release 1.1.0 | |
15 */ | |
16 class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node | |
17 { | |
18 /** | |
19 * @var array | |
20 */ | |
21 protected $coverageData; | |
22 | |
23 /** | |
24 * @var array | |
25 */ | |
26 protected $testData; | |
27 | |
28 /** | |
29 * @var int | |
30 */ | |
31 protected $numExecutableLines = 0; | |
32 | |
33 /** | |
34 * @var int | |
35 */ | |
36 protected $numExecutedLines = 0; | |
37 | |
38 /** | |
39 * @var array | |
40 */ | |
41 protected $classes = array(); | |
42 | |
43 /** | |
44 * @var array | |
45 */ | |
46 protected $traits = array(); | |
47 | |
48 /** | |
49 * @var array | |
50 */ | |
51 protected $functions = array(); | |
52 | |
53 /** | |
54 * @var array | |
55 */ | |
56 protected $linesOfCode = array(); | |
57 | |
58 /** | |
59 * @var int | |
60 */ | |
61 protected $numTestedTraits = 0; | |
62 | |
63 /** | |
64 * @var int | |
65 */ | |
66 protected $numTestedClasses = 0; | |
67 | |
68 /** | |
69 * @var int | |
70 */ | |
71 protected $numMethods = null; | |
72 | |
73 /** | |
74 * @var int | |
75 */ | |
76 protected $numTestedMethods = null; | |
77 | |
78 /** | |
79 * @var int | |
80 */ | |
81 protected $numTestedFunctions = null; | |
82 | |
83 /** | |
84 * @var array | |
85 */ | |
86 protected $startLines = array(); | |
87 | |
88 /** | |
89 * @var array | |
90 */ | |
91 protected $endLines = array(); | |
92 | |
93 /** | |
94 * @var bool | |
95 */ | |
96 protected $cacheTokens; | |
97 | |
98 /** | |
99 * Constructor. | |
100 * | |
101 * @param string $name | |
102 * @param PHP_CodeCoverage_Report_Node $parent | |
103 * @param array $coverageData | |
104 * @param array $testData | |
105 * @param bool $cacheTokens | |
106 * @throws PHP_CodeCoverage_Exception | |
107 */ | |
108 public function __construct($name, PHP_CodeCoverage_Report_Node $parent, array $coverageData, array $testData, $cacheTokens) | |
109 { | |
110 if (!is_bool($cacheTokens)) { | |
111 throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( | |
112 1, | |
113 'boolean' | |
114 ); | |
115 } | |
116 | |
117 parent::__construct($name, $parent); | |
118 | |
119 $this->coverageData = $coverageData; | |
120 $this->testData = $testData; | |
121 $this->cacheTokens = $cacheTokens; | |
122 | |
123 $this->calculateStatistics(); | |
124 } | |
125 | |
126 /** | |
127 * Returns the number of files in/under this node. | |
128 * | |
129 * @return int | |
130 */ | |
131 public function count() | |
132 { | |
133 return 1; | |
134 } | |
135 | |
136 /** | |
137 * Returns the code coverage data of this node. | |
138 * | |
139 * @return array | |
140 */ | |
141 public function getCoverageData() | |
142 { | |
143 return $this->coverageData; | |
144 } | |
145 | |
146 /** | |
147 * Returns the test data of this node. | |
148 * | |
149 * @return array | |
150 */ | |
151 public function getTestData() | |
152 { | |
153 return $this->testData; | |
154 } | |
155 | |
156 /** | |
157 * Returns the classes of this node. | |
158 * | |
159 * @return array | |
160 */ | |
161 public function getClasses() | |
162 { | |
163 return $this->classes; | |
164 } | |
165 | |
166 /** | |
167 * Returns the traits of this node. | |
168 * | |
169 * @return array | |
170 */ | |
171 public function getTraits() | |
172 { | |
173 return $this->traits; | |
174 } | |
175 | |
176 /** | |
177 * Returns the functions of this node. | |
178 * | |
179 * @return array | |
180 */ | |
181 public function getFunctions() | |
182 { | |
183 return $this->functions; | |
184 } | |
185 | |
186 /** | |
187 * Returns the LOC/CLOC/NCLOC of this node. | |
188 * | |
189 * @return array | |
190 */ | |
191 public function getLinesOfCode() | |
192 { | |
193 return $this->linesOfCode; | |
194 } | |
195 | |
196 /** | |
197 * Returns the number of executable lines. | |
198 * | |
199 * @return int | |
200 */ | |
201 public function getNumExecutableLines() | |
202 { | |
203 return $this->numExecutableLines; | |
204 } | |
205 | |
206 /** | |
207 * Returns the number of executed lines. | |
208 * | |
209 * @return int | |
210 */ | |
211 public function getNumExecutedLines() | |
212 { | |
213 return $this->numExecutedLines; | |
214 } | |
215 | |
216 /** | |
217 * Returns the number of classes. | |
218 * | |
219 * @return int | |
220 */ | |
221 public function getNumClasses() | |
222 { | |
223 return count($this->classes); | |
224 } | |
225 | |
226 /** | |
227 * Returns the number of tested classes. | |
228 * | |
229 * @return int | |
230 */ | |
231 public function getNumTestedClasses() | |
232 { | |
233 return $this->numTestedClasses; | |
234 } | |
235 | |
236 /** | |
237 * Returns the number of traits. | |
238 * | |
239 * @return int | |
240 */ | |
241 public function getNumTraits() | |
242 { | |
243 return count($this->traits); | |
244 } | |
245 | |
246 /** | |
247 * Returns the number of tested traits. | |
248 * | |
249 * @return int | |
250 */ | |
251 public function getNumTestedTraits() | |
252 { | |
253 return $this->numTestedTraits; | |
254 } | |
255 | |
256 /** | |
257 * Returns the number of methods. | |
258 * | |
259 * @return int | |
260 */ | |
261 public function getNumMethods() | |
262 { | |
263 if ($this->numMethods === null) { | |
264 $this->numMethods = 0; | |
265 | |
266 foreach ($this->classes as $class) { | |
267 foreach ($class['methods'] as $method) { | |
268 if ($method['executableLines'] > 0) { | |
269 $this->numMethods++; | |
270 } | |
271 } | |
272 } | |
273 | |
274 foreach ($this->traits as $trait) { | |
275 foreach ($trait['methods'] as $method) { | |
276 if ($method['executableLines'] > 0) { | |
277 $this->numMethods++; | |
278 } | |
279 } | |
280 } | |
281 } | |
282 | |
283 return $this->numMethods; | |
284 } | |
285 | |
286 /** | |
287 * Returns the number of tested methods. | |
288 * | |
289 * @return int | |
290 */ | |
291 public function getNumTestedMethods() | |
292 { | |
293 if ($this->numTestedMethods === null) { | |
294 $this->numTestedMethods = 0; | |
295 | |
296 foreach ($this->classes as $class) { | |
297 foreach ($class['methods'] as $method) { | |
298 if ($method['executableLines'] > 0 && | |
299 $method['coverage'] == 100) { | |
300 $this->numTestedMethods++; | |
301 } | |
302 } | |
303 } | |
304 | |
305 foreach ($this->traits as $trait) { | |
306 foreach ($trait['methods'] as $method) { | |
307 if ($method['executableLines'] > 0 && | |
308 $method['coverage'] == 100) { | |
309 $this->numTestedMethods++; | |
310 } | |
311 } | |
312 } | |
313 } | |
314 | |
315 return $this->numTestedMethods; | |
316 } | |
317 | |
318 /** | |
319 * Returns the number of functions. | |
320 * | |
321 * @return int | |
322 */ | |
323 public function getNumFunctions() | |
324 { | |
325 return count($this->functions); | |
326 } | |
327 | |
328 /** | |
329 * Returns the number of tested functions. | |
330 * | |
331 * @return int | |
332 */ | |
333 public function getNumTestedFunctions() | |
334 { | |
335 if ($this->numTestedFunctions === null) { | |
336 $this->numTestedFunctions = 0; | |
337 | |
338 foreach ($this->functions as $function) { | |
339 if ($function['executableLines'] > 0 && | |
340 $function['coverage'] == 100) { | |
341 $this->numTestedFunctions++; | |
342 } | |
343 } | |
344 } | |
345 | |
346 return $this->numTestedFunctions; | |
347 } | |
348 | |
349 /** | |
350 * Calculates coverage statistics for the file. | |
351 */ | |
352 protected function calculateStatistics() | |
353 { | |
354 $classStack = $functionStack = array(); | |
355 | |
356 if ($this->cacheTokens) { | |
357 $tokens = PHP_Token_Stream_CachingFactory::get($this->getPath()); | |
358 } else { | |
359 $tokens = new PHP_Token_Stream($this->getPath()); | |
360 } | |
361 | |
362 $this->processClasses($tokens); | |
363 $this->processTraits($tokens); | |
364 $this->processFunctions($tokens); | |
365 $this->linesOfCode = $tokens->getLinesOfCode(); | |
366 unset($tokens); | |
367 | |
368 for ($lineNumber = 1; $lineNumber <= $this->linesOfCode['loc']; $lineNumber++) { | |
369 if (isset($this->startLines[$lineNumber])) { | |
370 // Start line of a class. | |
371 if (isset($this->startLines[$lineNumber]['className'])) { | |
372 if (isset($currentClass)) { | |
373 $classStack[] = &$currentClass; | |
374 } | |
375 | |
376 $currentClass = &$this->startLines[$lineNumber]; | |
377 } // Start line of a trait. | |
378 elseif (isset($this->startLines[$lineNumber]['traitName'])) { | |
379 $currentTrait = &$this->startLines[$lineNumber]; | |
380 } // Start line of a method. | |
381 elseif (isset($this->startLines[$lineNumber]['methodName'])) { | |
382 $currentMethod = &$this->startLines[$lineNumber]; | |
383 } // Start line of a function. | |
384 elseif (isset($this->startLines[$lineNumber]['functionName'])) { | |
385 if (isset($currentFunction)) { | |
386 $functionStack[] = &$currentFunction; | |
387 } | |
388 | |
389 $currentFunction = &$this->startLines[$lineNumber]; | |
390 } | |
391 } | |
392 | |
393 if (isset($this->coverageData[$lineNumber])) { | |
394 if (isset($currentClass)) { | |
395 $currentClass['executableLines']++; | |
396 } | |
397 | |
398 if (isset($currentTrait)) { | |
399 $currentTrait['executableLines']++; | |
400 } | |
401 | |
402 if (isset($currentMethod)) { | |
403 $currentMethod['executableLines']++; | |
404 } | |
405 | |
406 if (isset($currentFunction)) { | |
407 $currentFunction['executableLines']++; | |
408 } | |
409 | |
410 $this->numExecutableLines++; | |
411 | |
412 if (count($this->coverageData[$lineNumber]) > 0) { | |
413 if (isset($currentClass)) { | |
414 $currentClass['executedLines']++; | |
415 } | |
416 | |
417 if (isset($currentTrait)) { | |
418 $currentTrait['executedLines']++; | |
419 } | |
420 | |
421 if (isset($currentMethod)) { | |
422 $currentMethod['executedLines']++; | |
423 } | |
424 | |
425 if (isset($currentFunction)) { | |
426 $currentFunction['executedLines']++; | |
427 } | |
428 | |
429 $this->numExecutedLines++; | |
430 } | |
431 } | |
432 | |
433 if (isset($this->endLines[$lineNumber])) { | |
434 // End line of a class. | |
435 if (isset($this->endLines[$lineNumber]['className'])) { | |
436 unset($currentClass); | |
437 | |
438 if ($classStack) { | |
439 end($classStack); | |
440 $key = key($classStack); | |
441 $currentClass = &$classStack[$key]; | |
442 unset($classStack[$key]); | |
443 } | |
444 } // End line of a trait. | |
445 elseif (isset($this->endLines[$lineNumber]['traitName'])) { | |
446 unset($currentTrait); | |
447 } // End line of a method. | |
448 elseif (isset($this->endLines[$lineNumber]['methodName'])) { | |
449 unset($currentMethod); | |
450 } // End line of a function. | |
451 elseif (isset($this->endLines[$lineNumber]['functionName'])) { | |
452 unset($currentFunction); | |
453 | |
454 if ($functionStack) { | |
455 end($functionStack); | |
456 $key = key($functionStack); | |
457 $currentFunction = &$functionStack[$key]; | |
458 unset($functionStack[$key]); | |
459 } | |
460 } | |
461 } | |
462 } | |
463 | |
464 foreach ($this->traits as &$trait) { | |
465 foreach ($trait['methods'] as &$method) { | |
466 if ($method['executableLines'] > 0) { | |
467 $method['coverage'] = ($method['executedLines'] / | |
468 $method['executableLines']) * 100; | |
469 } else { | |
470 $method['coverage'] = 100; | |
471 } | |
472 | |
473 $method['crap'] = $this->crap( | |
474 $method['ccn'], | |
475 $method['coverage'] | |
476 ); | |
477 | |
478 $trait['ccn'] += $method['ccn']; | |
479 } | |
480 | |
481 if ($trait['executableLines'] > 0) { | |
482 $trait['coverage'] = ($trait['executedLines'] / | |
483 $trait['executableLines']) * 100; | |
484 } else { | |
485 $trait['coverage'] = 100; | |
486 } | |
487 | |
488 if ($trait['coverage'] == 100) { | |
489 $this->numTestedClasses++; | |
490 } | |
491 | |
492 $trait['crap'] = $this->crap( | |
493 $trait['ccn'], | |
494 $trait['coverage'] | |
495 ); | |
496 } | |
497 | |
498 foreach ($this->classes as &$class) { | |
499 foreach ($class['methods'] as &$method) { | |
500 if ($method['executableLines'] > 0) { | |
501 $method['coverage'] = ($method['executedLines'] / | |
502 $method['executableLines']) * 100; | |
503 } else { | |
504 $method['coverage'] = 100; | |
505 } | |
506 | |
507 $method['crap'] = $this->crap( | |
508 $method['ccn'], | |
509 $method['coverage'] | |
510 ); | |
511 | |
512 $class['ccn'] += $method['ccn']; | |
513 } | |
514 | |
515 if ($class['executableLines'] > 0) { | |
516 $class['coverage'] = ($class['executedLines'] / | |
517 $class['executableLines']) * 100; | |
518 } else { | |
519 $class['coverage'] = 100; | |
520 } | |
521 | |
522 if ($class['coverage'] == 100) { | |
523 $this->numTestedClasses++; | |
524 } | |
525 | |
526 $class['crap'] = $this->crap( | |
527 $class['ccn'], | |
528 $class['coverage'] | |
529 ); | |
530 } | |
531 } | |
532 | |
533 /** | |
534 * @param PHP_Token_Stream $tokens | |
535 */ | |
536 protected function processClasses(PHP_Token_Stream $tokens) | |
537 { | |
538 $classes = $tokens->getClasses(); | |
539 unset($tokens); | |
540 | |
541 $link = $this->getId() . '.html#'; | |
542 | |
543 foreach ($classes as $className => $class) { | |
544 $this->classes[$className] = array( | |
545 'className' => $className, | |
546 'methods' => array(), | |
547 'startLine' => $class['startLine'], | |
548 'executableLines' => 0, | |
549 'executedLines' => 0, | |
550 'ccn' => 0, | |
551 'coverage' => 0, | |
552 'crap' => 0, | |
553 'package' => $class['package'], | |
554 'link' => $link . $class['startLine'] | |
555 ); | |
556 | |
557 $this->startLines[$class['startLine']] = &$this->classes[$className]; | |
558 $this->endLines[$class['endLine']] = &$this->classes[$className]; | |
559 | |
560 foreach ($class['methods'] as $methodName => $method) { | |
561 $this->classes[$className]['methods'][$methodName] = array( | |
562 'methodName' => $methodName, | |
563 'signature' => $method['signature'], | |
564 'startLine' => $method['startLine'], | |
565 'endLine' => $method['endLine'], | |
566 'executableLines' => 0, | |
567 'executedLines' => 0, | |
568 'ccn' => $method['ccn'], | |
569 'coverage' => 0, | |
570 'crap' => 0, | |
571 'link' => $link . $method['startLine'] | |
572 ); | |
573 | |
574 $this->startLines[$method['startLine']] = &$this->classes[$className]['methods'][$methodName]; | |
575 $this->endLines[$method['endLine']] = &$this->classes[$className]['methods'][$methodName]; | |
576 } | |
577 } | |
578 } | |
579 | |
580 /** | |
581 * @param PHP_Token_Stream $tokens | |
582 */ | |
583 protected function processTraits(PHP_Token_Stream $tokens) | |
584 { | |
585 $traits = $tokens->getTraits(); | |
586 unset($tokens); | |
587 | |
588 $link = $this->getId() . '.html#'; | |
589 | |
590 foreach ($traits as $traitName => $trait) { | |
591 $this->traits[$traitName] = array( | |
592 'traitName' => $traitName, | |
593 'methods' => array(), | |
594 'startLine' => $trait['startLine'], | |
595 'executableLines' => 0, | |
596 'executedLines' => 0, | |
597 'ccn' => 0, | |
598 'coverage' => 0, | |
599 'crap' => 0, | |
600 'package' => $trait['package'], | |
601 'link' => $link . $trait['startLine'] | |
602 ); | |
603 | |
604 $this->startLines[$trait['startLine']] = &$this->traits[$traitName]; | |
605 $this->endLines[$trait['endLine']] = &$this->traits[$traitName]; | |
606 | |
607 foreach ($trait['methods'] as $methodName => $method) { | |
608 $this->traits[$traitName]['methods'][$methodName] = array( | |
609 'methodName' => $methodName, | |
610 'signature' => $method['signature'], | |
611 'startLine' => $method['startLine'], | |
612 'endLine' => $method['endLine'], | |
613 'executableLines' => 0, | |
614 'executedLines' => 0, | |
615 'ccn' => $method['ccn'], | |
616 'coverage' => 0, | |
617 'crap' => 0, | |
618 'link' => $link . $method['startLine'] | |
619 ); | |
620 | |
621 $this->startLines[$method['startLine']] = &$this->traits[$traitName]['methods'][$methodName]; | |
622 $this->endLines[$method['endLine']] = &$this->traits[$traitName]['methods'][$methodName]; | |
623 } | |
624 } | |
625 } | |
626 | |
627 /** | |
628 * @param PHP_Token_Stream $tokens | |
629 */ | |
630 protected function processFunctions(PHP_Token_Stream $tokens) | |
631 { | |
632 $functions = $tokens->getFunctions(); | |
633 unset($tokens); | |
634 | |
635 $link = $this->getId() . '.html#'; | |
636 | |
637 foreach ($functions as $functionName => $function) { | |
638 $this->functions[$functionName] = array( | |
639 'functionName' => $functionName, | |
640 'signature' => $function['signature'], | |
641 'startLine' => $function['startLine'], | |
642 'executableLines' => 0, | |
643 'executedLines' => 0, | |
644 'ccn' => $function['ccn'], | |
645 'coverage' => 0, | |
646 'crap' => 0, | |
647 'link' => $link . $function['startLine'] | |
648 ); | |
649 | |
650 $this->startLines[$function['startLine']] = &$this->functions[$functionName]; | |
651 $this->endLines[$function['endLine']] = &$this->functions[$functionName]; | |
652 } | |
653 } | |
654 | |
655 /** | |
656 * Calculates the Change Risk Anti-Patterns (CRAP) index for a unit of code | |
657 * based on its cyclomatic complexity and percentage of code coverage. | |
658 * | |
659 * @param int $ccn | |
660 * @param float $coverage | |
661 * @return string | |
662 * @since Method available since Release 1.2.0 | |
663 */ | |
664 protected function crap($ccn, $coverage) | |
665 { | |
666 if ($coverage == 0) { | |
667 return (string) (pow($ccn, 2) + $ccn); | |
668 } | |
669 | |
670 if ($coverage >= 95) { | |
671 return (string) $ccn; | |
672 } | |
673 | |
674 return sprintf( | |
675 '%01.2F', | |
676 pow($ccn, 2) * pow(1 - $coverage/100, 3) + $ccn | |
677 ); | |
678 } | |
679 } |