diff --git a/composer.json b/composer.json index 6527ed2f3..e315a9bf4 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "phpunit/php-text-template": "^1.2", "sebastian/code-unit-reverse-lookup": "^1.0", "sebastian/environment": "^2.0", - "sebastian/version": "^2.0" + "sebastian/version": "^2.0", + "theseer/tokenizer": "^1.1" }, "require-dev": { "phpunit/phpunit": "^6.0", diff --git a/src/Report/Xml/Facade.php b/src/Report/Xml/Facade.php index 9cfbd7aaa..d7511bde5 100644 --- a/src/Report/Xml/Facade.php +++ b/src/Report/Xml/Facade.php @@ -148,7 +148,7 @@ private function processFile(FileNode $file, Directory $context) } foreach ($file->getCoverageData() as $line => $tests) { - if (!is_array($tests) || count($tests) == 0) { + if (!is_array($tests) || count($tests) === 0) { continue; } @@ -161,6 +161,10 @@ private function processFile(FileNode $file, Directory $context) $coverage->finalize(); } + $fileReport->getSource()->setSourceCode( + file_get_contents($file->getPath()) + ); + $this->saveDocument($fileReport->asDom(), $file->getId()); } diff --git a/src/Report/Xml/Report.php b/src/Report/Xml/Report.php index a6e1e63ba..455524fe6 100644 --- a/src/Report/Xml/Report.php +++ b/src/Report/Xml/Report.php @@ -70,4 +70,23 @@ private function getUnitObject($tagName, $name) return new Unit($node, $name); } + + public function getSource() + { + $source = $this->getContextNode()->getElementsByTagNameNS( + 'http://schema.phpunit.de/coverage/1.0', + 'source' + )->item(0); + + if (!$source) { + $source = $this->getContextNode()->appendChild( + $this->getDomDocument()->createElementNS( + 'http://schema.phpunit.de/coverage/1.0', + 'source' + ) + ); + } + + return new Source($source); + } } diff --git a/src/Report/Xml/Source.php b/src/Report/Xml/Source.php new file mode 100644 index 000000000..f6780f2d5 --- /dev/null +++ b/src/Report/Xml/Source.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use TheSeer\Tokenizer\NamespaceUri; +use TheSeer\Tokenizer\Tokenizer; +use TheSeer\Tokenizer\XMLSerializer; + +class Source +{ + /** @var \DOMElement */ + private $context; + + /** + * @param \DOMElement $context + */ + public function __construct(\DOMElement $context) + { + $this->context = $context; + } + + /** + * @param string $source + */ + public function setSourceCode(string $source) + { + $context = $this->context; + + $tokens = (new Tokenizer())->parse($source); + $srcDom = (new XMLSerializer(new NamespaceUri($context->namespaceURI)))->toDom($tokens); + + $context->parentNode->replaceChild( + $context->ownerDocument->importNode($srcDom->documentElement, true), + $context + ); + } +} diff --git a/tests/_files/Report/XML/CoverageForBankAccount/BankAccount.php.xml b/tests/_files/Report/XML/CoverageForBankAccount/BankAccount.php.xml index 4186c8bf9..63cc369ec 100644 --- a/tests/_files/Report/XML/CoverageForBankAccount/BankAccount.php.xml +++ b/tests/_files/Report/XML/CoverageForBankAccount/BankAccount.php.xml @@ -36,5 +36,227 @@ + + + <?php + + + class + + BankAccount + + + { + + + + protected + + $balance + + = + + 0 + ; + + + + + public + + function + + getBalance + ( + ) + + + + { + + + + return + + $this + -> + balance + ; + + + + } + + + + + protected + + function + + setBalance + ( + $balance + ) + + + + { + + + + if + + ( + $balance + + >= + + 0 + ) + + { + + + + $this + -> + balance + + = + + $balance + ; + + + + } + + else + + { + + + + throw + + new + + RuntimeException + ; + + + + } + + + + } + + + + + public + + function + + depositMoney + ( + $balance + ) + + + + { + + + + $this + -> + setBalance + ( + $this + -> + getBalance + ( + ) + + + + + $balance + ) + ; + + + + + return + + $this + -> + getBalance + ( + ) + ; + + + + } + + + + + public + + function + + withdrawMoney + ( + $balance + ) + + + + { + + + + $this + -> + setBalance + ( + $this + -> + getBalance + ( + ) + + - + + $balance + ) + ; + + + + + return + + $this + -> + getBalance + ( + ) + ; + + + + } + + + } + + + diff --git a/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.xml b/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.xml index d6e1da7ea..c22518d8d 100644 --- a/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.xml +++ b/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.xml @@ -37,5 +37,126 @@ + + + <?php + + + + class + + CoveredClassWithAnonymousFunctionInStaticMethod + + + { + + + + public + + static + + function + + runAnonymous + ( + ) + + + + { + + + + $filter + + = + + [ + 'abc124' + , + + 'abc123' + , + + '123' + ] + ; + + + + + array_walk + ( + + + + $filter + , + + + + function + + ( + & + $val + , + + $key + ) + + { + + + + $val + + = + + preg_replace + ( + '|[^0-9]|' + , + + '' + , + + $val + ) + ; + + + + } + + + + ) + ; + + + + + // Should be covered + + + + $extravar + + = + + true + ; + + + + } + + + } + + + diff --git a/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/source_with_ignore.php.xml b/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/source_with_ignore.php.xml index 5f8ce25b6..9a8fc6621 100644 --- a/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/source_with_ignore.php.xml +++ b/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/source_with_ignore.php.xml @@ -24,5 +24,164 @@ + + + <?php + + + if + + ( + $neverHappens + ) + + { + + + + // @codeCoverageIgnoreStart + + + + print + + '*' + ; + + + + // @codeCoverageIgnoreEnd + + + } + + + + /** + + + * @codeCoverageIgnore + + + */ + + + class + + Foo + + + { + + + + public + + function + + bar + ( + ) + + + + { + + + + } + + + } + + + + class + + Bar + + + { + + + + /** + + + * @codeCoverageIgnore + + + */ + + + + public + + function + + foo + ( + ) + + + + { + + + + } + + + } + + + + function + + baz + ( + ) + + + { + + + + print + + '*' + ; + + // @codeCoverageIgnore + + + } + + + + interface + + Bor + + + { + + + + public + + function + + foo + ( + ) + ; + + + + } + + +