diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c46252..b2af6b5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - php-versions: ['8.1'] + php-versions: ['8.1', '8.2'] steps: - uses: actions/checkout@v3 @@ -35,9 +35,9 @@ jobs: uses: actions/cache@v3 with: path: vendor - key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-php-${{ matrix.php-versions }}-${{ hashFiles('composer.json') }} restore-keys: | - ${{ runner.os }}-php- + ${{ runner.os }}-php-${{ matrix.php-versions }} - name: Install dependencies run: composer install --prefer-dist --no-progress diff --git a/composer.json b/composer.json index 597b739..482d89f 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,8 @@ "symfony/finder": "^6.1", "symfony/console": "^6.1", "symfony/event-dispatcher": "^6.1", - "webmozart/assert": "^1.11" + "webmozart/assert": "^1.11", + "texthtml/maybe": "^0.2.0" }, "require-dev": { "phpunit/phpunit": "^9.5", diff --git a/composer.lock b/composer.lock index 4da72ee..e7bd235 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": "435eac9b2116c25ee0e5c5063a28a351", + "content-hash": "c8c0f2e8fca1987cae920b2c27913e77", "packages": [ { "name": "psr/container", @@ -111,23 +111,23 @@ }, { "name": "symfony/console", - "version": "v6.1.3", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "43fcb5c5966b43c56bcfa481368d90d748936ab8" + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/43fcb5c5966b43c56bcfa481368d90d748936ab8", - "reference": "43fcb5c5966b43c56bcfa481368d90d748936ab8", + "url": "https://api.github.com/repos/symfony/console/zipball/8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/string": "^5.4|^6.0" }, "conflict": { @@ -149,12 +149,6 @@ "symfony/process": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, "type": "library", "autoload": { "psr-4": { @@ -182,12 +176,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.1.3" + "source": "https://github.com/symfony/console/tree/v6.3.0" }, "funding": [ { @@ -203,20 +197,20 @@ "type": "tidelift" } ], - "time": "2022-07-22T14:17:57+00:00" + "time": "2023-05-29T12:49:39+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.1.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", - "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { @@ -225,7 +219,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.1-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -254,7 +248,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -270,28 +264,29 @@ "type": "tidelift" } ], - "time": "2022-02-25T11:15:52+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.1.0", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347" + "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a0449a7ad7daa0f7c0acd508259f80544ab5a347", - "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", + "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/event-dispatcher-contracts": "^2|^3" + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", @@ -304,13 +299,9 @@ "symfony/error-handler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/stopwatch": "^5.4|^6.0" }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, "type": "library", "autoload": { "psr-4": { @@ -337,7 +328,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.1.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.0" }, "funding": [ { @@ -353,33 +344,30 @@ "type": "tidelift" } ], - "time": "2022-05-05T16:51:07+00:00" + "time": "2023-04-21T14:41:17+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.1.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "02ff5eea2f453731cfbc6bc215e456b781480448" + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/02ff5eea2f453731cfbc6bc215e456b781480448", - "reference": "02ff5eea2f453731cfbc6bc215e456b781480448", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", "shasum": "" }, "require": { "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.1-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -416,7 +404,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.1.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" }, "funding": [ { @@ -432,20 +420,20 @@ "type": "tidelift" } ], - "time": "2022-02-25T11:15:52+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/finder", - "version": "v6.1.3", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709" + "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709", - "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709", + "url": "https://api.github.com/repos/symfony/finder/zipball/d9b01ba073c44cef617c7907ce2419f8d00d75e2", + "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2", "shasum": "" }, "require": { @@ -480,7 +468,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.1.3" + "source": "https://github.com/symfony/finder/tree/v6.3.0" }, "funding": [ { @@ -496,20 +484,20 @@ "type": "tidelift" } ], - "time": "2022-07-29T07:42:06+00:00" + "time": "2023-04-02T01:25:41+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.26.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", "shasum": "" }, "require": { @@ -524,7 +512,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.26-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -562,7 +550,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" }, "funding": [ { @@ -578,20 +566,20 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.26.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", "shasum": "" }, "require": { @@ -603,7 +591,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.26-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -643,7 +631,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" }, "funding": [ { @@ -659,20 +647,20 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", "shasum": "" }, "require": { @@ -684,7 +672,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.26-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -727,7 +715,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" }, "funding": [ { @@ -743,20 +731,20 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.26.0", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", "shasum": "" }, "require": { @@ -771,7 +759,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.26-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -810,7 +798,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" }, "funding": [ { @@ -826,20 +814,20 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.1.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239" + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239", - "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", "shasum": "" }, "require": { @@ -849,13 +837,10 @@ "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.1-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -895,7 +880,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.1.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" }, "funding": [ { @@ -911,20 +896,20 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:18:58+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/string", - "version": "v6.1.3", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f35241f45c30bcd9046af2bb200a7086f70e1d6b" + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f35241f45c30bcd9046af2bb200a7086f70e1d6b", - "reference": "f35241f45c30bcd9046af2bb200a7086f70e1d6b", + "url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f", + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f", "shasum": "" }, "require": { @@ -935,12 +920,13 @@ "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", @@ -980,7 +966,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.1.3" + "source": "https://github.com/symfony/string/tree/v6.3.0" }, "funding": [ { @@ -996,7 +982,62 @@ "type": "tidelift" } ], - "time": "2022-07-27T15:50:51+00:00" + "time": "2023-03-21T21:06:29+00:00" + }, + { + "name": "texthtml/maybe", + "version": "v0.2.0", + "source": { + "type": "git", + "url": "https://github.com/texthtml/maybe.git", + "reference": "2a8a47e41af899ce7aaabfcf640f805411fe41da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/texthtml/maybe/zipball/2a8a47e41af899ce7aaabfcf640f805411fe41da", + "reference": "2a8a47e41af899ce7aaabfcf640f805411fe41da", + "shasum": "" + }, + "require-dev": { + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^9.5", + "slevomat/coding-standard": "^8.0", + "squizlabs/php_codesniffer": "^3.6", + "symfony/console": "^6.1", + "symfony/finder": "^6.1", + "texthtml/doctest": "^0.2", + "vimeo/psalm": "^4.22" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions/option.php", + "src/functions/result.php" + ], + "psr-4": { + "TH\\Maybe\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Mathieu Rochette", + "email": "mathieu@texthtml.net" + } + ], + "description": "Option & Result types", + "support": { + "issues": "https://github.com/texthtml/maybe/issues", + "source": "https://github.com/texthtml/maybe/tree/v0.2.0" + }, + "time": "2023-07-04T09:25:11+00:00" }, { "name": "webmozart/assert", @@ -1060,35 +1101,38 @@ "packages-dev": [ { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.7.2", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "4be43904336affa5c2f70744a348312336afd0da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", - "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", + "reference": "4be43904336affa5c2f70744a348312336afd0da", "shasum": "" }, "require": { "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3", + "php": ">=5.4", "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" }, "require-dev": { "composer/composer": "*", + "ext-json": "*", + "ext-zip": "*", "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0" + "phpcompatibility/php-compatibility": "^9.0", + "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" }, "autoload": { "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1104,7 +1148,7 @@ }, { "name": "Contributors", - "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", @@ -1128,23 +1172,23 @@ "tests" ], "support": { - "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", - "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "source": "https://github.com/PHPCSStandards/composer-installer" }, - "time": "2022-02-04T12:51:07+00:00" + "time": "2023-01-05T11:28:13+00:00" }, { - "name": "doctrine/instantiator", - "version": "1.4.1", + "name": "doctrine/deprecations", + "version": "v1.1.1", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "shasum": "" }, "require": { @@ -1152,13 +1196,60 @@ }, "require-dev": { "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + }, + "time": "2023-06-03T09:27:29+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -1185,7 +1276,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -1201,20 +1292,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { @@ -1252,7 +1343,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { @@ -1260,20 +1351,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { "name": "nikic/php-parser", - "version": "v4.14.0", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -1314,9 +1405,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2022-05-31T20:59:12+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "phar-io/manifest", @@ -1541,25 +1632,33 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.6.1", + "version": "1.7.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b2fe4d22a5426f38e014855322200b97b5362c0d", + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" + "doctrine/deprecations": "^1.0", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" }, "require-dev": { "ext-tokenizer": "*", - "psalm/phar": "^4.8" + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" }, "type": "library", "extra": { @@ -1585,33 +1684,34 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.2" }, - "time": "2022-03-15T21:29:03+00:00" + "time": "2023-05-30T18:13:47+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" + "reference": "15873c65b207b07765dbc3c95d20fdf4a320cbe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/15873c65b207b07765dbc3c95d20fdf4a320cbe2", + "reference": "15873c65b207b07765dbc3c95d20fdf4a320cbe2", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", + "doctrine/instantiator": "^1.2 || ^2.0", + "php": "^7.2 || 8.0.* || 8.1.* || 8.2.*", "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0", "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { "phpspec/phpspec": "^6.0 || ^7.0", + "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", @@ -1652,22 +1752,22 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" + "source": "https://github.com/phpspec/prophecy/tree/v1.17.0" }, - "time": "2021-12-08T12:19:24+00:00" + "time": "2023-02-02T15:41:36+00:00" }, { "name": "phpspec/prophecy-phpunit", - "version": "v2.0.1", + "version": "v2.0.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy-phpunit.git", - "reference": "2d7a9df55f257d2cba9b1d0c0963a54960657177" + "reference": "9f26c224a2fa335f33e6666cc078fbf388255e87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/2d7a9df55f257d2cba9b1d0c0963a54960657177", - "reference": "2d7a9df55f257d2cba9b1d0c0963a54960657177", + "url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/9f26c224a2fa335f33e6666cc078fbf388255e87", + "reference": "9f26c224a2fa335f33e6666cc078fbf388255e87", "shasum": "" }, "require": { @@ -1704,34 +1804,33 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy-phpunit/issues", - "source": "https://github.com/phpspec/prophecy-phpunit/tree/v2.0.1" + "source": "https://github.com/phpspec/prophecy-phpunit/tree/v2.0.2" }, - "time": "2020-07-09T08:33:42+00:00" + "time": "2023-04-18T11:58:05+00:00" }, { "name": "phpstan/extension-installer", - "version": "1.1.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/phpstan/extension-installer.git", - "reference": "66c7adc9dfa38b6b5838a9fb728b68a7d8348051" + "reference": "f45734bfb9984c6c56c4486b71230355f066a58a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/66c7adc9dfa38b6b5838a9fb728b68a7d8348051", - "reference": "66c7adc9dfa38b6b5838a9fb728b68a7d8348051", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a", + "reference": "f45734bfb9984c6c56c4486b71230355f066a58a", "shasum": "" }, "require": { - "composer-plugin-api": "^1.1 || ^2.0", - "php": "^7.1 || ^8.0", - "phpstan/phpstan": ">=0.11.6" + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0" }, "require-dev": { - "composer/composer": "^1.8", - "phing/phing": "^2.16.3", + "composer/composer": "^2.0", "php-parallel-lint/php-parallel-lint": "^1.2.0", - "phpstan/phpstan-strict-rules": "^0.11 || ^0.12" + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" }, "type": "composer-plugin", "extra": { @@ -1749,28 +1848,30 @@ "description": "Composer plugin for automatic installation of PHPStan extensions", "support": { "issues": "https://github.com/phpstan/extension-installer/issues", - "source": "https://github.com/phpstan/extension-installer/tree/1.1.0" + "source": "https://github.com/phpstan/extension-installer/tree/1.3.1" }, - "time": "2020-12-13T13:06:13+00:00" + "time": "2023-05-24T08:59:17+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.7.0", + "version": "1.22.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "367a8d9d5f7da2a0136422d27ce8840583926955" + "reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/367a8d9d5f7da2a0136422d27ce8840583926955", - "reference": "367a8d9d5f7da2a0136422d27ce8840583926955", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/65c39594fbd8c67abfc68bb323f86447bab79cc0", + "reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.5", @@ -1794,22 +1895,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.7.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.22.1" }, - "time": "2022-08-09T12:23:23+00:00" + "time": "2023-06-29T20:46:06+00:00" }, { "name": "phpstan/phpstan", - "version": "1.8.2", + "version": "1.10.23", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c" + "reference": "65ab678d1248a8bc6fde456f0d7ff3562a61a4cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/65ab678d1248a8bc6fde456f0d7ff3562a61a4cd", + "reference": "65ab678d1248a8bc6fde456f0d7ff3562a61a4cd", "shasum": "" }, "require": { @@ -1833,9 +1934,16 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.8.2" + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, "funding": [ { @@ -1846,34 +1954,30 @@ "url": "https://github.com/phpstan", "type": "github" }, - { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, { "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", "type": "tidelift" } ], - "time": "2022-07-20T09:57:31+00:00" + "time": "2023-07-04T13:32:44+00:00" }, { "name": "phpstan/phpstan-phpunit", - "version": "1.1.1", + "version": "1.3.13", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "4a3c437c09075736285d1cabb5c75bf27ed0bc84" + "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/4a3c437c09075736285d1cabb5c75bf27ed0bc84", - "reference": "4a3c437c09075736285d1cabb5c75bf27ed0bc84", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d8bdab0218c5eb0964338d24a8511b65e9c94fa5", + "reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.5.0" + "phpstan/phpstan": "^1.10" }, "conflict": { "phpunit/phpunit": "<7.0" @@ -1905,31 +2009,32 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.1.1" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.13" }, - "time": "2022-04-20T15:24:25+00:00" + "time": "2023-05-26T11:05:59+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.3.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "543675a9be82d4befb9ca0bd8cdc9d211665037f" + "reference": "b21c03d4f6f3a446e4311155f4be9d65048218e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/543675a9be82d4befb9ca0bd8cdc9d211665037f", - "reference": "543675a9be82d4befb9ca0bd8cdc9d211665037f", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b21c03d4f6f3a446e4311155f4be9d65048218e6", + "reference": "b21c03d4f6f3a446e4311155f4be9d65048218e6", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.7.15" + "phpstan/phpstan": "^1.10" }, "require-dev": { "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^1.1", "phpstan/phpstan-phpunit": "^1.0", "phpunit/phpunit": "^9.5" }, @@ -1953,28 +2058,28 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.3.0" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.1" }, - "time": "2022-06-24T06:47:20+00:00" + "time": "2023-03-29T14:47:40+00:00" }, { "name": "phpstan/phpstan-symfony", - "version": "1.2.9", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-symfony.git", - "reference": "f4cb3b8915d3656e780f305f01c86b70ff933272" + "reference": "7332b90dfc291ac5b4b83fbca2081936faa1e3f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/f4cb3b8915d3656e780f305f01c86b70ff933272", - "reference": "f4cb3b8915d3656e780f305f01c86b70ff933272", + "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/7332b90dfc291ac5b4b83fbca2081936faa1e3f9", + "reference": "7332b90dfc291ac5b4b83fbca2081936faa1e3f9", "shasum": "" }, "require": { "ext-simplexml": "*", "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.8.2" + "phpstan/phpstan": "^1.9.18" }, "conflict": { "symfony/framework-bundle": "<3.0" @@ -1984,17 +2089,17 @@ "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^8.5.29 || ^9.5", "psr/container": "1.0 || 1.1.1", - "symfony/config": "^4.2 || ^5.0", - "symfony/console": "^4.0 || ^5.0", - "symfony/dependency-injection": "^4.0 || ^5.0", - "symfony/form": "^4.0 || ^5.0", - "symfony/framework-bundle": "^4.4 || ^5.0", - "symfony/http-foundation": "^5.1", - "symfony/messenger": "^4.2 || ^5.0", + "symfony/config": "^5.4 || ^6.1", + "symfony/console": "^5.4 || ^6.1", + "symfony/dependency-injection": "^5.4 || ^6.1", + "symfony/form": "^5.4 || ^6.1", + "symfony/framework-bundle": "^5.4 || ^6.1", + "symfony/http-foundation": "^5.4 || ^6.1", + "symfony/messenger": "^5.4", "symfony/polyfill-php80": "^1.24", - "symfony/serializer": "^4.0 || ^5.0" + "symfony/serializer": "^5.4" }, "type": "phpstan-extension", "extra": { @@ -2024,29 +2129,29 @@ "description": "Symfony Framework extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-symfony/issues", - "source": "https://github.com/phpstan/phpstan-symfony/tree/1.2.9" + "source": "https://github.com/phpstan/phpstan-symfony/tree/1.3.2" }, - "time": "2022-08-05T20:13:38+00:00" + "time": "2023-05-16T12:46:15+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.16", + "version": "9.2.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2593003befdcc10db5e213f9f28814f5aa8ac073" + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2593003befdcc10db5e213f9f28814f5aa8ac073", - "reference": "2593003befdcc10db5e213f9f28814f5aa8ac073", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -2061,8 +2166,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -2095,7 +2200,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.16" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" }, "funding": [ { @@ -2103,7 +2208,7 @@ "type": "github" } ], - "time": "2022-08-20T05:26:47+00:00" + "time": "2023-03-06T12:58:08+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2348,20 +2453,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.22", + "version": "9.6.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "e329ac6e8744f461518272612a479fde958752fe" + "reference": "a9aceaf20a682aeacf28d582654a1670d8826778" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e329ac6e8744f461518272612a479fde958752fe", - "reference": "e329ac6e8744f461518272612a479fde958752fe", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9aceaf20a682aeacf28d582654a1670d8826778", + "reference": "a9aceaf20a682aeacf28d582654a1670d8826778", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -2372,7 +2477,6 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", @@ -2380,22 +2484,19 @@ "phpunit/php-timer": "^5.0.2", "sebastian/cli-parser": "^1.0.1", "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", + "sebastian/comparator": "^4.0.8", "sebastian/diff": "^4.0.3", "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", + "sebastian/exporter": "^4.0.5", "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", + "sebastian/type": "^3.2", "sebastian/version": "^3.0.2" }, - "require-dev": { - "phpspec/prophecy-phpunit": "^2.0.1" - }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -2403,7 +2504,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -2434,7 +2535,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.22" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.9" }, "funding": [ { @@ -2444,9 +2546,13 @@ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2022-08-20T08:25:46+00:00" + "time": "2023-06-11T06:13:56+00:00" }, { "name": "sebastian/cli-parser", @@ -2617,16 +2723,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -2679,7 +2785,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -2687,7 +2793,7 @@ "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", @@ -2748,16 +2854,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", "shasum": "" }, "require": { @@ -2802,7 +2908,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" }, "funding": [ { @@ -2810,20 +2916,20 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2023-05-07T05:35:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -2865,7 +2971,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -2873,20 +2979,20 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { @@ -2942,7 +3048,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" }, "funding": [ { @@ -2950,7 +3056,7 @@ "type": "github" } ], - "time": "2021-11-11T14:18:36+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", @@ -3187,16 +3293,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -3235,10 +3341,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -3246,7 +3352,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -3305,16 +3411,16 @@ }, { "name": "sebastian/type", - "version": "3.0.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -3326,7 +3432,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3349,7 +3455,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -3357,7 +3463,7 @@ "type": "github" } ], - "time": "2022-03-15T09:54:48+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -3414,32 +3520,32 @@ }, { "name": "slevomat/coding-standard", - "version": "8.4.0", + "version": "8.13.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "02f27326be19633a1b6ba76745390bbf9a4be0b6" + "reference": "a13c15e20f2d307a1ca8dec5313ec462a4466470" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/02f27326be19633a1b6ba76745390bbf9a4be0b6", - "reference": "02f27326be19633a1b6ba76745390bbf9a4be0b6", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/a13c15e20f2d307a1ca8dec5313ec462a4466470", + "reference": "a13c15e20f2d307a1ca8dec5313ec462a4466470", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": ">=1.7.0 <1.8.0", + "phpstan/phpdoc-parser": "^1.22.0", "squizlabs/php_codesniffer": "^3.7.1" }, "require-dev": { "phing/phing": "2.17.4", "php-parallel-lint/php-parallel-lint": "1.3.2", - "phpstan/phpstan": "1.4.10|1.8.2", - "phpstan/phpstan-deprecation-rules": "1.0.0", - "phpstan/phpstan-phpunit": "1.0.0|1.1.1", - "phpstan/phpstan-strict-rules": "1.3.0", - "phpunit/phpunit": "7.5.20|8.5.21|9.5.21" + "phpstan/phpstan": "1.10.21", + "phpstan/phpstan-deprecation-rules": "1.1.3", + "phpstan/phpstan-phpunit": "1.3.13", + "phpstan/phpstan-strict-rules": "1.5.1", + "phpunit/phpunit": "7.5.20|8.5.21|9.6.8|10.2.2" }, "type": "phpcodesniffer-standard", "extra": { @@ -3449,7 +3555,7 @@ }, "autoload": { "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard" + "SlevomatCodingStandard\\": "SlevomatCodingStandard/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3457,9 +3563,13 @@ "MIT" ], "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "keywords": [ + "dev", + "phpcs" + ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.4.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.13.1" }, "funding": [ { @@ -3471,20 +3581,20 @@ "type": "tidelift" } ], - "time": "2022-08-09T19:03:45+00:00" + "time": "2023-06-25T12:52:34+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.7.1", + "version": "3.7.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", "shasum": "" }, "require": { @@ -3520,14 +3630,15 @@ "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ "phpcs", - "standards" + "standards", + "static analysis" ], "support": { "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2022-06-18T07:21:10+00:00" + "time": "2023-02-22T23:07:41+00:00" }, { "name": "theseer/tokenizer", diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 15a1968..b52a883 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -17,13 +17,16 @@ + + + @@ -44,6 +47,18 @@ + + + + + + + + + + + + diff --git a/src/Application.php b/src/Application.php index 8e474c7..7f4354f 100755 --- a/src/Application.php +++ b/src/Application.php @@ -45,7 +45,7 @@ protected function execute(Input\InputInterface $input, Output\OutputInterface $ $testSuite->addSubscriber(new Subscriber\Summary($input, $output)); $testSuite->addSubscriber(new Subscriber\TestExecutor()); - return $testSuite->run($input->getOption("bail")) + return $testSuite->run($input->getOption("bail") ?? false) === TestOutcome::Success ? Command::SUCCESS : Command::FAILURE; } diff --git a/src/Event/AfterTestSuite.php b/src/Event/AfterTestSuite.php index 0659800..b556aad 100755 --- a/src/Event/AfterTestSuite.php +++ b/src/Event/AfterTestSuite.php @@ -2,10 +2,12 @@ namespace TH\DocTest\Event; +use TH\DocTest\TestOutcome; + final class AfterTestSuite { public function __construct( - public readonly bool $success, + public readonly TestOutcome $outcome, ) { } } diff --git a/src/Iterator/AllExamples.php b/src/Iterator/AllExamples.php index 7be4587..58482fb 100755 --- a/src/Iterator/AllExamples.php +++ b/src/Iterator/AllExamples.php @@ -4,6 +4,7 @@ use TH\DocTest\Example; use TH\DocTest\Location; +use TH\Maybe\Option; final class AllExamples implements Examples { @@ -38,29 +39,28 @@ private function iterateComment(string $comment, Location $location): \Traversab $lines = new \ArrayIterator(\explode(PHP_EOL, $comment)); $index = 1; - while ($example = $this->nextExample($lines, $location, $index++)) { - yield $example; + while (($example = $this->nextExample($lines, $location, $index++))->isSome()) { + yield $example->unwrap(); } } /** * @param \ArrayIterator $lines + * @return Option */ - private function nextExample(\ArrayIterator $lines, Location $location, int $index): ?Example + private function nextExample(\ArrayIterator $lines, Location $location, int $index): Option { - $codeblockStartedAt = $this->findFencedCodeBlockStart($lines); - - if ($codeblockStartedAt === null) { - return null; - } - - return $this->readExample($lines, $location->startingAt($codeblockStartedAt, $index)); + return $this->findFencedCodeBlockStart($lines)->andThen( + fn (int $codeblockStartedAt) + => $this->readExample($lines, $location->startingAt($codeblockStartedAt, $index)), + ); } /** * @param \ArrayIterator $lines + * @return Option */ - private function readExample(\ArrayIterator $lines, Location $location): ?Example + private function readExample(\ArrayIterator $lines, Location $location): Option { $buffer = []; @@ -69,30 +69,31 @@ private function readExample(\ArrayIterator $lines, Location $location): ?Exampl $lines->next(); if ($this->endOfAPHPFencedCodeBlock($line)) { - return new Example(\implode(PHP_EOL, $buffer), $location->ofLength($lines->key())); + return Option\some(new Example(\implode(PHP_EOL, $buffer), $location->ofLength($lines->key()))); } $buffer[] = \preg_replace("/^\s*\*( ?)/", "", $line); } - return null; + return Option\none(); } /** * @param \ArrayIterator $lines + * @return Option */ - private function findFencedCodeBlockStart(\ArrayIterator $lines): ?int + private function findFencedCodeBlockStart(\ArrayIterator $lines): Option { while ($lines->valid()) { $line = $lines->current(); $lines->next(); if ($this->startOfAPHPFencedCodeBlock($line)) { - return $lines->key(); + return Option\some($lines->key()); } } - return null; + return Option\none(); } private function endOfAPHPFencedCodeBlock(string $line): bool diff --git a/src/Iterator/CommentReflectionSources.php b/src/Iterator/CommentReflectionSources.php index 0cb6ddd..240722d 100755 --- a/src/Iterator/CommentReflectionSources.php +++ b/src/Iterator/CommentReflectionSources.php @@ -28,7 +28,7 @@ public function getIterator(): \Traversable $path = \stream_resolve_include_path($file->getPathname()); if ($path === false) { - throw new \RuntimeException("Could not resolve path to a file to include: $path"); + throw new \RuntimeException("Could not resolve path to a file to include: {$file->getPathname()}"); } include_once $files[] = $path; diff --git a/src/Iterator/Files.php b/src/Iterator/Files.php index 1a6ea78..ff4db23 100755 --- a/src/Iterator/Files.php +++ b/src/Iterator/Files.php @@ -45,11 +45,7 @@ public function iteratePaths(): \Traversable */ private function iterate(string $pattern): \Traversable { - $paths = \glob($pattern); - - if ($paths === false) { - return; - } + $paths = \glob($pattern) ?: []; foreach ($paths as $path) { yield from $this->iteratePath($path); diff --git a/src/Location.php b/src/Location.php index 315c8b3..ef6187c 100755 --- a/src/Location.php +++ b/src/Location.php @@ -2,6 +2,8 @@ namespace TH\DocTest; +use TH\Maybe\Option; + final class Location implements \Stringable { /** @@ -10,9 +12,12 @@ final class Location implements \Stringable public function __construct( public readonly \ReflectionClass|\ReflectionMethod|\ReflectionFunction $source, public readonly string $name, - public readonly ?string $path, - public readonly ?int $startLine, - public readonly ?int $endLine, + /** @var Option */ + public readonly Option $path, + /** @var Option */ + public readonly Option $startLine, + /** @var Option */ + public readonly Option $endLine, public readonly int $index, ) { } @@ -23,8 +28,8 @@ public function startingAt(int $offset, int $index): Location $this->source, $this->name, $this->path, - $this->startLine !== null ? $this->startLine + $offset : null, - null, + $this->startLine->map(static fn (int $startLine) => $startLine + $offset), + Option\none(), $index, ); } @@ -36,7 +41,7 @@ public function ofLength(int $length): Location $this->name, $this->path, $this->startLine, - $this->startLine !== null ? $this->startLine + $length : null, + $this->startLine->map(static fn (int $startLine) => $startLine + $length), $this->index, ); } @@ -54,14 +59,13 @@ public static function fromReflection( $name = "{$source->getDeclaringClass()->getName()}::$name(…)"; } - $startLine = $source->getStartLine(); + /** @var Option $endLine */ + $endLine = Option\fromValue($source->getStartLine(), false); - if ($startLine !== false) { - $endLine = $startLine; - $startLine -= \substr_count($comment, \PHP_EOL); - } else { - $endLine = $startLine = null; - } + $startLine = $endLine->map( + static fn (int $startLine) + => $startLine - \substr_count($comment, \PHP_EOL), + ); return new self( $source, @@ -73,12 +77,16 @@ public static function fromReflection( ); } - private static function makePathRelative(string|false $path): ?string + /** + * @return Option + */ + private static function makePathRelative(string|false $path): Option { static $stripSrcDirPattern; if ($path === false) { - return null; + /** @var Option */ + return Option\none(); } $stripSrcDirPattern ??= "/^" . \preg_quote( @@ -86,12 +94,26 @@ private static function makePathRelative(string|false $path): ?string delimiter: "/", ) . "(\/*)/"; - return \preg_replace($stripSrcDirPattern, "", $path) - ?? throw new \RuntimeException("Making path relative failed for : $path"); + return Option\some( + \preg_replace($stripSrcDirPattern, "", $path) + ?? throw new \RuntimeException( + "Making path relative failed for `$path`: " . \preg_last_error_msg(), + \preg_last_error(), + ), + ); } public function __toString(): string { - return "{$this->name}#{$this->index} ({$this->path}:{$this->startLine})"; + $location = $this->path + ->map( + fn (string $path) + => " (" . $this->startLine + ->map(static fn (int $startLine) => ":$startLine") + ->unwrapOr("") . ")", + ) + ->unwrapOr(""); + + return "{$this->name}#{$this->index}$location"; } } diff --git a/src/Subscriber/Summary.php b/src/Subscriber/Summary.php index 257a444..58b904d 100755 --- a/src/Subscriber/Summary.php +++ b/src/Subscriber/Summary.php @@ -53,7 +53,7 @@ public function countFailure(): void public function printSummary(Event\AfterTestSuite $event): void { - if ($event->success) { + if ($event->outcome->isSuccess()) { $this->style->success("All tests succeeded ({$this->numberOfSuccesses})"); return; diff --git a/src/Subscriber/TestExecutor.php b/src/Subscriber/TestExecutor.php index a442d17..b0f5144 100755 --- a/src/Subscriber/TestExecutor.php +++ b/src/Subscriber/TestExecutor.php @@ -5,6 +5,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use TH\DocTest\Event; use TH\DocTest\Location; +use TH\Maybe\Option; use Webmozart\Assert\Assert; /** @@ -37,9 +38,10 @@ public function execute(Event\ExecuteTest $event): void \ob_start(); try { - $expectedFailure === null - ? $test->eval() - : self::assertThrows($test->eval(...), $expectedFailure); + $expectedFailure->mapOrElse( + static fn (array $expectedFailure) => self::assertThrows($test->eval(...), $expectedFailure), + $test->eval(...), + ); } finally { $output = \ob_get_clean(); \assert(\is_string($output), "example messed up with output buffers"); @@ -80,19 +82,47 @@ private static function assertThrows(callable $callable, array $expectedFailure) } /** - * @return Failure + * @return Option */ - private static function expectedFailure(string $code): ?array + private static function expectedFailure(string $code): Option + { + foreach (self::expectedFailures($code) as $failure) { + if ($failure->isSome()) { + return $failure; + } + } + + /** @var Option */ + return Option\none(); + } + + /** + * @return \Traversable> + */ + private static function expectedFailures(string $code): \Traversable { foreach (\explode(PHP_EOL, $code) as $line) { - \preg_match("/\/\/\s*@throws\s*(?[^ ]+)\s+(?[^\s].*[^\s])\s*/", $line, $matches); + yield self::lineFailure($line); + } + } - if (\array_key_exists("class", $matches)) { - return ["class" => $matches["class"], "message" => $matches["message"]]; + /** + * @return Option + */ + private static function lineFailure(string $line): Option + { + \preg_match("/\/\/\s*@throws\s*(?[^ ]+)\s+(?[^\s].*[^\s])\s*/", $line, $matches); + + if (\array_key_exists("class", $matches)) { + if (!\is_a($matches["class"], \Throwable::class, allow_string: true)) { + throw new \RuntimeException("`{$matches['class']}` isn't a `\Throwable`"); } + + return Option\some(["class" => $matches["class"], "message" => $matches["message"]]); } - return null; + /** @var Option */ + return Option\none(); } private static function expectedOutput(string $code): string diff --git a/src/TestOutcome.php b/src/TestOutcome.php new file mode 100755 index 0000000..024f296 --- /dev/null +++ b/src/TestOutcome.php @@ -0,0 +1,28 @@ +isFailure() + ? $left + : $right; + } +} diff --git a/src/TestSuite.php b/src/TestSuite.php index 4e5fa7f..95933a9 100755 --- a/src/TestSuite.php +++ b/src/TestSuite.php @@ -17,28 +17,27 @@ public function __construct( $this->eventDispatcher = new EventDispatcher(); } - public function run(bool $bail): bool + public function run(bool $bail): TestOutcome { $this->eventDispatcher->dispatch(new Event\BeforeTestSuite()); - $allSuccesful = true; + $outcome = TestOutcome::Success; try { foreach ($this->examples as $example) { - if ($this->runExample($example)) { - continue; - } + $outcome = TestOutcome::and( + $outcome, + $this->runExample($example), + ); - if ($bail) { - return false; + if ($bail && $outcome->isFailure()) { + return $outcome; } - - $allSuccesful = false; } - return $allSuccesful; + return $outcome; } finally { - $this->eventDispatcher->dispatch(new Event\AfterTestSuite(success: $allSuccesful)); + $this->eventDispatcher->dispatch(new Event\AfterTestSuite(outcome: $outcome)); } } @@ -55,7 +54,7 @@ public static function fromPaths(array $paths, string $filter): self return new self(FilteredExamples::fromPaths($paths, $filter)); } - private function runExample(Example $example): bool + private function runExample(Example $example): TestOutcome { try { $this->eventDispatcher->dispatch(new Event\BeforeTest($example)); @@ -63,12 +62,12 @@ private function runExample(Example $example): bool $this->eventDispatcher->dispatch(new Event\AfterTest($example)); $this->eventDispatcher->dispatch(new Event\AfterTestSuccess($example)); - return true; + return TestOutcome::Success; } catch (\Throwable $th) { $this->eventDispatcher->dispatch(new Event\AfterTest($example)); $this->eventDispatcher->dispatch(new Event\AfterTestFailure($example, $th)); - return false; + return TestOutcome::Failure; } } } diff --git a/tests/Subscriber/TestExecutorTest.php b/tests/Subscriber/TestExecutorTest.php index 446932e..0d7141b 100644 --- a/tests/Subscriber/TestExecutorTest.php +++ b/tests/Subscriber/TestExecutorTest.php @@ -9,6 +9,7 @@ use TH\DocTest\Example; use TH\DocTest\Location; use TH\DocTest\Subscriber\TestExecutor; +use TH\Maybe\Option; /** * @phpstan-type Failure array{class:class-string<\Throwable>,message:string} @@ -24,24 +25,24 @@ public function setUp(): void /** * @dataProvider examplesProvider - * @param Failure|null $failure + * @param Option $failure * @throws \InvalidArgumentException */ - public function testExamples(Example $example, ?array $failure): void + public function testExamples(Example $example, Option $failure): void { - if ($failure !== null) { + $failure->inspect(function (array $failure): void { $this->expectException($failure["class"]); $message = \preg_quote($failure["message"], "/"); $this->expectExceptionMessageMatches("/^$message$/"); - } + }); $this->testExecutor->execute(new ExecuteTest($example)); - self::assertNull($failure); + self::assertTrue($failure->isNone()); } /** - * @return \Traversable + * @return \Traversable}> * @throws \Symfony\Component\Finder\Exception\DirectoryNotFoundException */ public function examplesProvider(): \Traversable @@ -54,9 +55,9 @@ public function examplesProvider(): \Traversable $location = new Location( new ReflectionClass($this::class), $this::class, - path: $path, - startLine: 1, - endLine: null, + path: Option\some($path), + startLine: Option\some(1), + endLine: Option\none(), index: $index++, ); @@ -80,7 +81,7 @@ public function examples(): \Traversable } /** - * @return array{code:string,failure:?Failure}} + * @return array{code:string,failure:Option}} */ private function loadExample(\SplFileInfo $example): array { @@ -89,25 +90,30 @@ private function loadExample(\SplFileInfo $example): array $code = \preg_replace("/^<\?php/", "", $code); \assert(\is_string($code), "Something wrong happened"); - $failure = null; - - \preg_match("/^( *)\/\/(?.*)/", $code, $matches); - - if ($matches !== []) { - \preg_match("/(?[^ ]+) (?.+)/", $matches["comment"], $matches); - if ($matches !== []) { - \assert(\is_string($matches["class"])); + $failure = self::pregMatch("/^( *)\/\/(?.*)/", $code) + ->andThen(static fn (array $matches) + => self::pregMatch("/(?[^ ]+) (?.+)/", $matches["comment"])) + ->map(static function (array $matches) { \assert( \is_subclass_of($matches["class"], \Throwable::class), "{$matches["class"]} is not a Throwable", ); - \assert(\is_string($matches["message"])); - $failure = ["class" => $matches["class"], "message" => $matches["message"]]; - } - } + /** @var Failure */ + return ["class" => $matches["class"], "message" => $matches["message"]]; + }); return ["code" => $code, "failure" => $failure]; } + + /** + * @return Option> + */ + private static function pregMatch(string $pattern, string $subject): Option + { + \preg_match($pattern, $subject, $matches); + + return Option\fromValue($matches, []); + } }