annotate vendor/phpunit/php-code-coverage/src/Node/File.php @ 19:fa3358dc1485 tip

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