AbstractNode.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of phpunit/php-code-coverage.
  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. namespace SebastianBergmann\CodeCoverage\Node;
  11. use const DIRECTORY_SEPARATOR;
  12. use function array_merge;
  13. use function str_ends_with;
  14. use function str_replace;
  15. use function substr;
  16. use Countable;
  17. use SebastianBergmann\CodeCoverage\Util\Percentage;
  18. /**
  19. * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage
  20. *
  21. * @psalm-import-type LinesOfCodeType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser
  22. * @psalm-import-type ProcessedFunctionType from \SebastianBergmann\CodeCoverage\Node\File
  23. * @psalm-import-type ProcessedClassType from \SebastianBergmann\CodeCoverage\Node\File
  24. * @psalm-import-type ProcessedTraitType from \SebastianBergmann\CodeCoverage\Node\File
  25. */
  26. abstract class AbstractNode implements Countable
  27. {
  28. private readonly string $name;
  29. private string $pathAsString;
  30. private array $pathAsArray;
  31. private readonly ?AbstractNode $parent;
  32. private string $id;
  33. public function __construct(string $name, ?self $parent = null)
  34. {
  35. if (str_ends_with($name, DIRECTORY_SEPARATOR)) {
  36. $name = substr($name, 0, -1);
  37. }
  38. $this->name = $name;
  39. $this->parent = $parent;
  40. $this->processId();
  41. $this->processPath();
  42. }
  43. public function name(): string
  44. {
  45. return $this->name;
  46. }
  47. public function id(): string
  48. {
  49. return $this->id;
  50. }
  51. public function pathAsString(): string
  52. {
  53. return $this->pathAsString;
  54. }
  55. public function pathAsArray(): array
  56. {
  57. return $this->pathAsArray;
  58. }
  59. public function parent(): ?self
  60. {
  61. return $this->parent;
  62. }
  63. public function percentageOfTestedClasses(): Percentage
  64. {
  65. return Percentage::fromFractionAndTotal(
  66. $this->numberOfTestedClasses(),
  67. $this->numberOfClasses(),
  68. );
  69. }
  70. public function percentageOfTestedTraits(): Percentage
  71. {
  72. return Percentage::fromFractionAndTotal(
  73. $this->numberOfTestedTraits(),
  74. $this->numberOfTraits(),
  75. );
  76. }
  77. public function percentageOfTestedClassesAndTraits(): Percentage
  78. {
  79. return Percentage::fromFractionAndTotal(
  80. $this->numberOfTestedClassesAndTraits(),
  81. $this->numberOfClassesAndTraits(),
  82. );
  83. }
  84. public function percentageOfTestedFunctions(): Percentage
  85. {
  86. return Percentage::fromFractionAndTotal(
  87. $this->numberOfTestedFunctions(),
  88. $this->numberOfFunctions(),
  89. );
  90. }
  91. public function percentageOfTestedMethods(): Percentage
  92. {
  93. return Percentage::fromFractionAndTotal(
  94. $this->numberOfTestedMethods(),
  95. $this->numberOfMethods(),
  96. );
  97. }
  98. public function percentageOfTestedFunctionsAndMethods(): Percentage
  99. {
  100. return Percentage::fromFractionAndTotal(
  101. $this->numberOfTestedFunctionsAndMethods(),
  102. $this->numberOfFunctionsAndMethods(),
  103. );
  104. }
  105. public function percentageOfExecutedLines(): Percentage
  106. {
  107. return Percentage::fromFractionAndTotal(
  108. $this->numberOfExecutedLines(),
  109. $this->numberOfExecutableLines(),
  110. );
  111. }
  112. public function percentageOfExecutedBranches(): Percentage
  113. {
  114. return Percentage::fromFractionAndTotal(
  115. $this->numberOfExecutedBranches(),
  116. $this->numberOfExecutableBranches(),
  117. );
  118. }
  119. public function percentageOfExecutedPaths(): Percentage
  120. {
  121. return Percentage::fromFractionAndTotal(
  122. $this->numberOfExecutedPaths(),
  123. $this->numberOfExecutablePaths(),
  124. );
  125. }
  126. public function numberOfClassesAndTraits(): int
  127. {
  128. return $this->numberOfClasses() + $this->numberOfTraits();
  129. }
  130. public function numberOfTestedClassesAndTraits(): int
  131. {
  132. return $this->numberOfTestedClasses() + $this->numberOfTestedTraits();
  133. }
  134. public function classesAndTraits(): array
  135. {
  136. return array_merge($this->classes(), $this->traits());
  137. }
  138. public function numberOfFunctionsAndMethods(): int
  139. {
  140. return $this->numberOfFunctions() + $this->numberOfMethods();
  141. }
  142. public function numberOfTestedFunctionsAndMethods(): int
  143. {
  144. return $this->numberOfTestedFunctions() + $this->numberOfTestedMethods();
  145. }
  146. /**
  147. * @psalm-return array<string, ProcessedClassType>
  148. */
  149. abstract public function classes(): array;
  150. /**
  151. * @psalm-return array<string, ProcessedTraitType>
  152. */
  153. abstract public function traits(): array;
  154. /**
  155. * @psalm-return array<string, ProcessedFunctionType>
  156. */
  157. abstract public function functions(): array;
  158. /**
  159. * @psalm-return LinesOfCodeType
  160. */
  161. abstract public function linesOfCode(): array;
  162. abstract public function numberOfExecutableLines(): int;
  163. abstract public function numberOfExecutedLines(): int;
  164. abstract public function numberOfExecutableBranches(): int;
  165. abstract public function numberOfExecutedBranches(): int;
  166. abstract public function numberOfExecutablePaths(): int;
  167. abstract public function numberOfExecutedPaths(): int;
  168. abstract public function numberOfClasses(): int;
  169. abstract public function numberOfTestedClasses(): int;
  170. abstract public function numberOfTraits(): int;
  171. abstract public function numberOfTestedTraits(): int;
  172. abstract public function numberOfMethods(): int;
  173. abstract public function numberOfTestedMethods(): int;
  174. abstract public function numberOfFunctions(): int;
  175. abstract public function numberOfTestedFunctions(): int;
  176. private function processId(): void
  177. {
  178. if ($this->parent === null) {
  179. $this->id = 'index';
  180. return;
  181. }
  182. $parentId = $this->parent->id();
  183. if ($parentId === 'index') {
  184. $this->id = str_replace(':', '_', $this->name);
  185. } else {
  186. $this->id = $parentId . '/' . $this->name;
  187. }
  188. }
  189. private function processPath(): void
  190. {
  191. if ($this->parent === null) {
  192. $this->pathAsArray = [$this];
  193. $this->pathAsString = $this->name;
  194. return;
  195. }
  196. $this->pathAsArray = $this->parent->pathAsArray();
  197. $this->pathAsString = $this->parent->pathAsString() . DIRECTORY_SEPARATOR . $this->name;
  198. $this->pathAsArray[] = $this;
  199. }
  200. }