Calculator.php 2.3 KB

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