From bfe0e11c667db4c3f0c418296eddd0ea7630577e Mon Sep 17 00:00:00 2001 From: Anna Filina Date: Tue, 26 Jan 2021 08:48:51 -0500 Subject: [PATCH 01/10] First draft of config validation and parsing --- composer.json | 6 +- generator.xml.dist | 10 ++ src/Configuration/ConfigurationRepository.php | 11 ++ src/Configuration/Value/Configuration.php | 43 +++++++ src/Configuration/Value/Source.php | 35 ++++++ src/Configuration/Value/Standard.php | 24 ++++ .../XmlConfigurationRepository.php | 82 ++++++++++++++ src/Configuration/generator.xsd | 22 ++++ src/Value/Diff.php | 2 +- src/Value/Folder.php | 2 +- src/Value/Property.php | 2 +- src/Value/Sniff.php | 2 +- src/Value/Url.php | 2 +- src/Value/UrlList.php | 2 +- src/Value/Violation.php | 2 +- .../XmlConfigurationRepositoryTest.php | 106 ++++++++++++++++++ 16 files changed, 344 insertions(+), 9 deletions(-) create mode 100644 generator.xml.dist create mode 100644 src/Configuration/ConfigurationRepository.php create mode 100644 src/Configuration/Value/Configuration.php create mode 100644 src/Configuration/Value/Source.php create mode 100644 src/Configuration/Value/Standard.php create mode 100644 src/Configuration/XmlConfigurationRepository.php create mode 100644 src/Configuration/generator.xsd create mode 100644 tests/Configuration/XmlConfigurationRepositoryTest.php diff --git a/composer.json b/composer.json index 1242441..559d2aa 100644 --- a/composer.json +++ b/composer.json @@ -6,9 +6,11 @@ "danielstjules/stringy": "^3.1", "roave/better-reflection": "^4.12", "phpdocumentor/reflection-docblock": "^5.2", - "ext-simplexml": "*", "symfony/filesystem": "^5.2", - "symfony/process": "^5.2" + "symfony/process": "^5.2", + "ext-simplexml": "*", + "ext-dom": "*", + "ext-libxml": "*" }, "autoload": { "psr-4": { diff --git a/generator.xml.dist b/generator.xml.dist new file mode 100644 index 0000000..5c2e2b1 --- /dev/null +++ b/generator.xml.dist @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/Configuration/ConfigurationRepository.php b/src/Configuration/ConfigurationRepository.php new file mode 100644 index 0000000..959ff32 --- /dev/null +++ b/src/Configuration/ConfigurationRepository.php @@ -0,0 +1,11 @@ +inArray(['markdown'], sprintf('Invalid generator format "%s"', $format)); + + Assert::thatAll($sources) + ->isInstanceOf(Source::class); + + $this->format = $format; + $this->sources = $sources; + } + + public function getFormat(): string + { + return $this->format; + } + + /** + * @return Source[] + */ + public function getSources(): array + { + return $this->sources; + } +} diff --git a/src/Configuration/Value/Source.php b/src/Configuration/Value/Source.php new file mode 100644 index 0000000..4bd6cce --- /dev/null +++ b/src/Configuration/Value/Source.php @@ -0,0 +1,35 @@ +path = $path; + $this->standards = $standards; + } + + public function getPath(): string + { + return $this->path; + } + + /** + * @return Standard[] + */ + public function getStandards(): array + { + return $this->standards; + } +} diff --git a/src/Configuration/Value/Standard.php b/src/Configuration/Value/Standard.php new file mode 100644 index 0000000..af4c35d --- /dev/null +++ b/src/Configuration/Value/Standard.php @@ -0,0 +1,24 @@ +notBlank(); + + $this->path = $path; + } + + public function getPath(): string + { + return $this->path; + } +} diff --git a/src/Configuration/XmlConfigurationRepository.php b/src/Configuration/XmlConfigurationRepository.php new file mode 100644 index 0000000..a5eba48 --- /dev/null +++ b/src/Configuration/XmlConfigurationRepository.php @@ -0,0 +1,82 @@ +root = $root; + } + + public function getConfig(): Configuration + { + $paths = [$this->root . 'generator.xml', $this->root . '/generator.xml.dist']; + foreach ($paths as $path) { + if (file_exists($path)) { + return $this->parse($path); + } + } + + throw new RuntimeException( + sprintf('Could not find a configuration file in any of these paths: %s', implode(',', $paths)) + ); + } + + private function parse(string $path): Configuration + { + $dom = new DOMDocument; + $dom->load($path); + + set_error_handler(function(int $number, string $error) use ($path) { + throw new RuntimeException( + sprintf("The configuration file %s is invalid.\n%s", $path, $error) + ); + }); + $dom->schemaValidate(__DIR__ . '/generator.xsd'); + restore_error_handler(); + + $xml = new SimpleXMLElement(file_get_contents($path)); + + return new Configuration( + (string)$xml['format'], + $this->getSources($xml), + ); + } + + /** + * @return Source[] + */ + private function getSources(SimpleXMLElement $xml): array + { + return array_map(function (SimpleXMLElement $source): Source { + return new Source( + (string)$source['path'], + $this->getStandards($source) + ); + }, $xml->xpath('source')); + } + + /** + * @return Standard[] + */ + private function getStandards(SimpleXMLElement $xml): array + { + return array_map(function (SimpleXMLElement $standard): Standard { + return new Standard( + (string)$standard['path'] + ); + }, $xml->xpath('standard')); + } +} diff --git a/src/Configuration/generator.xsd b/src/Configuration/generator.xsd new file mode 100644 index 0000000..44af4cf --- /dev/null +++ b/src/Configuration/generator.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Value/Diff.php b/src/Value/Diff.php index 03e1f53..b991ae9 100644 --- a/src/Value/Diff.php +++ b/src/Value/Diff.php @@ -5,7 +5,7 @@ use Assert\Assert; -class Diff +final class Diff { private string $before; private string $after; diff --git a/src/Value/Folder.php b/src/Value/Folder.php index 76fdb84..d07a3d6 100644 --- a/src/Value/Folder.php +++ b/src/Value/Folder.php @@ -5,7 +5,7 @@ use Assert\Assert; -class Folder +final class Folder { private string $path; diff --git a/src/Value/Property.php b/src/Value/Property.php index 80856dc..1c017c4 100644 --- a/src/Value/Property.php +++ b/src/Value/Property.php @@ -5,7 +5,7 @@ use Assert\Assert; -class Property +final class Property { private string $name; private string $type; diff --git a/src/Value/Sniff.php b/src/Value/Sniff.php index deb666d..c277762 100644 --- a/src/Value/Sniff.php +++ b/src/Value/Sniff.php @@ -5,7 +5,7 @@ use Assert\Assert; -class Sniff +final class Sniff { private string $code; private string $docblock; diff --git a/src/Value/Url.php b/src/Value/Url.php index 92ed716..4ed7d88 100644 --- a/src/Value/Url.php +++ b/src/Value/Url.php @@ -5,7 +5,7 @@ use Assert\Assert; -class Url +final class Url { private string $url; diff --git a/src/Value/UrlList.php b/src/Value/UrlList.php index c852847..1fbd5e2 100644 --- a/src/Value/UrlList.php +++ b/src/Value/UrlList.php @@ -6,7 +6,7 @@ /** * Collection of unique URLs. */ -class UrlList +final class UrlList { /** * @var Url[] diff --git a/src/Value/Violation.php b/src/Value/Violation.php index 91ca7e5..29e4912 100644 --- a/src/Value/Violation.php +++ b/src/Value/Violation.php @@ -5,7 +5,7 @@ use Assert\Assert; -class Violation +final class Violation { private string $code; private string $description; diff --git a/tests/Configuration/XmlConfigurationRepositoryTest.php b/tests/Configuration/XmlConfigurationRepositoryTest.php new file mode 100644 index 0000000..bef3b5c --- /dev/null +++ b/tests/Configuration/XmlConfigurationRepositoryTest.php @@ -0,0 +1,106 @@ +expectException(RuntimeException::class); + $this->repo->getConfig(); + } + + /** @test */ + public function getConfig_WithInvalidSchema_ThrowException() + { + $this->expectException(RuntimeException::class); + + $xmlContent = + ' + + '; + + (new Filesystem)->dumpFile(self::XML_FILE_PATH, $xmlContent); + + $this->repo->getConfig(); + } + + /** @test */ + public function getConfig_WithBothFiles_PickNonDist() + { + $xmlContent = + ' + + + + + '; + + (new Filesystem)->dumpFile(self::XML_FILE_PATH, $xmlContent); + + $xmlDistContent = + ' + + + + '; + + (new Filesystem)->dumpFile(self::XML_DIST_FILE_PATH, $xmlDistContent); + + $config = $this->repo->getConfig(); + self::assertEquals( + 'Xml', + $config->getSources()[0]->getStandards()[0]->getPath() + ); + } + + /** @test */ + public function getConfig_WithValidFile_ReturnConfiguration() + { + $xmlContent = + ' + + + + + '; + + (new Filesystem)->dumpFile(self::XML_FILE_PATH, $xmlContent); + + self::assertEquals( + new Configuration( + 'markdown', + [ + new Source('path/to/code', [ + new Standard('Standard') + ]), + ] + ), + $this->repo->getConfig() + ); + } + + protected function setUp(): void + { + $fs = new Filesystem; + $fs->remove(self::XML_DIST_FILE_PATH); + $fs->remove(self::XML_FILE_PATH); + $this->repo = new XmlConfigurationRepository(new Folder('var/tests/')); + } +} From 8eb9cef7d8c0c1f67cb17ef5c835d1dabddc891b Mon Sep 17 00:00:00 2001 From: Anna Filina Date: Wed, 27 Jan 2021 17:42:32 -0500 Subject: [PATCH 02/10] Init --- src/CodeRepository/CodeRepositoryFactory.php | 11 ++++ ...deRepository.php => GitCodeRepository.php} | 21 +++---- src/CodeRepository/LocalCodeRepository.php | 60 +++++++++++++++++++ .../CodeRepository/GitCodeRepositoryTest.php | 12 ++++ 4 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 src/CodeRepository/CodeRepositoryFactory.php rename src/CodeRepository/{GithubCodeRepository.php => GitCodeRepository.php} (61%) create mode 100644 src/CodeRepository/LocalCodeRepository.php create mode 100644 tests/CodeRepository/GitCodeRepositoryTest.php diff --git a/src/CodeRepository/CodeRepositoryFactory.php b/src/CodeRepository/CodeRepositoryFactory.php new file mode 100644 index 0000000..431ae30 --- /dev/null +++ b/src/CodeRepository/CodeRepositoryFactory.php @@ -0,0 +1,11 @@ +getLocalFolder() . '/'); - $this->runProcess($this->getCloneOrPullProcess($repoPath, $repoName)); - $this->runProcess($this->getComposerInstallProcess($repoPath)); + $this->runProcess($this->getCloneOrPullProcess($localPath, $source->getPath())); + $this->runProcess($this->getComposerInstallProcess($localPath)); - return $repoPath; + return $localPath; } private function runProcess(Process $process): void @@ -28,21 +29,21 @@ private function runProcess(Process $process): void } } - private function getCloneOrPullProcess(Folder $repoPath, string $repoName): Process + private function getCloneOrPullProcess(Folder $localPath, string $sourcePath): Process { - if (!is_dir((string)$repoPath)) { + if (!is_dir((string)$localPath)) { return new Process([ 'git', 'clone', - 'git@github.com:' . $repoName, - $repoPath + $sourcePath, + (string)$localPath ]); } return new Process([ 'git', '-C', - $repoPath, + (string)$localPath, 'pull' ]); } diff --git a/src/CodeRepository/LocalCodeRepository.php b/src/CodeRepository/LocalCodeRepository.php new file mode 100644 index 0000000..d07c3a1 --- /dev/null +++ b/src/CodeRepository/LocalCodeRepository.php @@ -0,0 +1,60 @@ +getLocalFolder() . '/'); + + $this->runProcess($this->getCloneOrPullProcess($localPath, $source->getPath())); + $this->runProcess($this->getComposerInstallProcess($localPath)); + + return $localPath; + } + + private function runProcess(Process $process): void + { + $process->run(); + + if (!$process->isSuccessful()) { + throw new ProcessFailedException($process); + } + } + + private function getCloneOrPullProcess(Folder $localPath, string $sourcePath): Process + { + if (!is_dir((string)$localPath)) { + return new Process([ + 'git', + 'clone', + $sourcePath, + (string)$localPath + ]); + } + + return new Process([ + 'git', + '-C', + (string)$localPath, + 'pull' + ]); + } + + private function getComposerInstallProcess(Folder $repoPath): Process + { + return new Process([ + 'composer', + 'install', + '-d', + $repoPath + ]); + } +} diff --git a/tests/CodeRepository/GitCodeRepositoryTest.php b/tests/CodeRepository/GitCodeRepositoryTest.php new file mode 100644 index 0000000..e3aa562 --- /dev/null +++ b/tests/CodeRepository/GitCodeRepositoryTest.php @@ -0,0 +1,12 @@ + Date: Wed, 27 Jan 2021 18:54:19 -0500 Subject: [PATCH 03/10] Refactor to use configurable repos and standards; clean up code --- .gitignore | 1 + composer.lock | 84 ++++++++++--------- config/di.php | 10 ++- generator.xml.dist | 10 +-- src/CodeRepository/CodeRepository.php | 3 +- src/CodeRepository/GitCodeRepository.php | 12 ++- src/Configuration/Value/Source.php | 28 +++++++ .../XmlConfigurationRepository.php | 4 +- src/Generator/MarkdownGenerator.php | 4 +- src/Handler/GenerateHandler.php | 48 +++++++---- src/Parser/SniffParser.php | 3 +- src/SniffFinder/FilesystemSniffFinder.php | 22 ++--- src/Value/Url.php | 2 +- .../CodeRepository/GitCodeRepositoryTest.php | 46 ++++++++++ .../XmlConfigurationRepositoryTest.php | 8 +- tests/Handler/GenerateHandlerTest.php | 29 +++++-- 16 files changed, 212 insertions(+), 102 deletions(-) diff --git a/.gitignore b/.gitignore index 4da6094..99cb968 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ vendor var +!var/tests/repo !var/**/.gitkeep .phpunit.result.cache diff --git a/composer.lock b/composer.lock index 89eee70..177163a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d1e357dd79e21303096f74a1a97631ed", + "content-hash": "97cac23298e2e8e084027f91bde313f1", "packages": [ { "name": "beberlei/assert", @@ -763,26 +763,26 @@ }, { "name": "roave/signature", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/Roave/Signature.git", - "reference": "bbbcc317dfe3a750e27231c5d2130153aa4c41b3" + "reference": "5b5bb9499cfbcc78d9f472e03af1e97e4341ec7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/Signature/zipball/bbbcc317dfe3a750e27231c5d2130153aa4c41b3", - "reference": "bbbcc317dfe3a750e27231c5d2130153aa4c41b3", + "url": "https://api.github.com/repos/Roave/Signature/zipball/5b5bb9499cfbcc78d9f472e03af1e97e4341ec7c", + "reference": "5b5bb9499cfbcc78d9f472e03af1e97e4341ec7c", "shasum": "" }, "require": { - "php": "7.4.*" + "php": "7.4.*|8.0.*" }, "require-dev": { - "doctrine/coding-standard": "^8.1", - "infection/infection": "^0.17.5", - "phpunit/phpunit": "^9.3", - "vimeo/psalm": "^3.16" + "doctrine/coding-standard": "^8.2", + "infection/infection": "^0.20.2", + "phpunit/phpunit": "^9.5.1", + "vimeo/psalm": "^4.4" }, "type": "library", "autoload": { @@ -797,22 +797,22 @@ "description": "Sign and verify stuff", "support": { "issues": "https://github.com/Roave/Signature/issues", - "source": "https://github.com/Roave/Signature/tree/1.3.0" + "source": "https://github.com/Roave/Signature/tree/1.4.0" }, - "time": "2020-10-01T08:35:57+00:00" + "time": "2021-01-25T09:39:37+00:00" }, { "name": "symfony/console", - "version": "v5.2.1", + "version": "v5.2.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "47c02526c532fb381374dab26df05e7313978976" + "reference": "d62ec79478b55036f65e2602e282822b8eaaff0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/47c02526c532fb381374dab26df05e7313978976", - "reference": "47c02526c532fb381374dab26df05e7313978976", + "url": "https://api.github.com/repos/symfony/console/zipball/d62ec79478b55036f65e2602e282822b8eaaff0a", + "reference": "d62ec79478b55036f65e2602e282822b8eaaff0a", "shasum": "" }, "require": { @@ -871,7 +871,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Console Component", + "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", "keywords": [ "cli", @@ -880,7 +880,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.1" + "source": "https://github.com/symfony/console/tree/v5.2.2" }, "funding": [ { @@ -896,20 +896,20 @@ "type": "tidelift" } ], - "time": "2020-12-18T08:03:05+00:00" + "time": "2021-01-27T10:15:41+00:00" }, { "name": "symfony/filesystem", - "version": "v5.2.1", + "version": "v5.2.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d" + "reference": "262d033b57c73e8b59cd6e68a45c528318b15038" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/fa8f8cab6b65e2d99a118e082935344c5ba8c60d", - "reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/262d033b57c73e8b59cd6e68a45c528318b15038", + "reference": "262d033b57c73e8b59cd6e68a45c528318b15038", "shasum": "" }, "require": { @@ -939,10 +939,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Filesystem Component", + "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.2.1" + "source": "https://github.com/symfony/filesystem/tree/v5.2.2" }, "funding": [ { @@ -958,7 +958,7 @@ "type": "tidelift" } ], - "time": "2020-11-30T17:05:38+00:00" + "time": "2021-01-27T10:01:46+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1448,16 +1448,16 @@ }, { "name": "symfony/process", - "version": "v5.2.1", + "version": "v5.2.2", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "bd8815b8b6705298beaa384f04fabd459c10bedd" + "reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/bd8815b8b6705298beaa384f04fabd459c10bedd", - "reference": "bd8815b8b6705298beaa384f04fabd459c10bedd", + "url": "https://api.github.com/repos/symfony/process/zipball/313a38f09c77fbcdc1d223e57d368cea76a2fd2f", + "reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f", "shasum": "" }, "require": { @@ -1487,10 +1487,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Process Component", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.2.1" + "source": "https://github.com/symfony/process/tree/v5.2.2" }, "funding": [ { @@ -1506,7 +1506,7 @@ "type": "tidelift" } ], - "time": "2020-12-08T17:03:37+00:00" + "time": "2021-01-27T10:15:41+00:00" }, { "name": "symfony/service-contracts", @@ -1589,16 +1589,16 @@ }, { "name": "symfony/string", - "version": "v5.2.1", + "version": "v5.2.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed" + "reference": "c95468897f408dd0aca2ff582074423dd0455122" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed", - "reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed", + "url": "https://api.github.com/repos/symfony/string/zipball/c95468897f408dd0aca2ff582074423dd0455122", + "reference": "c95468897f408dd0aca2ff582074423dd0455122", "shasum": "" }, "require": { @@ -1641,7 +1641,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony String component", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", "keywords": [ "grapheme", @@ -1652,7 +1652,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.2.1" + "source": "https://github.com/symfony/string/tree/v5.2.2" }, "funding": [ { @@ -1668,7 +1668,7 @@ "type": "tidelift" } ], - "time": "2020-12-05T07:33:16+00:00" + "time": "2021-01-25T15:14:59+00:00" }, { "name": "webmozart/assert", @@ -3472,7 +3472,9 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "ext-simplexml": "*" + "ext-simplexml": "*", + "ext-dom": "*", + "ext-libxml": "*" }, "platform-dev": [], "plugin-api-version": "2.0.0" diff --git a/config/di.php b/config/di.php index 85b2b4e..b3125b0 100644 --- a/config/di.php +++ b/config/di.php @@ -2,14 +2,20 @@ declare(strict_types=1); use App\CodeRepository\CodeRepository; -use App\CodeRepository\GithubCodeRepository; +use App\CodeRepository\GitCodeRepository; +use App\Configuration\ConfigurationRepository; +use App\Configuration\XmlConfigurationRepository; use App\Generator\Generator as DocGenerator; use App\Generator\MarkdownGenerator; use App\SniffFinder\FilesystemSniffFinder; use App\SniffFinder\SniffFinder; +use App\Value\Folder; return [ - CodeRepository::class => DI\autowire(GithubCodeRepository::class), + CodeRepository::class => DI\autowire(GitCodeRepository::class), DocGenerator::class => DI\autowire(MarkdownGenerator::class), SniffFinder::class => DI\autowire(FilesystemSniffFinder::class), + ConfigurationRepository::class => DI\factory(function () { + return new XmlConfigurationRepository(new Folder(__DIR__ . '/../')); + }) ]; diff --git a/generator.xml.dist b/generator.xml.dist index 5c2e2b1..647bea3 100644 --- a/generator.xml.dist +++ b/generator.xml.dist @@ -1,10 +1,6 @@ - - - - - - - + + + diff --git a/src/CodeRepository/CodeRepository.php b/src/CodeRepository/CodeRepository.php index d132f32..1ff2784 100644 --- a/src/CodeRepository/CodeRepository.php +++ b/src/CodeRepository/CodeRepository.php @@ -3,11 +3,12 @@ namespace App\CodeRepository; +use App\Configuration\Value\Source; use App\Value\Folder; interface CodeRepository { public const CODE_DOWNLOAD_PATH = 'var/repos/'; - public function downloadCode(string $repoName): Folder; + public function getFolder(Source $source): Folder; } diff --git a/src/CodeRepository/GitCodeRepository.php b/src/CodeRepository/GitCodeRepository.php index c68f904..4cb4dbf 100644 --- a/src/CodeRepository/GitCodeRepository.php +++ b/src/CodeRepository/GitCodeRepository.php @@ -8,16 +8,14 @@ use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; -class GithubCodeRepository implements CodeRepository +class GitCodeRepository implements CodeRepository { - public function downloadCode(Source $source): Folder + public function getFolder(Source $source): Folder { - $localPath = new Folder(self::CODE_DOWNLOAD_PATH . $source->getLocalFolder() . '/'); + $this->runProcess($this->getCloneOrPullProcess($source->getLocalFolder(), $source->getPath())); + $this->runProcess($this->getComposerInstallProcess($source->getLocalFolder())); - $this->runProcess($this->getCloneOrPullProcess($localPath, $source->getPath())); - $this->runProcess($this->getComposerInstallProcess($localPath)); - - return $localPath; + return $source->getLocalFolder(); } private function runProcess(Process $process): void diff --git a/src/Configuration/Value/Source.php b/src/Configuration/Value/Source.php index 4bd6cce..00ea60c 100644 --- a/src/Configuration/Value/Source.php +++ b/src/Configuration/Value/Source.php @@ -3,13 +3,22 @@ namespace App\Configuration\Value; +use App\CodeRepository\CodeRepository; +use App\Value\Folder; +use function Stringy\create as s; + final class Source { + public const TYPE_GIT = 'git'; + public const TYPE_LOCAL = 'local'; + private string $path; /** * @var Standard[] */ private array $standards; + private Folder $localFolder; + private string $type = self::TYPE_LOCAL; /** * @param Standard[] $standards @@ -18,6 +27,20 @@ public function __construct(string $path, array $standards) { $this->path = $path; $this->standards = $standards; + + if (preg_match('/([^.\/]+)\.git$/', $path, $matches)) { + $this->localFolder = $this->createLocalFolder(CodeRepository::CODE_DOWNLOAD_PATH . $matches[1]); + $this->type = self::TYPE_GIT; + return; + } + + $this->localFolder = $this->createLocalFolder($path); + } + + private function createLocalFolder(string $path): Folder + { + $path = s($path)->ensureRight('/'); + return new Folder((string)$path); } public function getPath(): string @@ -25,6 +48,11 @@ public function getPath(): string return $this->path; } + public function getLocalFolder(): Folder + { + return $this->localFolder; + } + /** * @return Standard[] */ diff --git a/src/Configuration/XmlConfigurationRepository.php b/src/Configuration/XmlConfigurationRepository.php index a5eba48..7b52817 100644 --- a/src/Configuration/XmlConfigurationRepository.php +++ b/src/Configuration/XmlConfigurationRepository.php @@ -22,7 +22,7 @@ public function __construct(Folder $root) public function getConfig(): Configuration { - $paths = [$this->root . 'generator.xml', $this->root . '/generator.xml.dist']; + $paths = [$this->root . 'generator.xml', $this->root . 'generator.xml.dist']; foreach ($paths as $path) { if (file_exists($path)) { return $this->parse($path); @@ -39,7 +39,7 @@ private function parse(string $path): Configuration $dom = new DOMDocument; $dom->load($path); - set_error_handler(function(int $number, string $error) use ($path) { + set_error_handler(function (int $number, string $error) use ($path) { throw new RuntimeException( sprintf("The configuration file %s is invalid.\n%s", $path, $error) ); diff --git a/src/Generator/MarkdownGenerator.php b/src/Generator/MarkdownGenerator.php index b329433..2baaa73 100644 --- a/src/Generator/MarkdownGenerator.php +++ b/src/Generator/MarkdownGenerator.php @@ -27,8 +27,8 @@ public function createSniffDoc(Sniff $sniff): string {$this->getViolations($sniff->getViolations())} MD; - $sniffDoc = preg_replace('/\n{3,}/', "\n\n",$sniffDoc); - return preg_replace('/\n{2,}$/', "\n",$sniffDoc); + $sniffDoc = preg_replace('/\n{3,}/', "\n\n", $sniffDoc); + return preg_replace('/\n{2,}$/', "\n", $sniffDoc); } private function getDescription(Sniff $sniff): string diff --git a/src/Handler/GenerateHandler.php b/src/Handler/GenerateHandler.php index 8ebedf8..ad25c72 100644 --- a/src/Handler/GenerateHandler.php +++ b/src/Handler/GenerateHandler.php @@ -4,6 +4,7 @@ namespace App\Handler; use App\CodeRepository\CodeRepository; +use App\Configuration\ConfigurationRepository; use App\Generator\Generator; use App\SniffFinder\SniffFinder; use App\Value\Folder; @@ -14,12 +15,19 @@ class GenerateHandler private CodeRepository $codeRepository; private Generator $generator; private SniffFinder $sniffFinder; + private ConfigurationRepository $configRepo; - public function __construct(CodeRepository $codeRepository, Generator $generator, SniffFinder $sniffFinder) + public function __construct( + CodeRepository $codeRepository, + Generator $generator, + SniffFinder $sniffFinder, + ConfigurationRepository $configRepo + ) { $this->codeRepository = $codeRepository; $this->generator = $generator; $this->sniffFinder = $sniffFinder; + $this->configRepo = $configRepo; } /** @@ -27,27 +35,31 @@ public function __construct(CodeRepository $codeRepository, Generator $generator */ public function handle(string $sniffPath = null): iterable { - $repoName = 'PHPCompatibility/PHPCompatibility'; - $repoPath = $this->codeRepository->downloadCode($repoName); + $config = $this->configRepo->getConfig(); $filesystem = new Filesystem(); - $standardPath = new Folder($repoPath . 'PHPCompatibility/'); - yield "Searching for sniffs..."; + foreach ($config->getSources() as $source) { + $repoPath = $this->codeRepository->getFolder($source); + foreach ($source->getStandards() as $standard) { + $standardFolder = new Folder($repoPath . $standard->getPath() . '/'); + yield "Searching for sniffs in {$standardFolder}..."; - if ($sniffPath !== null) { - $sniffs = [$this->sniffFinder->getSniff($standardPath, $sniffPath)]; - } else { - $sniffs = $this->sniffFinder->getSniffs($standardPath); - } + if ($sniffPath !== null) { + $sniffs = [$this->sniffFinder->getSniff($standardFolder, $sniffPath)]; + } else { + $sniffs = $this->sniffFinder->getSniffs($standardFolder); + } - foreach ($sniffs as $sniff) { - $markdownPath = $this->sniffCodeToMarkdownPath($sniff->getCode()); - $filesystem->dumpFile( - // TODO: perhaps we can move this logic to the the sniff class - $markdownPath, - $this->generator->createSniffDoc($sniff) - ); - yield "Created file: {$markdownPath}"; + foreach ($sniffs as $sniff) { + $markdownPath = $this->sniffCodeToMarkdownPath($sniff->getCode()); + $filesystem->dumpFile( + // TODO: perhaps we can move this logic to the the sniff class + $markdownPath, + $this->generator->createSniffDoc($sniff) + ); + yield "Created file: {$markdownPath}"; + } + } } } diff --git a/src/Parser/SniffParser.php b/src/Parser/SniffParser.php index d8e4565..11973b6 100644 --- a/src/Parser/SniffParser.php +++ b/src/Parser/SniffParser.php @@ -206,7 +206,8 @@ private function getUrls(ReflectionClass $classInfo, array $xmlUrls): UrlList ->getTagsByName('link'); $urls = array_map(function (string $url) { - return new Url($url); + preg_match('/(http[^ ]+)/', $url, $matches); + return new Url($matches[0]); }, $links); return new UrlList(array_merge($urls, $xmlUrls)); diff --git a/src/SniffFinder/FilesystemSniffFinder.php b/src/SniffFinder/FilesystemSniffFinder.php index 58f744f..60a6ae3 100644 --- a/src/SniffFinder/FilesystemSniffFinder.php +++ b/src/SniffFinder/FilesystemSniffFinder.php @@ -25,14 +25,11 @@ public function getSniff(Folder $folder, string $sniffPath): Sniff return $parser->parse($sniffPath, $projectSourceLocator); } - public function getSniffs(Folder $folder): iterable + private function createProjectSourceLocator(Folder $folder): SourceLocator { - $parser = new SniffParser(); - $globSniffs = new GlobIterator($folder->getPath() . 'Sniffs/*/*Sniff.php'); - $projectSourceLocator = $this->createProjectSourceLocator($folder); - foreach ($globSniffs as $fileInfo) { - yield $parser->parse($fileInfo->getPathname(), $projectSourceLocator); - } + $astLocator = (new BetterReflection())->astLocator(); + $fileInfoIterator = $this->recursiveSearch($folder); + return new FileIteratorSourceLocator($fileInfoIterator, $astLocator); } /** @@ -47,10 +44,13 @@ private function recursiveSearch(Folder $folder): Iterator }); } - private function createProjectSourceLocator(Folder $folder): SourceLocator + public function getSniffs(Folder $folder): iterable { - $astLocator = (new BetterReflection())->astLocator(); - $fileInfoIterator = $this->recursiveSearch($folder); - return new FileIteratorSourceLocator($fileInfoIterator, $astLocator); + $parser = new SniffParser(); + $globSniffs = new GlobIterator($folder->getPath() . 'Sniffs/*/*Sniff.php'); + $projectSourceLocator = $this->createProjectSourceLocator($folder); + foreach ($globSniffs as $fileInfo) { + yield $parser->parse($fileInfo->getPathname(), $projectSourceLocator); + } } } diff --git a/src/Value/Url.php b/src/Value/Url.php index 4ed7d88..afceea0 100644 --- a/src/Value/Url.php +++ b/src/Value/Url.php @@ -12,7 +12,7 @@ final class Url public function __construct(string $url) { Assert::that($url) - ->url(); + ->url('Not a valid URL: ' . $url); $this->url = $url; } diff --git a/tests/CodeRepository/GitCodeRepositoryTest.php b/tests/CodeRepository/GitCodeRepositoryTest.php index e3aa562..71da3fb 100644 --- a/tests/CodeRepository/GitCodeRepositoryTest.php +++ b/tests/CodeRepository/GitCodeRepositoryTest.php @@ -4,9 +4,55 @@ namespace App\Tests\CodeRepository; use App\CodeRepository\GitCodeRepository; +use App\Configuration\Value\Source; use PHPUnit\Framework\TestCase; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Process\Exception\RuntimeException; /** @covers \App\CodeRepository\GitCodeRepository */ class GitCodeRepositoryTest extends TestCase { + const LOCAL_GIT_PATH = 'var/tests/repo/Standard.git'; + private GitCodeRepository $codeRepo; + + /** @test */ + public function getFolder_WithMissingPath_ThrowException() + { + $this->expectException(RuntimeException::class); + $sourcePath = 'var/repos/MISSING.git'; + $this->codeRepo->getFolder(new Source($sourcePath, [])); + } + + /** @test */ + public function getFolder_WithGitPath_InstallComposer() + { + $this->createGitRepo(); + (new Filesystem())->remove('var/repos/Standard'); // force fresh clone + + $this->codeRepo->getFolder(new Source(self::LOCAL_GIT_PATH, [])); + self::assertFileExists('var/repos/Standard/composer.lock'); + } + + private function createGitRepo(): void + { + $fs = new Filesystem; + $gitPath = self::LOCAL_GIT_PATH; + $fs->mkdir($gitPath); + $fs->dumpFile($gitPath . '/composer.json', '{}'); + `cd {$gitPath} && git init && git add composer.json && git commit -m "Init"`; + } + + /** @test */ + public function getFolder_WithExistingGitClone_InstallComposer() + { + $this->createGitRepo(); + + $this->codeRepo->getFolder(new Source(self::LOCAL_GIT_PATH, [])); + self::assertFileExists('var/repos/Standard/composer.lock'); + } + + protected function setUp(): void + { + $this->codeRepo = new GitCodeRepository(); + } } diff --git a/tests/Configuration/XmlConfigurationRepositoryTest.php b/tests/Configuration/XmlConfigurationRepositoryTest.php index bef3b5c..a452182 100644 --- a/tests/Configuration/XmlConfigurationRepositoryTest.php +++ b/tests/Configuration/XmlConfigurationRepositoryTest.php @@ -32,7 +32,7 @@ public function getConfig_WithInvalidSchema_ThrowException() $this->expectException(RuntimeException::class); $xmlContent = - ' + ' '; @@ -45,7 +45,7 @@ public function getConfig_WithInvalidSchema_ThrowException() public function getConfig_WithBothFiles_PickNonDist() { $xmlContent = - ' + ' @@ -55,7 +55,7 @@ public function getConfig_WithBothFiles_PickNonDist() (new Filesystem)->dumpFile(self::XML_FILE_PATH, $xmlContent); $xmlDistContent = - ' + ' @@ -74,7 +74,7 @@ public function getConfig_WithBothFiles_PickNonDist() public function getConfig_WithValidFile_ReturnConfiguration() { $xmlContent = - ' + ' diff --git a/tests/Handler/GenerateHandlerTest.php b/tests/Handler/GenerateHandlerTest.php index eb92c2a..64d3bc5 100644 --- a/tests/Handler/GenerateHandlerTest.php +++ b/tests/Handler/GenerateHandlerTest.php @@ -4,6 +4,10 @@ namespace App\Tests\Handler; use App\CodeRepository\CodeRepository; +use App\Configuration\ConfigurationRepository; +use App\Configuration\Value\Configuration; +use App\Configuration\Value\Source; +use App\Configuration\Value\Standard; use App\Generator\Generator; use App\Handler\GenerateHandler; use App\SniffFinder\SniffFinder; @@ -34,11 +38,15 @@ class GenerateHandlerTest extends TestCase * @var SniffFinder|MockObject */ private $sniffFinder; + /** + * @var ConfigurationRepository|MockObject + */ + private $configRepo; /** @test */ public function handle_WithoutArguments_CreatesFile() { - $this->codeRepository->method('downloadCode')->willReturn(new Folder('var/tests/')); + $this->codeRepository->method('getFolder')->willReturn(new Folder('var/tests/')); $sniffs = $this->createSniffs(['First', 'Second']); $this->sniffFinder->method('getSniffs')->willReturn($sniffs); $this->generator->method('createSniffDoc')->withConsecutive([$sniffs[0]], [$sniffs[1]]); @@ -48,7 +56,7 @@ public function handle_WithoutArguments_CreatesFile() self::assertEquals( [ - 'Searching for sniffs...', + 'Searching for sniffs in var/tests/Standard/...', 'Created file: var/markdown/Standard/Category/First.md', 'Created file: var/markdown/Standard/Category/Second.md' ], @@ -89,7 +97,7 @@ private function createSniff(string $name): Sniff /** @test */ public function handle_WithSniffPath_CreatesSingleFile() { - $this->codeRepository->method('downloadCode')->willReturn(new Folder('var/tests/')); + $this->codeRepository->method('getFolder')->willReturn(new Folder('var/tests/')); $this->sniffFinder->method('getSniff')->willReturn($this->createSniff('First')); /** @var \Generator $messages */ @@ -97,7 +105,7 @@ public function handle_WithSniffPath_CreatesSingleFile() self::assertEquals( [ - 'Searching for sniffs...', + 'Searching for sniffs in var/tests/Standard/...', 'Created file: var/markdown/Standard/Category/First.md', ], iterator_to_array($messages) @@ -111,11 +119,22 @@ protected function setUp(): void $this->codeRepository = $this->createMock(CodeRepository::class); $this->generator = $this->createMock(Generator::class); $this->sniffFinder = $this->createMock(SniffFinder::class); + $this->configRepo = $this->createMock(ConfigurationRepository::class); + + $this->configRepo->method('getConfig')->willReturn(new Configuration( + 'markdown', + [ + new Source('../Standard', [ + new Standard('Standard') + ]) + ] + )); $this->handler = new GenerateHandler( $this->codeRepository, $this->generator, - $this->sniffFinder + $this->sniffFinder, + $this->configRepo ); } } From 39f9fe3e6287ff661d0ce778a28f6beb7300a869 Mon Sep 17 00:00:00 2001 From: Anna Filina Date: Wed, 27 Jan 2021 18:54:52 -0500 Subject: [PATCH 04/10] Add option for generating docs for a local project --- src/CodeRepository/CodeRepositoryFactory.php | 15 ++++++- src/CodeRepository/LocalCodeRepository.php | 30 ++----------- .../CodeRepositoryFactoryTest.php | 32 ++++++++++++++ .../LocalCodeRepositoryTest.php | 43 +++++++++++++++++++ 4 files changed, 92 insertions(+), 28 deletions(-) create mode 100644 tests/CodeRepository/CodeRepositoryFactoryTest.php create mode 100644 tests/CodeRepository/LocalCodeRepositoryTest.php diff --git a/src/CodeRepository/CodeRepositoryFactory.php b/src/CodeRepository/CodeRepositoryFactory.php index 431ae30..7a62dc9 100644 --- a/src/CodeRepository/CodeRepositoryFactory.php +++ b/src/CodeRepository/CodeRepositoryFactory.php @@ -1,11 +1,22 @@ getLocalFolder() . '/'); + $this->runProcess($this->getComposerInstallProcess($source->getLocalFolder())); - $this->runProcess($this->getCloneOrPullProcess($localPath, $source->getPath())); - $this->runProcess($this->getComposerInstallProcess($localPath)); - - return $localPath; + return $source->getLocalFolder(); } private function runProcess(Process $process): void @@ -29,25 +26,6 @@ private function runProcess(Process $process): void } } - private function getCloneOrPullProcess(Folder $localPath, string $sourcePath): Process - { - if (!is_dir((string)$localPath)) { - return new Process([ - 'git', - 'clone', - $sourcePath, - (string)$localPath - ]); - } - - return new Process([ - 'git', - '-C', - (string)$localPath, - 'pull' - ]); - } - private function getComposerInstallProcess(Folder $repoPath): Process { return new Process([ diff --git a/tests/CodeRepository/CodeRepositoryFactoryTest.php b/tests/CodeRepository/CodeRepositoryFactoryTest.php new file mode 100644 index 0000000..1ee7a1d --- /dev/null +++ b/tests/CodeRepository/CodeRepositoryFactoryTest.php @@ -0,0 +1,32 @@ +expectException(RuntimeException::class); + $sourcePath = 'var/repos/MISSING'; + $this->codeRepo->getFolder(new Source($sourcePath, [])); + } + + /** @test */ + public function getFolder_WithExistingPath_InstallComposer() + { + $fs = new Filesystem; + $sourcePath = self::LOCAL_PATH; + $fs->remove($sourcePath); + $fs->mkdir($sourcePath); + $fs->dumpFile($sourcePath . '/composer.json', '{}'); + + $this->codeRepo->getFolder(new Source($sourcePath, [])); + self::assertFileExists('var/repos/Standard/composer.lock'); + } + + protected function setUp(): void + { + $this->codeRepo = new LocalCodeRepository(); + } +} From 14a8e175554299eaf5677a3b0981024f0765888b Mon Sep 17 00:00:00 2001 From: Anna Filina Date: Wed, 27 Jan 2021 19:23:57 -0500 Subject: [PATCH 05/10] Enable multiple code repo strategies --- config/di.php | 3 -- src/CodeRepository/CodeRepositoryFactory.php | 2 +- src/Configuration/Value/Source.php | 5 ++ src/Handler/GenerateHandler.php | 10 ++-- .../CodeRepositoryFactoryTest.php | 12 ++++- .../Configuration/Value/ConfigurationTest.php | 51 +++++++++++++++++++ tests/Configuration/Value/SourceTest.php | 47 +++++++++++++++++ tests/Configuration/Value/StandardTest.php | 30 +++++++++++ tests/Handler/GenerateHandlerTest.php | 18 ++++--- 9 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 tests/Configuration/Value/ConfigurationTest.php create mode 100644 tests/Configuration/Value/SourceTest.php create mode 100644 tests/Configuration/Value/StandardTest.php diff --git a/config/di.php b/config/di.php index b3125b0..b51af2d 100644 --- a/config/di.php +++ b/config/di.php @@ -1,8 +1,6 @@ DI\autowire(GitCodeRepository::class), DocGenerator::class => DI\autowire(MarkdownGenerator::class), SniffFinder::class => DI\autowire(FilesystemSniffFinder::class), ConfigurationRepository::class => DI\factory(function () { diff --git a/src/CodeRepository/CodeRepositoryFactory.php b/src/CodeRepository/CodeRepositoryFactory.php index 7a62dc9..26f6ab9 100644 --- a/src/CodeRepository/CodeRepositoryFactory.php +++ b/src/CodeRepository/CodeRepositoryFactory.php @@ -8,7 +8,7 @@ class CodeRepositoryFactory { - public static function fromType(string $type): CodeRepository + public function fromType(string $type): CodeRepository { switch ($type) { case Source::TYPE_GIT: diff --git a/src/Configuration/Value/Source.php b/src/Configuration/Value/Source.php index 00ea60c..c7fa46b 100644 --- a/src/Configuration/Value/Source.php +++ b/src/Configuration/Value/Source.php @@ -60,4 +60,9 @@ public function getStandards(): array { return $this->standards; } + + public function getType(): string + { + return $this->type; + } } diff --git a/src/Handler/GenerateHandler.php b/src/Handler/GenerateHandler.php index ad25c72..afc1f18 100644 --- a/src/Handler/GenerateHandler.php +++ b/src/Handler/GenerateHandler.php @@ -4,6 +4,7 @@ namespace App\Handler; use App\CodeRepository\CodeRepository; +use App\CodeRepository\CodeRepositoryFactory; use App\Configuration\ConfigurationRepository; use App\Generator\Generator; use App\SniffFinder\SniffFinder; @@ -12,19 +13,19 @@ class GenerateHandler { - private CodeRepository $codeRepository; + private CodeRepositoryFactory $codeRepositoryFactory; private Generator $generator; private SniffFinder $sniffFinder; private ConfigurationRepository $configRepo; public function __construct( - CodeRepository $codeRepository, + CodeRepositoryFactory $codeRepositoryFactory, Generator $generator, SniffFinder $sniffFinder, ConfigurationRepository $configRepo ) { - $this->codeRepository = $codeRepository; + $this->codeRepositoryFactory = $codeRepositoryFactory; $this->generator = $generator; $this->sniffFinder = $sniffFinder; $this->configRepo = $configRepo; @@ -39,7 +40,8 @@ public function handle(string $sniffPath = null): iterable $filesystem = new Filesystem(); foreach ($config->getSources() as $source) { - $repoPath = $this->codeRepository->getFolder($source); + $codeRepository = $this->codeRepositoryFactory->fromType($source->getType()); + $repoPath = $codeRepository->getFolder($source); foreach ($source->getStandards() as $standard) { $standardFolder = new Folder($repoPath . $standard->getPath() . '/'); yield "Searching for sniffs in {$standardFolder}..."; diff --git a/tests/CodeRepository/CodeRepositoryFactoryTest.php b/tests/CodeRepository/CodeRepositoryFactoryTest.php index 1ee7a1d..932af42 100644 --- a/tests/CodeRepository/CodeRepositoryFactoryTest.php +++ b/tests/CodeRepository/CodeRepositoryFactoryTest.php @@ -7,17 +7,25 @@ use App\CodeRepository\GitCodeRepository; use App\CodeRepository\LocalCodeRepository; use App\Configuration\Value\Source; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; /** @covers \App\CodeRepository\CodeRepositoryFactory */ class CodeRepositoryFactoryTest extends TestCase { + /** @test */ + public function fromType_WithInvalid_ThrowException() + { + $this->expectException(InvalidArgumentException::class); + (new CodeRepositoryFactory)->fromType('INVALID'); + } + /** @test */ public function fromType_WithGit_ReturnGitImplementation() { self::assertInstanceOf( GitCodeRepository::class, - CodeRepositoryFactory::fromType(Source::TYPE_GIT) + (new CodeRepositoryFactory)->fromType(Source::TYPE_GIT) ); } @@ -26,7 +34,7 @@ public function fromType_WithLocal_ReturnLocalImplementation() { self::assertInstanceOf( LocalCodeRepository::class, - CodeRepositoryFactory::fromType(Source::TYPE_LOCAL) + (new CodeRepositoryFactory)->fromType(Source::TYPE_LOCAL) ); } } diff --git a/tests/Configuration/Value/ConfigurationTest.php b/tests/Configuration/Value/ConfigurationTest.php new file mode 100644 index 0000000..94b602f --- /dev/null +++ b/tests/Configuration/Value/ConfigurationTest.php @@ -0,0 +1,51 @@ +createValidVO()->getSources(), + ); + } + + /** @test */ + public function getFormat() + { + self::assertEquals( + self::FORMAT, + $this->createValidVO()->getFormat(), + ); + } + + private function createValidVO(): Configuration + { + return new Configuration( + self::FORMAT, + self::$SOURCES + ); + } + + public static function setUpBeforeClass(): void + { + self::$SOURCES = [ + new Source('path/to/source', []) + ]; + } +} diff --git a/tests/Configuration/Value/SourceTest.php b/tests/Configuration/Value/SourceTest.php new file mode 100644 index 0000000..5b02f4a --- /dev/null +++ b/tests/Configuration/Value/SourceTest.php @@ -0,0 +1,47 @@ +getStandards() + ); + } + + /** @test */ + public function getLocalFolder_WithGit_PrependDownloadPath() + { + self::assertEquals( + new Folder('var/repos/repo/'), + (new Source('path/to/repo.git', []))->getLocalFolder() + ); + } + + /** @test */ + public function getPath() + { + self::assertEquals( + self::SOURCE_PATH, + (new Source(self::SOURCE_PATH, []))->getPath() + ); + } +} diff --git a/tests/Configuration/Value/StandardTest.php b/tests/Configuration/Value/StandardTest.php new file mode 100644 index 0000000..23e3bb9 --- /dev/null +++ b/tests/Configuration/Value/StandardTest.php @@ -0,0 +1,30 @@ +expectException(InvalidArgumentException::class); + new Standard(''); + } + + /** @test */ + public function getPath() + { + self::assertEquals( + self::STANDARD_PATH, + (new Standard(self::STANDARD_PATH))->getPath() + ); + } +} diff --git a/tests/Handler/GenerateHandlerTest.php b/tests/Handler/GenerateHandlerTest.php index 64d3bc5..9f46cb8 100644 --- a/tests/Handler/GenerateHandlerTest.php +++ b/tests/Handler/GenerateHandlerTest.php @@ -4,6 +4,7 @@ namespace App\Tests\Handler; use App\CodeRepository\CodeRepository; +use App\CodeRepository\CodeRepositoryFactory; use App\Configuration\ConfigurationRepository; use App\Configuration\Value\Configuration; use App\Configuration\Value\Source; @@ -27,9 +28,9 @@ class GenerateHandlerTest extends TestCase */ private GenerateHandler $handler; /** - * @var CodeRepository|MockObject + * @var CodeRepositoryFactory|MockObject */ - private $codeRepository; + private $codeRepositoryFactory; /** * @var Generator|MockObject */ @@ -46,7 +47,10 @@ class GenerateHandlerTest extends TestCase /** @test */ public function handle_WithoutArguments_CreatesFile() { - $this->codeRepository->method('getFolder')->willReturn(new Folder('var/tests/')); + $codeRepository = $this->createMock(CodeRepository::class); + $codeRepository->method('getFolder')->willReturn(new Folder('var/tests/')); + $this->codeRepositoryFactory->method('fromType')->willReturn($codeRepository); + $sniffs = $this->createSniffs(['First', 'Second']); $this->sniffFinder->method('getSniffs')->willReturn($sniffs); $this->generator->method('createSniffDoc')->withConsecutive([$sniffs[0]], [$sniffs[1]]); @@ -97,7 +101,9 @@ private function createSniff(string $name): Sniff /** @test */ public function handle_WithSniffPath_CreatesSingleFile() { - $this->codeRepository->method('getFolder')->willReturn(new Folder('var/tests/')); + $codeRepository = $this->createMock(CodeRepository::class); + $codeRepository->method('getFolder')->willReturn(new Folder('var/tests/')); + $this->codeRepositoryFactory->method('fromType')->willReturn($codeRepository); $this->sniffFinder->method('getSniff')->willReturn($this->createSniff('First')); /** @var \Generator $messages */ @@ -116,7 +122,7 @@ protected function setUp(): void { (new Filesystem())->remove('var/markdown/Standard'); - $this->codeRepository = $this->createMock(CodeRepository::class); + $this->codeRepositoryFactory = $this->createMock(CodeRepositoryFactory::class); $this->generator = $this->createMock(Generator::class); $this->sniffFinder = $this->createMock(SniffFinder::class); $this->configRepo = $this->createMock(ConfigurationRepository::class); @@ -131,7 +137,7 @@ protected function setUp(): void )); $this->handler = new GenerateHandler( - $this->codeRepository, + $this->codeRepositoryFactory, $this->generator, $this->sniffFinder, $this->configRepo From 25136af4d8b12db6337db9d13f6fd6a3ca47cbe3 Mon Sep 17 00:00:00 2001 From: Anna Filina Date: Wed, 27 Jan 2021 19:25:32 -0500 Subject: [PATCH 06/10] Bump coverage --- tests/Configuration/Value/SourceTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/Configuration/Value/SourceTest.php b/tests/Configuration/Value/SourceTest.php index 5b02f4a..e35bd13 100644 --- a/tests/Configuration/Value/SourceTest.php +++ b/tests/Configuration/Value/SourceTest.php @@ -36,6 +36,15 @@ public function getLocalFolder_WithGit_PrependDownloadPath() ); } + /** @test */ + public function getType_WithGit_ReturnGit() + { + self::assertEquals( + Source::TYPE_GIT, + (new Source('path/to/repo.git', []))->getType() + ); + } + /** @test */ public function getPath() { From 587dbc1f94be4172cb9ac7b6d8b1999710fe9240 Mon Sep 17 00:00:00 2001 From: Anna Filina Date: Wed, 27 Jan 2021 20:46:30 -0500 Subject: [PATCH 07/10] Create source locator from correct folder; better variable names --- composer.json | 3 ++- src/Configuration/generator.xsd | 4 +-- src/Handler/GenerateHandler.php | 9 +++---- src/SniffFinder/FilesystemSniffFinder.php | 10 +++---- src/SniffFinder/SniffFinder.php | 4 +-- src/Value/Folder.php | 2 +- src/Value/Url.php | 2 +- .../CodeRepository/GitCodeRepositoryTest.php | 2 +- .../Configuration/Value/ConfigurationTest.php | 26 +++++++++---------- .../SniffFinder/FilesystemSniffFinderTest.php | 6 +++++ var/repos/.gitkeep | 0 11 files changed, 37 insertions(+), 31 deletions(-) delete mode 100644 var/repos/.gitkeep diff --git a/composer.json b/composer.json index 559d2aa..c381f2c 100644 --- a/composer.json +++ b/composer.json @@ -8,6 +8,7 @@ "phpdocumentor/reflection-docblock": "^5.2", "symfony/filesystem": "^5.2", "symfony/process": "^5.2", + "nikic/php-parser": "4.6.*", "ext-simplexml": "*", "ext-dom": "*", "ext-libxml": "*" @@ -19,6 +20,6 @@ } }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^9.0" } } diff --git a/src/Configuration/generator.xsd b/src/Configuration/generator.xsd index 44af4cf..fe6c4af 100644 --- a/src/Configuration/generator.xsd +++ b/src/Configuration/generator.xsd @@ -3,10 +3,10 @@ - + - + diff --git a/src/Handler/GenerateHandler.php b/src/Handler/GenerateHandler.php index afc1f18..2aa7e83 100644 --- a/src/Handler/GenerateHandler.php +++ b/src/Handler/GenerateHandler.php @@ -3,7 +3,6 @@ namespace App\Handler; -use App\CodeRepository\CodeRepository; use App\CodeRepository\CodeRepositoryFactory; use App\Configuration\ConfigurationRepository; use App\Generator\Generator; @@ -41,15 +40,15 @@ public function handle(string $sniffPath = null): iterable foreach ($config->getSources() as $source) { $codeRepository = $this->codeRepositoryFactory->fromType($source->getType()); - $repoPath = $codeRepository->getFolder($source); + $sourceFolder = $codeRepository->getFolder($source); foreach ($source->getStandards() as $standard) { - $standardFolder = new Folder($repoPath . $standard->getPath() . '/'); + $standardFolder = new Folder($sourceFolder . $standard->getPath() . '/'); yield "Searching for sniffs in {$standardFolder}..."; if ($sniffPath !== null) { - $sniffs = [$this->sniffFinder->getSniff($standardFolder, $sniffPath)]; + $sniffs = [$this->sniffFinder->getSniff($standardFolder, $sourceFolder, $sniffPath)]; } else { - $sniffs = $this->sniffFinder->getSniffs($standardFolder); + $sniffs = $this->sniffFinder->getSniffs($standardFolder, $sourceFolder); } foreach ($sniffs as $sniff) { diff --git a/src/SniffFinder/FilesystemSniffFinder.php b/src/SniffFinder/FilesystemSniffFinder.php index 60a6ae3..ee4bddf 100644 --- a/src/SniffFinder/FilesystemSniffFinder.php +++ b/src/SniffFinder/FilesystemSniffFinder.php @@ -18,10 +18,10 @@ class FilesystemSniffFinder implements SniffFinder { - public function getSniff(Folder $folder, string $sniffPath): Sniff + public function getSniff(Folder $standardFolder, Folder $sourceFolder, string $sniffPath): Sniff { $parser = new SniffParser(); - $projectSourceLocator = $this->createProjectSourceLocator($folder); + $projectSourceLocator = $this->createProjectSourceLocator($sourceFolder); return $parser->parse($sniffPath, $projectSourceLocator); } @@ -44,11 +44,11 @@ private function recursiveSearch(Folder $folder): Iterator }); } - public function getSniffs(Folder $folder): iterable + public function getSniffs(Folder $standardFolder, Folder $sourceFolder): iterable { $parser = new SniffParser(); - $globSniffs = new GlobIterator($folder->getPath() . 'Sniffs/*/*Sniff.php'); - $projectSourceLocator = $this->createProjectSourceLocator($folder); + $globSniffs = new GlobIterator($standardFolder->getPath() . 'Sniffs/*/*Sniff.php'); + $projectSourceLocator = $this->createProjectSourceLocator($sourceFolder); foreach ($globSniffs as $fileInfo) { yield $parser->parse($fileInfo->getPathname(), $projectSourceLocator); } diff --git a/src/SniffFinder/SniffFinder.php b/src/SniffFinder/SniffFinder.php index c512125..e19088b 100644 --- a/src/SniffFinder/SniffFinder.php +++ b/src/SniffFinder/SniffFinder.php @@ -8,10 +8,10 @@ interface SniffFinder { - public function getSniff(Folder $folder, string $sniffPath): Sniff; + public function getSniff(Folder $standardFolder, Folder $sourceFolder, string $sniffPath): Sniff; /** * @return iterable */ - public function getSniffs(Folder $folder): iterable; + public function getSniffs(Folder $standardFolder, Folder $sourceFolder): iterable; } diff --git a/src/Value/Folder.php b/src/Value/Folder.php index d07a3d6..e14fd2d 100644 --- a/src/Value/Folder.php +++ b/src/Value/Folder.php @@ -17,7 +17,7 @@ public function __construct(string $path) $this->path = $path; } - public function __toString() + public function __toString(): string { return $this->getPath(); } diff --git a/src/Value/Url.php b/src/Value/Url.php index afceea0..bbe8ebb 100644 --- a/src/Value/Url.php +++ b/src/Value/Url.php @@ -17,7 +17,7 @@ public function __construct(string $url) $this->url = $url; } - public function __toString() + public function __toString(): string { return $this->getUrl(); } diff --git a/tests/CodeRepository/GitCodeRepositoryTest.php b/tests/CodeRepository/GitCodeRepositoryTest.php index 71da3fb..6eff07a 100644 --- a/tests/CodeRepository/GitCodeRepositoryTest.php +++ b/tests/CodeRepository/GitCodeRepositoryTest.php @@ -12,7 +12,7 @@ /** @covers \App\CodeRepository\GitCodeRepository */ class GitCodeRepositoryTest extends TestCase { - const LOCAL_GIT_PATH = 'var/tests/repo/Standard.git'; + private const LOCAL_GIT_PATH = 'var/tests/repo/Standard.git'; private GitCodeRepository $codeRepo; /** @test */ diff --git a/tests/Configuration/Value/ConfigurationTest.php b/tests/Configuration/Value/ConfigurationTest.php index 94b602f..bb8b7b1 100644 --- a/tests/Configuration/Value/ConfigurationTest.php +++ b/tests/Configuration/Value/ConfigurationTest.php @@ -16,21 +16,19 @@ class ConfigurationTest extends TestCase */ private static array $SOURCES; - /** @test */ - public function getSources() + public static function setUpBeforeClass(): void { - self::assertEquals( - self::$SOURCES, - $this->createValidVO()->getSources(), - ); + self::$SOURCES = [ + new Source('path/to/source', []) + ]; } /** @test */ - public function getFormat() + public function getSources() { self::assertEquals( - self::FORMAT, - $this->createValidVO()->getFormat(), + self::$SOURCES, + $this->createValidVO()->getSources(), ); } @@ -42,10 +40,12 @@ private function createValidVO(): Configuration ); } - public static function setUpBeforeClass(): void + /** @test */ + public function getFormat() { - self::$SOURCES = [ - new Source('path/to/source', []) - ]; + self::assertEquals( + self::FORMAT, + $this->createValidVO()->getFormat(), + ); } } diff --git a/tests/SniffFinder/FilesystemSniffFinderTest.php b/tests/SniffFinder/FilesystemSniffFinderTest.php index e161aff..457f88d 100644 --- a/tests/SniffFinder/FilesystemSniffFinderTest.php +++ b/tests/SniffFinder/FilesystemSniffFinderTest.php @@ -32,6 +32,9 @@ public function getSniffs() $sniffs = $this->finder->getSniffs( new Folder( 'var/tests/src/Standard/' + ), + new Folder( + 'var/tests/' ) ); self::assertEquals( @@ -114,6 +117,9 @@ public function getSniff() new Folder( 'var/tests/src/Standard/' ), + new Folder( + 'var/tests/' + ), self::PHP_SNIFF_PATH ) ); diff --git a/var/repos/.gitkeep b/var/repos/.gitkeep deleted file mode 100644 index e69de29..0000000 From 0d63fa652c838ed082b279451c62d8fdbf457b54 Mon Sep 17 00:00:00 2001 From: Anna Filina Date: Wed, 27 Jan 2021 20:50:29 -0500 Subject: [PATCH 08/10] Add readme --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..95cd4ff --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# PHPCS Documentation Generator + +Note: this currently works only with the PHPCompatibility standard. + +## Usage + +Copy the `generator.xml.dist` template to `generator.xml` and add your sources and standards. + +```sh +bin/phpcsdocs generate +``` From efedb908a59bb6849f18402bfa47659248c22bcf Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 27 Jan 2021 21:05:18 -0500 Subject: [PATCH 09/10] Set git configs on CI --- .github/workflows/phpunit.yml | 2 ++ tests/CodeRepository/GitCodeRepositoryTest.php | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index a29ac18..c2fd5ee 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -3,6 +3,8 @@ on: push jobs: phpunit: runs-on: ubuntu-latest + env: + IS_CI_TEST: true steps: - uses: actions/checkout@v1 - uses: shivammathur/setup-php@v2 diff --git a/tests/CodeRepository/GitCodeRepositoryTest.php b/tests/CodeRepository/GitCodeRepositoryTest.php index 6eff07a..4798400 100644 --- a/tests/CodeRepository/GitCodeRepositoryTest.php +++ b/tests/CodeRepository/GitCodeRepositoryTest.php @@ -39,6 +39,10 @@ private function createGitRepo(): void $gitPath = self::LOCAL_GIT_PATH; $fs->mkdir($gitPath); $fs->dumpFile($gitPath . '/composer.json', '{}'); + if (getenv('IS_CI_TEST')) { + `git config --global user.email "you@example.com"`; + `git config --global user.name "Your Name"`; + } `cd {$gitPath} && git init && git add composer.json && git commit -m "Init"`; } From 4488d4ad85b7cb0dd38ee63ac56eef34efadb0ef Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 27 Jan 2021 21:06:12 -0500 Subject: [PATCH 10/10] Update composer file --- composer.lock | 377 +++++++++++++++++--------------------------------- 1 file changed, 128 insertions(+), 249 deletions(-) diff --git a/composer.lock b/composer.lock index 177163a..fad8cb9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "97cac23298e2e8e084027f91bde313f1", + "content-hash": "27502a4c19ce2892bc1f63c5028e2b76", "packages": [ { "name": "beberlei/assert", @@ -180,16 +180,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.10.4", + "version": "v4.6.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" + "reference": "c346bbfafe2ff60680258b631afb730d186ed864" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c346bbfafe2ff60680258b631afb730d186ed864", + "reference": "c346bbfafe2ff60680258b631afb730d186ed864", "shasum": "" }, "require": { @@ -197,8 +197,8 @@ "php": ">=7.0" }, "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "ircmaxell/php-yacc": "0.0.5", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" }, "bin": [ "bin/php-parse" @@ -206,7 +206,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -230,9 +230,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.6.0" }, - "time": "2020-12-20T10:01:03+00:00" + "time": "2020-07-02T17:12:47+00:00" }, { "name": "opis/closure", @@ -1854,29 +1854,28 @@ }, { "name": "phar-io/manifest", - "version": "2.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" + "phar-io/version": "^2.0", + "php": "^5.6 || ^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -1910,24 +1909,24 @@ "issues": "https://github.com/phar-io/manifest/issues", "source": "https://github.com/phar-io/manifest/tree/master" }, - "time": "2020-06-27T14:33:11+00:00" + "time": "2018-07-08T19:23:20+00:00" }, { "name": "phar-io/version", - "version": "3.0.4", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "e4782611070e50613683d2b9a57730e9a3ba5451" + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451", - "reference": "e4782611070e50613683d2b9a57730e9a3ba5451", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^5.6 || ^7.0" }, "type": "library", "autoload": { @@ -1959,9 +1958,9 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.0.4" + "source": "https://github.com/phar-io/version/tree/master" }, - "time": "2020-12-13T23:18:30+00:00" + "time": "2018-07-08T19:19:57+00:00" }, { "name": "phpspec/prophecy", @@ -2032,35 +2031,32 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.5", + "version": "8.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1" + "reference": "ca6647ffddd2add025ab3f21644a441d7c146cdc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1", - "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca6647ffddd2add025ab3f21644a441d7c146cdc", + "reference": "ca6647ffddd2add025ab3f21644a441d7c146cdc", "shasum": "" }, "require": { "ext-dom": "*", - "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.10.2", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" + "php": "^7.3", + "phpunit/php-file-iterator": "^3.0", + "phpunit/php-text-template": "^2.0", + "phpunit/php-token-stream": "^4.0", + "sebastian/code-unit-reverse-lookup": "^2.0", + "sebastian/environment": "^5.0", + "sebastian/version": "^3.0", + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.0" }, "suggest": { "ext-pcov": "*", @@ -2069,7 +2065,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-master": "8.0-dev" } }, "autoload": { @@ -2097,7 +2093,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/8.0.2" }, "funding": [ { @@ -2105,7 +2101,7 @@ "type": "github" } ], - "time": "2020-11-28T06:44:49+00:00" + "time": "2020-05-23T08:02:54+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2349,72 +2345,35 @@ "time": "2020-10-26T13:16:10+00:00" }, { - "name": "phpunit/phpunit", - "version": "9.5.1", + "name": "phpunit/php-token-stream", + "version": "4.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360" + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7bdf4085de85a825f4424eae52c99a1cec2f360", - "reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/a853a0e183b9db7eed023d7933a858fa1c8d25a3", + "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.1", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.3", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3", - "sebastian/version": "^3.0.2" + "ext-tokenizer": "*", + "php": "^7.3 || ^8.0" }, "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "phpunit/phpunit": "^9.0" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "4.0-dev" } }, "autoload": { "classmap": [ "src/" - ], - "files": [ - "src/Framework/Assert/Functions.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2424,62 +2383,93 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ - "phpunit", - "testing", - "xunit" + "tokenizer" ], "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.1" + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" }, "funding": [ - { - "url": "https://phpunit.de/donate.html", - "type": "custom" - }, { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2021-01-17T07:42:25+00:00" + "abandoned": true, + "time": "2020-08-04T08:28:15+00:00" }, { - "name": "sebastian/cli-parser", - "version": "1.0.1", + "name": "phpunit/phpunit", + "version": "9.2.6", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "1c6a9e4312e209e659f1fce3ce88dd197c2448f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1c6a9e4312e209e659f1fce3ce88dd197c2448f6", + "reference": "1c6a9e4312e209e659f1fce3ce88dd197c2448f6", "shasum": "" }, "require": { - "php": ">=7.3" + "doctrine/instantiator": "^1.3.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.9.5", + "phar-io/manifest": "^1.0.3", + "phar-io/version": "^2.0.1", + "php": "^7.3", + "phpspec/prophecy": "^1.10.3", + "phpunit/php-code-coverage": "^8.0.2", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-invoker": "^3.0.2", + "phpunit/php-text-template": "^2.0.2", + "phpunit/php-timer": "^5.0.1", + "sebastian/code-unit": "^1.0.5", + "sebastian/comparator": "^4.0.3", + "sebastian/diff": "^4.0.1", + "sebastian/environment": "^5.1.2", + "sebastian/exporter": "^4.0.2", + "sebastian/global-state": "^4.0", + "sebastian/object-enumerator": "^4.0.2", + "sebastian/resource-operations": "^3.0.2", + "sebastian/type": "^2.1.1", + "sebastian/version": "^3.0.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "ext-pdo": "*", + "phpspec/prophecy-phpunit": "^2.0" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "9.2-dev" } }, "autoload": { "classmap": [ "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2493,19 +2483,28 @@ "role": "lead" } ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.2.6" }, "funding": [ + { + "url": "https://phpunit.de/donate.html", + "type": "custom" + }, { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2020-07-13T17:55:55+00:00" }, { "name": "sebastian/code-unit", @@ -2692,63 +2691,6 @@ ], "time": "2020-10-26T15:49:45+00:00" }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, { "name": "sebastian/diff", "version": "4.0.4", @@ -2957,26 +2899,26 @@ }, { "name": "sebastian/global-state", - "version": "5.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "a90ccbddffa067b51f574dea6eb25d5680839455" + "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455", - "reference": "a90ccbddffa067b51f574dea6eb25d5680839455", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bdb1e7c79e592b8c82cb1699be3c8743119b8a72", + "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72", "shasum": "" }, "require": { - "php": ">=7.3", + "php": "^7.3", "sebastian/object-reflector": "^2.0", "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.0" }, "suggest": { "ext-uopz": "*" @@ -2984,7 +2926,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3009,72 +2951,9 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/master" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:55:19+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2020-02-07T06:11:37+00:00" }, { "name": "sebastian/object-enumerator",