diff --git a/.travis.yml b/.travis.yml index c3af704..96b48e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,15 +6,11 @@ cache: - $HOME/.cache/composer/files matrix: include: - - php: 5.6 - php: 7.0 - php: 7.1 - env: UPDATE_COVERAGE=1 - php: 7.2 - - php: nightly - - php: hhvm - allow_failures: - - php: hhvm + env: UPDATE_COVERAGE=1 + - php: 7.3 - php: nightly fast_finish: true before_script: diff --git a/GitHooks/pre-commit b/GitHooks/pre-commit new file mode 100644 index 0000000..7aac0ba --- /dev/null +++ b/GitHooks/pre-commit @@ -0,0 +1,17 @@ +#!/bin/bash -e + +# This is a PSR-2 checking example for just the code about to be committed + +# Get the changes +files=$(mktemp) +diff=$(mktemp) + +git diff --cached --name-only --diff-filter=ACMR -- "*.php" > ${files} +git diff --cached > ${diff} + +# Run the phpcs report +phpcs=$(mktemp) +./vendor/bin/phpcs --file-list=${files} --parallel=2 --standard=psr2 --report=json > ${phpcs} || true + +check for differences +./vendor/bin/diffFilter --phpcs diff.txt phpcs.json \ No newline at end of file diff --git a/GitHooks/pre-receive b/GitHooks/pre-receive new file mode 100644 index 0000000..cf0b362 --- /dev/null +++ b/GitHooks/pre-receive @@ -0,0 +1,17 @@ +#!/bin/bash + +# This is a PSR-2 checking example for just the code about to be committed + +# Get the changes +files=$(mktemp) +diff=$(mktemp) + +git diff --name-only --diff-filter=ACMR -- "*.php" $1...$2 > ${files} +git diff $1...$2 > ${diff} + +# Run the phpcs report +phpcs=$(mktemp) +./vendor/bin/phpcs --file-list=${files} --parallel=2 --standard=psr2 --report=json > ${phpcs} || true + +check for differences +./vendor/bin/diffFilter --phpcs diff.txt phpcs.json diff --git a/README.md b/README.md index 2576483..e73a764 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Coverage checker allows new standards to be implemented incrementally, by only e Tools like phpcs and phpmd are an all or nothing approach, coverage checker allows this to work with the diff i.e. enforce all of the pull request / change request. +This is sometimes called "Baselining" + Also working with PHPunit to allow, for example 90% of new/edited code to be covered. which will increase the overall coverage over time. # Installing @@ -54,6 +56,12 @@ diffFilter will exit with a `0` status if the changed code passes the minimum co ## Extended guide A more in depth guide can be [found on the wiki](https://github.com/exussum12/coverageChecker/wiki) also some tips for speeding up the build. +## Installing as a git hook + +There are 2 examples hooks in the GitHooks directory, if you symlink to these diffFilter will run locally. + +pre-commit is before the commit happens +pre-receive will prevent you pushing # Full list of available diff filters diff --git a/bin/phpcsDiffFilter b/bin/phpcsDiffFilter deleted file mode 100755 index bf5d5ea..0000000 --- a/bin/phpcsDiffFilter +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env php -=5.5", + "php": ">=7.0", + "ext-xmlreader": "*", + "ext-json": "*", "nikic/php-parser": "^3.1||^4.0" } } diff --git a/examples/phpcsEnforce.sh b/examples/phpcsEnforce.sh index 94fc8a7..db02c83 100644 --- a/examples/phpcsEnforce.sh +++ b/examples/phpcsEnforce.sh @@ -6,12 +6,11 @@ set -e # Get the diff (changes since the branch was created git diff origin/master... > diff.txt -git diff origin/master... --name-only -- '*.php' > files.txt +git diff origin/master... --name-only --diff-filter=ACMR -- '*.php' > files.txt # Old versions of phpcs will need to use the syntax commented out. # Note the || true is important, Without this phpcs failing will fail the build! -# ./vendor/bin/phpcs --standard=psr2 src > phpcs.json || true ./vendor/bin/phpcs --file-list=files.txt --parallel=2 --standard=psr2 --report=json > phpcs.json || true diff --git a/src/ArgParser.php b/src/ArgParser.php index 9f0874c..ac4cc98 100644 --- a/src/ArgParser.php +++ b/src/ArgParser.php @@ -1,6 +1,8 @@ args = $args; } - public function getArg($name) + /** + * @throws ArgumentNotFound + */ + public function getArg(string $name): string { if (is_numeric($name)) { + $name = (int) $name; return $this->numericArg($name); } return $this->letterArg($name); } - protected function numericArg($position) + protected function numericArg(int $position): string { foreach ($this->args as $arg) { if ($arg{0} != '-' && $position-- == 0) { @@ -27,10 +33,10 @@ protected function numericArg($position) } } - return null; + throw new ArgumentNotFound(); } - protected function letterArg($name) + protected function letterArg($name): string { $name = $this->getAdjustedArg($name); foreach ($this->args as $arg) { @@ -41,24 +47,20 @@ protected function letterArg($name) } } - return false; + throw new ArgumentNotFound(); } - protected function splitArg($arg) + protected function splitArg(string $arg): array { - $value = true; - if (strpos($arg, '=')) { + $value = '1'; + if (strpos($arg, '=') > 0) { list($arg, $value) = explode('=', $arg, 2); } return array($value, $arg); } - /** - * @param string $name - * @return string - */ - protected function getAdjustedArg($name) + protected function getAdjustedArg(string $name): string { $name = strlen($name) == 1 ? '-' . $name : diff --git a/src/CodeLimits.php b/src/CodeLimits.php index 39bc76f..29b36d1 100644 --- a/src/CodeLimits.php +++ b/src/CodeLimits.php @@ -6,18 +6,18 @@ class CodeLimits protected $startLine; protected $endLine; - public function __construct($startLine, $endLine) + public function __construct(int $startLine, int $endLine) { $this->startLine = $startLine; $this->endLine = $endLine; } - public function getStartLine() + public function getStartLine(): int { return $this->startLine; } - public function getEndLine() + public function getEndLine(): int { return $this->endLine; } diff --git a/src/CoverageCheck.php b/src/CoverageCheck.php index bf56bd2..1003f81 100644 --- a/src/CoverageCheck.php +++ b/src/CoverageCheck.php @@ -45,10 +45,6 @@ class CoverageCheck * For example if the checker is phpunit, this class filters the phpunit * output by the diff of the pull request. giving only the common lines in * each - * - * @param DiffFileLoader $diff - * @param FileChecker $fileChecker - * @param FileMatcher $matcher */ public function __construct( DiffFileLoader $diff, @@ -63,9 +59,8 @@ public function __construct( /** * array of uncoveredLines and coveredLines - * @return array */ - public function getCoveredLines() + public function getCoveredLines(): array { $this->getDiff(); @@ -76,7 +71,7 @@ public function getCoveredLines() $diffFiles = array_keys($this->cache->diff); foreach ($diffFiles as $file) { $matchedFile = $this->findFile($file, $coveredFiles); - if ($matchedFile !== false) { + if ($matchedFile !== '') { $this->matchLines($file, $matchedFile); } } @@ -87,12 +82,7 @@ public function getCoveredLines() ]; } - /** - * @param string $file the filename containing the uncovered line - * @param int $line the number of the uncovered line - * @param array $message a list of messages showing why its uncovered - */ - protected function addUnCoveredLine($file, $line, $message) + protected function addUnCoveredLine(string $file, int $line, array $message) { if (!isset($this->uncoveredLines[$file])) { $this->uncoveredLines[$file] = []; @@ -101,11 +91,7 @@ protected function addUnCoveredLine($file, $line, $message) $this->uncoveredLines[$file][$line] = $message; } - /** - * @param string $file the filename containing the covered line - * @param int $line the number of the covered line - */ - protected function addCoveredLine($file, $line) + protected function addCoveredLine(string $file, int $line) { if (!isset($this->coveredLines[$file])) { $this->coveredLines[$file] = []; @@ -114,11 +100,7 @@ protected function addCoveredLine($file, $line) $this->coveredLines[$file][] = $line; } - /** - * @param string $fileName the file name in the diff - * @param string $matchedFile the file name of the matched file - */ - protected function matchLines($fileName, $matchedFile) + protected function matchLines(string $fileName, string $matchedFile) { foreach ($this->cache->diff[$fileName] as $line) { $messages = $this->fileChecker->getErrorsOnLine($matchedFile, $line); @@ -141,21 +123,21 @@ protected function matchLines($fileName, $matchedFile) } } - protected function addCoveredFile($file) + protected function addCoveredFile(string $file) { foreach ($this->cache->diff[$file] as $line) { $this->addCoveredLine($file, $line); } } - protected function addUnCoveredFile($file) + protected function addUnCoveredFile(string $file) { foreach ($this->cache->diff[$file] as $line) { $this->addUnCoveredLine($file, $line, ['No Cover']); } } - protected function getDiff() + protected function getDiff(): array { if (empty($this->cache->diff)) { $this->cache->diff = $this->diff->getChangedLines(); @@ -164,7 +146,7 @@ protected function getDiff() return $this->cache->diff; } - protected function handleFileNotFound($file) + protected function handleFileNotFound(string $file) { $unMatchedFile = $this->fileChecker->handleNotFoundFile(); @@ -177,13 +159,13 @@ protected function handleFileNotFound($file) } } - protected function findFile($file, $coveredFiles) + protected function findFile(string $file, array $coveredFiles): string { try { return $this->matcher->match($file, $coveredFiles); } catch (Exceptions\FileNotFound $e) { $this->handleFileNotFound($file); - return false; + return ''; } } } diff --git a/src/DiffFileLoader.php b/src/DiffFileLoader.php index dbd5102..dbab4d2 100644 --- a/src/DiffFileLoader.php +++ b/src/DiffFileLoader.php @@ -22,7 +22,7 @@ public function __construct($fileName) $this->diff = new DiffFileState(); } - public function getChangedLines() + public function getChangedLines(): array { if (( !is_readable($this->fileLocation) && @@ -45,7 +45,7 @@ public function getChangedLines() return $this->diff->getChangedLines(); } - private function getLineHandle($line) + private function getLineHandle(string $line): DiffLineHandle { foreach ($this->diffLines as $lineType) { $lineType = $this->getClass($lineType); @@ -53,11 +53,11 @@ private function getLineHandle($line) return $lineType; } } - //not found, Class it as context + // the line doesn't have a special meaning, its probably context return $this->getClass(DiffLineHandle\ContextLine::class); } - private function getClass($className) + private function getClass(string $className): DiffLineHandle { if (!isset($this->handles[$this->getFileHandleName($className)])) { $this->handles[ @@ -68,7 +68,7 @@ private function getClass($className) return $this->handles[$this->getFileHandleName($className)]; } - private function getFileHandleName($namespace) + private function getFileHandleName(string $namespace): string { $namespace = explode('\\', $namespace); return end($namespace); diff --git a/src/DiffFileLoaderOldVersion.php b/src/DiffFileLoaderOldVersion.php index 71aede4..7b3556e 100644 --- a/src/DiffFileLoaderOldVersion.php +++ b/src/DiffFileLoaderOldVersion.php @@ -1,6 +1,10 @@ new, this returns what used to be there + */ class DiffFileLoaderOldVersion extends DiffFileLoader { protected $diffLines = [ diff --git a/src/DiffFileState.php b/src/DiffFileState.php index 2faea65..09e82ef 100644 --- a/src/DiffFileState.php +++ b/src/DiffFileState.php @@ -7,12 +7,12 @@ class DiffFileState private $currentFile; private $changeLines = []; - public function setCurrentPosition($position) + public function setCurrentPosition(int $position) { $this->currentPosition = $position; } - public function setCurrentFile($currentFile) + public function setCurrentFile(string $currentFile) { $this->currentFile = $currentFile; } @@ -35,7 +35,7 @@ public function decrementCurrentPosition() $this->currentPosition--; } - public function getChangedLines() + public function getChangedLines(): array { return array_map('array_unique', $this->changeLines); } diff --git a/src/DiffLineHandle.php b/src/DiffLineHandle.php index d624417..dd0e0eb 100644 --- a/src/DiffLineHandle.php +++ b/src/DiffLineHandle.php @@ -10,7 +10,13 @@ public function __construct(DiffFileState $diff) $this->diffFileState = $diff; } - abstract public function handle($line); + /** + * If the line is valid, this function will run on that file + */ + abstract public function handle(string $line); - abstract public function isValid($line); + /** + * Check if the line is valid in the current context + */ + abstract public function isValid(string $line); } diff --git a/src/DiffLineHandle/ContextLine.php b/src/DiffLineHandle/ContextLine.php index 5e1808f..4dc8118 100644 --- a/src/DiffLineHandle/ContextLine.php +++ b/src/DiffLineHandle/ContextLine.php @@ -5,13 +5,12 @@ class ContextLine extends DiffLineHandle { - - public function handle($line) + public function handle(string $line) { - //no need to do anything, Its just context + //no need to do anything, It's just context } - public function isValid($line) + public function isValid(string $line): bool { return true; } diff --git a/src/DiffLineHandle/NewVersion/AddedLine.php b/src/DiffLineHandle/NewVersion/AddedLine.php index 80cb42c..c6f77e7 100644 --- a/src/DiffLineHandle/NewVersion/AddedLine.php +++ b/src/DiffLineHandle/NewVersion/AddedLine.php @@ -5,13 +5,12 @@ class AddedLine extends DiffLineHandle { - - public function handle($line) + public function handle(string $line) { $this->diffFileState->addChangeLine(); } - public function isValid($line) + public function isValid(string $line): bool { return $line[0] == '+'; } diff --git a/src/DiffLineHandle/NewVersion/DiffStart.php b/src/DiffLineHandle/NewVersion/DiffStart.php index 7008aee..41e214b 100644 --- a/src/DiffLineHandle/NewVersion/DiffStart.php +++ b/src/DiffLineHandle/NewVersion/DiffStart.php @@ -5,8 +5,7 @@ class DiffStart extends DiffLineHandle { - - public function handle($line) + public function handle(string $line) { $foundVariables = sscanf( $line, @@ -18,7 +17,7 @@ public function handle($line) $this->diffFileState->setCurrentPosition($newFrom - 1); } - public function isValid($line) + public function isValid(string $line): bool { return $line[0] == '@' && $line[1] == '@'; } diff --git a/src/DiffLineHandle/NewVersion/NewFile.php b/src/DiffLineHandle/NewVersion/NewFile.php index 5bb0437..3e2f4b4 100644 --- a/src/DiffLineHandle/NewVersion/NewFile.php +++ b/src/DiffLineHandle/NewVersion/NewFile.php @@ -5,8 +5,7 @@ class NewFile extends DiffLineHandle { - - public function handle($line) + public function handle(string $line) { $parsedLine = sscanf($line, '+++ %1s/%s'); @@ -20,7 +19,7 @@ public function handle($line) } } - public function isValid($line) + public function isValid(string $line): bool { return $line[0] == '+' && $line[1] == '+'; } diff --git a/src/DiffLineHandle/NewVersion/RemovedLine.php b/src/DiffLineHandle/NewVersion/RemovedLine.php index 7cb9317..dfd0e3e 100644 --- a/src/DiffLineHandle/NewVersion/RemovedLine.php +++ b/src/DiffLineHandle/NewVersion/RemovedLine.php @@ -5,13 +5,12 @@ class RemovedLine extends DiffLineHandle { - - public function handle($line) + public function handle(string $line) { $this->diffFileState->decrementCurrentPosition(); } - public function isValid($line) + public function isValid(string $line): bool { return $line[0] == '-'; } diff --git a/src/DiffLineHandle/OldVersion/AddedLine.php b/src/DiffLineHandle/OldVersion/AddedLine.php index d500f3e..f6890f0 100644 --- a/src/DiffLineHandle/OldVersion/AddedLine.php +++ b/src/DiffLineHandle/OldVersion/AddedLine.php @@ -6,13 +6,13 @@ class AddedLine extends DiffLineHandle { - public function handle($line) + public function handle(string $line) { $this->diffFileState->decrementCurrentPosition(); $this->diffFileState->addChangeLine(); } - public function isValid($line) + public function isValid(string $line): bool { return $line[0] == '+' && $line[1] != "+"; } diff --git a/src/DiffLineHandle/OldVersion/DiffStart.php b/src/DiffLineHandle/OldVersion/DiffStart.php index 2b1f2f7..5a9e72a 100644 --- a/src/DiffLineHandle/OldVersion/DiffStart.php +++ b/src/DiffLineHandle/OldVersion/DiffStart.php @@ -6,7 +6,7 @@ class DiffStart extends DiffLineHandle { - public function handle($line) + public function handle(string $line) { $foundVariables = sscanf( $line, @@ -18,7 +18,7 @@ public function handle($line) $this->diffFileState->setCurrentPosition($oldFrom - 1); } - public function isValid($line) + public function isValid(string $line): bool { return $line[0] == '@' && $line[1] == '@'; } diff --git a/src/DiffLineHandle/OldVersion/NewFile.php b/src/DiffLineHandle/OldVersion/NewFile.php index 5919e20..ab9d01c 100644 --- a/src/DiffLineHandle/OldVersion/NewFile.php +++ b/src/DiffLineHandle/OldVersion/NewFile.php @@ -6,14 +6,14 @@ class NewFile extends DiffLineHandle { - public function handle($line) + public function handle(string $line) { if (preg_match('#--- a?/(?.*)#', $line, $match)) { $this->diffFileState->setCurrentFile($match['filename']); } } - public function isValid($line) + public function isValid(string $line): bool { return $line[0] == '-' && $line[1] == '-'; } diff --git a/src/DiffLineHandle/OldVersion/RemovedLine.php b/src/DiffLineHandle/OldVersion/RemovedLine.php index 7e096f9..c0542cf 100644 --- a/src/DiffLineHandle/OldVersion/RemovedLine.php +++ b/src/DiffLineHandle/OldVersion/RemovedLine.php @@ -6,12 +6,12 @@ class RemovedLine extends DiffLineHandle { - public function handle($line) + public function handle(string $line) { $this->diffFileState->addChangeLine(); } - public function isValid($line) + public function isValid(string $line): bool { return $line[0] == '-'; } diff --git a/src/Exceptions/ArgumentNotFound.php b/src/Exceptions/ArgumentNotFound.php new file mode 100644 index 0000000..3fbb4d2 --- /dev/null +++ b/src/Exceptions/ArgumentNotFound.php @@ -0,0 +1,8 @@ +fileEndsWith($file, $needle)) { @@ -27,11 +27,8 @@ public function match($needle, array $haystack) /** * Find if two strings end in the same way - * @param string $haystack - * @param string $needle - * @return bool */ - protected function fileEndsWith($haystack, $needle) + protected function fileEndsWith(string $haystack, string $needle): bool { $length = strlen($needle); if (strlen($haystack) < $length) { diff --git a/src/FileMatchers/FileMapper.php b/src/FileMatchers/FileMapper.php index 5e7ff07..b6446d8 100644 --- a/src/FileMatchers/FileMapper.php +++ b/src/FileMatchers/FileMapper.php @@ -19,12 +19,7 @@ class FileMapper implements FileMatcher */ protected $newPath; - /** - * FileMapper constructor. - * @param string $originalPath - * @param string $newPath - */ - public function __construct($originalPath, $newPath) + public function __construct(string $originalPath, string $newPath) { $this->originalPath = $originalPath; $this->newPath = $newPath; @@ -33,7 +28,7 @@ public function __construct($originalPath, $newPath) /** * {@inheritdoc} */ - public function match($needle, array $haystack) + public function match(string $needle, array $haystack): string { foreach ($haystack as $file) { if ($this->checkMapping($file, $needle)) { @@ -44,12 +39,7 @@ public function match($needle, array $haystack) throw new FileNotFound(); } - /** - * @param string $file - * @param string $needle - * @return bool - */ - private function checkMapping($file, $needle) + private function checkMapping(string $file, string $needle): bool { return $file == str_replace( $this->originalPath, diff --git a/src/FileMatchers/Prefix.php b/src/FileMatchers/Prefix.php index c024e83..57d3a54 100644 --- a/src/FileMatchers/Prefix.php +++ b/src/FileMatchers/Prefix.php @@ -19,7 +19,7 @@ class Prefix implements FileMatcher * Prefix constructor. * @param string $prefix */ - public function __construct($prefix) + public function __construct(string $prefix) { $this->prefix = $prefix; } @@ -27,7 +27,7 @@ public function __construct($prefix) /** * {@inheritdoc} */ - public function match($needle, array $haystack) + public function match(string $needle, array $haystack): string { foreach ($haystack as $file) { if ($file == $this->prefix . $needle) { diff --git a/src/FileParser.php b/src/FileParser.php index 01974ce..ebdb393 100644 --- a/src/FileParser.php +++ b/src/FileParser.php @@ -51,7 +51,7 @@ protected function parse(Parser $parser) } } - protected function getCodeLimits(Node $node) + protected function getCodeLimits(Node $node): CodeLimits { $startLine = $node->getAttribute('startLine'); $endLine = $node->getAttribute('endLine'); @@ -93,10 +93,7 @@ private function handleNamespace(Namespace_ $node) } } - /** - * @param $node - */ - protected function handleNode($node) + protected function handleNode(Node $node) { $type = $node->getType(); if ($type == 'Stmt_Namespace') { diff --git a/src/BuddyLoader.php b/src/Loaders/Buddy.php similarity index 57% rename from src/BuddyLoader.php rename to src/Loaders/Buddy.php index c557c59..a75b815 100644 --- a/src/BuddyLoader.php +++ b/src/Loaders/Buddy.php @@ -1,16 +1,18 @@ .*?):(?P[0-9]+) \| (?P.*)$#'; - public static function getDescription() + public static function getDescription(): string { return 'Parses buddy (magic number detection) output'; } diff --git a/src/CheckstyleLoader.php b/src/Loaders/Checkstyle.php similarity index 78% rename from src/CheckstyleLoader.php rename to src/Loaders/Checkstyle.php index 19de52d..ad8773a 100644 --- a/src/CheckstyleLoader.php +++ b/src/Loaders/Checkstyle.php @@ -1,6 +1,7 @@ coveredLines = []; $reader = new XMLReader; @@ -49,7 +50,7 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $line) + public function getErrorsOnLine(string $file, int $line) { $errors = []; if (isset($this->coveredLines[$file][$line])) { @@ -70,16 +71,12 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses a report in checkstyle format'; } - /** - * @param XMLReader $reader - * @param string $currentFile - */ - protected function handleErrors($reader, $currentFile) + protected function handleErrors(XMLReader $reader, string $currentFile) { if ($reader->name === "error") { $this->coveredLines @@ -89,12 +86,7 @@ protected function handleErrors($reader, $currentFile) } } - /** - * @param XMLReader $reader - * @param string $currentFile - * @return string - */ - protected function handleFile($reader, $currentFile) + protected function handleFile(XMLReader $reader, string $currentFile): string { if (( $reader->name === "file" && diff --git a/src/CloverLoader.php b/src/Loaders/Clover.php similarity index 78% rename from src/CloverLoader.php rename to src/Loaders/Clover.php index 27f1f0b..afd5930 100644 --- a/src/CloverLoader.php +++ b/src/Loaders/Clover.php @@ -1,6 +1,7 @@ coveredLines = []; $reader = new XMLReader; @@ -49,7 +50,7 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $line) + public function getErrorsOnLine(string $file, int $line) { if (!isset($this->coveredLines[$file][$line])) { return null; @@ -71,12 +72,12 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses text output in clover (xml) format'; } - protected function checkForNewFiles($reader, $currentFile) + protected function checkForNewFiles(XMLReader $reader, string $currentFile) { if (( $reader->name === "file" && @@ -88,11 +89,7 @@ protected function checkForNewFiles($reader, $currentFile) return $currentFile; } - /** - * @param XMLReader $reader - * @param string $currentFile - */ - protected function addLine($reader, $currentFile) + protected function addLine(XMLReader $reader, string $currentFile) { $covered = $reader->getAttribute('count') > 0; @@ -102,11 +99,7 @@ protected function addLine($reader, $currentFile) = $covered ?: "No test coverage"; } - /** - * @param XMLReader $reader - * @param string $currentFile - */ - protected function handleStatement($reader, $currentFile) + protected function handleStatement(XMLReader $reader, string $currentFile) { if (( $reader->name === "line" && diff --git a/src/CodeClimateLoader.php b/src/Loaders/CodeClimate.php similarity index 84% rename from src/CodeClimateLoader.php rename to src/Loaders/CodeClimate.php index 056012b..0bdf34d 100644 --- a/src/CodeClimateLoader.php +++ b/src/Loaders/CodeClimate.php @@ -1,12 +1,14 @@ file as $line) { $this->addError($line); @@ -42,7 +44,7 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; if (isset($this->errors[$file][$lineNumber])) { @@ -63,7 +65,7 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parse codeclimate output'; } diff --git a/src/Generic.php b/src/Loaders/Generic.php similarity index 81% rename from src/Generic.php rename to src/Loaders/Generic.php index a58d97a..d800c85 100644 --- a/src/Generic.php +++ b/src/Loaders/Generic.php @@ -1,12 +1,14 @@ file, 'r'); while (($line = fgets($handle)) !== false) { @@ -49,7 +51,7 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; if (isset($this->errors[$file][$lineNumber])) { @@ -68,12 +70,12 @@ public function handleNotFoundFile() } - private function checkForFile($line) + private function checkForFile(string $line) { return preg_match($this->lineMatch, $line); } - private function addError($line) + private function addError(string $line) { $matches = []; if (preg_match($this->lineMatch, $line, $matches)) { diff --git a/src/HumbugLoader.php b/src/Loaders/Humbug.php similarity index 86% rename from src/HumbugLoader.php rename to src/Loaders/Humbug.php index 646d509..ad0a701 100644 --- a/src/HumbugLoader.php +++ b/src/Loaders/Humbug.php @@ -1,15 +1,15 @@ invalidLines = []; foreach ($this->errorMethods as $failures) { @@ -64,7 +64,7 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; if (isset($this->invalidLines[$file][$lineNumber])) { @@ -85,7 +85,7 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the json report format of humbug (mutation testing)'; } diff --git a/src/InfectionLoader.php b/src/Loaders/Infection.php similarity index 91% rename from src/InfectionLoader.php rename to src/Loaders/Infection.php index 96dc76e..4cf9dc5 100644 --- a/src/InfectionLoader.php +++ b/src/Loaders/Infection.php @@ -1,7 +1,9 @@ currentFile = ''; $this->currentLine = 0; @@ -49,11 +51,10 @@ public function parseLines() * Method to determine if the line is valid in the context * returning null does not include the line in the stats * Returns an array containing errors on a certain line - empty array means no errors - * @param string $file - * @param int $lineNumber + * * @return array|null */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { if (!isset($this->errors[$file][$lineNumber])) { return []; @@ -79,7 +80,7 @@ public function handleNotFoundFile() * this checker would be used * @return string */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the infection text log format'; } diff --git a/src/JacocoReport.php b/src/Loaders/Jacoco.php similarity index 78% rename from src/JacocoReport.php rename to src/Loaders/Jacoco.php index a2792f1..616bb9b 100644 --- a/src/JacocoReport.php +++ b/src/Loaders/Jacoco.php @@ -1,19 +1,19 @@ coveredLines = []; $reader = new XMLReader; @@ -32,7 +32,7 @@ public function parseLines() return array_keys($this->coveredLines); } - public static function getDescription() + public static function getDescription(): string { return 'Parses xml coverage report produced by Jacoco'; } @@ -41,7 +41,7 @@ public static function getDescription() * @param XMLReader $reader * @param string $currentFile */ - protected function addLine($reader, $currentFile) + protected function addLine(XMLReader $reader, string $currentFile) { if (( $reader->name === "line" @@ -53,7 +53,7 @@ protected function addLine($reader, $currentFile) } } - protected function findFile($reader, $currentNamespace, $currentFile) + protected function findFile(XMLReader $reader, string $currentNamespace, string $currentFile): string { if (( $reader->name === "sourcefile" && @@ -66,7 +66,7 @@ protected function findFile($reader, $currentNamespace, $currentFile) return $currentFile; } - protected function findNamespace($reader, $currentNamespace) + protected function findNamespace(XMLReader $reader, string $currentNamespace): string { if (( $reader->name === "package" && diff --git a/src/PhanJsonLoader.php b/src/Loaders/PhanJson.php similarity index 64% rename from src/PhanJsonLoader.php rename to src/Loaders/PhanJson.php index a8b9218..dd30c7b 100644 --- a/src/PhanJsonLoader.php +++ b/src/Loaders/PhanJson.php @@ -1,19 +1,19 @@ file = json_decode(file_get_contents($file)); } - public static function getDescription() + public static function getDescription(): string { return 'Parses phan (static analysis) in json format'; } diff --git a/src/PhanTextLoader.php b/src/Loaders/PhanText.php similarity index 58% rename from src/PhanTextLoader.php rename to src/Loaders/PhanText.php index 4ef7593..5cb97c2 100644 --- a/src/PhanTextLoader.php +++ b/src/Loaders/PhanText.php @@ -1,19 +1,21 @@ .*?):(?P[0-9]+)(?P.*)#'; /* * @inheritdoc */ - public static function getDescription() + public static function getDescription(): string { return 'Parse the default phan(static analysis) output'; } diff --git a/src/PhpCsLoader.php b/src/Loaders/PhpCs.php similarity index 91% rename from src/PhpCsLoader.php rename to src/Loaders/PhpCs.php index f05e876..12dd66a 100644 --- a/src/PhpCsLoader.php +++ b/src/Loaders/PhpCs.php @@ -1,18 +1,19 @@ invalidLines = []; foreach ($this->json->files as $fileName => $file) { @@ -98,7 +97,7 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; if (!empty($this->invalidFiles[$file])) { @@ -114,11 +113,7 @@ public function getErrorsOnLine($file, $lineNumber) return $errors; } - /** - * @param string $file - * @param stdClass $message - */ - protected function addInvalidLine($file, $message) + protected function addInvalidLine(string $file, stdClass $message) { if (!in_array($message->type, $this->failOnTypes)) { return; @@ -143,11 +138,9 @@ protected function addInvalidLine($file, $message) } /** - * @param $message - * @param array $list * @return bool|string */ - protected function messageStartsWith($message, array $list) + protected function messageStartsWith(string $message, array $list) { foreach ($list as $item) { if (strpos($message, $item) === 0) { @@ -198,7 +191,7 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the json report format of phpcs, this mode ' . 'only reports errors as violations'; diff --git a/src/PhpCsLoaderStrict.php b/src/Loaders/PhpCsStrict.php similarity index 68% rename from src/PhpCsLoaderStrict.php rename to src/Loaders/PhpCsStrict.php index ff059a5..2f7e60d 100644 --- a/src/PhpCsLoaderStrict.php +++ b/src/Loaders/PhpCsStrict.php @@ -1,12 +1,12 @@ errors = []; $this->errorRanges = []; @@ -55,9 +56,13 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; + if (empty($this->errorRanges[$file])) { + return $errors; + } + foreach ($this->errorRanges[$file] as $number => $error) { if (( $error['start'] <= $lineNumber && @@ -124,7 +129,7 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the xml report format of phpmd, this mode ' . 'reports multi line violations once per diff, instead ' . diff --git a/src/PhpMdLoaderStrict.php b/src/Loaders/PhpMdStrict.php similarity index 77% rename from src/PhpMdLoaderStrict.php rename to src/Loaders/PhpMdStrict.php index c886b5c..243bf61 100644 --- a/src/PhpMdLoaderStrict.php +++ b/src/Loaders/PhpMdStrict.php @@ -1,7 +1,5 @@ errorRanges[$file] as $error) { @@ -29,7 +27,7 @@ public function getErrorsOnLine($file, $lineNumber) /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the xml report format of phpmd, this mode ' . 'reports multi line violations once per line they occur '; diff --git a/src/PhpMndLoader.php b/src/Loaders/PhpMnd.php similarity index 70% rename from src/PhpMndLoader.php rename to src/Loaders/PhpMnd.php index 844005c..1c0b985 100644 --- a/src/PhpMndLoader.php +++ b/src/Loaders/PhpMnd.php @@ -1,7 +1,9 @@ file)) !== false) { $matches = []; - if (preg_match("/^(?[^:]+):(?[0-9]+)\. (?.+)/", $line, $matches)) { + $pattern = "/^(?[^:]+):(?[0-9]+)\. (?.+)/"; + if (preg_match($pattern, $line, $matches)) { $this->invalidLines [$matches['filename']] [$matches['lineNo']][] = $matches['message']; @@ -32,7 +35,7 @@ public function parseLines() /** * @inheritdoc */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; if (isset($this->invalidLines[$file][$lineNumber])) { @@ -53,7 +56,7 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the text output of phpmnd (Magic Number Detection)'; } diff --git a/src/PhpMndXmlLoader.php b/src/Loaders/PhpMndXml.php similarity index 88% rename from src/PhpMndXmlLoader.php rename to src/Loaders/PhpMndXml.php index 297021b..47057e3 100644 --- a/src/PhpMndXmlLoader.php +++ b/src/Loaders/PhpMndXml.php @@ -1,9 +1,10 @@ open($this->file); @@ -68,7 +69,7 @@ protected function handleErrors(XMLReader $reader, $currentFile) /** * @inheritdoc */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; if (isset($this->invalidLines[$file][$lineNumber])) { @@ -89,7 +90,7 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the XML output of phpmnd (Magic Number Detection)'; } diff --git a/src/PhpStanLoader.php b/src/Loaders/PhpStan.php similarity index 79% rename from src/PhpStanLoader.php rename to src/Loaders/PhpStan.php index 2b95f35..bb7fb06 100644 --- a/src/PhpStanLoader.php +++ b/src/Loaders/PhpStan.php @@ -1,17 +1,18 @@ [0-9]+)/'; @@ -34,7 +35,7 @@ public function __construct($filename) /** * {@inheritdoc} */ - public function parseLines() + public function parseLines(): array { $filename = ''; $lineNumber = 0; @@ -59,7 +60,7 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; if (isset($this->invalidLines[$file][$lineNumber])) { @@ -91,7 +92,7 @@ protected function checkForFilename($line, $currentFile) return $currentFile; } - protected function getLineNumber($line, $currentLineNumber) + protected function getLineNumber(string $line, int $currentLineNumber) { $matches = []; if (!preg_match($this->lineRegex, $line, $matches)) { @@ -102,7 +103,7 @@ protected function getLineNumber($line, $currentLineNumber) return false; } - return $matches['lineNumber']; + return (int) $matches['lineNumber']; } protected function getMessage($line) @@ -127,7 +128,7 @@ protected function trimLines() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the text output of phpstan'; } @@ -144,12 +145,16 @@ protected function handleRelatedError($filename, $line, $error) $line ); - $reflection = $this->getReflector($matches); - if ($reflection && ($filename = $reflection->getFileName())) { + try { + $reflection = $this->getReflector($matches); + $filename = $reflection->getFileName(); $currentLine = $reflection->getStartLine(); + while ($currentLine < $reflection->getEndLine()) { $this->addError($filename, $currentLine++, $error); } + } catch (Exception $exception) { + // can't find any more info about this method, so just carry on } } } @@ -167,11 +172,7 @@ protected function addError($filename, $lineNumber, $error) $this->invalidLines[$filename][$lineNumber][] = $error; } - /** - * @param array $matches - * @return ReflectionFunctionAbstract - */ - protected function getReflector($matches) + protected function getReflector(array $matches): ReflectionFunctionAbstract { if ($matches['class']) { return $this->getClassReflector($matches); @@ -180,21 +181,17 @@ protected function getReflector($matches) return $this->getFunctionReflector($matches); } - private function appendError($filename, $lineNumber, $error) + private function appendError(string $filename, int $lineNumber, string $error) { end($this->invalidLines[$filename][$lineNumber]); $key = key($this->invalidLines[$filename][$lineNumber]); $this->invalidLines[$filename][$lineNumber][$key] .= ' ' . $error; } - /** - * @param $matches - * @return bool|ReflectionMethod - */ - protected function getClassReflector($matches) + protected function getClassReflector(array $matches): ReflectionMethod { if (!method_exists($matches['class'], $matches['function'])) { - return false; + throw new Exception("Missing class function"); } return new ReflectionMethod( $matches['class'], @@ -202,14 +199,10 @@ protected function getClassReflector($matches) ); } - /** - * @param $matches - * @return bool|ReflectionFunction - */ - protected function getFunctionReflector($matches) + protected function getFunctionReflector(array $matches): ReflectionFunction { if (!function_exists($matches['function'])) { - return false; + throw new Exception("Missing function reflector"); } return new ReflectionFunction( $matches['function'] diff --git a/src/PhpUnitLoader.php b/src/Loaders/PhpUnit.php similarity index 50% rename from src/PhpUnitLoader.php rename to src/Loaders/PhpUnit.php index 8e851d9..ac4086c 100644 --- a/src/PhpUnitLoader.php +++ b/src/Loaders/PhpUnit.php @@ -1,21 +1,19 @@ file = fopen($file, 'r'); } - public function parseLines() + public function parseLines(): array { $block = []; $this->duplicateCode = []; @@ -33,7 +35,7 @@ public function parseLines() } - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; if (isset($this->duplicateCode[$file][$lineNumber])) { @@ -48,29 +50,29 @@ public function handleNotFoundFile() return true; } - public static function getDescription() + public static function getDescription(): string { return "Parses the text output from phpcpd (Copy Paste Detect)"; } - private function startOfBlock($line) + private function startOfBlock(string $line) { return preg_match('/^\s+-/', $line); } - private function hasFileName($line) + private function hasFileName(string $line) { return preg_match('/:\d+-\d+/', $line); } - private function addFoundBlock($line) + private function addFoundBlock(string $line) { $matches = []; preg_match('/\s+(?:- )?(?.*?):(?\d+)-(?\d+)$/', $line, $matches); return [$matches['fileName'] => range($matches['startLine'], $matches['endLine'])]; } - private function handleEndOfBlock($block) + private function handleEndOfBlock(array $block) { foreach ($block as $filename => $lines) { foreach ($lines as $lineNumber) { diff --git a/src/PsalmLoader.php b/src/Loaders/Psalm.php similarity index 83% rename from src/PsalmLoader.php rename to src/Loaders/Psalm.php index a5e0f00..d14fa1b 100644 --- a/src/PsalmLoader.php +++ b/src/Loaders/Psalm.php @@ -1,16 +1,16 @@ errors = []; $this->errorRanges = []; @@ -59,7 +59,7 @@ public function parseLines() /** * {@inheritdoc} */ - public function getErrorsOnLine($file, $lineNumber) + public function getErrorsOnLine(string $file, int $lineNumber) { $errors = []; foreach ($this->errorRanges[$file] as $number => $error) { @@ -117,7 +117,7 @@ public function handleNotFoundFile() /** * {@inheritdoc} */ - public static function getDescription() + public static function getDescription(): string { return 'Parses the xml report format of psalm'; } @@ -135,24 +135,12 @@ protected function addForAllLines($currentFile, $start, $end, $error) } } - /** - * @param XMLReader $reader - * @param string $name - * - * @return bool - */ - protected function isElementBeginning($reader, $name) + protected function isElementBeginning(XMLReader $reader, string $name): bool { return $reader->name === $name && $reader->nodeType == XMLReader::ELEMENT; } - /** - * @param XMLReader $reader - * @param string $name - * - * @return bool - */ - protected function isElementEnd($reader, $name) + protected function isElementEnd(XMLReader $reader, string $name): bool { return $reader->name === $name && $reader->nodeType == XMLReader::END_ELEMENT; } diff --git a/src/PylintLoader.php b/src/Loaders/Pylint.php similarity index 54% rename from src/PylintLoader.php rename to src/Loaders/Pylint.php index aff9930..473fc97 100644 --- a/src/PylintLoader.php +++ b/src/Loaders/Pylint.php @@ -1,16 +1,18 @@ .*?):(?P[0-9]+): \[.*?\](?P.*)#'; - public static function getDescription() + public static function getDescription(): string { return 'Parses PyLint output'; } diff --git a/src/Output.php b/src/Output.php index 4091506..94b3a3e 100644 --- a/src/Output.php +++ b/src/Output.php @@ -3,5 +3,5 @@ interface Output { - public function output($coverage, $percent, $minimumPercent); + public function output(array $coverage, float $percent, float $minimumPercent); } diff --git a/src/Outputs/Json.php b/src/Outputs/Json.php index 4b1aa2f..cf4fd21 100644 --- a/src/Outputs/Json.php +++ b/src/Outputs/Json.php @@ -6,7 +6,7 @@ class Json implements Output { - public function output($coverage, $percent, $minimumPercent) + public function output(array $coverage, float $percent, float $minimumPercent) { $violations = []; foreach ($coverage as $file => $lines) { diff --git a/src/Outputs/Phpcs.php b/src/Outputs/Phpcs.php index 7c3aa79..e5a251a 100644 --- a/src/Outputs/Phpcs.php +++ b/src/Outputs/Phpcs.php @@ -8,7 +8,7 @@ class Phpcs implements Output private $violations; - public function output($coverage, $percent, $minimumPercent) + public function output(array $coverage, float $percent, float $minimumPercent) { $this->violations = ['files' => []]; $total = 0; @@ -24,7 +24,7 @@ public function output($coverage, $percent, $minimumPercent) echo json_encode($this->violations) . "\n"; } - protected function displayErrors($errors, $file, $line) + protected function displayErrors(array $errors, string $file, int $line) { foreach ($errors as $error) { $current = &$this->violations['files'][$file]; @@ -45,7 +45,7 @@ protected function displayErrors($errors, $file, $line) } } - protected function addTotal($total) + protected function addTotal(int $total) { $this->violations['totals'] = [ 'errors' => $total, diff --git a/src/Outputs/Text.php b/src/Outputs/Text.php index 842f0e5..7324e19 100644 --- a/src/Outputs/Text.php +++ b/src/Outputs/Text.php @@ -5,7 +5,7 @@ class Text implements Output { - public function output($coverage, $percent, $minimumPercent) + public function output(array $coverage, float $percent, float $minimumPercent) { printf("%.2f%% Covered\n", $percent); diff --git a/src/PhpunitFilter.php b/src/PhpunitFilter.php index 47b61ea..b9969cb 100644 --- a/src/PhpunitFilter.php +++ b/src/PhpunitFilter.php @@ -40,19 +40,19 @@ public function getTestsForRunning($fuzziness = 0) return $this->groupTestsBySuite($runTests); } - protected function endsWith($haystack, $needle) + protected function endsWith(string $haystack, string $needle) { $length = strlen($needle); return (substr($haystack, -$length) === $needle); } - protected function stripFileExtension($file) + protected function stripFileExtension(string $file) { $ext = ".php"; return str_replace('/', '\\', substr($file, 0, -strlen($ext))); } - protected function groupTestsBySuite($tests) + protected function groupTestsBySuite(array $tests) { $groupedTests = []; foreach ($tests as $test) { @@ -67,8 +67,13 @@ protected function groupTestsBySuite($tests) return $groupedTests; } - public function matchFuzzyLines($fuzziness, $testData, $found, $line, $runTests) - { + public function matchFuzzyLines( + int $fuzziness, + array $testData, + string $found, + int $line, + array $runTests + ) { $index = -$fuzziness; do { if (isset($testData[$found][$line + $index])) { diff --git a/src/Runners/generic.php b/src/Runners/generic.php index 8ec8ba2..3b558b2 100644 --- a/src/Runners/generic.php +++ b/src/Runners/generic.php @@ -2,6 +2,7 @@ namespace exussum12\CoverageChecker\Runners; use exussum12\CoverageChecker; +use exussum12\CoverageChecker\Exceptions\ArgumentNotFound; use exussum12\CoverageChecker\Outputs\Json; use exussum12\CoverageChecker\Outputs\Phpcs; use exussum12\CoverageChecker\Outputs\Text; @@ -14,47 +15,55 @@ $args = new CoverageChecker\ArgParser($argv); CoverageChecker\checkForVersion($args); CoverageChecker\checkCallIsCorrect($args); -$minimumPercentCovered = CoverageChecker\getMinPercent($args->getArg(3)); + +try { + $minimumPercentCovered = CoverageChecker\getMinPercent($args->getArg('3')); +} catch (ArgumentNotFound $exception) { + $minimumPercentCovered = 100; +} $matcher = new CoverageChecker\FileMatchers\EndsWith(); $diff = new CoverageChecker\DiffFileLoader( - CoverageChecker\adjustForStdIn($args->getArg(1)) + CoverageChecker\adjustForStdIn($args->getArg('1')) ); -if ($autoload = $args->getArg('autoload')) { +try { + $autoload = $args->getArg('autoload'); if (file_exists(($autoload))) { require_once $autoload; } +} catch (ArgumentNotFound $exception) { + // do nothing, its not a required argument } $checkerArray = [ - 'buddy' => 'BuddyLoader', - 'checkstyle' => 'CheckstyleLoader', - 'clover' => 'CloverLoader', - 'codeclimate' => 'CodeClimateLoader', - 'humbug' => 'HumbugLoader', - 'infecton' => 'InfectionLoader', - 'jacoco' => 'JacocoReport', - 'phan' => 'PhanTextLoader', - 'phanJson' => 'PhanJsonLoader', + 'buddy' => 'Buddy', + 'checkstyle' => 'Checkstyle', + 'clover' => 'Clover', + 'codeclimate' => 'CodeClimate', + 'humbug' => 'Humbug', + 'infecton' => 'Infection', + 'jacoco' => 'Jacoco', + 'phan' => 'PhanText', + 'phanJson' => 'PhanJson', 'phpcpd' => 'Phpcpd', - 'phpcs' => 'PhpCsLoader', - 'phpcsStrict' => 'PhpCsLoaderStrict', - 'phpmd' => 'PhpMdLoader', - 'phpmdStrict' => 'PhpMdLoaderStrict', - 'phpmnd' => 'PhpMndLoader', - 'phpmndXml' => 'PhpMndXmlLoader', - 'phpstan' => 'PhpStanLoader', - 'phpunit' => 'PhpUnitLoader', - 'pylint' => 'PylintLoader', - 'psalm' => 'PsalmLoader', + 'phpcs' => 'PhpCs', + 'phpcsStrict' => 'PhpCsStrict', + 'phpmd' => 'PhpMd', + 'phpmdStrict' => 'PhpMdStrict', + 'phpmnd' => 'PhpMnd', + 'phpmndXml' => 'PhpMndXml', + 'phpstan' => 'PhpStan', + 'phpunit' => 'PhpUnit', + 'pylint' => 'Pylint', + 'psalm' => 'Psalm', ]; $fileCheck = CoverageChecker\getFileChecker( $args, $checkerArray, - CoverageChecker\adjustForStdIn($args->getArg(2)) + CoverageChecker\adjustForStdIn($args->getArg('2')) ); $outputArray = [ @@ -62,11 +71,10 @@ 'json' => Json::class, 'phpcs' => Phpcs::class, ]; -$report = 'text'; -$requestedReport = $args->getArg('report'); - -if (isset($outputArray[$requestedReport])) { - $report = $requestedReport; +try { + $report = $args->getArg('report'); +} catch (ArgumentNotFound $exception) { + $report = 'text'; } $report = new $outputArray[$report]; diff --git a/src/functions.php b/src/functions.php index fa2c363..0b3b3ad 100644 --- a/src/functions.php +++ b/src/functions.php @@ -2,6 +2,7 @@ namespace exussum12\CoverageChecker; use Exception; +use exussum12\CoverageChecker\Exceptions\ArgumentNotFound; use exussum12\CoverageChecker\Outputs\Text; function findAutoLoader() @@ -38,7 +39,10 @@ function findAutoLoader() function checkCallIsCorrect(ArgParser $args) { - if (!$args->getArg(1) || !$args->getArg(2)) { + try { + $args->getArg('1'); + $args->getArg('2'); + } catch (ArgumentNotFound $exception) { throw new Exception( "Missing arguments, please call with diff and check file\n" . "e.g. vendor/bin/diffFilter --phpcs diff.txt phpcs.json", @@ -50,7 +54,7 @@ function checkCallIsCorrect(ArgParser $args) /** * @codeCoverageIgnore */ -function adjustForStdIn($argument) +function adjustForStdIn(string $argument) { if ($argument == "-") { return "php://stdin"; @@ -79,7 +83,7 @@ function getMinPercent($percent) return $minimumPercentCovered; } -function handleOutput($lines, $minimumPercentCovered, Output $output) +function handleOutput(array $lines, float $minimumPercentCovered, Output $output) { $coveredLines = calculateLines($lines['coveredLines']); $uncoveredLines = calculateLines($lines['uncoveredLines']); @@ -108,7 +112,7 @@ function handleOutput($lines, $minimumPercentCovered, Output $output) ); } -function calculateLines($lines) +function calculateLines(array $lines) { return array_sum(array_map('count', $lines)); } @@ -125,12 +129,18 @@ function ($exception) { ); } -function getFileChecker(ArgParser $args, array $argMapper, $filename) -{ +function getFileChecker( + ArgParser $args, + array $argMapper, + string $filename +): FileChecker { foreach ($argMapper as $arg => $class) { - if ($args->getArg($arg)) { - $class = __NAMESPACE__ . '\\' . $class; + try { + $args->getArg($arg); + $class = __NAMESPACE__ . '\\Loaders\\' . $class; return new $class($filename); + } catch (ArgumentNotFound $exception) { + continue; } } printOptions($argMapper); @@ -145,7 +155,7 @@ function printOptions(array $arguments) $width = (int) (`tput cols` ?: $defaultWidth); $width -= 2 * $tabWidth; foreach ($arguments as $argument => $class) { - $class = __NAMESPACE__ . '\\' . $class; + $class = __NAMESPACE__ . '\\Loaders\\' . $class; $argument = adjustArgument($argument, $tabWidth); @@ -173,7 +183,11 @@ function adjustArgument($argument, $tabWidth) function checkForVersion(ArgParser $args) { - if ($args->getArg("v")) { - throw new Exception('Version: 0.10.3-dev', 0); + try { + $args->getArg("v"); + } catch (ArgumentNotFound $e) { + return; } + + throw new Exception('Version: 0.10.3-dev', 0); } diff --git a/tests/ArgParserTest.php b/tests/ArgParserTest.php index a21d73d..5444ac9 100644 --- a/tests/ArgParserTest.php +++ b/tests/ArgParserTest.php @@ -3,48 +3,50 @@ use PHPUnit\Framework\TestCase; use exussum12\CoverageChecker\ArgParser; +use exussum12\CoverageChecker\Exceptions\ArgumentNotFound; class ArgParserTest extends TestCase { - public function testNumericArgs() + protected $parser; + + public function setUp() { $args = [ 'file.php', - '--some-opt', + '--some-opt=some-val', 'file', '-a', 'file2', ]; + $this->parser = new ArgParser($args); + } + public function testNumericArgs() + { + $this->assertSame("file", $this->parser->getArg(1)); + $this->assertSame("file2", $this->parser->getArg(2)); + } + + public function testInvalidNumericalArg() + { + $this->expectException(ArgumentNotFound::class); - $argParser = new ArgParser($args); - $this->assertSame("file", $argParser->getArg(1)); - $this->assertSame("file2", $argParser->getArg(2)); - $this->assertNull($argParser->getArg(3)); + $this->parser->getArg(3); } public function testAlphaArgs() { - $args = [ - 'file.php', - '--some-opt', - 'file', - '-a', - 'file2', - ]; + $this->assertSame("1", $this->parser->getArg('a')); + } - $argParser = new ArgParser($args); - $this->assertTrue($argParser->getArg('a')); - $this->assertTrue($argParser->getArg('some-opt')); - $this->assertFalse($argParser->getArg('non-existant')); + public function testInvalidAlphaArgs() + { + $this->expectException(ArgumentNotFound::class); + + $this->parser->getArg('non-existent'); } public function testArgumentsWithValues() { - $args = [ - '--some-opt=some-val', - ]; - - $argParser = new ArgParser($args); - $this->assertEquals('some-val', $argParser->getArg('some-opt')); + $this->assertEquals('some-val', $this->parser->getArg('some-opt')); } } diff --git a/tests/CheckstyleTest.php b/tests/CheckstyleTest.php deleted file mode 100644 index 96a930e..0000000 --- a/tests/CheckstyleTest.php +++ /dev/null @@ -1,16 +0,0 @@ -phan = new CheckstyleLoader(__DIR__ . '/fixtures/checkstyle.xml'); - } -} diff --git a/tests/CodeClimateTest.php b/tests/CodeClimateTest.php deleted file mode 100644 index 92234bb..0000000 --- a/tests/CodeClimateTest.php +++ /dev/null @@ -1,16 +0,0 @@ -phan = new CodeClimateLoader(__DIR__ . '/fixtures/codeclimate.json'); - } -} diff --git a/tests/CoverageCheckTest.php b/tests/CoverageCheckTest.php index d6e286d..d79e660 100644 --- a/tests/CoverageCheckTest.php +++ b/tests/CoverageCheckTest.php @@ -5,7 +5,7 @@ use exussum12\CoverageChecker\CoverageCheck; use exussum12\CoverageChecker\DiffFileLoader; use exussum12\CoverageChecker\FileMatchers; -use exussum12\CoverageChecker\CloverLoader; +use exussum12\CoverageChecker\Loaders\Clover; class CoverageCheckTest extends TestCase { @@ -20,12 +20,11 @@ public function testCoverage() ]); - $xmlReport = $this->createMock(CloverLoader::class); + $xmlReport = $this->createMock(Clover::class); $xmlReport->method('parseLines') ->willReturn([ '/full/path/to/testFile1.php', '/full/path/to/testFile2.php', - ]); $xmlReport->method('getErrorsOnLine') @@ -77,7 +76,7 @@ public function testCoverageFailed() ]); - $xmlReport = $this->createMock(CloverLoader::class); + $xmlReport = $this->createMock(Clover::class); $xmlReport->method('parseLines') ->willReturn([ '/full/path/to/testFile1.php', @@ -132,11 +131,10 @@ public function testAddingAllUnknownsCovered() ]); - $xmlReport = $this->createMock(CloverLoader::class); + $xmlReport = $this->createMock(Clover::class); $xmlReport->method('parseLines') ->willReturn([ '/full/path/to/testFile1.php', - ]); $xmlReport->method('handleNotFoundFile') @@ -188,7 +186,7 @@ public function testAddingAllUnknownsUnCovered() ]); - $xmlReport = $this->createMock(CloverLoader::class); + $xmlReport = $this->createMock(Clover::class); $xmlReport->method('parseLines') ->willReturn([ '/full/path/to/testFile1.php', @@ -245,7 +243,7 @@ public function testCoverageForContextLines() ]); - $xmlReport = $this->createMock(CloverLoader::class); + $xmlReport = $this->createMock(Clover::class); $xmlReport->method('parseLines') ->willReturn([ '/full/path/to/testFile1.php' diff --git a/tests/Loaders/CheckstyleTest.php b/tests/Loaders/CheckstyleTest.php new file mode 100644 index 0000000..910cdbe --- /dev/null +++ b/tests/Loaders/CheckstyleTest.php @@ -0,0 +1,16 @@ +phan = new Checkstyle(__DIR__ . '/../fixtures/checkstyle.xml'); + } +} diff --git a/tests/Loaders/CodeClimateTest.php b/tests/Loaders/CodeClimateTest.php new file mode 100644 index 0000000..f6a3872 --- /dev/null +++ b/tests/Loaders/CodeClimateTest.php @@ -0,0 +1,16 @@ +phan = new CodeClimate(__DIR__ . '/../fixtures/codeclimate.json'); + } +} diff --git a/tests/HumbugLoaderTest.php b/tests/Loaders/HumbugLoaderTest.php similarity index 73% rename from tests/HumbugLoaderTest.php rename to tests/Loaders/HumbugLoaderTest.php index 47701ee..227a3f1 100644 --- a/tests/HumbugLoaderTest.php +++ b/tests/Loaders/HumbugLoaderTest.php @@ -1,15 +1,15 @@ parseLines(); $this->assertEquals(1, count($invalidFiles)); @@ -27,13 +27,13 @@ public function testCanMakeClass() public function testHandleFileNotFound() { - $humbug = new HumbugLoader(__DIR__ . '/fixtures/humbug.json'); + $humbug = new Humbug(__DIR__ . '/../fixtures/humbug.json'); $this->assertTrue($humbug->handleNotFoundFile()); } public function testBadFormat() { $this->expectException(InvalidArgumentException::class); - new HumbugLoader(__DIR__ . '/fixtures/change.txt'); + new Humbug(__DIR__ . '/../fixtures/change.txt'); } } diff --git a/tests/InfectionLoaderTest.php b/tests/Loaders/InfectionLoaderTest.php similarity index 74% rename from tests/InfectionLoaderTest.php rename to tests/Loaders/InfectionLoaderTest.php index 0676c06..57cea46 100644 --- a/tests/InfectionLoaderTest.php +++ b/tests/Loaders/InfectionLoaderTest.php @@ -1,8 +1,8 @@ parseLines(); $file = '/home/scott/code/coverageChecker/src/DiffFilter.php'; @@ -36,7 +36,7 @@ public function testCanParseFile() public function testFileNotFound() { - $infection = new InfectionLoader(__DIR__ . '/fixtures/infection-log.txt'); + $infection = new Infection(__DIR__ . '/../fixtures/infection-log.txt'); $this->assertTrue($infection->handleNotFoundFile()); } } diff --git a/tests/JacocoLoaderTest.php b/tests/Loaders/JacocoLoaderTest.php similarity index 82% rename from tests/JacocoLoaderTest.php rename to tests/Loaders/JacocoLoaderTest.php index de6e611..6760505 100644 --- a/tests/JacocoLoaderTest.php +++ b/tests/Loaders/JacocoLoaderTest.php @@ -1,15 +1,15 @@ parseLines(); $expected = [ 'org/jacoco/examples/maven/java/HelloWorld.java', diff --git a/tests/LoadCloverReportTest.php b/tests/Loaders/LoadCloverReportTest.php similarity index 79% rename from tests/LoadCloverReportTest.php rename to tests/Loaders/LoadCloverReportTest.php index fe466c1..bdc6779 100644 --- a/tests/LoadCloverReportTest.php +++ b/tests/Loaders/LoadCloverReportTest.php @@ -1,15 +1,14 @@ parseLines(); $expected = [ '/path/to/file/changedFile.php', @@ -32,7 +31,7 @@ public function testLoadXML() public function testCorrectMissingFile() { - $xmlReport = new CloverLoader(__DIR__ . '/fixtures/coverage.xml'); + $xmlReport = new Clover(__DIR__ . '/fixtures/coverage.xml'); $this->assertNull($xmlReport->handleNotFoundFile()); } diff --git a/tests/LoadPhpMdReportStrictTest.php b/tests/Loaders/LoadPhpMdReportStrictTest.php similarity index 80% rename from tests/LoadPhpMdReportStrictTest.php rename to tests/Loaders/LoadPhpMdReportStrictTest.php index 38fc8d4..36687f3 100644 --- a/tests/LoadPhpMdReportStrictTest.php +++ b/tests/Loaders/LoadPhpMdReportStrictTest.php @@ -1,14 +1,14 @@ parseLines(); $file = '/full/path/to/file/src/CoverageCheck.php'; $expected = [$file]; @@ -39,7 +39,7 @@ public function testClassCanLoad() public function testCorrectMissingFile() { - $phpmd = new PhpMdLoaderStrict(__DIR__ . '/fixtures/phpmd.xml'); + $phpmd = new PhpMdStrict(__DIR__ . '/../fixtures/phpmd.xml'); $this->assertTrue($phpmd->handleNotFoundFile()); } diff --git a/tests/LoadPhpMdReportTest.php b/tests/Loaders/LoadPhpMdReportTest.php similarity index 82% rename from tests/LoadPhpMdReportTest.php rename to tests/Loaders/LoadPhpMdReportTest.php index 01354b5..dde76e5 100644 --- a/tests/LoadPhpMdReportTest.php +++ b/tests/Loaders/LoadPhpMdReportTest.php @@ -1,14 +1,14 @@ parseLines(); $file = '/full/path/to/file/src/CoverageCheck.php'; $expected = [$file]; @@ -38,7 +38,7 @@ public function testClassCanLoad() public function testCorrectMissingFile() { - $phpmd = new PhpMdLoader(__DIR__ . '/fixtures/phpmd.xml'); + $phpmd = new PhpMd(__DIR__ . '/fixtures/phpmd.xml'); $this->assertTrue($phpmd->handleNotFoundFile()); } diff --git a/tests/LoadPhpcsReportTest.php b/tests/Loaders/LoadPhpcsReportTest.php similarity index 73% rename from tests/LoadPhpcsReportTest.php rename to tests/Loaders/LoadPhpcsReportTest.php index e32988e..20e65f8 100644 --- a/tests/LoadPhpcsReportTest.php +++ b/tests/Loaders/LoadPhpcsReportTest.php @@ -1,15 +1,16 @@ parseLines(); $this->assertEquals( @@ -23,23 +24,24 @@ public function testCanMakeClass() } /** - * @expectedException \InvalidArgumentException + * @expectedException InvalidArgumentException */ public function testRejectsInvalidData() { - new PhpCsLoader(__DIR__ . '/fixtures/change.txt'); + $this->expectException(InvalidArgumentException::class); + new PhpCs(__DIR__ . '/../fixtures/change.txt'); } public function testCorrectMissingFile() { - $phpcs = new PhpCsLoader(__DIR__ . '/fixtures/phpcs.json'); + $phpcs = new PhpCs(__DIR__ . '/../fixtures/phpcs.json'); $this->assertTrue($phpcs->handleNotFoundFile()); } public function testStrictMode() { - $phpcs = new PhpCsLoaderStrict(__DIR__ . '/fixtures/phpcsstrict.json'); + $phpcs = new PhpCsStrict(__DIR__ . '/../fixtures/phpcsstrict.json'); $phpcs->parseLines(); $this->assertEquals( @@ -55,7 +57,7 @@ public function testStrictMode() public function testWholeFileError() { - $phpcs = new PhpCsLoaderStrict(__DIR__ . '/fixtures/wholeFileErrorPhpcs.json'); + $phpcs = new PhpCsStrict(__DIR__ . '/../fixtures/wholeFileErrorPhpcs.json'); $phpcs->parseLines(); $this->assertEquals( diff --git a/tests/PhanJsonTest.php b/tests/Loaders/PhanJsonTest.php similarity index 50% rename from tests/PhanJsonTest.php rename to tests/Loaders/PhanJsonTest.php index 67a514e..5434163 100644 --- a/tests/PhanJsonTest.php +++ b/tests/Loaders/PhanJsonTest.php @@ -1,7 +1,7 @@ phan = new PhanJsonLoader(__DIR__ . '/fixtures/phan.json'); + $this->phan = new PhanJson(__DIR__ . '/../fixtures/phan.json'); } } diff --git a/tests/PhanTextTest.php b/tests/Loaders/PhanTextTest.php similarity index 78% rename from tests/PhanTextTest.php rename to tests/Loaders/PhanTextTest.php index d15301d..1e97da2 100644 --- a/tests/PhanTextTest.php +++ b/tests/Loaders/PhanTextTest.php @@ -1,17 +1,17 @@ phan = new PhanTextLoader(__DIR__ . '/fixtures/phan.txt'); + $this->phan = new PhanText(__DIR__ . '/../fixtures/phan.txt'); } public function testOutput() diff --git a/tests/PhpMndTest.php b/tests/Loaders/PhpMndTest.php similarity index 83% rename from tests/PhpMndTest.php rename to tests/Loaders/PhpMndTest.php index 85f5cf7..80c60db 100644 --- a/tests/PhpMndTest.php +++ b/tests/Loaders/PhpMndTest.php @@ -2,7 +2,7 @@ namespace exussum12\CoverageChecker\tests; use PHPUnit\Framework\TestCase; -use exussum12\CoverageChecker\PhpMndLoader; +use exussum12\CoverageChecker\Loaders\PhpMnd; class PhpMndTest extends TestCase { @@ -10,10 +10,10 @@ class PhpMndTest extends TestCase public function setUp() { - $file = __DIR__ . "/fixtures/phpmnd.txt"; - $this->mnd = new PhpMndLoader($file); + $file = __DIR__ . '/../fixtures/phpmnd.txt'; + $this->mnd = new PhpMnd($file); - $this->assertInstanceOf(PhpMndLoader::class, $this->mnd); + $this->assertInstanceOf(PhpMnd::class, $this->mnd); } public function testGetOutput() diff --git a/tests/PhpStanTest.php b/tests/Loaders/PhpStanTest.php similarity index 85% rename from tests/PhpStanTest.php rename to tests/Loaders/PhpStanTest.php index fd6d5ad..9c6f842 100644 --- a/tests/PhpStanTest.php +++ b/tests/Loaders/PhpStanTest.php @@ -2,17 +2,17 @@ namespace exussum12\CoverageChecker\tests; use PHPUnit\Framework\TestCase; -use exussum12\CoverageChecker\PhpStanLoader; +use exussum12\CoverageChecker\Loaders\PhpStan; class PhpStanTest extends TestCase { - /** @var PhpStanLoader */ + /** @var PhpStan */ protected $stan; public function setUp() { - $file = __DIR__ . "/fixtures/phpstan.txt"; - $this->stan = new PhpStanLoader($file); + $file = __DIR__ . '/../fixtures/phpstan.txt'; + $this->stan = new PhpStan($file); } public function testGetOutput() diff --git a/tests/PhpcpdTest.php b/tests/Loaders/PhpcpdTest.php similarity index 83% rename from tests/PhpcpdTest.php rename to tests/Loaders/PhpcpdTest.php index 26cd7b0..b7c2edb 100644 --- a/tests/PhpcpdTest.php +++ b/tests/Loaders/PhpcpdTest.php @@ -1,8 +1,8 @@ cpd = new Phpcpd(__DIR__ . '/fixtures/phpcpd.txt'); + $this->cpd = new Phpcpd(__DIR__ . '/../fixtures/phpcpd.txt'); + $this->cpd->parseLines(); } diff --git a/tests/PhpmndXmlDiffFilterTest.php b/tests/Loaders/PhpmndXmlDiffFilterTest.php similarity index 86% rename from tests/PhpmndXmlDiffFilterTest.php rename to tests/Loaders/PhpmndXmlDiffFilterTest.php index 00c943c..3fd163b 100644 --- a/tests/PhpmndXmlDiffFilterTest.php +++ b/tests/Loaders/PhpmndXmlDiffFilterTest.php @@ -2,7 +2,7 @@ namespace exussum12\CoverageChecker\tests; use PHPUnit\Framework\TestCase; -use exussum12\CoverageChecker\PhpMndXmlLoader; +use exussum12\CoverageChecker\Loaders\PhpMndXml; class PhpmndXmlDiffFilterTest extends TestCase { @@ -12,8 +12,8 @@ class PhpmndXmlDiffFilterTest extends TestCase public function setUp() { parent::setUp(); - $file = __DIR__ . "/fixtures/phpmnd.xml"; - $this->mnd = new PhpMndXmlLoader($file); + $file = __DIR__ . "/../fixtures/phpmnd.xml"; + $this->mnd = new PhpMndXml($file); } public function testValidFiles() diff --git a/tests/Loaders/PylintTest.php b/tests/Loaders/PylintTest.php new file mode 100644 index 0000000..ac65f0c --- /dev/null +++ b/tests/Loaders/PylintTest.php @@ -0,0 +1,15 @@ +phan = new Pylint(__DIR__ . '/../fixtures/pylint.txt'); + } +} diff --git a/tests/PylintTest.php b/tests/PylintTest.php deleted file mode 100644 index 67b8844..0000000 --- a/tests/PylintTest.php +++ /dev/null @@ -1,15 +0,0 @@ -phan = new PylintLoader(__DIR__ . '/fixtures/pylint.txt'); - } -} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 74c550f..7b90122 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,11 +1,18 @@