annotate vendor/phpunit/php-code-coverage/src/Report/Crap4j.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\Report;
Chris@14 12
Chris@14 13 use SebastianBergmann\CodeCoverage\CodeCoverage;
Chris@14 14 use SebastianBergmann\CodeCoverage\InvalidArgumentException;
Chris@14 15 use SebastianBergmann\CodeCoverage\Node\File;
Chris@14 16 use SebastianBergmann\CodeCoverage\RuntimeException;
Chris@14 17
Chris@14 18 class Crap4j
Chris@14 19 {
Chris@14 20 /**
Chris@14 21 * @var int
Chris@14 22 */
Chris@14 23 private $threshold;
Chris@14 24
Chris@14 25 /**
Chris@14 26 * @param int $threshold
Chris@14 27 */
Chris@14 28 public function __construct($threshold = 30)
Chris@14 29 {
Chris@14 30 if (!\is_int($threshold)) {
Chris@14 31 throw InvalidArgumentException::create(
Chris@14 32 1,
Chris@14 33 'integer'
Chris@14 34 );
Chris@14 35 }
Chris@14 36
Chris@14 37 $this->threshold = $threshold;
Chris@14 38 }
Chris@14 39
Chris@14 40 /**
Chris@14 41 * @param CodeCoverage $coverage
Chris@14 42 * @param string $target
Chris@14 43 * @param string $name
Chris@14 44 *
Chris@14 45 * @return string
Chris@14 46 *
Chris@14 47 * @throws \SebastianBergmann\CodeCoverage\RuntimeException
Chris@14 48 */
Chris@14 49 public function process(CodeCoverage $coverage, $target = null, $name = null)
Chris@14 50 {
Chris@14 51 $document = new \DOMDocument('1.0', 'UTF-8');
Chris@14 52 $document->formatOutput = true;
Chris@14 53
Chris@14 54 $root = $document->createElement('crap_result');
Chris@14 55 $document->appendChild($root);
Chris@14 56
Chris@14 57 $project = $document->createElement('project', \is_string($name) ? $name : '');
Chris@14 58 $root->appendChild($project);
Chris@14 59 $root->appendChild($document->createElement('timestamp', \date('Y-m-d H:i:s', (int) $_SERVER['REQUEST_TIME'])));
Chris@14 60
Chris@14 61 $stats = $document->createElement('stats');
Chris@14 62 $methodsNode = $document->createElement('methods');
Chris@14 63
Chris@14 64 $report = $coverage->getReport();
Chris@14 65 unset($coverage);
Chris@14 66
Chris@14 67 $fullMethodCount = 0;
Chris@14 68 $fullCrapMethodCount = 0;
Chris@14 69 $fullCrapLoad = 0;
Chris@14 70 $fullCrap = 0;
Chris@14 71
Chris@14 72 foreach ($report as $item) {
Chris@14 73 $namespace = 'global';
Chris@14 74
Chris@14 75 if (!$item instanceof File) {
Chris@14 76 continue;
Chris@14 77 }
Chris@14 78
Chris@14 79 $file = $document->createElement('file');
Chris@14 80 $file->setAttribute('name', $item->getPath());
Chris@14 81
Chris@14 82 $classes = $item->getClassesAndTraits();
Chris@14 83
Chris@14 84 foreach ($classes as $className => $class) {
Chris@14 85 foreach ($class['methods'] as $methodName => $method) {
Chris@14 86 $crapLoad = $this->getCrapLoad($method['crap'], $method['ccn'], $method['coverage']);
Chris@14 87
Chris@14 88 $fullCrap += $method['crap'];
Chris@14 89 $fullCrapLoad += $crapLoad;
Chris@14 90 $fullMethodCount++;
Chris@14 91
Chris@14 92 if ($method['crap'] >= $this->threshold) {
Chris@14 93 $fullCrapMethodCount++;
Chris@14 94 }
Chris@14 95
Chris@14 96 $methodNode = $document->createElement('method');
Chris@14 97
Chris@14 98 if (!empty($class['package']['namespace'])) {
Chris@14 99 $namespace = $class['package']['namespace'];
Chris@14 100 }
Chris@14 101
Chris@14 102 $methodNode->appendChild($document->createElement('package', $namespace));
Chris@14 103 $methodNode->appendChild($document->createElement('className', $className));
Chris@14 104 $methodNode->appendChild($document->createElement('methodName', $methodName));
Chris@14 105 $methodNode->appendChild($document->createElement('methodSignature', \htmlspecialchars($method['signature'])));
Chris@14 106 $methodNode->appendChild($document->createElement('fullMethod', \htmlspecialchars($method['signature'])));
Chris@14 107 $methodNode->appendChild($document->createElement('crap', $this->roundValue($method['crap'])));
Chris@14 108 $methodNode->appendChild($document->createElement('complexity', $method['ccn']));
Chris@14 109 $methodNode->appendChild($document->createElement('coverage', $this->roundValue($method['coverage'])));
Chris@14 110 $methodNode->appendChild($document->createElement('crapLoad', \round($crapLoad)));
Chris@14 111
Chris@14 112 $methodsNode->appendChild($methodNode);
Chris@14 113 }
Chris@14 114 }
Chris@14 115 }
Chris@14 116
Chris@14 117 $stats->appendChild($document->createElement('name', 'Method Crap Stats'));
Chris@14 118 $stats->appendChild($document->createElement('methodCount', $fullMethodCount));
Chris@14 119 $stats->appendChild($document->createElement('crapMethodCount', $fullCrapMethodCount));
Chris@14 120 $stats->appendChild($document->createElement('crapLoad', \round($fullCrapLoad)));
Chris@14 121 $stats->appendChild($document->createElement('totalCrap', $fullCrap));
Chris@14 122
Chris@14 123 if ($fullMethodCount > 0) {
Chris@14 124 $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount);
Chris@14 125 } else {
Chris@14 126 $crapMethodPercent = 0;
Chris@14 127 }
Chris@14 128
Chris@14 129 $stats->appendChild($document->createElement('crapMethodPercent', $crapMethodPercent));
Chris@14 130
Chris@14 131 $root->appendChild($stats);
Chris@14 132 $root->appendChild($methodsNode);
Chris@14 133
Chris@14 134 $buffer = $document->saveXML();
Chris@14 135
Chris@14 136 if ($target !== null) {
Chris@14 137 if (!\is_dir(\dirname($target))) {
Chris@14 138 \mkdir(\dirname($target), 0777, true);
Chris@14 139 }
Chris@14 140
Chris@14 141 if (@\file_put_contents($target, $buffer) === false) {
Chris@14 142 throw new RuntimeException(
Chris@14 143 \sprintf(
Chris@14 144 'Could not write to "%s',
Chris@14 145 $target
Chris@14 146 )
Chris@14 147 );
Chris@14 148 }
Chris@14 149 }
Chris@14 150
Chris@14 151 return $buffer;
Chris@14 152 }
Chris@14 153
Chris@14 154 /**
Chris@14 155 * @param float $crapValue
Chris@14 156 * @param int $cyclomaticComplexity
Chris@14 157 * @param float $coveragePercent
Chris@14 158 *
Chris@14 159 * @return float
Chris@14 160 */
Chris@14 161 private function getCrapLoad($crapValue, $cyclomaticComplexity, $coveragePercent)
Chris@14 162 {
Chris@14 163 $crapLoad = 0;
Chris@14 164
Chris@14 165 if ($crapValue >= $this->threshold) {
Chris@14 166 $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100);
Chris@14 167 $crapLoad += $cyclomaticComplexity / $this->threshold;
Chris@14 168 }
Chris@14 169
Chris@14 170 return $crapLoad;
Chris@14 171 }
Chris@14 172
Chris@14 173 /**
Chris@14 174 * @param float $value
Chris@14 175 *
Chris@14 176 * @return float
Chris@14 177 */
Chris@14 178 private function roundValue($value)
Chris@14 179 {
Chris@14 180 return \round($value, 2);
Chris@14 181 }
Chris@14 182 }