diff options
Diffstat (limited to 'vendor/phpunit/php-code-coverage/src/StaticAnalysis')
5 files changed, 349 insertions, 237 deletions
diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php index cdaad5613..f53da078a 100644 --- a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php @@ -9,15 +9,15 @@ */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; -use function assert; -use function crc32; use function file_get_contents; use function file_put_contents; +use function implode; use function is_file; +use function md5; use function serialize; -use GlobIterator; +use function unserialize; use SebastianBergmann\CodeCoverage\Util\Filesystem; -use SplFileInfo; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage @@ -50,10 +50,6 @@ final class CachingFileAnalyser implements FileAnalyser $this->analyser = $analyser; $this->directory = $directory; - - if (self::$cacheVersion === null) { - $this->calculateCacheVersion(); - } } public function classesIn(string $filename): array @@ -165,19 +161,24 @@ final class CachingFileAnalyser implements FileAnalyser private function cacheFile(string $filename): string { - return $this->directory . DIRECTORY_SEPARATOR . hash('sha256', $filename . crc32(file_get_contents($filename)) . self::$cacheVersion); + return $this->directory . DIRECTORY_SEPARATOR . md5($filename . "\0" . file_get_contents($filename) . "\0" . self::cacheVersion()); } - private function calculateCacheVersion(): void + private static function cacheVersion(): string { - $buffer = ''; + if (self::$cacheVersion !== null) { + return self::$cacheVersion; + } - foreach (new GlobIterator(__DIR__ . '/*.php') as $file) { - assert($file instanceof SplFileInfo); + $buffer = []; - $buffer .= file_get_contents($file->getPathname()); + foreach ((new FileIteratorFacade)->getFilesAsArray(__DIR__, '.php') as $file) { + $buffer[] = $file; + $buffer[] = file_get_contents($file); } - self::$cacheVersion = (string) crc32($buffer); + self::$cacheVersion = md5(implode("\0", $buffer)); + + return self::$cacheVersion; } } diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php index 8d357b202..8a2003fa8 100644 --- a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php @@ -9,6 +9,7 @@ */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; +use function assert; use function implode; use function rtrim; use function trim; @@ -314,6 +315,8 @@ final class CodeUnitFindingVisitor extends NodeVisitorAbstract if ($_type instanceof Name) { $types[] = $_type->toCodeString(); } else { + assert($_type instanceof Identifier); + $types[] = $_type->toString(); } } diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php index ae0b08ae7..506f27524 100644 --- a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -9,46 +9,19 @@ */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; +use function array_diff_key; +use function assert; +use function count; +use function current; +use function end; +use function explode; +use function max; +use function preg_match; +use function preg_quote; +use function range; +use function reset; +use function sprintf; use PhpParser\Node; -use PhpParser\Node\Expr\Array_; -use PhpParser\Node\Expr\ArrayDimFetch; -use PhpParser\Node\Expr\ArrayItem; -use PhpParser\Node\Expr\Assign; -use PhpParser\Node\Expr\BinaryOp; -use PhpParser\Node\Expr\CallLike; -use PhpParser\Node\Expr\Cast; -use PhpParser\Node\Expr\Closure; -use PhpParser\Node\Expr\Match_; -use PhpParser\Node\Expr\MethodCall; -use PhpParser\Node\Expr\NullsafePropertyFetch; -use PhpParser\Node\Expr\PropertyFetch; -use PhpParser\Node\Expr\StaticPropertyFetch; -use PhpParser\Node\Expr\Ternary; -use PhpParser\Node\MatchArm; -use PhpParser\Node\Scalar\Encapsed; -use PhpParser\Node\Stmt\Break_; -use PhpParser\Node\Stmt\Case_; -use PhpParser\Node\Stmt\Catch_; -use PhpParser\Node\Stmt\Class_; -use PhpParser\Node\Stmt\ClassMethod; -use PhpParser\Node\Stmt\Continue_; -use PhpParser\Node\Stmt\Do_; -use PhpParser\Node\Stmt\Echo_; -use PhpParser\Node\Stmt\Else_; -use PhpParser\Node\Stmt\ElseIf_; -use PhpParser\Node\Stmt\Expression; -use PhpParser\Node\Stmt\Finally_; -use PhpParser\Node\Stmt\For_; -use PhpParser\Node\Stmt\Foreach_; -use PhpParser\Node\Stmt\Goto_; -use PhpParser\Node\Stmt\If_; -use PhpParser\Node\Stmt\Property; -use PhpParser\Node\Stmt\Return_; -use PhpParser\Node\Stmt\Switch_; -use PhpParser\Node\Stmt\Throw_; -use PhpParser\Node\Stmt\TryCatch; -use PhpParser\Node\Stmt\Unset_; -use PhpParser\Node\Stmt\While_; use PhpParser\NodeVisitorAbstract; /** @@ -57,217 +30,337 @@ use PhpParser\NodeVisitorAbstract; final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract { /** - * @psalm-var array<int, int> + * @var int */ - private $executableLines = []; + private $nextBranch = 0; /** - * @psalm-var array<int, int> + * @var string */ - private $propertyLines = []; + private $source; /** - * @psalm-var array<int, Return_> + * @var array<int, int> */ - private $returns = []; + private $executableLinesGroupedByBranch = []; - public function enterNode(Node $node): void + /** + * @var array<int, bool> + */ + private $unsets = []; + + /** + * @var array<int, string> + */ + private $commentsToCheckForUnset = []; + + public function __construct(string $source) { - $this->savePropertyLines($node); + $this->source = $source; + } - if (!$this->isExecutable($node)) { - return; - } + public function enterNode(Node $node): void + { + foreach ($node->getComments() as $comment) { + $commentLine = $comment->getStartLine(); - foreach ($this->getLines($node) as $line) { - if (isset($this->propertyLines[$line])) { - return; + if (!isset($this->executableLinesGroupedByBranch[$commentLine])) { + continue; } - $this->executableLines[$line] = $line; + foreach (explode("\n", $comment->getText()) as $text) { + $this->commentsToCheckForUnset[$commentLine] = $text; + $commentLine++; + } } - } - /** - * @psalm-return array<int, int> - */ - public function executableLines(): array - { - $this->computeReturns(); + if ($node instanceof Node\Scalar\String_ || + $node instanceof Node\Scalar\EncapsedStringPart) { + $startLine = $node->getStartLine() + 1; + $endLine = $node->getEndLine() - 1; - sort($this->executableLines); + if ($startLine <= $endLine) { + foreach (range($startLine, $endLine) as $line) { + unset($this->executableLinesGroupedByBranch[$line]); + } + } - return $this->executableLines; - } + return; + } - private function savePropertyLines(Node $node): void - { - if (!$node instanceof Property && !$node instanceof Node\Stmt\ClassConst) { + if ($node instanceof Node\Stmt\Declare_ || + $node instanceof Node\Stmt\DeclareDeclare || + $node instanceof Node\Stmt\Else_ || + $node instanceof Node\Stmt\EnumCase || + $node instanceof Node\Stmt\Finally_ || + $node instanceof Node\Stmt\Interface_ || + $node instanceof Node\Stmt\Label || + $node instanceof Node\Stmt\Namespace_ || + $node instanceof Node\Stmt\Nop || + $node instanceof Node\Stmt\Switch_ || + $node instanceof Node\Stmt\TryCatch || + $node instanceof Node\Stmt\Use_ || + $node instanceof Node\Stmt\UseUse || + $node instanceof Node\Expr\ConstFetch || + $node instanceof Node\Expr\Match_ || + $node instanceof Node\Expr\Variable || + $node instanceof Node\ComplexType || + $node instanceof Node\Const_ || + $node instanceof Node\Identifier || + $node instanceof Node\Name || + $node instanceof Node\Param || + $node instanceof Node\Scalar) { return; } - foreach (range($node->getStartLine(), $node->getEndLine()) as $index) { - $this->propertyLines[$index] = $index; + if ($node instanceof Node\Stmt\Throw_) { + $this->setLineBranch($node->expr->getEndLine(), $node->expr->getEndLine(), ++$this->nextBranch); + + return; } - } - private function computeReturns(): void - { - foreach ($this->returns as $return) { - foreach (range($return->getStartLine(), $return->getEndLine()) as $loc) { - if (isset($this->executableLines[$loc])) { - continue 2; + if ($node instanceof Node\Stmt\Enum_ || + $node instanceof Node\Stmt\Function_ || + $node instanceof Node\Stmt\Class_ || + $node instanceof Node\Stmt\ClassMethod || + $node instanceof Node\Expr\Closure || + $node instanceof Node\Stmt\Trait_) { + $isConcreteClassLike = $node instanceof Node\Stmt\Enum_ || $node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Trait_; + + if (null !== $node->stmts) { + foreach ($node->stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Nop) { + continue; + } + + foreach (range($stmt->getStartLine(), $stmt->getEndLine()) as $line) { + unset($this->executableLinesGroupedByBranch[$line]); + + if ( + $isConcreteClassLike && + !$stmt instanceof Node\Stmt\ClassMethod + ) { + $this->unsets[$line] = true; + } + } } } - $line = $return->getEndLine(); + if ($isConcreteClassLike) { + return; + } + + $hasEmptyBody = [] === $node->stmts || + null === $node->stmts || + ( + 1 === count($node->stmts) && + $node->stmts[0] instanceof Node\Stmt\Nop + ); + + if ($hasEmptyBody) { + if ($node->getEndLine() === $node->getStartLine()) { + return; + } + + $this->setLineBranch($node->getEndLine(), $node->getEndLine(), ++$this->nextBranch); - if ($return->expr !== null) { - $line = $return->expr->getStartLine(); + return; } - $this->executableLines[$line] = $line; + return; } - } - /** - * @return int[] - */ - private function getLines(Node $node): array - { - if ($node instanceof Cast || - $node instanceof PropertyFetch || - $node instanceof NullsafePropertyFetch || - $node instanceof StaticPropertyFetch) { - return [$node->getEndLine()]; - } + if ($node instanceof Node\Expr\ArrowFunction) { + $startLine = max( + $node->getStartLine() + 1, + $node->expr->getStartLine() + ); - if ($node instanceof ArrayDimFetch) { - if (null === $node->dim) { - return []; + $endLine = $node->expr->getEndLine(); + + if ($endLine < $startLine) { + return; } - return [$node->dim->getStartLine()]; + $this->setLineBranch($startLine, $endLine, ++$this->nextBranch); + + return; } - if ($node instanceof Array_) { - $startLine = $node->getStartLine(); + if ($node instanceof Node\Expr\Ternary) { + if (null !== $node->if && + $node->getStartLine() !== $node->if->getEndLine()) { + $this->setLineBranch($node->if->getStartLine(), $node->if->getEndLine(), ++$this->nextBranch); + } - if (isset($this->executableLines[$startLine])) { - return []; + if ($node->getStartLine() !== $node->else->getEndLine()) { + $this->setLineBranch($node->else->getStartLine(), $node->else->getEndLine(), ++$this->nextBranch); } - if ([] === $node->items) { - return [$node->getEndLine()]; + return; + } + + if ($node instanceof Node\Expr\BinaryOp\Coalesce) { + if ($node->getStartLine() !== $node->getEndLine()) { + $this->setLineBranch($node->getEndLine(), $node->getEndLine(), ++$this->nextBranch); } - if ($node->items[0] instanceof ArrayItem) { - return [$node->items[0]->getStartLine()]; + return; + } + + if ($node instanceof Node\Stmt\If_ || + $node instanceof Node\Stmt\ElseIf_ || + $node instanceof Node\Stmt\Case_) { + if (null === $node->cond) { + return; } + + $this->setLineBranch( + $node->cond->getStartLine(), + $node->cond->getStartLine(), + ++$this->nextBranch + ); + + return; } - if ($node instanceof ClassMethod) { - if ($node->name->name !== '__construct') { - return []; + if ($node instanceof Node\Stmt\For_) { + $startLine = null; + $endLine = null; + + if ([] !== $node->init) { + $startLine = $node->init[0]->getStartLine(); + + end($node->init); + + $endLine = current($node->init)->getEndLine(); + + reset($node->init); } - $existsAPromotedProperty = false; + if ([] !== $node->cond) { + if (null === $startLine) { + $startLine = $node->cond[0]->getStartLine(); + } + + end($node->cond); + + $endLine = current($node->cond)->getEndLine(); - foreach ($node->getParams() as $param) { - if (0 !== ($param->flags & Class_::VISIBILITY_MODIFIER_MASK)) { - $existsAPromotedProperty = true; + reset($node->cond); + } - break; + if ([] !== $node->loop) { + if (null === $startLine) { + $startLine = $node->loop[0]->getStartLine(); } + + end($node->loop); + + $endLine = current($node->loop)->getEndLine(); + + reset($node->loop); } - if ($existsAPromotedProperty) { - // Only the line with `function` keyword should be listed here - // but `nikic/php-parser` doesn't provide a way to fetch it - return range($node->getStartLine(), $node->name->getEndLine()); + if (null === $startLine || null === $endLine) { + return; } - return []; - } + $this->setLineBranch( + $startLine, + $endLine, + ++$this->nextBranch + ); - if ($node instanceof MethodCall) { - return [$node->name->getStartLine()]; + return; } - if ($node instanceof Ternary) { - $lines = [$node->cond->getStartLine()]; + if ($node instanceof Node\Stmt\Foreach_) { + $this->setLineBranch( + $node->expr->getStartLine(), + $node->valueVar->getEndLine(), + ++$this->nextBranch + ); - if (null !== $node->if) { - $lines[] = $node->if->getStartLine(); - } + return; + } - $lines[] = $node->else->getStartLine(); + if ($node instanceof Node\Stmt\While_ || + $node instanceof Node\Stmt\Do_) { + $this->setLineBranch( + $node->cond->getStartLine(), + $node->cond->getEndLine(), + ++$this->nextBranch + ); - return $lines; + return; } - if ($node instanceof Match_) { - return [$node->cond->getStartLine()]; + if ($node instanceof Node\Stmt\Catch_) { + assert([] !== $node->types); + $startLine = $node->types[0]->getStartLine(); + end($node->types); + $endLine = current($node->types)->getEndLine(); + + $this->setLineBranch( + $startLine, + $endLine, + ++$this->nextBranch + ); + + return; } - if ($node instanceof MatchArm) { - return [$node->body->getStartLine()]; + if ($node instanceof Node\Expr\CallLike) { + if (isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { + $branch = $this->executableLinesGroupedByBranch[$node->getStartLine()]; + } else { + $branch = ++$this->nextBranch; + } + + $this->setLineBranch($node->getStartLine(), $node->getEndLine(), $branch); + + return; } - if ($node instanceof Expression && ( - $node->expr instanceof Cast || - $node->expr instanceof Match_ || - $node->expr instanceof MethodCall - )) { - return []; + if (isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { + return; } - if ($node instanceof Return_) { - $this->returns[] = $node; + $this->setLineBranch($node->getStartLine(), $node->getEndLine(), ++$this->nextBranch); + } + + public function afterTraverse(array $nodes): void + { + $lines = explode("\n", $this->source); + + foreach ($lines as $lineNumber => $line) { + $lineNumber++; - return []; + if (1 === preg_match('/^\s*$/', $line) || + ( + isset($this->commentsToCheckForUnset[$lineNumber]) && + 1 === preg_match(sprintf('/^\s*%s\s*$/', preg_quote($this->commentsToCheckForUnset[$lineNumber], '/')), $line) + )) { + unset($this->executableLinesGroupedByBranch[$lineNumber]); + } } - return [$node->getStartLine()]; + $this->executableLinesGroupedByBranch = array_diff_key( + $this->executableLinesGroupedByBranch, + $this->unsets + ); } - private function isExecutable(Node $node): bool + public function executableLinesGroupedByBranch(): array { - return $node instanceof Assign || - $node instanceof ArrayDimFetch || - $node instanceof Array_ || - $node instanceof BinaryOp || - $node instanceof Break_ || - $node instanceof CallLike || - $node instanceof Case_ || - $node instanceof Cast || - $node instanceof Catch_ || - $node instanceof ClassMethod || - $node instanceof Closure || - $node instanceof Continue_ || - $node instanceof Do_ || - $node instanceof Echo_ || - $node instanceof ElseIf_ || - $node instanceof Else_ || - $node instanceof Encapsed || - $node instanceof Expression || - $node instanceof Finally_ || - $node instanceof For_ || - $node instanceof Foreach_ || - $node instanceof Goto_ || - $node instanceof If_ || - $node instanceof Match_ || - $node instanceof MatchArm || - $node instanceof MethodCall || - $node instanceof NullsafePropertyFetch || - $node instanceof PropertyFetch || - $node instanceof Return_ || - $node instanceof StaticPropertyFetch || - $node instanceof Switch_ || - $node instanceof Ternary || - $node instanceof Throw_ || - $node instanceof TryCatch || - $node instanceof Unset_ || - $node instanceof While_; + return $this->executableLinesGroupedByBranch; + } + + private function setLineBranch(int $start, int $end, int $branch): void + { + foreach (range($start, $end) as $line) { + $this->executableLinesGroupedByBranch[$line] = $branch; + } } } diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php index ebb879e84..3c0b2373c 100644 --- a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php @@ -10,9 +10,11 @@ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; use function array_merge; +use function assert; use function range; use function strpos; use PhpParser\Node; +use PhpParser\Node\Attribute; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; @@ -52,7 +54,8 @@ final class IgnoredLinesFindingVisitor extends NodeVisitorAbstract !$node instanceof Trait_ && !$node instanceof Interface_ && !$node instanceof ClassMethod && - !$node instanceof Function_) { + !$node instanceof Function_ && + !$node instanceof Attribute) { return; } @@ -60,11 +63,16 @@ final class IgnoredLinesFindingVisitor extends NodeVisitorAbstract return; } - // Workaround for https://bugs.xdebug.org/view.php?id=1798 if ($node instanceof Class_ || $node instanceof Trait_ || - $node instanceof Interface_) { + $node instanceof Interface_ || + $node instanceof Attribute) { $this->ignoredLines[] = $node->getStartLine(); + + assert($node->name !== null); + + // Workaround for https://github.com/nikic/PHP-Parser/issues/886 + $this->ignoredLines[] = $node->name->getStartLine(); } if (!$this->useAnnotationsForIgnoringCode) { @@ -75,6 +83,19 @@ final class IgnoredLinesFindingVisitor extends NodeVisitorAbstract return; } + $this->processDocComment($node); + } + + /** + * @psalm-return list<int> + */ + public function ignoredLines(): array + { + return $this->ignoredLines; + } + + private function processDocComment(Node $node): void + { $docComment = $node->getDocComment(); if ($docComment === null) { @@ -95,12 +116,4 @@ final class IgnoredLinesFindingVisitor extends NodeVisitorAbstract ); } } - - /** - * @psalm-return list<int> - */ - public function ignoredLines(): array - { - return $this->ignoredLines; - } } diff --git a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php index 8edf973e2..e68638219 100644 --- a/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php +++ b/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php @@ -9,11 +9,14 @@ */ namespace SebastianBergmann\CodeCoverage\StaticAnalysis; +use function array_merge; use function array_unique; use function assert; use function file_get_contents; use function is_array; use function max; +use function range; +use function sort; use function sprintf; use function substr_count; use function token_get_all; @@ -153,7 +156,7 @@ final class ParsingFileAnalyser implements FileAnalyser $codeUnitFindingVisitor = new CodeUnitFindingVisitor; $lineCountingVisitor = new LineCountingVisitor($linesOfCode); $ignoredLinesFindingVisitor = new IgnoredLinesFindingVisitor($this->useAnnotationsForIgnoringCode, $this->ignoreDeprecatedCode); - $executableLinesFindingVisitor = new ExecutableLinesFindingVisitor; + $executableLinesFindingVisitor = new ExecutableLinesFindingVisitor($source); $traverser->addVisitor(new NameResolver); $traverser->addVisitor(new ParentConnectingVisitor); @@ -172,7 +175,7 @@ final class ParsingFileAnalyser implements FileAnalyser $filename, $error->getMessage() ), - (int) $error->getCode(), + $error->getCode(), $error ); } @@ -181,7 +184,7 @@ final class ParsingFileAnalyser implements FileAnalyser $this->classes[$filename] = $codeUnitFindingVisitor->classes(); $this->traits[$filename] = $codeUnitFindingVisitor->traits(); $this->functions[$filename] = $codeUnitFindingVisitor->functions(); - $this->executableLines[$filename] = $executableLinesFindingVisitor->executableLines(); + $this->executableLines[$filename] = $executableLinesFindingVisitor->executableLinesGroupedByBranch(); $this->ignoredLines[$filename] = []; $this->findLinesIgnoredByLineBasedAnnotations($filename, $source, $this->useAnnotationsForIgnoringCode); @@ -206,45 +209,44 @@ final class ParsingFileAnalyser implements FileAnalyser private function findLinesIgnoredByLineBasedAnnotations(string $filename, string $source, bool $useAnnotationsForIgnoringCode): void { - $ignore = false; - $stop = false; + if (!$useAnnotationsForIgnoringCode) { + return; + } + + $start = false; foreach (token_get_all($source) as $token) { - if (!is_array($token)) { + if (!is_array($token) || + !(T_COMMENT === $token[0] || T_DOC_COMMENT === $token[0])) { continue; } - switch ($token[0]) { - case T_COMMENT: - case T_DOC_COMMENT: - if (!$useAnnotationsForIgnoringCode) { - break; - } - - $comment = trim($token[1]); - - if ($comment === '// @codeCoverageIgnore' || - $comment === '//@codeCoverageIgnore') { - $ignore = true; - $stop = true; - } elseif ($comment === '// @codeCoverageIgnoreStart' || - $comment === '//@codeCoverageIgnoreStart') { - $ignore = true; - } elseif ($comment === '// @codeCoverageIgnoreEnd' || - $comment === '//@codeCoverageIgnoreEnd') { - $stop = true; - } - - break; - } + $comment = trim($token[1]); - if ($ignore) { + if ($comment === '// @codeCoverageIgnore' || + $comment === '//@codeCoverageIgnore') { $this->ignoredLines[$filename][] = $token[2]; - if ($stop) { - $ignore = false; - $stop = false; + continue; + } + + if ($comment === '// @codeCoverageIgnoreStart' || + $comment === '//@codeCoverageIgnoreStart') { + $start = $token[2]; + + continue; + } + + if ($comment === '// @codeCoverageIgnoreEnd' || + $comment === '//@codeCoverageIgnoreEnd') { + if (false === $start) { + $start = $token[2]; } + + $this->ignoredLines[$filename] = array_merge( + $this->ignoredLines[$filename], + range($start, $token[2]) + ); } } } |