Calculator.php 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of sebastian/complexity.
  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\Complexity;
  11. use PhpParser\Error;
  12. use PhpParser\Node;
  13. use PhpParser\NodeTraverser;
  14. use PhpParser\NodeVisitor\NameResolver;
  15. use PhpParser\NodeVisitor\ParentConnectingVisitor;
  16. use PhpParser\ParserFactory;
  17. final class Calculator
  18. {
  19. /**
  20. * @throws RuntimeException
  21. */
  22. public function calculateForSourceFile(string $sourceFile): ComplexityCollection
  23. {
  24. return $this->calculateForSourceString(file_get_contents($sourceFile));
  25. }
  26. /**
  27. * @throws RuntimeException
  28. */
  29. public function calculateForSourceString(string $source): ComplexityCollection
  30. {
  31. try {
  32. $nodes = (new ParserFactory)->createForHostVersion()->parse($source);
  33. assert($nodes !== null);
  34. return $this->calculateForAbstractSyntaxTree($nodes);
  35. // @codeCoverageIgnoreStart
  36. } catch (Error $error) {
  37. throw new RuntimeException(
  38. $error->getMessage(),
  39. (int) $error->getCode(),
  40. $error
  41. );
  42. }
  43. // @codeCoverageIgnoreEnd
  44. }
  45. /**
  46. * @param Node[] $nodes
  47. *
  48. * @throws RuntimeException
  49. */
  50. public function calculateForAbstractSyntaxTree(array $nodes): ComplexityCollection
  51. {
  52. $traverser = new NodeTraverser;
  53. $complexityCalculatingVisitor = new ComplexityCalculatingVisitor(true);
  54. $traverser->addVisitor(new NameResolver);
  55. $traverser->addVisitor(new ParentConnectingVisitor);
  56. $traverser->addVisitor($complexityCalculatingVisitor);
  57. try {
  58. /* @noinspection UnusedFunctionResultInspection */
  59. $traverser->traverse($nodes);
  60. // @codeCoverageIgnoreStart
  61. } catch (Error $error) {
  62. throw new RuntimeException(
  63. $error->getMessage(),
  64. (int) $error->getCode(),
  65. $error
  66. );
  67. }
  68. // @codeCoverageIgnoreEnd
  69. return $complexityCalculatingVisitor->result();
  70. }
  71. }