annotate vendor/phpunit/php-code-coverage/src/Node/Builder.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\CodeCoverage;
Chris@14 14
Chris@14 15 class Builder
Chris@14 16 {
Chris@14 17 /**
Chris@14 18 * @param CodeCoverage $coverage
Chris@14 19 *
Chris@14 20 * @return Directory
Chris@14 21 */
Chris@14 22 public function build(CodeCoverage $coverage)
Chris@14 23 {
Chris@14 24 $files = $coverage->getData();
Chris@14 25 $commonPath = $this->reducePaths($files);
Chris@14 26 $root = new Directory(
Chris@14 27 $commonPath,
Chris@14 28 null
Chris@14 29 );
Chris@14 30
Chris@14 31 $this->addItems(
Chris@14 32 $root,
Chris@14 33 $this->buildDirectoryStructure($files),
Chris@14 34 $coverage->getTests(),
Chris@14 35 $coverage->getCacheTokens()
Chris@14 36 );
Chris@14 37
Chris@14 38 return $root;
Chris@14 39 }
Chris@14 40
Chris@14 41 /**
Chris@14 42 * @param Directory $root
Chris@14 43 * @param array $items
Chris@14 44 * @param array $tests
Chris@14 45 * @param bool $cacheTokens
Chris@14 46 */
Chris@14 47 private function addItems(Directory $root, array $items, array $tests, $cacheTokens)
Chris@14 48 {
Chris@14 49 foreach ($items as $key => $value) {
Chris@14 50 if (\substr($key, -2) == '/f') {
Chris@14 51 $key = \substr($key, 0, -2);
Chris@14 52
Chris@14 53 if (\file_exists($root->getPath() . DIRECTORY_SEPARATOR . $key)) {
Chris@14 54 $root->addFile($key, $value, $tests, $cacheTokens);
Chris@14 55 }
Chris@14 56 } else {
Chris@14 57 $child = $root->addDirectory($key);
Chris@14 58 $this->addItems($child, $value, $tests, $cacheTokens);
Chris@14 59 }
Chris@14 60 }
Chris@14 61 }
Chris@14 62
Chris@14 63 /**
Chris@14 64 * Builds an array representation of the directory structure.
Chris@14 65 *
Chris@14 66 * For instance,
Chris@14 67 *
Chris@14 68 * <code>
Chris@14 69 * Array
Chris@14 70 * (
Chris@14 71 * [Money.php] => Array
Chris@14 72 * (
Chris@14 73 * ...
Chris@14 74 * )
Chris@14 75 *
Chris@14 76 * [MoneyBag.php] => Array
Chris@14 77 * (
Chris@14 78 * ...
Chris@14 79 * )
Chris@14 80 * )
Chris@14 81 * </code>
Chris@14 82 *
Chris@14 83 * is transformed into
Chris@14 84 *
Chris@14 85 * <code>
Chris@14 86 * Array
Chris@14 87 * (
Chris@14 88 * [.] => Array
Chris@14 89 * (
Chris@14 90 * [Money.php] => Array
Chris@14 91 * (
Chris@14 92 * ...
Chris@14 93 * )
Chris@14 94 *
Chris@14 95 * [MoneyBag.php] => Array
Chris@14 96 * (
Chris@14 97 * ...
Chris@14 98 * )
Chris@14 99 * )
Chris@14 100 * )
Chris@14 101 * </code>
Chris@14 102 *
Chris@14 103 * @param array $files
Chris@14 104 *
Chris@14 105 * @return array
Chris@14 106 */
Chris@14 107 private function buildDirectoryStructure($files)
Chris@14 108 {
Chris@14 109 $result = [];
Chris@14 110
Chris@14 111 foreach ($files as $path => $file) {
Chris@14 112 $path = \explode('/', $path);
Chris@14 113 $pointer = &$result;
Chris@14 114 $max = \count($path);
Chris@14 115
Chris@14 116 for ($i = 0; $i < $max; $i++) {
Chris@14 117 if ($i == ($max - 1)) {
Chris@14 118 $type = '/f';
Chris@14 119 } else {
Chris@14 120 $type = '';
Chris@14 121 }
Chris@14 122
Chris@14 123 $pointer = &$pointer[$path[$i] . $type];
Chris@14 124 }
Chris@14 125
Chris@14 126 $pointer = $file;
Chris@14 127 }
Chris@14 128
Chris@14 129 return $result;
Chris@14 130 }
Chris@14 131
Chris@14 132 /**
Chris@14 133 * Reduces the paths by cutting the longest common start path.
Chris@14 134 *
Chris@14 135 * For instance,
Chris@14 136 *
Chris@14 137 * <code>
Chris@14 138 * Array
Chris@14 139 * (
Chris@14 140 * [/home/sb/Money/Money.php] => Array
Chris@14 141 * (
Chris@14 142 * ...
Chris@14 143 * )
Chris@14 144 *
Chris@14 145 * [/home/sb/Money/MoneyBag.php] => Array
Chris@14 146 * (
Chris@14 147 * ...
Chris@14 148 * )
Chris@14 149 * )
Chris@14 150 * </code>
Chris@14 151 *
Chris@14 152 * is reduced to
Chris@14 153 *
Chris@14 154 * <code>
Chris@14 155 * Array
Chris@14 156 * (
Chris@14 157 * [Money.php] => Array
Chris@14 158 * (
Chris@14 159 * ...
Chris@14 160 * )
Chris@14 161 *
Chris@14 162 * [MoneyBag.php] => Array
Chris@14 163 * (
Chris@14 164 * ...
Chris@14 165 * )
Chris@14 166 * )
Chris@14 167 * </code>
Chris@14 168 *
Chris@14 169 * @param array $files
Chris@14 170 *
Chris@14 171 * @return string
Chris@14 172 */
Chris@14 173 private function reducePaths(&$files)
Chris@14 174 {
Chris@14 175 if (empty($files)) {
Chris@14 176 return '.';
Chris@14 177 }
Chris@14 178
Chris@14 179 $commonPath = '';
Chris@14 180 $paths = \array_keys($files);
Chris@14 181
Chris@14 182 if (\count($files) == 1) {
Chris@14 183 $commonPath = \dirname($paths[0]) . '/';
Chris@14 184 $files[\basename($paths[0])] = $files[$paths[0]];
Chris@14 185
Chris@14 186 unset($files[$paths[0]]);
Chris@14 187
Chris@14 188 return $commonPath;
Chris@14 189 }
Chris@14 190
Chris@14 191 $max = \count($paths);
Chris@14 192
Chris@14 193 for ($i = 0; $i < $max; $i++) {
Chris@14 194 // strip phar:// prefixes
Chris@14 195 if (\strpos($paths[$i], 'phar://') === 0) {
Chris@14 196 $paths[$i] = \substr($paths[$i], 7);
Chris@14 197 $paths[$i] = \strtr($paths[$i], '/', DIRECTORY_SEPARATOR);
Chris@14 198 }
Chris@14 199 $paths[$i] = \explode(DIRECTORY_SEPARATOR, $paths[$i]);
Chris@14 200
Chris@14 201 if (empty($paths[$i][0])) {
Chris@14 202 $paths[$i][0] = DIRECTORY_SEPARATOR;
Chris@14 203 }
Chris@14 204 }
Chris@14 205
Chris@14 206 $done = false;
Chris@14 207 $max = \count($paths);
Chris@14 208
Chris@14 209 while (!$done) {
Chris@14 210 for ($i = 0; $i < $max - 1; $i++) {
Chris@14 211 if (!isset($paths[$i][0]) ||
Chris@14 212 !isset($paths[$i + 1][0]) ||
Chris@14 213 $paths[$i][0] != $paths[$i + 1][0]) {
Chris@14 214 $done = true;
Chris@14 215
Chris@14 216 break;
Chris@14 217 }
Chris@14 218 }
Chris@14 219
Chris@14 220 if (!$done) {
Chris@14 221 $commonPath .= $paths[0][0];
Chris@14 222
Chris@14 223 if ($paths[0][0] != DIRECTORY_SEPARATOR) {
Chris@14 224 $commonPath .= DIRECTORY_SEPARATOR;
Chris@14 225 }
Chris@14 226
Chris@14 227 for ($i = 0; $i < $max; $i++) {
Chris@14 228 \array_shift($paths[$i]);
Chris@14 229 }
Chris@14 230 }
Chris@14 231 }
Chris@14 232
Chris@14 233 $original = \array_keys($files);
Chris@14 234 $max = \count($original);
Chris@14 235
Chris@14 236 for ($i = 0; $i < $max; $i++) {
Chris@14 237 $files[\implode('/', $paths[$i])] = $files[$original[$i]];
Chris@14 238 unset($files[$original[$i]]);
Chris@14 239 }
Chris@14 240
Chris@14 241 \ksort($files);
Chris@14 242
Chris@14 243 return \substr($commonPath, 0, -1);
Chris@14 244 }
Chris@14 245 }