diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 59db2da4..d0c1fb55 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -13,7 +13,7 @@ jobs: steps: - name: "Dependabot metadata" id: "metadata" - uses: "dependabot/fetch-metadata@v2.0.0" + uses: "dependabot/fetch-metadata@v2.4.0" with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: "Enable auto-merge for Dependabot PRs" diff --git a/.github/workflows/documentation.yaml b/.github/workflows/documentation.yaml new file mode 100644 index 00000000..2d960e2a --- /dev/null +++ b/.github/workflows/documentation.yaml @@ -0,0 +1,61 @@ +name: "Documentation" + +on: # yamllint disable-line rule:truthy + push: + branches: + - "6.x" + pull_request: null + +jobs: + documentation: + name: "Documentation" + runs-on: "ubuntu-latest" + steps: + - name: "Checkout" + uses: "actions/checkout@v4" + + - name: "Build" + uses: "phpDocumentor/phpDocumentor@master" + + - name: "Deploy" + if: "${{ github.event_name == 'push' && github.ref == 'refs/heads/6.x' }}" + uses: "actions/upload-artifact@v4" + with: + name: "documentation" + path: "build/docs" + retention-days: 1 + + deploy: + name: "Deploy" + if: "${{ github.event_name == 'push' && github.ref == 'refs/heads/6.x' }}" + runs-on: "ubuntu-latest" + needs: "documentation" + steps: + - name: "Checkout" + uses: "actions/checkout@v4" + with: + repository: "phpDocumentor/docs" + token: "${{ secrets.BOT_TOKEN }}" + path: "docs" + + - name: "Download" + uses: "actions/download-artifact@v4" + with: + name: "documentation" + path: "build/docs" + + - name: "Copy files" + run: "rsync -r --delete build/docs/* docs/docs/components/reflection" + + - name: "Commit" + uses: "stefanzweifel/git-auto-commit-action@v6" + with: + repository: "docs" + commit_message: "Update reflection documentation" + + - name: "Push" + uses: "ad-m/github-push-action@master" + with: + directory: "docs" + github_token: "${{ secrets.BOT_TOKEN }}" + repository: "phpDocumentor/docs" diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml index a2f335dd..dade650d 100644 --- a/.github/workflows/integrate.yaml +++ b/.github/workflows/integrate.yaml @@ -13,7 +13,7 @@ on: # yamllint disable-line rule:truthy jobs: code-coverage: name: "Code Coverage" - uses: "phpDocumentor/.github/.github/workflows/code-coverage.yml@v0.5.0" + uses: "phpDocumentor/.github/.github/workflows/code-coverage.yml@v0.8" with: php-version: "8.2" @@ -41,31 +41,31 @@ jobs: dependency-analysis: name: "Dependency analysis" - uses: "phpDocumentor/.github/.github/workflows/dependency-analysis.yml@v0.5.0" + uses: "phpDocumentor/.github/.github/workflows/dependency-analysis.yml@v0.8" with: php-version: "8.2" lint-root: name: "Lint root" - uses: "phpDocumentor/.github/.github/workflows/lint.yml@v0.5.0" + uses: "phpDocumentor/.github/.github/workflows/lint.yml@v0.8" with: php-version: "8.2" composer-options: "--no-check-publish --ansi" static-analysis: name: "Static analysis" - uses: "phpDocumentor/.github/.github/workflows/static-analysis.yml@v0.5.0" + uses: "phpDocumentor/.github/.github/workflows/static-analysis.yml@main" with: php-version: "8.2" php-extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, pcntl, posix" unit-tests: name: "Unit test" - uses: "phpDocumentor/.github/.github/workflows/continuous-integration.yml@v0.5.0" + uses: "phpDocumentor/.github/.github/workflows/continuous-integration.yml@v0.8" integration-tests: name: "Integration test" - uses: "phpDocumentor/.github/.github/workflows/continuous-integration.yml@v0.5.0" + uses: "phpDocumentor/.github/.github/workflows/continuous-integration.yml@v0.8" needs: "unit-tests" with: test-suite: "integration" diff --git a/.gitignore b/.gitignore index 2f7c377a..9e915a18 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ vendor/ # By default the phpunit.xml.dist is provided; you can override this using a local config file phpunit.xml .phpunit.result.cache +.phpunit.cache + +.phpdoc/cache diff --git a/.phpdoc/template/base.html.twig b/.phpdoc/template/base.html.twig new file mode 100644 index 00000000..194b2192 --- /dev/null +++ b/.phpdoc/template/base.html.twig @@ -0,0 +1,15 @@ +{% extends 'layout.html.twig' %} + +{% set topMenu = { + "menu": [ + { "name": "About", "url": "https://phpdoc.org/"}, + { "name": "Components", "url": "https://phpdoc.org/components.html"}, + { "name": "Documentation", "url": "https://docs.phpdoc.org/"}, + ], + "social": [ + { "iconClass": "fab fa-mastodon", "url": "https://phpc.social/@phpdoc"}, + { "iconClass": "fab fa-github", "url": "https://github.com/phpdocumentor/typeresolver"}, + { "iconClass": "fas fa-envelope-open-text", "url": "https://github.com/orgs/phpDocumentor/discussions"} + ] +} +%} diff --git a/Makefile b/Makefile index 31d69963..272b3d6c 100644 --- a/Makefile +++ b/Makefile @@ -11,9 +11,9 @@ fix-code-style: docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpcbf .PHONY: static-code-analysis -static-code-analysis: vendor ## Runs a static code analysis with phpstan/phpstan and vimeo/psalm - docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpstan --configuration=phpstan.neon - docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/psalm +static-code-analysis: #vendor ## Runs a static code analysis with phpstan/phpstan and vimeo/psalm + docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.2-cli vendor/bin/phpstan --configuration=phpstan.neon + docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.2-cli vendor/bin/psalm.phar --show-info=true --threads=4 .PHONY: test test: test-unit test-functional ## Runs all test suites with phpunit/phpunit @@ -25,7 +25,7 @@ test-unit: ## Runs unit tests with phpunit/phpunit .PHONY: test-functional test-functional: ## Runs unit tests with phpunit/phpunit - docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpunit --testsuite=functional + docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpunit --testsuite=integration .PHONY: dependency-analysis dependency-analysis: vendor ## Runs a dependency analysis with maglnet/composer-require-checker @@ -45,3 +45,7 @@ rector: ## Refactor code using rector .PHONY: pre-commit-test pre-commit-test: fix-code-style test code-style static-code-analysis + +.PHONY: docs +docs: ## Generate documentation + docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phpdoc:3-unstable diff --git a/README.md b/README.md index 2405f0de..ef4113d3 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ are however several advantages to using this library: In order to inspect a codebase you need to tell composer to include the `phpdocumentor/reflection` package. This can easily be done using the following command in your command line terminal: - composer require phpdocumentor/reflection:~5.0 + composer require phpdocumentor/reflection:~6.0 After the installation is complete no further configuration is necessary and you can immediately start using it. diff --git a/composer-require-checker.json b/composer-require-checker.json index e2718623..a4883184 100644 --- a/composer-require-checker.json +++ b/composer-require-checker.json @@ -2,7 +2,8 @@ "symbol-whitelist" : [ "null", "true", "false", "static", "self", "parent", - "array", "string", "int", "float", "bool", "iterable", "callable", "void", "object" + "array", "string", "int", "float", "bool", "iterable", "callable", "void", "object", + "PhpParser\\Node\\Stmt\\PropertyProperty" ], "php-core-extensions" : [ "Core", diff --git a/composer.json b/composer.json index 64a59bd8..5240c509 100644 --- a/composer.json +++ b/composer.json @@ -5,6 +5,9 @@ "homepage": "http://www.phpdoc.org", "license": "MIT", "autoload": { + "files": [ + "src/php-parser/Modifiers.php" + ], "psr-4": { "phpDocumentor\\": "src/phpDocumentor" } @@ -12,15 +15,18 @@ "autoload-dev": { "psr-4": { "phpDocumentor\\": [ - "tests/integration/", "tests/unit/phpDocumentor", "tests/bench/" + ], + "phpDocumentor\\Reflection\\": [ + "tests/integration" ] } }, "require": { - "php": "8.1.*|8.2.*|8.3.*", - "nikic/php-parser": "~4.14 || ^5.0", + "php": "8.1.*|8.2.*|8.3.*|8.4.*", + "composer-runtime-api": "^2", + "nikic/php-parser": "~4.18 || ^5.0", "phpdocumentor/reflection-common": "^2.1", "phpdocumentor/reflection-docblock": "^5", "phpdocumentor/type-resolver": "^1.2", @@ -29,18 +35,18 @@ }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "doctrine/coding-standard": "^12.0", + "doctrine/coding-standard": "^13.0", + "eliashaeussler/phpunit-attributes": "^1.7", "mikey179/vfsstream": "~1.2", "mockery/mockery": "~1.6.0", "phpspec/prophecy-phpunit": "^2.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.8", - "phpstan/phpstan-php-parser": "^1.1", "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^10.0", + "psalm/phar": "^6.0", "rector/rector": "^1.0.0", - "squizlabs/php_codesniffer": "^3.8", - "vimeo/psalm": "^5.0" + "squizlabs/php_codesniffer": "^3.8" }, "config": { "preferred-install": { diff --git a/composer.lock b/composer.lock index 1958c424..a23f058b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,33 +4,34 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a75aa0bc395a71d9fa4f95b7292ae854", + "content-hash": "febb226458a175a8889e92fc89e662ce", "packages": [ { "name": "doctrine/deprecations", - "version": "1.1.3", + "version": "1.1.5", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, "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" + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -38,7 +39,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "Doctrine\\Deprecations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -49,31 +50,33 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" }, - "time": "2024-01-30T19:34:25+00:00" + "time": "2025-04-07T20:06:18+00:00" }, { "name": "nikic/php-parser", - "version": "v4.19.1", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b" + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4e1b88d21c69391150ace211e9eaf05810858d0b", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.1" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -81,7 +84,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -105,9 +108,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" }, - "time": "2024-03-17T08:10:35+00:00" + "time": "2025-05-31T08:24:38+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -164,28 +167,35 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", + "version": "5.6.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62", + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.1", "ext-filter": "*", - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26" }, "type": "library", "extra": { @@ -209,35 +219,35 @@ }, { "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "email": "opensource@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.2" }, - "time": "2021-10-19T17:43:47+00:00" + "time": "2025-04-13T19:20:35+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.2", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "153ae662783729388a584b4361f2545e4d841e3c" + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", - "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" + "phpstan/phpdoc-parser": "^1.18|^2.0" }, "require-dev": { "ext-tokenizer": "*", @@ -273,36 +283,36 @@ "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.8.2" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" }, - "time": "2024-02-23T11:10:43+00:00" + "time": "2024-11-09T15:12:26+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.26.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "231e3186624c03d7e7c890ec662b81e6b0405227" + "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/231e3186624c03d7e7c890ec662b81e6b0405227", - "reference": "231e3186624c03d7e7c890ec662b81e6b0405227", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^5.3.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, "type": "library", @@ -320,32 +330,32 @@ "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.26.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0" }, - "time": "2024-02-23T16:05:55+00:00" + "time": "2025-02-19T13:28:12+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.29.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -386,7 +396,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" }, "funding": [ { @@ -402,7 +412,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "webmozart/assert", @@ -465,44 +475,39 @@ ], "packages-dev": [ { - "name": "amphp/amp", - "version": "v2.6.2", + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "4be43904336affa5c2f70744a348312336afd0da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", + "reference": "4be43904336affa5c2f70744a348312336afd0da", "shasum": "" }, "require": { - "php": ">=7.1" + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" }, "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", + "composer/composer": "*", "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" + "ext-zip": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0", + "yoast/phpunit-polyfills": "^1.0" }, - "type": "library", + "type": "composer-plugin", "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" }, "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], "psr-4": { - "Amp\\": "lib" + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -511,156 +516,129 @@ ], "authors": [ { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" }, { - "name": "Niklas Keller", - "email": "me@kelunik.com" + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" } ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" ], "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "source": "https://github.com/PHPCSStandards/composer-installer" }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-02-20T17:52:18+00:00" + "time": "2023-01-05T11:28:13+00:00" }, { - "name": "amphp/byte-stream", - "version": "v1.8.1", + "name": "doctrine/coding-standard", + "version": "13.0.1", "source": { "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" + "url": "https://github.com/doctrine/coding-standard.git", + "reference": "0affd62169186f32de725ca612e6129e81186a21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", + "url": "https://api.github.com/repos/doctrine/coding-standard/zipball/0affd62169186f32de725ca612e6129e81186a21", + "reference": "0affd62169186f32de725ca612e6129e81186a21", "shasum": "" }, "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0.0", + "php": "^7.4 || ^8.0", + "slevomat/coding-standard": "^8.16", + "squizlabs/php_codesniffer": "^3.7" }, + "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" }, { - "name": "Niklas Keller", - "email": "me@kelunik.com" + "name": "Steve Müller", + "email": "st.mueller@dzh-online.de" } ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", + "description": "The Doctrine Coding Standard is a set of PHPCS rules applied to all Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/coding-standard.html", "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" + "checks", + "code", + "coding", + "cs", + "dev", + "doctrine", + "rules", + "sniffer", + "sniffs", + "standard", + "style" ], "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" + "issues": "https://github.com/doctrine/coding-standard/issues", + "source": "https://github.com/doctrine/coding-standard/tree/13.0.1" }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" + "time": "2025-05-14T10:54:19+00:00" }, { - "name": "composer/pcre", - "version": "3.1.2", + "name": "doctrine/instantiator", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/4775f35b2d70865807c89d32c8e7385b86eb0ace", - "reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" + "php": "^8.1" }, "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" + "doctrine/coding-standard": "^11", + "ext-pdo": "*", + "ext-phar": "*", + "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", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, "autoload": { "psr-4": { - "Composer\\Pcre\\": "src" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -669,1556 +647,363 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" } ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" + "constructor", + "instantiate" ], "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.2" + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { - "url": "https://packagist.com", + "url": "https://www.doctrine-project.org/sponsorship.html", "type": "custom" }, { - "url": "https://github.com/composer", - "type": "github" + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", "type": "tidelift" } ], - "time": "2024-03-07T15:38:35+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { - "name": "composer/semver", - "version": "3.4.0", + "name": "eliashaeussler/phpunit-attributes", + "version": "1.7.0", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + "url": "https://github.com/eliashaeussler/phpunit-attributes.git", + "reference": "4c0832e0c7577500bd00ce570b23812abbdf95c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "url": "https://api.github.com/repos/eliashaeussler/phpunit-attributes/zipball/4c0832e0c7577500bd00ce570b23812abbdf95c2", + "reference": "4c0832e0c7577500bd00ce570b23812abbdf95c2", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", + "phpunit/phpunit": "^10.5.35 || ^11.4 || ^12.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" + "armin/editorconfig-cli": "^1.8 || ^2.0", + "eliashaeussler/php-cs-fixer-config": "^2.0", + "eliashaeussler/phpstan-config": "^2.5.1", + "eliashaeussler/rector-config": "^3.0", + "ergebnis/composer-normalize": "^2.30", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpcov": "^9.0 || ^10.0 || ^11.0", + "symfony/console": "^6.4 || ^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, "autoload": { "psr-4": { - "Composer\\Semver\\": "src" + "EliasHaeussler\\PHPUnitAttributes\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "GPL-3.0-or-later" ], "authors": [ { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" + "name": "Elias Häußler", + "email": "elias@haeussler.dev", + "homepage": "https://haeussler.dev", + "role": "Maintainer" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], + "description": "Provides additional attributes for tests with PHPUnit", "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.0" + "issues": "https://github.com/eliashaeussler/phpunit-attributes/issues", + "source": "https://github.com/eliashaeussler/phpunit-attributes/tree/1.7.0" }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2023-08-31T09:50:34+00:00" + "time": "2025-03-07T22:01:25+00:00" }, { - "name": "composer/xdebug-handler", - "version": "3.0.3", + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", "source": { "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", "shasum": "" }, "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" }, "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" }, "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" } }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } + "BSD-3-Clause" ], - "description": "Restarts a process without Xdebug.", + "description": "This is the PHP port of Hamcrest Matchers", "keywords": [ - "Xdebug", - "performance" + "test" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T21:32:43+00:00" + "time": "2020-07-09T08:09:16+00:00" }, { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", + "name": "mikey179/vfsstream", + "version": "v1.6.12", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" + "url": "https://github.com/bovigo/vfsStream.git", + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "php": ">=7.1.0" }, "require-dev": { - "composer/composer": "*", - "ext-json": "*", - "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", - "yoast/phpunit-polyfills": "^1.0" + "phpunit/phpunit": "^7.5||^8.5||^9.6", + "yoast/phpunit-polyfills": "^2.0" }, - "type": "composer-plugin", + "type": "library", "extra": { - "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + "branch-alias": { + "dev-master": "1.6.x-dev" + } }, "autoload": { - "psr-4": { - "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + "psr-0": { + "org\\bovigo\\vfs\\": "src/main/php" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "source": "https://github.com/PHPCSStandards/composer-installer" - }, - "time": "2023-01-05T11:28:13+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" + "name": "Frank Kleine", + "homepage": "http://frankkleine.de/", + "role": "Developer" } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" ], - "description": "implementation of xdg base directory specification for php", + "description": "Virtual file system to mock the real file system in unit tests.", + "homepage": "http://vfs.bovigo.org/", "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + "issues": "https://github.com/bovigo/vfsStream/issues", + "source": "https://github.com/bovigo/vfsStream/tree/master", + "wiki": "https://github.com/bovigo/vfsStream/wiki" }, - "time": "2019-12-04T15:06:13+00:00" + "time": "2024-08-29T18:43:31+00:00" }, { - "name": "doctrine/coding-standard", - "version": "12.0.0", + "name": "mockery/mockery", + "version": "1.6.12", "source": { "type": "git", - "url": "https://github.com/doctrine/coding-standard.git", - "reference": "1b2b7dc58c68833af481fb9325c25abd40681c79" + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/coding-standard/zipball/1b2b7dc58c68833af481fb9325c25abd40681c79", - "reference": "1b2b7dc58c68833af481fb9325c25abd40681c79", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0.0", - "php": "^7.2 || ^8.0", - "slevomat/coding-standard": "^8.11", - "squizlabs/php_codesniffer": "^3.7" - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Steve Müller", - "email": "st.mueller@dzh-online.de" - } - ], - "description": "The Doctrine Coding Standard is a set of PHPCS rules applied to all Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/coding-standard.html", - "keywords": [ - "checks", - "code", - "coding", - "cs", - "dev", - "doctrine", - "rules", - "sniffer", - "sniffs", - "standard", - "style" - ], - "support": { - "issues": "https://github.com/doctrine/coding-standard/issues", - "source": "https://github.com/doctrine/coding-standard/tree/12.0.0" - }, - "time": "2023-04-24T17:43:28+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": "" + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" }, - "require": { - "php": "^8.1" + "conflict": { + "phpunit/phpunit": "<8.0" }, "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" }, { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:23:10+00:00" - }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" ], - "description": "A more advanced JSONRPC implementation", "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" }, - "time": "2021-06-11T22:34:44+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.2", + "name": "myclabs/deep-copy", + "version": "1.13.1", "source": { "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], "psr-4": { - "LanguageServerProtocol\\": "src/" + "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } + "MIT" ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" - }, - "time": "2022-03-02T22:36:06+00:00" - }, - { - "name": "fidry/cpu-core-counter", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/f92996c4d5c1a696a6a970e20f7c4216200fcc42", - "reference": "f92996c4d5c1a696a6a970e20f7c4216200fcc42", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^8.5.31 || ^9.5.26", - "webmozarts/strict-phpunit": "^7.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Fidry\\CpuCoreCounter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com" - } - ], - "description": "Tiny utility to get the number of CPU cores.", - "keywords": [ - "CPU", - "core" - ], - "support": { - "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.1.0" - }, - "funding": [ - { - "url": "https://github.com/theofidry", - "type": "github" - } - ], - "time": "2024-02-07T09:43:46+00:00" - }, - { - "name": "hamcrest/hamcrest-php", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "shasum": "" - }, - "require": { - "php": "^5.3|^7.0|^8.0" - }, - "replace": { - "cordoval/hamcrest-php": "*", - "davedevelopment/hamcrest-php": "*", - "kodova/hamcrest-php": "*" - }, - "require-dev": { - "phpunit/php-file-iterator": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "classmap": [ - "hamcrest" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "This is the PHP port of Hamcrest Matchers", - "keywords": [ - "test" - ], - "support": { - "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" - }, - "time": "2020-07-09T08:09:16+00:00" - }, - { - "name": "mikey179/vfsstream", - "version": "v1.6.11", - "source": { - "type": "git", - "url": "https://github.com/bovigo/vfsStream.git", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.5|^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-0": { - "org\\bovigo\\vfs\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Frank Kleine", - "homepage": "http://frankkleine.de/", - "role": "Developer" - } - ], - "description": "Virtual file system to mock the real file system in unit tests.", - "homepage": "http://vfs.bovigo.org/", - "support": { - "issues": "https://github.com/bovigo/vfsStream/issues", - "source": "https://github.com/bovigo/vfsStream/tree/master", - "wiki": "https://github.com/bovigo/vfsStream/wiki" - }, - "time": "2022-02-23T02:02:42+00:00" - }, - { - "name": "mockery/mockery", - "version": "1.6.11", - "source": { - "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "81a161d0b135df89951abd52296adf97deb0723d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/81a161d0b135df89951abd52296adf97deb0723d", - "reference": "81a161d0b135df89951abd52296adf97deb0723d", - "shasum": "" - }, - "require": { - "hamcrest/hamcrest-php": "^2.0.1", - "lib-pcre": ">=7.0", - "php": ">=7.3" - }, - "conflict": { - "phpunit/phpunit": "<8.0" - }, - "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.17", - "symplify/easy-coding-standard": "^12.1.14" - }, - "type": "library", - "autoload": { - "files": [ - "library/helpers.php", - "library/Mockery.php" - ], - "psr-4": { - "Mockery\\": "library/Mockery" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "https://github.com/padraic", - "role": "Author" - }, - { - "name": "Dave Marshall", - "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "https://davedevelopment.co.uk", - "role": "Developer" - }, - { - "name": "Nathanael Esayeas", - "email": "nathanael.esayeas@protonmail.com", - "homepage": "https://github.com/ghostwriter", - "role": "Lead Developer" - } - ], - "description": "Mockery is a simple yet flexible PHP mock object framework", - "homepage": "https://github.com/mockery/mockery", - "keywords": [ - "BDD", - "TDD", - "library", - "mock", - "mock objects", - "mockery", - "stub", - "test", - "test double", - "testing" - ], - "support": { - "docs": "https://docs.mockery.io/", - "issues": "https://github.com/mockery/mockery/issues", - "rss": "https://github.com/mockery/mockery/releases.atom", - "security": "https://github.com/mockery/mockery/security/advisories", - "source": "https://github.com/mockery/mockery" - }, - "time": "2024-03-21T18:34:15+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.11.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", + "description": "Create deep copies (clones) of your objects", "keywords": [ "clone", "copy", "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2023-03-08T13:26:56+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.4.1", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/132c75c7dd83e45353ebb9c6c9f591952995bbf0", - "reference": "132c75c7dd83e45353ebb9c6c9f591952995bbf0", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.4.1" - }, - "time": "2024-01-31T06:18:54+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "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.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.19.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "67a759e7d8746d501c41536ba40cd9c0a07d6a87" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/67a759e7d8746d501c41536ba40cd9c0a07d6a87", - "reference": "67a759e7d8746d501c41536ba40cd9c0a07d6a87", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2 || ^2.0", - "php": "^7.2 || 8.0.* || 8.1.* || 8.2.* || 8.3.*", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0 || ^5.0 || ^6.0", - "sebastian/recursion-context": "^3.0 || ^4.0 || ^5.0 || ^6.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^8.0 || ^9.0 || ^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "dev", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.19.0" - }, - "time": "2024-02-29T11:52:51+00:00" - }, - { - "name": "phpspec/prophecy-phpunit", - "version": "v2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy-phpunit.git", - "reference": "16e1247e139434bce0bac09848bc5c8d882940fc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/16e1247e139434bce0bac09848bc5c8d882940fc", - "reference": "16e1247e139434bce0bac09848bc5c8d882940fc", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8", - "phpspec/prophecy": "^1.18", - "phpunit/phpunit": "^9.1 || ^10.1 || ^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\PhpUnit\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christophe Coevoet", - "email": "stof@notk.org" - } - ], - "description": "Integrating the Prophecy mocking library in PHPUnit test cases", - "homepage": "http://phpspec.net", - "keywords": [ - "phpunit", - "prophecy" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy-phpunit/issues", - "source": "https://github.com/phpspec/prophecy-phpunit/tree/v2.2.0" - }, - "time": "2024-03-01T08:33:58+00:00" - }, - { - "name": "phpstan/extension-installer", - "version": "1.3.1", - "source": { - "type": "git", - "url": "https://github.com/phpstan/extension-installer.git", - "reference": "f45734bfb9984c6c56c4486b71230355f066a58a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a", - "reference": "f45734bfb9984c6c56c4486b71230355f066a58a", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.0", - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.9.0" - }, - "require-dev": { - "composer/composer": "^2.0", - "php-parallel-lint/php-parallel-lint": "^1.2.0", - "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PHPStan\\ExtensionInstaller\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPStan\\ExtensionInstaller\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "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.3.1" - }, - "time": "2023-05-24T08:59:17+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "1.10.66", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "94779c987e4ebd620025d9e5fdd23323903950bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/94779c987e4ebd620025d9e5fdd23323903950bd", - "reference": "94779c987e4ebd620025d9e5fdd23323903950bd", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "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", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" - } - ], - "time": "2024-03-28T16:17:31+00:00" - }, - { - "name": "phpstan/phpstan-php-parser", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-php-parser.git", - "reference": "1c7670dd92da864b5d019f22d9f512a6ae18b78e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-php-parser/zipball/1c7670dd92da864b5d019f22d9f512a6ae18b78e", - "reference": "1c7670dd92da864b5d019f22d9f512a6ae18b78e", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0", - "phpstan/phpstan": "^1.3" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5" - }, - "type": "phpstan-extension", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - }, - "phpstan": { - "includes": [ - "extension.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHP-Parser extensions for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-php-parser/issues", - "source": "https://github.com/phpstan/phpstan-php-parser/tree/1.1.0" - }, - "abandoned": true, - "time": "2021-12-16T19:43:32+00:00" - }, - { - "name": "phpstan/phpstan-webmozart-assert", - "version": "1.2.6", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-webmozart-assert.git", - "reference": "c1739d090e44b82b41b8e32f429fa68ddc28072a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-webmozart-assert/zipball/c1739d090e44b82b41b8e32f429fa68ddc28072a", - "reference": "c1739d090e44b82b41b8e32f429fa68ddc28072a", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "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", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "webmozart/assert": "^1.11.0" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan webmozart/assert extension", - "support": { - "issues": "https://github.com/phpstan/phpstan-webmozart-assert/issues", - "source": "https://github.com/phpstan/phpstan-webmozart-assert/tree/1.2.6" - }, - "time": "2024-03-30T14:14:20+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.31", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", - "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" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "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": { - "branch-alias": { - "dev-master": "9.2-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 that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:37:42+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.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": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-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": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" + "object", + "object graph" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2025-04-29T12:36:36+00:00" }, { - "name": "phpunit/php-text-template", + "name": "phar-io/manifest", "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -2231,55 +1016,53 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", - "role": "lead" + "role": "Developer" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/theseer", "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2024-03-03T12:33:53+00:00" }, { - "name": "phpunit/php-timer", - "version": "5.0.3", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "php": "^7.2 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -2290,158 +1073,130 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", - "role": "lead" + "role": "Developer" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], + "description": "Library for handling version information and constraints", "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "phpunit/phpunit", - "version": "9.6.17", + "name": "phpspec/prophecy", + "version": "v1.22.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd" + "url": "https://github.com/phpspec/prophecy.git", + "reference": "35f1adb388946d92e6edab2aa2cb2b60e132ebd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd", - "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/35f1adb388946d92e6edab2aa2cb2b60e132ebd5", + "reference": "35f1adb388946d92e6edab2aa2cb2b60e132ebd5", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "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.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.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.2", - "sebastian/version": "^3.0.2" + "doctrine/instantiator": "^1.2 || ^2.0", + "php": "^7.4 || 8.0.* || 8.1.* || 8.2.* || 8.3.* || 8.4.*", + "phpdocumentor/reflection-docblock": "^5.2", + "sebastian/comparator": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "sebastian/recursion-context": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" }, - "suggest": { - "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" + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.40", + "phpspec/phpspec": "^6.0 || ^7.0", + "phpstan/phpstan": "^2.1.13", + "phpunit/phpunit": "^8.0 || ^9.0 || ^10.0" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-master": "1.x-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] + "psr-4": { + "Prophecy\\": "src/Prophecy" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", "keywords": [ - "phpunit", - "testing", - "xunit" + "Double", + "Dummy", + "dev", + "fake", + "mock", + "spy", + "stub" ], "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17" + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.22.0" }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2024-02-23T13:14:51+00:00" + "time": "2025-04-29T14:58:06+00:00" }, { - "name": "psr/container", - "version": "2.0.2", + "name": "phpspec/prophecy-phpunit", + "version": "v2.4.0", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "url": "https://github.com/phpspec/prophecy-phpunit.git", + "reference": "d3c28041d9390c9bca325a08c5b2993ac855bded" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/d3c28041d9390c9bca325a08c5b2993ac855bded", + "reference": "d3c28041d9390c9bca325a08c5b2993ac855bded", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": "^7.3 || ^8", + "phpspec/prophecy": "^1.18", + "phpunit/phpunit": "^9.1 || ^10.1 || ^11.0 || ^12.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "Prophecy\\PhpUnit\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2450,104 +1205,93 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Christophe Coevoet", + "email": "stof@notk.org" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "Integrating the Prophecy mocking library in PHPUnit test cases", + "homepage": "http://phpspec.net", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "phpunit", + "prophecy" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "issues": "https://github.com/phpspec/prophecy-phpunit/issues", + "source": "https://github.com/phpspec/prophecy-phpunit/tree/v2.4.0" }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2025-05-13T13:52:32+00:00" }, { - "name": "psr/log", - "version": "3.0.0", + "name": "phpstan/extension-installer", + "version": "1.4.3", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936", "shasum": "" }, "require": { - "php": ">=8.0.0" + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0 || ^2.0" }, - "type": "library", + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "type": "composer-plugin", "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } + "class": "PHPStan\\ExtensionInstaller\\Plugin" }, "autoload": { "psr-4": { - "Psr\\Log\\": "src" + "PHPStan\\ExtensionInstaller\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Composer plugin for automatic installation of PHPStan extensions", "keywords": [ - "log", - "psr", - "psr-3" + "dev", + "static analysis" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" }, - "time": "2021-07-14T16:46:02+00:00" + "time": "2024-09-04T20:21:43+00:00" }, { - "name": "rector/rector", - "version": "1.0.4", + "name": "phpstan/phpstan", + "version": "1.12.9", "source": { "type": "git", - "url": "https://github.com/rectorphp/rector.git", - "reference": "6e04d0eb087aef707fa0c5686d33d6ff61f4a555" + "url": "https://github.com/phpstan/phpstan.git", + "reference": "ceb937fb39a92deabc02d20709cf14b2c452502c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/6e04d0eb087aef707fa0c5686d33d6ff61f4a555", - "reference": "6e04d0eb087aef707fa0c5686d33d6ff61f4a555", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ceb937fb39a92deabc02d20709cf14b2c452502c", + "reference": "ceb937fb39a92deabc02d20709cf14b2c452502c", "shasum": "" }, "require": { - "php": "^7.2|^8.0", - "phpstan/phpstan": "^1.10.57" + "php": "^7.2|^8.0" }, "conflict": { - "rector/rector-doctrine": "*", - "rector/rector-downgrade-php": "*", - "rector/rector-phpunit": "*", - "rector/rector-symfony": "*" - }, - "suggest": { - "ext-dom": "To manipulate phpunit.xml via the custom-rule command" + "phpstan/phpstan-shim": "*" }, "bin": [ - "bin/rector" + "phpstan", + "phpstan.phar" ], "type": "library", "autoload": { @@ -2559,105 +1303,121 @@ "license": [ "MIT" ], - "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ - "automation", "dev", - "migration", - "refactoring" + "static analysis" ], "support": { - "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/1.0.4" + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, "funding": [ { - "url": "https://github.com/tomasvotruba", + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", "type": "github" } ], - "time": "2024-04-05T09:01:07+00:00" + "time": "2024-11-10T17:10:04+00:00" }, { - "name": "sebastian/cli-parser", - "version": "1.0.2", + "name": "phpstan/phpstan-webmozart-assert", + "version": "1.2.11", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + "url": "https://github.com/phpstan/phpstan-webmozart-assert.git", + "reference": "960dd44e8466191590dd0d7940d3e9496eebebbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "url": "https://api.github.com/repos/phpstan/phpstan-webmozart-assert/zipball/960dd44e8466191590dd0d7940d3e9496eebebbd", + "reference": "960dd44e8466191590dd0d7940d3e9496eebebbd", "shasum": "" }, "require": { - "php": ">=7.3" + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.12" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^1.2", + "phpstan/phpstan-phpunit": "^1.4", + "phpstan/phpstan-strict-rules": "^1.6", + "phpunit/phpunit": "^9.5", + "webmozart/assert": "^1.11.0" }, - "type": "library", + "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-master": "1.0-dev" + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PHPStan\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } + "MIT" ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", + "description": "PHPStan webmozart/assert extension", "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + "issues": "https://github.com/phpstan/phpstan-webmozart-assert/issues", + "source": "https://github.com/phpstan/phpstan-webmozart-assert/tree/1.2.11" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:27:43+00:00" + "time": "2024-09-11T15:48:08+00:00" }, { - "name": "sebastian/code-unit", - "version": "1.0.8", + "name": "phpunit/php-code-coverage", + "version": "10.1.16", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { - "php": ">=7.3" + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "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": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "10.1.x-dev" } }, "autoload": { @@ -2676,11 +1436,17 @@ "role": "lead" } ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { @@ -2688,32 +1454,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2024-08-22T04:31:57+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "name": "phpunit/php-file-iterator", + "version": "4.1.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -2728,14 +1494,20 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -2743,34 +1515,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { - "name": "sebastian/comparator", - "version": "4.0.8", + "name": "phpunit/php-invoker", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -2785,31 +1559,18 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ - "comparator", - "compare", - "equality" + "process" ], "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { @@ -2817,33 +1578,32 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2023-02-03T06:56:09+00:00" }, { - "name": "sebastian/complexity", - "version": "2.0.3", + "name": "phpunit/php-text-template", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -2862,11 +1622,15 @@ "role": "lead" } ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -2874,33 +1638,32 @@ "type": "github" } ], - "time": "2023-12-22T06:19:30+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { - "name": "sebastian/diff", - "version": "4.0.6", + "name": "phpunit/php-timer", + "version": "6.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -2915,24 +1678,18 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" + "timer" ], "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { @@ -2940,38 +1697,66 @@ "type": "github" } ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { - "name": "sebastian/environment", - "version": "5.1.5", + "name": "phpunit/phpunit", + "version": "10.5.46", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "8080be387a5be380dda48c6f41cee4a13aadab3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8080be387a5be380dda48c6f41cee4a13aadab3d", + "reference": "8080be387a5be380dda48c6f41cee4a13aadab3d", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.3", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, "suggest": { - "ext-posix": "*" + "ext-soap": "To be able to generate mocks based on WSDL files" }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "10.5-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -2983,194 +1768,164 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", "keywords": [ - "Xdebug", - "environment", - "hhvm" + "phpunit", + "testing", + "xunit" ], "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.46" }, "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2025-05-02T06:46:24+00:00" }, { - "name": "sebastian/exporter", - "version": "4.0.6", + "name": "psalm/phar", + "version": "6.8.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "url": "https://github.com/psalm/phar.git", + "reference": "333a7a0d7805b699860262e1b4ea8cf14e1cd118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/psalm/phar/zipball/333a7a0d7805b699860262e1b4ea8cf14e1cd118", + "reference": "333a7a0d7805b699860262e1b4ea8cf14e1cd118", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "php": "^7.1 || ^8.0" }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "conflict": { + "vimeo/psalm": "*" }, + "bin": [ + "psalm.phar" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" + "MIT" ], + "description": "Composer-based Psalm Phar", "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "issues": "https://github.com/psalm/phar/issues", + "source": "https://github.com/psalm/phar/tree/6.8.2" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-02-20T08:23:26+00:00" }, { - "name": "sebastian/global-state", - "version": "5.0.7", + "name": "rector/rector", + "version": "1.2.10", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "url": "https://github.com/rectorphp/rector.git", + "reference": "40f9cf38c05296bd32f444121336a521a293fa61" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/40f9cf38c05296bd32f444121336a521a293fa61", + "reference": "40f9cf38c05296bd32f444121336a521a293fa61", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": "^7.2|^8.0", + "phpstan/phpstan": "^1.12.5" }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" + "conflict": { + "rector/rector-doctrine": "*", + "rector/rector-downgrade-php": "*", + "rector/rector-phpunit": "*", + "rector/rector-symfony": "*" }, "suggest": { - "ext-uopz": "*" + "ext-dom": "To manipulate phpunit.xml via the custom-rule command" }, + "bin": [ + "bin/rector" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } + "MIT" ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "description": "Instant Upgrade and Automated Refactoring of any PHP code", "keywords": [ - "global state" + "automation", + "dev", + "migration", + "refactoring" ], "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/1.2.10" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/tomasvotruba", "type": "github" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2024-11-08T13:59:10+00:00" }, { - "name": "sebastian/lines-of-code", - "version": "1.0.4", + "name": "sebastian/cli-parser", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -3189,11 +1944,12 @@ "role": "lead" } ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { @@ -3201,34 +1957,32 @@ "type": "github" } ], - "time": "2023-12-22T06:20:34+00:00" + "time": "2024-03-02T07:12:49+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "4.0.4", + "name": "sebastian/code-unit", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -3243,14 +1997,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { @@ -3258,32 +2013,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2023-02-03T06:58:43+00:00" }, { - "name": "sebastian/object-reflector", - "version": "2.0.4", + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3301,11 +2056,11 @@ "email": "sebastian@phpunit.de" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { @@ -3313,32 +2068,36 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2023-02-03T06:59:15+00:00" }, { - "name": "sebastian/recursion-context", - "version": "4.0.5", + "name": "sebastian/comparator", + "version": "5.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", "shasum": "" }, "require": { - "php": ">=7.3" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -3360,15 +2119,25 @@ "email": "whatthejeff@gmail.com" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" }, "funding": [ { @@ -3376,32 +2145,33 @@ "type": "github" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2024-10-18T14:56:07+00:00" }, { - "name": "sebastian/resource-operations", - "version": "3.0.3", + "name": "sebastian/complexity", + "version": "3.2.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { - "php": ">=7.3" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.2-dev" } }, "autoload": { @@ -3416,14 +2186,16 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { @@ -3431,32 +2203,33 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2023-12-21T08:37:17+00:00" }, { - "name": "sebastian/type", - "version": "3.2.1", + "name": "sebastian/diff", + "version": "5.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -3471,15 +2244,25 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { @@ -3487,29 +2270,35 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { - "name": "sebastian/version", - "version": "3.0.2", + "name": "sebastian/environment", + "version": "6.1.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -3524,941 +2313,659 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "slevomat/coding-standard", - "version": "8.14.1", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/fea1fd6f137cc84f9cba0ae30d549615dbc6a926", - "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", - "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": "^1.23.1", - "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.10.37", - "phpstan/phpstan-deprecation-rules": "1.1.4", - "phpstan/phpstan-phpunit": "1.3.14", - "phpstan/phpstan-strict-rules": "1.5.1", - "phpunit/phpunit": "8.5.21|9.6.8|10.3.5" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "8.x-dev" - } - }, - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "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.14.1" - }, - "funding": [ - { - "url": "https://github.com/kukulich", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", - "type": "tidelift" - } - ], - "time": "2023-10-08T07:28:08+00:00" - }, - { - "name": "spatie/array-to-xml", - "version": "3.2.3", - "source": { - "type": "git", - "url": "https://github.com/spatie/array-to-xml.git", - "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/c95fd4db94ec199f798d4b5b4a81757bd20d88ab", - "reference": "c95fd4db94ec199f798d4b5b4a81757bd20d88ab", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^8.0" - }, - "require-dev": { - "mockery/mockery": "^1.2", - "pestphp/pest": "^1.21", - "spatie/pest-plugin-snapshots": "^1.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Spatie\\ArrayToXml\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "homepage": "https://freek.dev", - "role": "Developer" + "email": "sebastian@phpunit.de" } ], - "description": "Convert an array to xml", - "homepage": "https://github.com/spatie/array-to-xml", + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ - "array", - "convert", - "xml" + "Xdebug", + "environment", + "hhvm" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.2.3" + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { - "url": "https://spatie.be/open-source/support-us", - "type": "custom" - }, - { - "url": "https://github.com/spatie", + "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2024-02-07T10:39:02+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "3.9.1", + "name": "sebastian/exporter", + "version": "5.1.2", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "267a4405fff1d9c847134db3a3c92f1ab7f77909" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/267a4405fff1d9c847134db3a3c92f1ab7f77909", - "reference": "267a4405fff1d9c847134db3a3c92f1ab7f77909", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", "shasum": "" }, "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + "phpunit/phpunit": "^10.0" }, - "bin": [ - "bin/phpcbf", - "bin/phpcs" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-main": "5.1-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { - "name": "Greg Sherwood", - "role": "Former lead" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Juliette Reinders Folmer", - "role": "Current lead" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ - "phpcs", - "standards", - "static analysis" + "export", + "exporter" ], "support": { - "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", - "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", - "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" }, "funding": [ { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" } ], - "time": "2024-03-31T21:03:09+00:00" + "time": "2024-03-02T07:17:12+00:00" }, { - "name": "symfony/console", - "version": "v6.4.4", + "name": "sebastian/global-state", + "version": "6.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "0d9e4eb5ad413075624378f474c4167ea202de78" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0d9e4eb5ad413075624378f474c4167ea202de78", - "reference": "0d9e4eb5ad413075624378f474c4167ea202de78", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "ext-dom": "*", + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ - "cli", - "command-line", - "console", - "terminal" + "global state" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.4" + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-02-22T20:27:10+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { - "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "name": "sebastian/lines-of-code", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=8.1" }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "dev-main": "2.0-dev" } }, "autoload": { - "files": [ - "function.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { - "name": "symfony/filesystem", - "version": "v6.4.3", + "name": "sebastian/object-enumerator", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb", - "reference": "7f3b1755eb49297a0827a7575d5d2b2fd11cc9fb", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.3" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "name": "sebastian/object-reflector", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" + "php": ">=8.1" }, - "suggest": { - "ext-ctype": "For best performance" + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "branch-alias": { + "dev-main": "3.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "name": "sebastian/recursion-context", + "version": "5.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, - "suggest": { - "ext-intl": "For best performance" + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "branch-alias": { + "dev-main": "5.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2023-02-03T07:05:40+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "name": "sebastian/type", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, - "suggest": { - "ext-intl": "For best performance" + "require-dev": { + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "branch-alias": { + "dev-main": "4.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, "classmap": [ - "Resources/stubs" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "name": "sebastian/version", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" + "php": ">=8.1" }, "type": "library", "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "branch-alias": { + "dev-main": "4.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { - "name": "symfony/service-contracts", - "version": "v3.4.1", + "name": "slevomat/coding-standard", + "version": "8.18.0", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "f3b23cb9b26301b8c3c7bb03035a1bee23974593" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/f3b23cb9b26301b8c3c7bb03035a1bee23974593", + "reference": "f3b23cb9b26301b8c3c7bb03035a1bee23974593", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", + "php": "^7.4 || ^8.0", + "phpstan/phpdoc-parser": "^2.1.0", + "squizlabs/php_codesniffer": "^3.12.2" }, - "conflict": { - "ext-psr": "<1.1|>=2" + "require-dev": { + "phing/phing": "3.0.1", + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/phpstan": "2.1.13", + "phpstan/phpstan-deprecation-rules": "2.0.2", + "phpstan/phpstan-phpunit": "2.0.6", + "phpstan/phpstan-strict-rules": "2.0.4", + "phpunit/phpunit": "9.6.8|10.5.45|11.4.4|11.5.17|12.1.3" }, - "type": "library", + "type": "phpcodesniffer-standard", "extra": { "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "dev-master": "8.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] + "SlevomatCodingStandard\\": "SlevomatCodingStandard/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "dev", + "phpcs" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/8.18.0" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "url": "https://github.com/kukulich", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2025-05-01T09:40:50+00:00" }, { - "name": "symfony/string", - "version": "v6.4.4", + "name": "squizlabs/php_codesniffer", + "version": "3.13.2", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "5b5e3821314f947dd040c70f7992a64eac89025c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", - "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5b5e3821314f947dd040c70f7992a64eac89025c", + "reference": "5b5e3821314f947dd040c70f7992a64eac89025c", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Greg Sherwood", + "role": "Former lead" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], - "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", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" + "phpcs", + "standards", + "static analysis" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.4" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, "funding": [ { - "url": "https://symfony.com/sponsor", - "type": "custom" + "url": "https://github.com/PHPCSStandards", + "type": "github" }, { - "url": "https://github.com/fabpot", + "url": "https://github.com/jrfnl", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-02-01T13:16:41+00:00" + "time": "2025-06-17T22:17:01+00:00" }, { "name": "theseer/tokenizer", @@ -4509,116 +3016,6 @@ } ], "time": "2024-03-03T12:36:25+00:00" - }, - { - "name": "vimeo/psalm", - "version": "5.23.1", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "8471a896ccea3526b26d082f4461eeea467f10a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/8471a896ccea3526b26d082f4461eeea467f10a4", - "reference": "8471a896ccea3526b26d082f4461eeea467f10a4", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer-runtime-api": "^2", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.1", - "felixfbecker/language-server-protocol": "^1.5.2", - "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.16", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "sebastian/diff": "^4.0 || ^5.0 || ^6.0", - "spatie/array-to-xml": "^2.17.0 || ^3.0", - "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" - }, - "conflict": { - "nikic/php-parser": "4.17.0" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "amphp/phpunit-util": "^2.0", - "bamarni/composer-bin-plugin": "^1.4", - "brianium/paratest": "^6.9", - "ext-curl": "*", - "mockery/mockery": "^1.5", - "nunomaduro/mock-final-classes": "^1.1", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpdoc-parser": "^1.6", - "phpunit/phpunit": "^9.6", - "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "project", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev", - "dev-4.x": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php", - "static analysis" - ], - "support": { - "docs": "https://psalm.dev/docs", - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm" - }, - "time": "2024-03-11T20:33:46+00:00" } ], "aliases": [], @@ -4627,11 +3024,12 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "8.1.*|8.2.*|8.3.*" + "php": "8.1.*|8.2.*|8.3.*|8.4.*", + "composer-runtime-api": "^2" }, "platform-dev": [], "platform-overrides": { "php": "8.1.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/docs/extending/index.rst b/docs/extending/index.rst new file mode 100644 index 00000000..3ad13ccf --- /dev/null +++ b/docs/extending/index.rst @@ -0,0 +1,34 @@ +.. _extending: + +Extend the library +================== + +The model exposed by this library is closed for inheritance. We did this to ensure the model is stable and does not +change via external factors. The complexity of this project makes it hard to keep all the internal classes stable. +The model is designed to be cached and constructed very carefully to ensure performance and memory usage are optimal. + +Metadata +-------- + +Metadata is a way to extend the model with additional information. We call this metadata, as all first class +elements in the reflected codebase are part of the model. Extra data can be added to these elements using metadata. + +Elements supporting metadata are: + +.. phpdoc:class-list:: [?(@.interfaces contains "\phpDocumentor\Reflection\Metadata\MetaDataContainer")] + + .. phpdoc:name:: + +.. warning:: + + Adding metadata might break the posibilty to cache the model. Be carefull with circular references and large + objects. We do recommend to keep the metadata small and simple. + +Continue reading :doc:`Creating your first metadata <meta-data>`_ to learn how to create your own metadata. + +.. toctree:: + :maxdepth: 1 + :titlesonly: + :hidden: + + meta-data diff --git a/docs/meta-data.rst b/docs/extending/meta-data.rst similarity index 100% rename from docs/meta-data.rst rename to docs/extending/meta-data.rst diff --git a/docs/filtering.rst b/docs/filtering.rst deleted file mode 100644 index e8425d00..00000000 --- a/docs/filtering.rst +++ /dev/null @@ -1,4 +0,0 @@ -Filtering -========= - -.. info:: The contents for this page are planned but need to be written, please come back later to check for this \ No newline at end of file diff --git a/docs/getting-started.rst b/docs/getting-started.rst new file mode 100644 index 00000000..447f37ad --- /dev/null +++ b/docs/getting-started.rst @@ -0,0 +1,49 @@ +Getting started +=============== + +This page will give you a quick introduction to the `phpdocumentor/reflection` package and how to get started with it. + +Installation +------------ + +In order to inspect a codebase you need to tell composer to include the `phpdocumentor/reflection` package. This +can easily be done using the following command in your command line terminal: + +.. code-block:: bash + + composer require phpdocumentor/reflection:~6.0 + +In order to use the library you need to include the autoloader of composer in your code. + This can be done by adding the following line to your code: + +.. code-block:: php + + <?php + require_once 'vendor/autoload.php'; + +After the installation is complete no further configuration is necessary and you can immediately start using it. + +Basic usage +------------ + +The :php:class:`\phpDocumentor\Reflection\Php\ProjectFactory` class is the entry point to the library and is used to create a new +project object that contains all the information about your codebase. It is configured with sensible defaults. And for most +usecases you can just use it as is. + +.. code-block:: php + + $projectFactory = \phpDocumentor\Reflection\Php\ProjectFactory::createInstance(); + +At this point we are ready to analyze your complete project or just one file at the time. Just pass an array of file paths to the `create` method of the project factory. + +.. code-block:: php + + $projectFiles = [new \phpDocumentor\Reflection\File\LocalFile('tests/example.file.php')]; + $project = $projectFactory->create('My Project', $projectFiles); + +When the process is ready a new object of type :php:class:`phpDocumentor\Reflection\Php\Project` will be returned that +contains a complete hierarchy of all files with their classes, traits and interfaces (and everything in there), but also +all namespaces and packages as a hierarchical tree. +This library does not provide a way to access the structure of the codebase in a searchable way. +This is up to the consumer of the library to implement. + diff --git a/docs/incremental-updates.rst b/docs/incremental-updates.rst deleted file mode 100644 index 8f83164b..00000000 --- a/docs/incremental-updates.rst +++ /dev/null @@ -1,4 +0,0 @@ -Incremental updates -=================== - -.. info:: The contents for this page are planned but need to be written, please come back later to check for this \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index d4f2f984..52b3506e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,7 +1,28 @@ Reflection ========== +Using this library it is possible to statically reflect one or more files and create an object graph representing +your application's structure, including accompanying in-source documentation using DocBlocks. + +The information that this library provides is similar to what the (built-in) Reflection extension of PHP provides; there +are however several advantages to using this library: + +- Due to its Static nature it does not execute procedural code in your reflected files where Dynamic Reflection does. +- Because the none of the code is interpreted by PHP (and executed) Static Reflection uses less memory. +- Can reflect complete files +- Can reflect a whole project by reflecting multiple files. +- Reflects the contents of a DocBlock instead of just mentioning there is one. +- Is capable of analyzing code written for any PHP version (starting at 5.2) up to the lastest version, even if your installed + PHP version is lower than the code you are reflecting. + +.. note:: + As this library focuses on reflecting the structure of the codebase, it does not provide any options to manipulate + the output. If you want to collect more information from the codebase you can read about :ref:`extending the library <extending>`. + .. toctree:: :hidden: + :maxdepth: 2 - meta-data + getting-started + reflection-structure + extending/index diff --git a/docs/inspecting.rst b/docs/inspecting.rst deleted file mode 100644 index 660040f2..00000000 --- a/docs/inspecting.rst +++ /dev/null @@ -1,4 +0,0 @@ -Inspecting -========== - -.. info:: The contents for this page are planned but need to be written, please come back later to check for this \ No newline at end of file diff --git a/docs/integrating-with-silex-and-cilex.rst b/docs/integrating-with-silex-and-cilex.rst deleted file mode 100644 index 4b80a411..00000000 --- a/docs/integrating-with-silex-and-cilex.rst +++ /dev/null @@ -1,4 +0,0 @@ -Integrating with Silex and Cilex -================================ - -.. info:: The contents for this page are planned but need to be written, please come back later to check for this \ No newline at end of file diff --git a/docs/reflection-structure.rst b/docs/reflection-structure.rst new file mode 100644 index 00000000..55fb23d6 --- /dev/null +++ b/docs/reflection-structure.rst @@ -0,0 +1,20 @@ +Reflection structure +==================== + +The project created by the :php:class:`\phpDocumentor\Reflection\Php\ProjectFactory` class contains a hierarchy of objects +that represent the structure of your codebase. This hierarchy includes: + +Files + Each file is represented by an object of type :php:class:`\phpDocumentor\Reflection\Php\File` which contains + information about the file such as its name, path, and contents. But also the elements that are defined in the file. + Files can be accessed through the :php:method:`\phpDocumentor\Reflection\Php\Project::getFiles()` method of the project object. + Files are a flat list of all files that were analyzed, regardless of their location in the directory structure. + +Namespaces + Namespaces are represented by objects of type :php:class:`\phpDocumentor\Reflection\Php\Namespace_`. Each namespace + contains a list of classes, interfaces, traits, and functions that are defined within it. Namespaces can be accessed + through the :php:method:`\phpDocumentor\Reflection\Php\Project::getNamespaces()` method of the project object. + Namespaces are hierarchical and can contain sub-namespaces. + +Both namespaces and files do contain the other structural elements that are defined in them, such as classes, interfaces, traits, and functions. +This library does not provide a way to access the structure of the codebase in a searchable way. This is up to the consumer of the library to implement. diff --git a/docs/usage.rst b/docs/usage.rst deleted file mode 100644 index 35474b2a..00000000 --- a/docs/usage.rst +++ /dev/null @@ -1,4 +0,0 @@ -Usage -===== - -.. info:: The contents for this page are planned but need to be written, please come back later to check for this \ No newline at end of file diff --git a/phpcs.xml.dist b/phpcs.xml.dist index ba5c120c..99089501 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -18,10 +18,27 @@ <exclude name="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming.SuperfluousPrefix"/> <exclude name="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming.SuperfluousSuffix"/> <exclude name="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix"/> + <exclude name="SlevomatCodingStandard.Commenting.ForbiddenAnnotations"/> <exclude name="Squiz.Commenting.FunctionComment"/> </rule> + <rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations"> + <properties> + <property name="forbiddenAnnotations" type="array"> + <element value="@author"/> + <element value="@category"/> + <element value="@copyright"/> + <element value="@created"/> + <element value="@license"/> + <element value="@package"/> + <element value="@since"/> + <element value="@subpackage"/> + <element value="@version"/> + </property> + </properties> + </rule> + <rule ref="Generic.Formatting.SpaceAfterNot"> <properties> <property name="spacing" value="0"/> diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml new file mode 100644 index 00000000..8c277c77 --- /dev/null +++ b/phpdoc.dist.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<phpdocumentor + configVersion="3" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="https://www.phpdoc.org" + xsi:noNamespaceSchemaLocation="data/xsd/phpdoc.xsd" +> + <title>Guides</title> + <paths> + <output>build/docs</output> + </paths> + <version number="6.2.0"> + <folder>latest</folder> + <api> + <source dsn="."> + <path>src/phpDocumentor</path> + </source> + <output>api</output> + <ignore hidden="true" symlinks="true"> + <path>tests/**/*</path> + <path>build/**/*</path> + <path>var/**/*</path> + <path>vendor/**/*</path> + </ignore> + <extensions> + <extension>php</extension> + </extensions> + <ignore-tags> + <ignore-tag>template</ignore-tag> + <ignore-tag>template-extends</ignore-tag> + <ignore-tag>template-implements</ignore-tag> + <ignore-tag>extends</ignore-tag> + <ignore-tag>implements</ignore-tag> + </ignore-tags> + <default-package-name>phpDocumentor</default-package-name> + </api> + <guide> + <source dsn="."> + <path>docs</path> + </source> + <output>guides</output> + </guide> + </version> + <template name="default" /> +</phpdocumentor> diff --git a/phpstan.neon b/phpstan.neon index 3f6932cd..71dffd7c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,7 +2,6 @@ parameters: paths: - src - checkGenericClassInNonGenericObjectType: false level: max ignoreErrors: @@ -16,10 +15,6 @@ parameters: - '#Parameter \#1 \$fqsen of class phpDocumentor\\Reflection\\Php\\(.*) constructor expects phpDocumentor\\Reflection\\Fqsen, mixed given\.#' - '#Parameter \#1 \$fqsen of method phpDocumentor\\Reflection\\Php\\File::addNamespace\(\) expects phpDocumentor\\Reflection\\Fqsen, mixed given\.#' # - # there is one test case that prevents changing PropertyIterator::getDefault() to just return Expr (this is set in PhpParser) - # src/phpDocumentor/Reflection/Php/Factory/Property.php - - '#Parameter \#1 \$node of method PhpParser\\PrettyPrinterAbstract::prettyPrintExpr\(\) expects PhpParser\\Node\\Expr, PhpParser\\Node\\Expr\|string given\.#' - # # Type hint in php-parser is incorrect. - '#Cannot cast PhpParser\\Node\\Expr\|string to string.#' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 235ec710..cbc56b39 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,18 +1,14 @@ <?xml version="1.0" encoding="utf-8"?> - -<phpunit - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.0/phpunit.xsd" - colors="true" - verbose="true" - bootstrap="vendor/autoload.php" - forceCoversAnnotation="true" - convertDeprecationsToExceptions="true" - beStrictAboutCoversAnnotation="false" - beStrictAboutOutputDuringTests="true" - beStrictAboutChangesToGlobalState="true" - beStrictAboutTodoAnnotatedTests="true" -> +<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" colors="true" bootstrap="vendor/autoload.php" beStrictAboutOutputDuringTests="true" beStrictAboutChangesToGlobalState="true" cacheDirectory=".phpunit.cache" requireCoverageMetadata="true" beStrictAboutCoverageMetadata="false"> + <extensions> + <bootstrap class="EliasHaeussler\PHPUnitAttributes\PHPUnitAttributesExtension" /> + </extensions> + <coverage> + <report> + <clover outputFile="build/logs/clover.xml"/> + <html outputDirectory="build/coverage" lowUpperBound="35" highLowerBound="70"/> + </report> + </coverage> <testsuites> <testsuite name="unit"> <directory>./tests/unit</directory> @@ -21,22 +17,10 @@ <directory>./tests/integration</directory> </testsuite> </testsuites> - <filter> - <whitelist> + <logging/> + <source> + <include> <directory suffix=".php">./src/</directory> - </whitelist> - </filter> - <logging> - <log type="coverage-html" - target="build/coverage" - lowUpperBound="35" - highLowerBound="70"/> - <log type="coverage-clover" target="build/logs/clover.xml"/> - </logging> - <listeners> - <listener - class="Mockery\Adapter\Phpunit\TestListener" - file="vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php" - /> - </listeners> + </include> + </source> </phpunit> diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 0f5ee145..2ec6bdbc 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,163 +1,236 @@ <?xml version="1.0" encoding="UTF-8"?> -<files psalm-version="4.26.0@6998fabb2bf528b65777bf9941920888d23c03ac"> +<files psalm-version="6.8.2@720ed6b578ac24f9543c65c3d4cecea0ff348ccd"> + <file src="src/phpDocumentor/Reflection/File/LocalFile.php"> + <FalsableReturnStatement> + <code><![CDATA[md5_file($this->path)]]></code> + </FalsableReturnStatement> + <InvalidFalsableReturnType> + <code><![CDATA[string]]></code> + </InvalidFalsableReturnType> + <UnusedClass> + <code><![CDATA[LocalFile]]></code> + </UnusedClass> + </file> + <file src="src/phpDocumentor/Reflection/Metadata/MetaDataContainer.php"> + <PossiblyUnusedMethod> + <code><![CDATA[addMetadata]]></code> + <code><![CDATA[getMetadata]]></code> + </PossiblyUnusedMethod> + </file> <file src="src/phpDocumentor/Reflection/Middleware/ChainFactory.php"> - <DocblockTypeContradiction occurrences="1"> - <code>gettype($middleware)</code> - </DocblockTypeContradiction> - <MissingClosureParamType occurrences="1"> - <code>$command</code> + <MissingClosureParamType> + <code><![CDATA[$command]]></code> </MissingClosureParamType> - <MixedArgument occurrences="1"> - <code>$command</code> + <MixedArgument> + <code><![CDATA[$command]]></code> </MixedArgument> - <MixedArgumentTypeCoercion occurrences="1"> - <code>$lastCallable</code> + <MixedArgumentTypeCoercion> + <code><![CDATA[$lastCallable]]></code> </MixedArgumentTypeCoercion> - <RedundantConditionGivenDocblockType occurrences="1"> - <code>is_object($middleware)</code> - </RedundantConditionGivenDocblockType> </file> <file src="src/phpDocumentor/Reflection/NodeVisitor/ElementNameResolver.php"> - <NoInterfaceProperties occurrences="1"> - <code>$node->fqsen</code> - </NoInterfaceProperties> - <MixedAssignment occurrences="1"> - <code>$part</code> - </MixedAssignment> - <MixedOperand occurrences="1"> - <code>$part</code> - </MixedOperand> + <ImplicitToStringCast> + <code><![CDATA[$node->name]]></code> + <code><![CDATA[$node->name]]></code> + <code><![CDATA[$node->name]]></code> + <code><![CDATA[$node->name]]></code> + <code><![CDATA[$node->name]]></code> + <code><![CDATA[$part]]></code> + </ImplicitToStringCast> + <MixedPropertyTypeCoercion> + <code><![CDATA[new SplDoublyLinkedList()]]></code> + </MixedPropertyTypeCoercion> + <PossiblyNullOperand> + <code><![CDATA[$part]]></code> + </PossiblyNullOperand> </file> - <file src="src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php"> - <RedundantCondition occurrences="1"> - <code>is_object($object)</code> - </RedundantCondition> - <TypeDoesNotContainType occurrences="1"> - <code>gettype($object)</code> - </TypeDoesNotContainType> - </file> - <file src="src/phpDocumentor/Reflection/Php/Factory/Argument.php"> - <PossiblyInvalidCast occurrences="1"> - <code>$object->var->name</code> - </PossiblyInvalidCast> - <RedundantConditionGivenDocblockType occurrences="1"> - <code>isInstanceOf</code> - </RedundantConditionGivenDocblockType> - <UndefinedMethod occurrences="1"> - <code>addArgument</code> - </UndefinedMethod> + <file src="src/phpDocumentor/Reflection/Php/AttributeContainer.php"> + <PossiblyUnusedMethod> + <code><![CDATA[getAttributes]]></code> + </PossiblyUnusedMethod> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/ClassConstant.php"> - <PossiblyUndefinedMethod occurrences="1"> - <code>addConstant</code> + <PossiblyUndefinedMethod> + <code><![CDATA[addConstant]]></code> </PossiblyUndefinedMethod> - <RedundantCondition occurrences="1"> - <code>$const->getValue() !== null</code> + <RedundantCondition> + <code><![CDATA[$const->getValue() !== null]]></code> </RedundantCondition> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/ClassConstantIterator.php"> - <MixedInferredReturnType occurrences="1"> - <code>Fqsen</code> - </MixedInferredReturnType> - <MixedReturnStatement occurrences="1"/> + <MixedReturnStatement> + <code><![CDATA[$this->classConstants->consts[$this->index]->getAttribute('fqsen')]]></code> + </MixedReturnStatement> + <PossiblyUnusedMethod> + <code><![CDATA[getName]]></code> + <code><![CDATA[isPublic]]></code> + </PossiblyUnusedMethod> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/Class_.php"> - <MixedArgument occurrences="1"/> + <ImplicitToStringCast> + <code><![CDATA[$object->extends]]></code> + </ImplicitToStringCast> + <MixedArgument> + <code><![CDATA[$object->getAttribute('fqsen')]]></code> + </MixedArgument> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/ConstructorPromotion.php"> - <PossiblyInvalidCast occurrences="1"> - <code>$param->var->name</code> + <ImplicitToStringCast> + <code><![CDATA[$methodContainer->getFqsen()]]></code> + </ImplicitToStringCast> + <PossiblyInvalidCast> + <code><![CDATA[$param->var->name]]></code> </PossiblyInvalidCast> + <RedundantCondition> + <code><![CDATA[$param->hooks]]></code> + </RedundantCondition> + <TypeDoesNotContainType> + <code><![CDATA[[]]]></code> + </TypeDoesNotContainType> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/EnumCase.php"> - <MixedArgument occurrences="1"/> + <MixedArgument> + <code><![CDATA[$object->getAttribute('fqsen')]]></code> + </MixedArgument> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/Enum_.php"> - <MixedArgument occurrences="1"/> + <MixedArgument> + <code><![CDATA[$object->getAttribute('fqsen')]]></code> + </MixedArgument> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/File.php"> - <MissingClosureParamType occurrences="1"> - <code>$command</code> + <MissingClosureParamType> + <code><![CDATA[$command]]></code> </MissingClosureParamType> - <MixedArgument occurrences="2"> - <code>$command</code> - <code>$file</code> + <MixedArgument> + <code><![CDATA[$command]]></code> + <code><![CDATA[$file]]></code> </MixedArgument> - <MixedAssignment occurrences="1"> - <code>$file</code> + <MixedAssignment> + <code><![CDATA[$file]]></code> </MixedAssignment> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/Function_.php"> - <DocblockTypeContradiction occurrences="1"> - <code>is_array($object->stmts)</code> - </DocblockTypeContradiction> - <MixedArgument occurrences="1"/> + <MixedArgument> + <code><![CDATA[$object->getAttribute('fqsen')]]></code> + </MixedArgument> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/GlobalConstant.php"> - <RedundantCondition occurrences="1"> - <code>$const->getValue() !== null</code> + <RedundantCondition> + <code><![CDATA[$const->getValue() !== null]]></code> </RedundantCondition> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/GlobalConstantIterator.php"> - <MixedInferredReturnType occurrences="1"> - <code>Fqsen</code> - </MixedInferredReturnType> - <MixedReturnStatement occurrences="1"/> + <MixedReturnStatement> + <code><![CDATA[$this->constant->consts[$this->index]->getAttribute('fqsen')]]></code> + </MixedReturnStatement> + <PossiblyUnusedMethod> + <code><![CDATA[getName]]></code> + </PossiblyUnusedMethod> + </file> + <file src="src/phpDocumentor/Reflection/Php/Factory/IfStatement.php"> + <ClassMustBeFinal> + <code><![CDATA[IfStatement]]></code> + </ClassMustBeFinal> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/Interface_.php"> - <MixedArgument occurrences="1"/> + <MixedArgument> + <code><![CDATA[$object->getAttribute('fqsen')]]></code> + </MixedArgument> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/Method.php"> - <MixedArgument occurrences="1"/> - <UndefinedMethod occurrences="1"> - <code>addMethod</code> + <MixedArgument> + <code><![CDATA[$object->getAttribute('fqsen')]]></code> + </MixedArgument> + <UndefinedMethod> + <code><![CDATA[addMethod]]></code> </UndefinedMethod> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/Namespace_.php"> - <DocblockTypeContradiction occurrences="1"> - <code>gettype($object)</code> - </DocblockTypeContradiction> - <MixedArgument occurrences="1"/> - <RedundantConditionGivenDocblockType occurrences="1"> - <code>is_object($object)</code> - </RedundantConditionGivenDocblockType> + <ClassMustBeFinal> + <code><![CDATA[Namespace_]]></code> + </ClassMustBeFinal> + <MixedArgument> + <code><![CDATA[$object->getAttribute('fqsen') ?? new Fqsen('\\')]]></code> + </MixedArgument> + </file> + <file src="src/phpDocumentor/Reflection/Php/Factory/Noop.php"> + <ClassMustBeFinal> + <code><![CDATA[Noop]]></code> + </ClassMustBeFinal> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/Property.php"> - <PossiblyInvalidArgument occurrences="1"> - <code>$iterator->getDefault()</code> - </PossiblyInvalidArgument> - <UndefinedMethod occurrences="1"> - <code>addProperty</code> + <UndefinedMethod> + <code><![CDATA[addProperty]]></code> </UndefinedMethod> </file> + <file src="src/phpDocumentor/Reflection/Php/Factory/PropertyBuilder.php"> + <PropertyNotSetInConstructor> + <code><![CDATA[$endLocation]]></code> + <code><![CDATA[$fqsen]]></code> + <code><![CDATA[$startLocation]]></code> + <code><![CDATA[$type]]></code> + </PropertyNotSetInConstructor> + </file> <file src="src/phpDocumentor/Reflection/Php/Factory/PropertyIterator.php"> - <MixedInferredReturnType occurrences="1"> - <code>Fqsen</code> - </MixedInferredReturnType> - <MixedReturnStatement occurrences="1"/> + <MixedReturnStatement> + <code><![CDATA[$this->property->props[$this->index]->getAttribute('fqsen')]]></code> + </MixedReturnStatement> + <PossiblyUnusedMethod> + <code><![CDATA[getName]]></code> + </PossiblyUnusedMethod> + </file> + <file src="src/phpDocumentor/Reflection/Php/Factory/Reducer/Parameter.php"> + <ClassMustBeFinal> + <code><![CDATA[Parameter]]></code> + </ClassMustBeFinal> </file> <file src="src/phpDocumentor/Reflection/Php/Factory/Trait_.php"> - <MixedArgument occurrences="1"/> + <MixedArgument> + <code><![CDATA[$object->getAttribute('fqsen')]]></code> + </MixedArgument> + </file> + <file src="src/phpDocumentor/Reflection/Php/NodesFactory.php"> + <ClassMustBeFinal> + <code><![CDATA[NodesFactory]]></code> + </ClassMustBeFinal> + <PossiblyUnusedParam> + <code><![CDATA[$kind]]></code> + </PossiblyUnusedParam> + </file> + <file src="src/phpDocumentor/Reflection/Php/ProjectFactory.php"> + <ImplicitToStringCast> + <code><![CDATA[$namespace->getFqsen()]]></code> + <code><![CDATA[$namespace->getFqsen()]]></code> + <code><![CDATA[$namespace->getFqsen()]]></code> + <code><![CDATA[$namespace->getFqsen()]]></code> + <code><![CDATA[$namespace->getFqsen()]]></code> + <code><![CDATA[$namespace->getFqsen()]]></code> + </ImplicitToStringCast> + <PossiblyUnusedMethod> + <code><![CDATA[addStrategy]]></code> + <code><![CDATA[createInstance]]></code> + </PossiblyUnusedMethod> </file> <file src="src/phpDocumentor/Reflection/Php/ProjectFactoryStrategies.php"> - <MixedArgument occurrences="1"> - <code>$object</code> + <MixedArgument> + <code><![CDATA[$object]]></code> </MixedArgument> - <MixedPropertyTypeCoercion occurrences="1"> - <code>new SplPriorityQueue()</code> + <MixedPropertyTypeCoercion> + <code><![CDATA[new SplPriorityQueue()]]></code> </MixedPropertyTypeCoercion> </file> <file src="src/phpDocumentor/Reflection/Php/ValueEvaluator/ConstantEvaluator.php"> - <MixedInferredReturnType occurrences="1"> - <code>string</code> - </MixedInferredReturnType> - <MixedReturnStatement occurrences="1"> - <code>$evaluator->evaluateSilently($expr)</code> + <MixedReturnStatement> + <code><![CDATA[$evaluator->evaluateSilently($expr)]]></code> </MixedReturnStatement> </file> <file src="src/phpDocumentor/Reflection/Types/NamespaceNodeToContext.php"> - <MixedArgumentTypeCoercion occurrences="1"> - <code>$this->aliasesToFullyQualifiedNames($namespace)</code> + <ClassMustBeFinal> + <code><![CDATA[NamespaceNodeToContext]]></code> + </ClassMustBeFinal> + <MixedArgumentTypeCoercion> + <code><![CDATA[$this->aliasesToFullyQualifiedNames($namespace)]]></code> </MixedArgumentTypeCoercion> </file> </files> diff --git a/psalm.xml b/psalm.xml index 8b73b240..bdac9dad 100644 --- a/psalm.xml +++ b/psalm.xml @@ -16,5 +16,6 @@ <issueHandlers> <LessSpecificReturnType errorLevel="info" /> <MoreSpecificImplementedParamType errorLevel="info" /> + <DeprecatedConstant errorLevel="info" /> </issueHandlers> </psalm> diff --git a/src/php-parser/Modifiers.php b/src/php-parser/Modifiers.php new file mode 100644 index 00000000..69ac740b --- /dev/null +++ b/src/php-parser/Modifiers.php @@ -0,0 +1,31 @@ +<?php + +declare(strict_types=1); + +namespace PhpParser; + +use Composer\InstalledVersions; + +use function strpos; + +if (strpos(InstalledVersions::getVersion('nikic/php-parser') ?? '', '4') === 0) { + /** + * Modifiers used (as a bit mask) by various flags subnodes, for example on classes, functions, + * properties and constants. + */ + final class Modifiers + { + public const PUBLIC = 1; + public const PROTECTED = 2; + public const PRIVATE = 4; + public const STATIC = 8; + public const ABSTRACT = 16; + public const FINAL = 32; + public const READONLY = 64; + public const PUBLIC_SET = 128; + public const PROTECTED_SET = 256; + public const PRIVATE_SET = 512; + + public const VISIBILITY_SET_MASK = self::PUBLIC_SET | self::PROTECTED_SET | self::PRIVATE_SET; + } +} diff --git a/src/phpDocumentor/Reflection/Exception.php b/src/phpDocumentor/Reflection/Exception.php index bd1ccddb..6ef2403a 100644 --- a/src/phpDocumentor/Reflection/Exception.php +++ b/src/phpDocumentor/Reflection/Exception.php @@ -17,6 +17,8 @@ * An exception specifically originating from the Reflection component. * * @link http://phpdoc.org + * + * @api */ class Exception extends \Exception { diff --git a/src/phpDocumentor/Reflection/File/LocalFile.php b/src/phpDocumentor/Reflection/File/LocalFile.php index cf8e58ab..7ac4b743 100644 --- a/src/phpDocumentor/Reflection/File/LocalFile.php +++ b/src/phpDocumentor/Reflection/File/LocalFile.php @@ -14,6 +14,7 @@ namespace phpDocumentor\Reflection\File; use InvalidArgumentException; +use Override; use phpDocumentor\Reflection\File; use function file_exists; @@ -43,6 +44,7 @@ public function __construct(string $path) /** * Returns the content of the file as a string. */ + #[Override] public function getContents(): string { return (string) file_get_contents($this->path); @@ -51,6 +53,7 @@ public function getContents(): string /** * Returns md5 hash of the file. */ + #[Override] public function md5(): string { return md5_file($this->path); @@ -59,6 +62,7 @@ public function md5(): string /** * Returns a relative path to the file. */ + #[Override] public function path(): string { return $this->path; diff --git a/src/phpDocumentor/Reflection/NodeVisitor/ElementNameResolver.php b/src/phpDocumentor/Reflection/NodeVisitor/ElementNameResolver.php index 35414437..730acfd9 100644 --- a/src/phpDocumentor/Reflection/NodeVisitor/ElementNameResolver.php +++ b/src/phpDocumentor/Reflection/NodeVisitor/ElementNameResolver.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\NodeVisitor; +use Override; use phpDocumentor\Reflection\Fqsen; use PhpParser\Node; use PhpParser\Node\Const_; @@ -34,6 +35,7 @@ final class ElementNameResolver extends NodeVisitorAbstract { + /** @var SplDoublyLinkedList<Node\Identifier|string|null> */ private SplDoublyLinkedList $parts; public function __construct() @@ -46,6 +48,7 @@ public function __construct() * * @inheritDoc */ + #[Override] public function beforeTraverse(array $nodes) { $this->resetState('\\'); @@ -58,6 +61,7 @@ public function beforeTraverse(array $nodes) * * @inheritDoc */ + #[Override] public function leaveNode(Node $node) { switch ($node::class) { @@ -68,6 +72,7 @@ public function leaveNode(Node $node) case ClassMethod::class: case Trait_::class: case PropertyProperty::class: + case Node\PropertyItem::class: case ClassConst::class: case Const_::class: case Interface_::class: @@ -84,13 +89,8 @@ public function leaveNode(Node $node) /** * Adds fqsen property to a node when applicable. - * - * @todo this method is decorating the Node with an $fqsen property... - * since we can't declare it in PhpParser/NodeAbstract, - * we should add a decorator class wrapper in Reflection... - * that should clear up the PHPSTAN errors about - * "access to an undefined property ::$fqsen". */ + #[Override] public function enterNode(Node $node): int|null { switch ($node::class) { @@ -132,6 +132,7 @@ public function enterNode(Node $node): int|null $this->parts->push($node->name); $this->setFqsen($node); break; + case Node\PropertyItem::class: case PropertyProperty::class: $this->parts->push('::$' . $node->name); $this->setFqsen($node); diff --git a/src/phpDocumentor/Reflection/NodeVisitor/FindingVisitor.php b/src/phpDocumentor/Reflection/NodeVisitor/FindingVisitor.php new file mode 100644 index 00000000..9bc17ab1 --- /dev/null +++ b/src/phpDocumentor/Reflection/NodeVisitor/FindingVisitor.php @@ -0,0 +1,17 @@ +<?php + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\NodeVisitor; + +use PhpParser\NodeVisitor\FirstFindingVisitor as BaseFindingVisitor; + +final class FindingVisitor extends BaseFindingVisitor +{ + public function __construct(callable $filterCallback) + { + parent::__construct($filterCallback); + + $this->foundNode = null; + } +} diff --git a/src/phpDocumentor/Reflection/Php/Argument.php b/src/phpDocumentor/Reflection/Php/Argument.php index 4706d240..25fb6010 100644 --- a/src/phpDocumentor/Reflection/Php/Argument.php +++ b/src/phpDocumentor/Reflection/Php/Argument.php @@ -18,6 +18,8 @@ /** * Descriptor representing a single Argument of a method or function. + * + * @api */ final class Argument { diff --git a/src/phpDocumentor/Reflection/Php/AsymmetricVisibility.php b/src/phpDocumentor/Reflection/Php/AsymmetricVisibility.php new file mode 100644 index 00000000..1877f398 --- /dev/null +++ b/src/phpDocumentor/Reflection/Php/AsymmetricVisibility.php @@ -0,0 +1,26 @@ +<?php + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\Php; + +/** @api */ +final class AsymmetricVisibility extends Visibility +{ + public function __construct( + private Visibility $readVisibility, + private Visibility $writeVisibility, + ) { + parent::__construct((string) $readVisibility); + } + + public function getReadVisibility(): Visibility + { + return $this->readVisibility; + } + + public function getWriteVisibility(): Visibility + { + return $this->writeVisibility; + } +} diff --git a/src/phpDocumentor/Reflection/Php/Attribute.php b/src/phpDocumentor/Reflection/Php/Attribute.php index 26ccf7e8..19071316 100644 --- a/src/phpDocumentor/Reflection/Php/Attribute.php +++ b/src/phpDocumentor/Reflection/Php/Attribute.php @@ -4,9 +4,11 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; +/** @api */ final class Attribute implements Element { /** @param CallArgument[] $arguments */ @@ -14,6 +16,7 @@ public function __construct(private readonly Fqsen $fqsen, private readonly arra { } + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -25,6 +28,7 @@ public function getArguments(): array return $this->arguments; } + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/CallArgument.php b/src/phpDocumentor/Reflection/Php/CallArgument.php index e619d052..38570690 100644 --- a/src/phpDocumentor/Reflection/Php/CallArgument.php +++ b/src/phpDocumentor/Reflection/Php/CallArgument.php @@ -4,6 +4,11 @@ namespace phpDocumentor\Reflection\Php; +/** + * Represents an argument in a function or method call. + * + * @api + */ final class CallArgument { public function __construct(private readonly string $value, private readonly string|null $name = null) diff --git a/src/phpDocumentor/Reflection/Php/Class_.php b/src/phpDocumentor/Reflection/Php/Class_.php index e6b44a1b..654b050e 100644 --- a/src/phpDocumentor/Reflection/Php/Class_.php +++ b/src/phpDocumentor/Reflection/Php/Class_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; @@ -21,6 +22,8 @@ /** * Descriptor representing a Class. + * + * @api */ // @codingStandardsIgnoreStart final class Class_ implements Element, MetaDataContainerInterface, AttributeContainer @@ -202,6 +205,7 @@ public function addUsedTrait(Fqsen $fqsen): void /** * Returns the Fqsen of the element. */ + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -210,6 +214,7 @@ public function getFqsen(): Fqsen /** * Returns the name of the element. */ + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/Constant.php b/src/phpDocumentor/Reflection/Php/Constant.php index 861957da..3d9bf700 100644 --- a/src/phpDocumentor/Reflection/Php/Constant.php +++ b/src/phpDocumentor/Reflection/Php/Constant.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; @@ -21,6 +22,8 @@ /** * Descriptor representing a constant + * + * @api */ final class Constant implements Element, MetaDataContainerInterface, AttributeContainer { @@ -61,6 +64,7 @@ public function getValue(): string|null /** * Returns the Fqsen of the element. */ + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -69,6 +73,7 @@ public function getFqsen(): Fqsen /** * Returns the name of the element. */ + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/EnumCase.php b/src/phpDocumentor/Reflection/Php/EnumCase.php index 63393a80..1d30fc36 100644 --- a/src/phpDocumentor/Reflection/Php/EnumCase.php +++ b/src/phpDocumentor/Reflection/Php/EnumCase.php @@ -4,12 +4,18 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; +/** + * Represents a case in an Enum. + * + * @api + */ final class EnumCase implements Element, MetaDataContainerInterface, AttributeContainer { use MetadataContainer; @@ -38,11 +44,13 @@ public function __construct( $this->endLocation = $endLocation; } + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; } + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/Enum_.php b/src/phpDocumentor/Reflection/Php/Enum_.php index 30abc5da..511cdc16 100644 --- a/src/phpDocumentor/Reflection/Php/Enum_.php +++ b/src/phpDocumentor/Reflection/Php/Enum_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; @@ -20,6 +21,11 @@ use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; use phpDocumentor\Reflection\Type; +/** + * Descriptor representing an Enum. + * + * @api + */ final class Enum_ implements Element, MetaDataContainerInterface, AttributeContainer { use MetadataContainer; @@ -64,11 +70,13 @@ public function __construct( $this->endLocation = $endLocation; } + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; } + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php b/src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php index 3e655605..95b1a7bd 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php +++ b/src/phpDocumentor/Reflection/Php/Factory/AbstractFactory.php @@ -14,6 +14,7 @@ namespace phpDocumentor\Reflection\Php\Factory; use InvalidArgumentException; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer; @@ -30,8 +31,8 @@ abstract class AbstractFactory implements ProjectFactoryStrategy { /** @param iterable<Reducer> $reducers */ public function __construct( - private readonly DocBlockFactoryInterface $docBlockFactory, - private readonly iterable $reducers = [], + protected readonly DocBlockFactoryInterface $docBlockFactory, + protected readonly iterable $reducers = [], ) { } @@ -40,8 +41,10 @@ public function __construct( * * @param object $object object to check. */ + #[Override] abstract public function matches(ContextStack $context, object $object): bool; + #[Override] public function create(ContextStack $context, object $object, StrategyContainer $strategies): void { if (!$this->matches($context, $object)) { diff --git a/src/phpDocumentor/Reflection/Php/Factory/ClassConstant.php b/src/phpDocumentor/Reflection/Php/Factory/ClassConstant.php index 838b97fe..9c594109 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/ClassConstant.php +++ b/src/phpDocumentor/Reflection/Php/Factory/ClassConstant.php @@ -13,11 +13,13 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\Class_; use phpDocumentor\Reflection\Php\Constant as ConstantElement; use phpDocumentor\Reflection\Php\Enum_; +use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer; use phpDocumentor\Reflection\Php\Interface_; use phpDocumentor\Reflection\Php\StrategyContainer; use phpDocumentor\Reflection\Php\Trait_; @@ -34,11 +36,16 @@ */ final class ClassConstant extends AbstractFactory { - public function __construct(DocBlockFactoryInterface $blockFactory, private readonly PrettyPrinter $valueConverter) - { - parent::__construct($blockFactory); + /** @param iterable<Reducer> $reducers */ + public function __construct( + DocBlockFactoryInterface $blockFactory, + private readonly PrettyPrinter $valueConverter, + iterable $reducers = [], + ) { + parent::__construct($blockFactory, $reducers); } + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof ClassConst; @@ -54,6 +61,7 @@ public function matches(ContextStack $context, object $object): bool * @param ClassConst $object object to convert to an Element * @param StrategyContainer $strategies used to convert nested objects. */ + #[Override] protected function doCreate( ContextStack $context, object $object, @@ -73,7 +81,7 @@ protected function doCreate( $constants = new ClassConstantIterator($object); foreach ($constants as $const) { - $constantContainer->addConstant(new ConstantElement( + $constant = new ConstantElement( $const->getFqsen(), $this->createDocBlock($const->getDocComment(), $context->getTypeContext()), $const->getValue() !== null ? $this->valueConverter->prettyPrintExpr($const->getValue()) : null, @@ -81,7 +89,17 @@ protected function doCreate( new Location($const->getEndLine()), $this->buildVisibility($const), $const->isFinal(), - )); + ); + + foreach ($this->reducers as $reducer) { + $constant = $reducer->reduce($context, $const, $strategies, $constant); + } + + if ($constant === null) { + continue; + } + + $constantContainer->addConstant($constant); } return null; diff --git a/src/phpDocumentor/Reflection/Php/Factory/ClassConstantIterator.php b/src/phpDocumentor/Reflection/Php/Factory/ClassConstantIterator.php index d365230b..93e1f23c 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/ClassConstantIterator.php +++ b/src/phpDocumentor/Reflection/Php/Factory/ClassConstantIterator.php @@ -14,6 +14,7 @@ namespace phpDocumentor\Reflection\Php\Factory; use Iterator; +use Override; use phpDocumentor\Reflection\Fqsen; use PhpParser\Comment\Doc; use PhpParser\Node\Expr; @@ -123,30 +124,35 @@ public function isFinal(): bool } /** @link http://php.net/manual/en/iterator.current.php */ + #[Override] public function current(): self { return $this; } /** @link http://php.net/manual/en/iterator.next.php */ + #[Override] public function next(): void { ++$this->index; } /** @link http://php.net/manual/en/iterator.key.php */ + #[Override] public function key(): int|null { return $this->index; } /** @link http://php.net/manual/en/iterator.valid.php */ + #[Override] public function valid(): bool { return isset($this->classConstants->consts[$this->index]); } /** @link http://php.net/manual/en/iterator.rewind.php */ + #[Override] public function rewind(): void { $this->index = 0; diff --git a/src/phpDocumentor/Reflection/Php/Factory/Class_.php b/src/phpDocumentor/Reflection/Php/Factory/Class_.php index 531d7590..9c0f825e 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Class_.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Class_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\Class_ as ClassElement; @@ -27,6 +28,7 @@ */ final class Class_ extends AbstractFactory { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof ClassNode; @@ -41,6 +43,7 @@ public function matches(ContextStack $context, object $object): bool * @param ContextStack $context of the created object * @param ClassNode $object */ + #[Override] protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): object|null { $docBlock = $this->createDocBlock($object->getDocComment(), $context->getTypeContext()); @@ -48,7 +51,7 @@ protected function doCreate(ContextStack $context, object $object, StrategyConta $classElement = new ClassElement( $object->getAttribute('fqsen'), $docBlock, - $object->extends ? new Fqsen('\\' . $object->extends) : null, + isset($object->extends) ? new Fqsen('\\' . $object->extends) : null, $object->isAbstract(), $object->isFinal(), new Location($object->getLine()), diff --git a/src/phpDocumentor/Reflection/Php/Factory/ConstructorPromotion.php b/src/phpDocumentor/Reflection/Php/Factory/ConstructorPromotion.php index db055441..ef8754e8 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/ConstructorPromotion.php +++ b/src/phpDocumentor/Reflection/Php/Factory/ConstructorPromotion.php @@ -5,31 +5,34 @@ namespace phpDocumentor\Reflection\Php\Factory; use OutOfBoundsException; +use Override; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\Class_ as ClassElement; +use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer; use phpDocumentor\Reflection\Php\ProjectFactoryStrategy; -use phpDocumentor\Reflection\Php\Property; use phpDocumentor\Reflection\Php\StrategyContainer; -use phpDocumentor\Reflection\Php\Visibility; +use PhpParser\Modifiers; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Param; -use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; use Webmozart\Assert\Assert; final class ConstructorPromotion extends AbstractFactory { + /** @param iterable<Reducer> $reducers */ public function __construct( private readonly ProjectFactoryStrategy $methodStrategy, DocBlockFactoryInterface $docBlockFactory, private readonly PrettyPrinter $valueConverter, + iterable $reducers = [], ) { - parent::__construct($docBlockFactory); + parent::__construct($docBlockFactory, $reducers); } + #[Override] public function matches(ContextStack $context, object $object): bool { try { @@ -42,6 +45,7 @@ public function matches(ContextStack $context, object $object): bool } /** @param ClassMethod $object */ + #[Override] protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): object|null { $this->methodStrategy->create($context, $object, $strategies); @@ -51,48 +55,48 @@ protected function doCreate(ContextStack $context, object $object, StrategyConta continue; } - $this->promoteParameterToProperty($context, $param); + $this->promoteParameterToProperty($context, $strategies, $param); } return $context->peek(); } - private function promoteParameterToProperty(ContextStack $context, Param $param): void + private function promoteParameterToProperty(ContextStack $context, StrategyContainer $strategies, Param $param): void { $methodContainer = $context->peek(); Assert::isInstanceOf($methodContainer, ClassElement::class); Assert::isInstanceOf($param->var, Variable::class); - $property = new Property( - new Fqsen($methodContainer->getFqsen() . '::$' . (string) $param->var->name), - $this->buildPropertyVisibilty($param->flags), - $this->createDocBlock($param->getDocComment(), $context->getTypeContext()), - $param->default !== null ? $this->valueConverter->prettyPrintExpr($param->default) : null, - false, - new Location($param->getLine()), - new Location($param->getEndLine()), - (new Type())->fromPhpParser($param->type), - $this->readOnly($param->flags), - ); - - $methodContainer->addProperty($property); - } - - private function buildPropertyVisibilty(int $flags): Visibility - { - if ((bool) ($flags & Class_::MODIFIER_PRIVATE) === true) { - return new Visibility(Visibility::PRIVATE_); + $property = PropertyBuilder::create( + $this->valueConverter, + $this->docBlockFactory, + $strategies, + $this->reducers, + )->fqsen(new Fqsen($methodContainer->getFqsen() . '::$' . (string) $param->var->name)) + ->visibility($param) + ->type($param->type) + ->docblock($param->getDocComment()) + ->default($param->default) + ->readOnly($this->readOnly($param->flags)) + ->static(false) + ->startLocation(new Location($param->getLine(), $param->getStartFilePos())) + ->endLocation(new Location($param->getEndLine(), $param->getEndFilePos())) + ->hooks($param->hooks ?? []) + ->build($context); + + foreach ($this->reducers as $reducer) { + $property = $reducer->reduce($context, $param, $strategies, $property); } - if ((bool) ($flags & Class_::MODIFIER_PROTECTED) === true) { - return new Visibility(Visibility::PROTECTED_); + if ($property === null) { + return; } - return new Visibility(Visibility::PUBLIC_); + $methodContainer->addProperty($property); } private function readOnly(int $flags): bool { - return (bool) ($flags & Class_::MODIFIER_READONLY) === true; + return (bool) ($flags & Modifiers::READONLY) === true; } } diff --git a/src/phpDocumentor/Reflection/Php/Factory/ContextStack.php b/src/phpDocumentor/Reflection/Php/Factory/ContextStack.php index d4c17af7..1d5878d4 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/ContextStack.php +++ b/src/phpDocumentor/Reflection/Php/Factory/ContextStack.php @@ -8,6 +8,7 @@ use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Php\File as FileElement; use phpDocumentor\Reflection\Php\Project; +use phpDocumentor\Reflection\Php\PropertyHook; use phpDocumentor\Reflection\Types\Context as TypeContext; use function array_reverse; @@ -15,14 +16,14 @@ final class ContextStack { - /** @var (Element|FileElement)[] */ + /** @var (Element|FileElement|PropertyHook)[] */ private array $elements = []; public function __construct(private readonly Project $project, private readonly TypeContext|null $typeContext = null) { } - /** @param (Element|FileElement)[] $elements */ + /** @param (Element|FileElement|PropertyHook)[] $elements */ private static function createFromSelf(Project $project, TypeContext|null $typeContext, array $elements): self { $self = new self($project, $typeContext); @@ -31,7 +32,7 @@ private static function createFromSelf(Project $project, TypeContext|null $typeC return $self; } - public function push(Element|FileElement $element): self + public function push(Element|FileElement|PropertyHook $element): self { $elements = $this->elements; $elements[] = $element; @@ -54,7 +55,7 @@ public function getProject(): Project return $this->project; } - public function peek(): Element|FileElement + public function peek(): Element|FileElement|PropertyHook { $element = end($this->elements); if ($element === false) { @@ -72,7 +73,7 @@ public function peek(): Element|FileElement * * @param class-string $type */ - public function search(string $type): Element|FileElement|null + public function search(string $type): Element|FileElement|PropertyHook|null { $reverseElements = array_reverse($this->elements); foreach ($reverseElements as $element) { diff --git a/src/phpDocumentor/Reflection/Php/Factory/Define.php b/src/phpDocumentor/Reflection/Php/Factory/Define.php index 1d8b8692..28a4fe36 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Define.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Define.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; @@ -52,6 +53,7 @@ public function __construct( parent::__construct($docBlockFactory); } + #[Override] public function matches(ContextStack $context, object $object): bool { if (!$object instanceof Expression) { @@ -79,6 +81,7 @@ public function matches(ContextStack $context, object $object): bool * @param Expression $object object to convert to an Element * @param StrategyContainer $strategies used to convert nested objects. */ + #[Override] protected function doCreate( ContextStack $context, object $object, diff --git a/src/phpDocumentor/Reflection/Php/Factory/EnumCase.php b/src/phpDocumentor/Reflection/Php/Factory/EnumCase.php index bf05ae34..14338d94 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/EnumCase.php +++ b/src/phpDocumentor/Reflection/Php/Factory/EnumCase.php @@ -4,10 +4,12 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\Enum_ as EnumElement; use phpDocumentor\Reflection\Php\EnumCase as EnumCaseElement; +use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer; use phpDocumentor\Reflection\Php\StrategyContainer; use PhpParser\Node\Stmt\EnumCase as EnumCaseNode; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; @@ -16,17 +18,23 @@ final class EnumCase extends AbstractFactory { - public function __construct(DocBlockFactoryInterface $docBlockFactory, private readonly PrettyPrinter $prettyPrinter) - { - parent::__construct($docBlockFactory); + /** @param iterable<Reducer> $reducers */ + public function __construct( + DocBlockFactoryInterface $docBlockFactory, + private readonly PrettyPrinter $prettyPrinter, + iterable $reducers = [], + ) { + parent::__construct($docBlockFactory, $reducers); } + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof EnumCaseNode; } /** @param EnumCaseNode $object */ + #[Override] protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): object|null { $docBlock = $this->createDocBlock($object->getDocComment(), $context->getTypeContext()); diff --git a/src/phpDocumentor/Reflection/Php/Factory/Enum_.php b/src/phpDocumentor/Reflection/Php/Factory/Enum_.php index 9abccfa7..4a8d7b46 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Enum_.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Enum_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\File as FileElement; @@ -23,12 +24,14 @@ final class Enum_ extends AbstractFactory { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof EnumNode; } /** @param EnumNode $object */ + #[Override] protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): object|null { $docBlock = $this->createDocBlock($object->getDocComment(), $context->getTypeContext()); diff --git a/src/phpDocumentor/Reflection/Php/Factory/File.php b/src/phpDocumentor/Reflection/Php/Factory/File.php index f7d4d8fa..46fba96d 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/File.php +++ b/src/phpDocumentor/Reflection/Php/Factory/File.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\DocBlock as DocBlockInstance; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\File as FileSystemFile; @@ -67,6 +68,7 @@ public function __construct( $this->middlewareChain = ChainFactory::createExecutionChain($middleware, $lastCallable); } + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof FileSystemFile; @@ -82,6 +84,7 @@ public function matches(ContextStack $context, object $object): bool * @param FileSystemFile $object path to the file to convert to an File object. * @param StrategyContainer $strategies used to convert nested objects. */ + #[Override] protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): object|null { $command = new CreateCommand($context, $object, $strategies); diff --git a/src/phpDocumentor/Reflection/Php/Factory/Function_.php b/src/phpDocumentor/Reflection/Php/Factory/Function_.php index 191f1e05..fc771552 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Function_.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Function_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\File as FileElement; use phpDocumentor\Reflection\Php\Function_ as FunctionDescriptor; @@ -21,8 +22,6 @@ use PhpParser\Node\Stmt\Function_ as FunctionNode; use Webmozart\Assert\Assert; -use function is_array; - /** * Strategy to convert Function_ to FunctionDescriptor * @@ -31,6 +30,7 @@ */ final class Function_ extends AbstractFactory implements ProjectFactoryStrategy { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof FunctionNode && $context->peek() instanceof FileElement; @@ -42,6 +42,7 @@ public function matches(ContextStack $context, object $object): bool * @param ContextStack $context of the created object * @param FunctionNode $object */ + #[Override] protected function doCreate( ContextStack $context, object $object, @@ -61,10 +62,6 @@ protected function doCreate( $file->addFunction($function); - if (!is_array($object->stmts)) { - return $function; - } - $thisContext = $context->push($function); foreach ($object->stmts as $stmt) { $strategy = $strategies->findMatching($thisContext, $stmt); diff --git a/src/phpDocumentor/Reflection/Php/Factory/GlobalConstant.php b/src/phpDocumentor/Reflection/Php/Factory/GlobalConstant.php index ae352e11..fc1e04ac 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/GlobalConstant.php +++ b/src/phpDocumentor/Reflection/Php/Factory/GlobalConstant.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\Constant as ConstantElement; @@ -38,6 +39,7 @@ public function __construct(DocBlockFactoryInterface $docBlockFactory, private r parent::__construct($docBlockFactory); } + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof Const_; @@ -53,6 +55,7 @@ public function matches(ContextStack $context, object $object): bool * @param Const_ $object object to convert to an Element * @param StrategyContainer $strategies used to convert nested objects. */ + #[Override] protected function doCreate( ContextStack $context, object $object, diff --git a/src/phpDocumentor/Reflection/Php/Factory/GlobalConstantIterator.php b/src/phpDocumentor/Reflection/Php/Factory/GlobalConstantIterator.php index 11f5a6db..ccbf11c8 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/GlobalConstantIterator.php +++ b/src/phpDocumentor/Reflection/Php/Factory/GlobalConstantIterator.php @@ -14,6 +14,7 @@ namespace phpDocumentor\Reflection\Php\Factory; use Iterator; +use Override; use phpDocumentor\Reflection\Fqsen; use PhpParser\Comment\Doc; use PhpParser\Node\Expr; @@ -89,30 +90,35 @@ public function getValue(): Expr } /** @link http://php.net/manual/en/iterator.current.php */ + #[Override] public function current(): self { return $this; } /** @link http://php.net/manual/en/iterator.next.php */ + #[Override] public function next(): void { ++$this->index; } /** @link http://php.net/manual/en/iterator.key.php */ + #[Override] public function key(): int|null { return $this->index; } /** @link http://php.net/manual/en/iterator.valid.php */ + #[Override] public function valid(): bool { return isset($this->constant->consts[$this->index]); } /** @link http://php.net/manual/en/iterator.rewind.php */ + #[Override] public function rewind(): void { $this->index = 0; diff --git a/src/phpDocumentor/Reflection/Php/Factory/IfStatement.php b/src/phpDocumentor/Reflection/Php/Factory/IfStatement.php index c108cc08..1ce43476 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/IfStatement.php +++ b/src/phpDocumentor/Reflection/Php/Factory/IfStatement.php @@ -4,6 +4,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\Php\ProjectFactoryStrategy; use phpDocumentor\Reflection\Php\StrategyContainer; use PhpParser\Node\Stmt\Else_; @@ -11,12 +12,14 @@ class IfStatement implements ProjectFactoryStrategy { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof If_; } /** @param If_ $object */ + #[Override] public function create(ContextStack $context, object $object, StrategyContainer $strategies): void { foreach ($object->stmts as $stmt) { diff --git a/src/phpDocumentor/Reflection/Php/Factory/Interface_.php b/src/phpDocumentor/Reflection/Php/Factory/Interface_.php index 352b552a..bc4fbc0a 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Interface_.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Interface_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\File as FileElement; @@ -27,6 +28,7 @@ */ final class Interface_ extends AbstractFactory implements ProjectFactoryStrategy { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof InterfaceNode; @@ -42,6 +44,7 @@ public function matches(ContextStack $context, object $object): bool * @param InterfaceNode $object object to convert to an Element * @param StrategyContainer $strategies used to convert nested objects. */ + #[Override] protected function doCreate( ContextStack $context, object $object, diff --git a/src/phpDocumentor/Reflection/Php/Factory/Method.php b/src/phpDocumentor/Reflection/Php/Factory/Method.php index fbef4c70..2ffe0a8b 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Method.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Method.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\Class_; use phpDocumentor\Reflection\Php\Enum_; @@ -31,6 +32,7 @@ */ final class Method extends AbstractFactory { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof ClassMethod; @@ -42,6 +44,7 @@ public function matches(ContextStack $context, object $object): bool * @param ClassMethod $object object to convert to an MethodDescriptor * @param ContextStack $context of the created object */ + #[Override] protected function doCreate( ContextStack $context, object $object, diff --git a/src/phpDocumentor/Reflection/Php/Factory/Namespace_.php b/src/phpDocumentor/Reflection/Php/Factory/Namespace_.php index 7a15d4c5..788b5b42 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Namespace_.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Namespace_.php @@ -5,6 +5,7 @@ namespace phpDocumentor\Reflection\Php\Factory; use InvalidArgumentException; +use Override; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Php\File as FileElement; use phpDocumentor\Reflection\Php\ProjectFactoryStrategy; @@ -18,12 +19,14 @@ class Namespace_ implements ProjectFactoryStrategy { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof NamespaceNode; } /** @param NamespaceNode $object */ + #[Override] public function create(ContextStack $context, object $object, StrategyContainer $strategies): void { if (!$this->matches($context, $object)) { diff --git a/src/phpDocumentor/Reflection/Php/Factory/Noop.php b/src/phpDocumentor/Reflection/Php/Factory/Noop.php index bbe4f98e..c59d2cb6 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Noop.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Noop.php @@ -4,16 +4,19 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\Php\ProjectFactoryStrategy; use phpDocumentor\Reflection\Php\StrategyContainer; class Noop implements ProjectFactoryStrategy { + #[Override] public function matches(ContextStack $context, object $object): bool { return true; } + #[Override] public function create(ContextStack $context, object $object, StrategyContainer $strategies): void { } diff --git a/src/phpDocumentor/Reflection/Php/Factory/Property.php b/src/phpDocumentor/Reflection/Php/Factory/Property.php index 1682f5f9..4c146677 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Property.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Property.php @@ -13,13 +13,14 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\DocBlockFactoryInterface; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\Class_; +use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer; use phpDocumentor\Reflection\Php\Property as PropertyDescriptor; use phpDocumentor\Reflection\Php\StrategyContainer; use phpDocumentor\Reflection\Php\Trait_; -use phpDocumentor\Reflection\Php\Visibility; use PhpParser\Node\Stmt\Property as PropertyNode; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; use Webmozart\Assert\Assert; @@ -32,14 +33,16 @@ */ final class Property extends AbstractFactory { - /** - * Initializes the object. - */ - public function __construct(DocBlockFactoryInterface $docBlockFactory, private readonly PrettyPrinter $valueConverter) - { - parent::__construct($docBlockFactory); + /** @param iterable<Reducer> $reducers */ + public function __construct( + DocBlockFactoryInterface $docBlockFactory, + private readonly PrettyPrinter $valueConverter, + iterable $reducers = [], + ) { + parent::__construct($docBlockFactory, $reducers); } + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof PropertyNode; @@ -54,6 +57,7 @@ public function matches(ContextStack $context, object $object): bool * @param ContextStack $context used to convert nested objects. * @param PropertyNode $object */ + #[Override] protected function doCreate( ContextStack $context, object $object, @@ -70,42 +74,35 @@ protected function doCreate( $iterator = new PropertyIterator($object); foreach ($iterator as $stmt) { - $default = null; - if ($iterator->getDefault() !== null) { - $default = $this->valueConverter->prettyPrintExpr($iterator->getDefault()); - } + $property = PropertyBuilder::create( + $this->valueConverter, + $this->docBlockFactory, + $strategies, + $this->reducers, + ) + ->fqsen($stmt->getFqsen()) + ->visibility($stmt) + ->type($stmt->getType()) + ->docblock($stmt->getDocComment()) + ->default($iterator->getDefault()) + ->static($stmt->isStatic()) + ->startLocation(new Location($stmt->getLine())) + ->endLocation(new Location($stmt->getEndLine())) + ->readOnly($stmt->isReadonly()) + ->hooks($stmt->getHooks()) + ->build($context); - $propertyContainer->addProperty( - new PropertyDescriptor( - $stmt->getFqsen(), - $this->buildVisibility($stmt), - $this->createDocBlock($stmt->getDocComment(), $context->getTypeContext()), - $default, - $stmt->isStatic(), - new Location($stmt->getLine()), - new Location($stmt->getEndLine()), - (new Type())->fromPhpParser($stmt->getType()), - $stmt->isReadonly(), - ), - ); - } - - return null; - } + foreach ($this->reducers as $reducer) { + $property = $reducer->reduce($context, $object, $strategies, $property); + } - /** - * Converts the visibility of the property to a valid Visibility object. - */ - private function buildVisibility(PropertyIterator $node): Visibility - { - if ($node->isPrivate()) { - return new Visibility(Visibility::PRIVATE_); - } + if ($property === null) { + continue; + } - if ($node->isProtected()) { - return new Visibility(Visibility::PROTECTED_); + $propertyContainer->addProperty($property); } - return new Visibility(Visibility::PUBLIC_); + return null; } } diff --git a/src/phpDocumentor/Reflection/Php/Factory/PropertyBuilder.php b/src/phpDocumentor/Reflection/Php/Factory/PropertyBuilder.php new file mode 100644 index 00000000..db1a2776 --- /dev/null +++ b/src/phpDocumentor/Reflection/Php/Factory/PropertyBuilder.php @@ -0,0 +1,344 @@ +<?php + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\Php\Factory; + +use phpDocumentor\Reflection\DocBlockFactoryInterface; +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\Location; +use phpDocumentor\Reflection\NodeVisitor\FindingVisitor; +use phpDocumentor\Reflection\Php\AsymmetricVisibility; +use phpDocumentor\Reflection\Php\Factory\Reducer\Reducer; +use phpDocumentor\Reflection\Php\Property as PropertyElement; +use phpDocumentor\Reflection\Php\PropertyHook; +use phpDocumentor\Reflection\Php\StrategyContainer; +use phpDocumentor\Reflection\Php\Visibility; +use PhpParser\Comment\Doc; +use PhpParser\Modifiers; +use PhpParser\Node; +use PhpParser\Node\ComplexType; +use PhpParser\Node\Expr; +use PhpParser\Node\Expr\PropertyFetch; +use PhpParser\Node\Expr\Variable; +use PhpParser\Node\Identifier; +use PhpParser\Node\Name; +use PhpParser\Node\Param; +use PhpParser\Node\PropertyHook as PropertyHookNode; +use PhpParser\NodeTraverser; +use PhpParser\PrettyPrinter\Standard as PrettyPrinter; + +use function array_filter; +use function array_map; +use function count; +use function method_exists; + +/** + * This class is responsible for building a property element from a PhpParser node. + * + * @internal + */ +final class PropertyBuilder +{ + private Fqsen $fqsen; + private Visibility $visibility; + private bool $readOnly = false; + private Identifier|Name|ComplexType|null $type; + private Doc|null $docblock = null; + + private Expr|null $default = null; + private bool $static = false; + private Location $startLocation; + private Location $endLocation; + + /** @var PropertyHookNode[] */ + private array $hooks = []; + + /** @param iterable<Reducer> $reducers */ + private function __construct( + private PrettyPrinter $valueConverter, + private DocBlockFactoryInterface $docBlockFactory, + private StrategyContainer $strategies, + private iterable $reducers, + ) { + $this->visibility = new Visibility(Visibility::PUBLIC_); + } + + /** @param iterable<Reducer> $reducers */ + public static function create( + PrettyPrinter $valueConverter, + DocBlockFactoryInterface $docBlockFactory, + StrategyContainer $strategies, + iterable $reducers, + ): self { + return new self($valueConverter, $docBlockFactory, $strategies, $reducers); + } + + public function fqsen(Fqsen $fqsen): self + { + $this->fqsen = $fqsen; + + return $this; + } + + public function visibility(Param|PropertyIterator $node): self + { + $this->visibility = $this->buildVisibility($node); + + return $this; + } + + public function type(Identifier|Name|ComplexType|null $type): self + { + $this->type = $type; + + return $this; + } + + public function readOnly(bool $readOnly): self + { + $this->readOnly = $readOnly; + + return $this; + } + + public function docblock(Doc|null $docblock): self + { + $this->docblock = $docblock; + + return $this; + } + + public function default(Expr|null $default): self + { + $this->default = $default; + + return $this; + } + + public function static(bool $static): self + { + $this->static = $static; + + return $this; + } + + public function startLocation(Location $startLocation): self + { + $this->startLocation = $startLocation; + + return $this; + } + + public function endLocation(Location $endLocation): self + { + $this->endLocation = $endLocation; + + return $this; + } + + /** @param PropertyHookNode[] $hooks */ + public function hooks(array $hooks): self + { + $this->hooks = $hooks; + + return $this; + } + + public function build(ContextStack $context): PropertyElement + { + $hooks = array_filter(array_map( + fn (PropertyHookNode $hook) => $this->buildHook($hook, $context, $this->visibility), + $this->hooks, + )); + + // Check if this is a virtual property by examining all hooks + $isVirtual = $this->isVirtualProperty($this->hooks, $this->fqsen->getName()); + + return new PropertyElement( + $this->fqsen, + $this->visibility, + $this->docblock !== null ? $this->docBlockFactory->create($this->docblock->getText(), $context->getTypeContext()) : null, + $this->default !== null ? $this->valueConverter->prettyPrintExpr($this->default) : null, + $this->static, + $this->startLocation, + $this->endLocation, + (new Type())->fromPhpParser($this->type), + $this->readOnly, + $hooks, + $isVirtual, + ); + } + + /** + * Returns true when current property has asymmetric accessors. + * + * This method will always return false when your phpparser version is < 5.2 + */ + private function isAsymmetric(Param|PropertyIterator $node): bool + { + if (method_exists($node, 'isPrivateSet') === false) { + return false; + } + + return $node->isPublicSet() || $node->isProtectedSet() || $node->isPrivateSet(); + } + + private function buildVisibility(Param|PropertyIterator $node): Visibility + { + if ($this->isAsymmetric($node) === false) { + return $this->buildReadVisibility($node); + } + + $readVisibility = $this->buildReadVisibility($node); + $writeVisibility = $this->buildWriteVisibility($node); + + if ((string) $writeVisibility === (string) $readVisibility) { + return $readVisibility; + } + + return new AsymmetricVisibility( + $readVisibility, + $writeVisibility, + ); + } + + private function buildReadVisibility(Param|PropertyIterator $node): Visibility + { + if ($node instanceof Param && method_exists($node, 'isPublic') === false) { + return $this->buildVisibilityFromFlags($node->flags); + } + + if ($node->isPrivate()) { + return new Visibility(Visibility::PRIVATE_); + } + + if ($node->isProtected()) { + return new Visibility(Visibility::PROTECTED_); + } + + return new Visibility(Visibility::PUBLIC_); + } + + private function buildVisibilityFromFlags(int $flags): Visibility + { + if ((bool) ($flags & Modifiers::PRIVATE) === true) { + return new Visibility(Visibility::PRIVATE_); + } + + if ((bool) ($flags & Modifiers::PROTECTED) === true) { + return new Visibility(Visibility::PROTECTED_); + } + + return new Visibility(Visibility::PUBLIC_); + } + + private function buildWriteVisibility(Param|PropertyIterator $node): Visibility + { + if ($node->isPrivateSet()) { + return new Visibility(Visibility::PRIVATE_); + } + + if ($node->isProtectedSet()) { + return new Visibility(Visibility::PROTECTED_); + } + + return new Visibility(Visibility::PUBLIC_); + } + + private function buildHook(PropertyHookNode $hook, ContextStack $context, Visibility $propertyVisibility): PropertyHook|null + { + $doc = $hook->getDocComment(); + + $result = new PropertyHook( + $hook->name->toString(), + $this->buildHookVisibility($hook->name->toString(), $propertyVisibility), + $doc !== null ? $this->docBlockFactory->create($doc->getText(), $context->getTypeContext()) : null, + $hook->isFinal(), + new Location($hook->getStartLine()), + new Location($hook->getEndLine()), + ); + + foreach ($this->reducers as $reducer) { + $result = $reducer->reduce($context, $hook, $this->strategies, $result); + } + + if ($result === null) { + return $result; + } + + $thisContext = $context->push($result); + foreach ($hook->getStmts() ?? [] as $stmt) { + $strategy = $this->strategies->findMatching($thisContext, $stmt); + $strategy->create($thisContext, $stmt, $this->strategies); + } + + return $result; + } + + /** + * Detects if a property is virtual by checking if any of its hooks reference the property itself. + * + * A virtual property is one where no defined hook references the property itself. + * For example, in the 'get' hook, it doesn't use $this->propertyName. + * + * @param PropertyHookNode[] $hooks The property hooks to check + * @param string $propertyName The name of the property + * + * @return bool True if the property is virtual, false otherwise + */ + private function isVirtualProperty(array $hooks, string $propertyName): bool + { + if (empty($hooks)) { + return false; + } + + foreach ($hooks as $hook) { + $stmts = $hook->getStmts(); + + if ($stmts === null || count($stmts) === 0) { + continue; + } + + $finder = new FindingVisitor( + static function (Node $node) use ($propertyName) { + // Check if the node is a property fetch that references the property + return $node instanceof PropertyFetch && $node->name instanceof Identifier && + $node->name->toString() === $propertyName && + $node->var instanceof Variable && + $node->var->name === 'this'; + }, + ); + + $traverser = new NodeTraverser($finder); + $traverser->traverse($stmts); + + if ($finder->getFoundNode() !== null) { + return false; + } + } + + return true; + } + + /** + * Builds the hook visibility based on the hook name and property visibility. + * + * @param string $hookName The name of the hook ('get' or 'set') + * @param Visibility $propertyVisibility The visibility of the property + * + * @return Visibility The appropriate visibility for the hook + */ + private function buildHookVisibility(string $hookName, Visibility $propertyVisibility): Visibility + { + if ($propertyVisibility instanceof AsymmetricVisibility === false) { + return $propertyVisibility; + } + + return match ($hookName) { + 'get' => $propertyVisibility->getReadVisibility(), + 'set' => $propertyVisibility->getWriteVisibility(), + default => $propertyVisibility, + }; + } +} diff --git a/src/phpDocumentor/Reflection/Php/Factory/PropertyIterator.php b/src/phpDocumentor/Reflection/Php/Factory/PropertyIterator.php index 00b58da6..ea0c5cac 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/PropertyIterator.php +++ b/src/phpDocumentor/Reflection/Php/Factory/PropertyIterator.php @@ -14,14 +14,19 @@ namespace phpDocumentor\Reflection\Php\Factory; use Iterator; +use Override; use phpDocumentor\Reflection\Fqsen; use PhpParser\Comment\Doc; use PhpParser\Node\ComplexType; use PhpParser\Node\Expr; use PhpParser\Node\Identifier; use PhpParser\Node\Name; +use PhpParser\Node\PropertyHook; use PhpParser\Node\Stmt\Property as PropertyNode; +use function method_exists; +use function property_exists; + /** * This class acts like a combination of a PropertyNode and PropertyProperty to * be able to create property descriptors using a normal strategy. @@ -48,6 +53,20 @@ public function isPublic(): bool return $this->property->isPublic(); } + /** + * Returns asymmetric accessor value for current property. + * + * This method will return the same value as {@see self::isPublic()} when your phpparser version is < 5.2 + */ + public function isPublicSet(): bool + { + if ($this->isAsymmetric() === false) { + return $this->isPublic(); + } + + return $this->property->isPublic(); + } + /** * returns true when the current property is protected. */ @@ -56,6 +75,20 @@ public function isProtected(): bool return $this->property->isProtected(); } + /** + * Returns asymetric accessor value for current property. + * + * This method will return the same value as {@see self::isProtected()} when your phpparser version is < 5.2 + */ + public function isProtectedSet(): bool + { + if ($this->isAsymmetric() === false) { + return $this->isProtected(); + } + + return $this->property->isProtectedSet(); + } + /** * returns true when the current property is private. */ @@ -64,6 +97,34 @@ public function isPrivate(): bool return $this->property->isPrivate(); } + /** + * Returns asymetric accessor value for current property. + * + * This method will return the same value as {@see self::isPrivate()} when your phpparser version is < 5.2 + */ + public function isPrivateSet(): bool + { + if ($this->isAsymmetric() === false) { + return $this->isPrivate(); + } + + return $this->property->isPrivateSet(); + } + + /** + * Returns true when current property has asymetric accessors. + * + * This method will always return false when your phpparser version is < 5.2 + */ + public function isAsymmetric(): bool + { + if (method_exists($this->property, 'isPrivateSet') === false) { + return false; + } + + return $this->property->isPublicSet() || $this->property->isProtectedSet() || $this->property->isPrivateSet(); + } + /** * returns true when the current property is static. */ @@ -130,7 +191,7 @@ public function getName(): string /** * returns the default value of the current property. */ - public function getDefault(): string|Expr|null + public function getDefault(): Expr|null { return $this->property->props[$this->index]->default; } @@ -143,31 +204,46 @@ public function getFqsen(): Fqsen return $this->property->props[$this->index]->getAttribute('fqsen'); } + /** @return PropertyHook[] */ + public function getHooks(): array + { + if (property_exists($this->property, 'hooks') === false) { + return []; + } + + return $this->property->hooks; + } + /** @link http://php.net/manual/en/iterator.current.php */ + #[Override] public function current(): self { return $this; } /** @link http://php.net/manual/en/iterator.next.php */ + #[Override] public function next(): void { ++$this->index; } /** @link http://php.net/manual/en/iterator.key.php */ + #[Override] public function key(): int|null { return $this->index; } /** @link http://php.net/manual/en/iterator.valid.php */ + #[Override] public function valid(): bool { return isset($this->property->props[$this->index]); } /** @link http://php.net/manual/en/iterator.rewind.php */ + #[Override] public function rewind(): void { $this->index = 0; diff --git a/src/phpDocumentor/Reflection/Php/Factory/Reducer/Attribute.php b/src/phpDocumentor/Reflection/Php/Factory/Reducer/Attribute.php index 41984f0a..ed448610 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Reducer/Attribute.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Reducer/Attribute.php @@ -5,6 +5,7 @@ namespace phpDocumentor\Reflection\Php\Factory\Reducer; use InvalidArgumentException; +use Override; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Php\AttributeContainer; use phpDocumentor\Reflection\Php\CallArgument; @@ -28,6 +29,7 @@ public function __construct() $this->printer = new Standard(); } + #[Override] public function reduce( ContextStack $context, object $object, diff --git a/src/phpDocumentor/Reflection/Php/Factory/Reducer/Parameter.php b/src/phpDocumentor/Reflection/Php/Factory/Reducer/Parameter.php index b9eb81a0..074defc1 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Reducer/Parameter.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Reducer/Parameter.php @@ -4,11 +4,13 @@ namespace phpDocumentor\Reflection\Php\Factory\Reducer; +use Override; use phpDocumentor\Reflection\Php\Argument as ArgumentDescriptor; use phpDocumentor\Reflection\Php\Factory\ContextStack; use phpDocumentor\Reflection\Php\Factory\Type; use phpDocumentor\Reflection\Php\Function_; use phpDocumentor\Reflection\Php\Method; +use phpDocumentor\Reflection\Php\PropertyHook; use phpDocumentor\Reflection\Php\StrategyContainer; use PhpParser\Node\Expr\Variable; use PhpParser\Node\FunctionLike; @@ -23,6 +25,7 @@ public function __construct(private readonly PrettyPrinter $valueConverter) { } + #[Override] public function reduce( ContextStack $context, object $object, @@ -33,7 +36,7 @@ public function reduce( return $carry; } - if ($carry instanceof Method === false && $carry instanceof Function_ === false) { + if ($carry instanceof Method === false && $carry instanceof Function_ === false && $carry instanceof PropertyHook === false) { return null; } diff --git a/src/phpDocumentor/Reflection/Php/Factory/Reducer/Reducer.php b/src/phpDocumentor/Reflection/Php/Factory/Reducer/Reducer.php index aa8321e0..a1e10a10 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Reducer/Reducer.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Reducer/Reducer.php @@ -9,6 +9,13 @@ interface Reducer { + /** + * @param TCarry|null $carry + * + * @return TCarry|null + * + * @template TCarry of object + */ public function reduce( ContextStack $context, object $object, diff --git a/src/phpDocumentor/Reflection/Php/Factory/TraitUse.php b/src/phpDocumentor/Reflection/Php/Factory/TraitUse.php index 9881d286..6ac062e9 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/TraitUse.php +++ b/src/phpDocumentor/Reflection/Php/Factory/TraitUse.php @@ -5,6 +5,7 @@ namespace phpDocumentor\Reflection\Php\Factory; use InvalidArgumentException; +use Override; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Php\Class_; use phpDocumentor\Reflection\Php\Enum_; @@ -15,6 +16,7 @@ final class TraitUse implements ProjectFactoryStrategy { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof TraitUseNode; @@ -24,6 +26,7 @@ public function matches(ContextStack $context, object $object): bool * @param ContextStack $context of the created object * @param TraitUseNode $object */ + #[Override] public function create(ContextStack $context, object $object, StrategyContainer $strategies): void { if ($this->matches($context, $object) === false) { diff --git a/src/phpDocumentor/Reflection/Php/Factory/Trait_.php b/src/phpDocumentor/Reflection/Php/Factory/Trait_.php index 74624327..41245877 100644 --- a/src/phpDocumentor/Reflection/Php/Factory/Trait_.php +++ b/src/phpDocumentor/Reflection/Php/Factory/Trait_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php\Factory; +use Override; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Php\File as FileElement; use phpDocumentor\Reflection\Php\StrategyContainer; @@ -22,6 +23,7 @@ final class Trait_ extends AbstractFactory { + #[Override] public function matches(ContextStack $context, object $object): bool { return $object instanceof TraitNode; @@ -36,6 +38,7 @@ public function matches(ContextStack $context, object $object): bool * @param ContextStack $context used to convert nested objects. * @param TraitNode $object */ + #[Override] protected function doCreate(ContextStack $context, object $object, StrategyContainer $strategies): object|null { $trait = new TraitElement( diff --git a/src/phpDocumentor/Reflection/Php/File.php b/src/phpDocumentor/Reflection/Php/File.php index 9ef2702c..bd9cc2ae 100644 --- a/src/phpDocumentor/Reflection/Php/File.php +++ b/src/phpDocumentor/Reflection/Php/File.php @@ -21,6 +21,8 @@ /** * Represents a file in the project. + * + * @api */ final class File implements MetaDataContainerInterface { diff --git a/src/phpDocumentor/Reflection/Php/Function_.php b/src/phpDocumentor/Reflection/Php/Function_.php index 21bca78d..5b5034ea 100644 --- a/src/phpDocumentor/Reflection/Php/Function_.php +++ b/src/phpDocumentor/Reflection/Php/Function_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; @@ -23,6 +24,8 @@ /** * Descriptor representing a function + * + * @api */ // @codingStandardsIgnoreStart final class Function_ implements Element, MetaDataContainerInterface, AttributeContainer @@ -90,6 +93,7 @@ public function addArgument(Argument $argument): void /** * Returns the Fqsen of the element. */ + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -98,6 +102,7 @@ public function getFqsen(): Fqsen /** * Returns the name of the element. */ + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/Interface_.php b/src/phpDocumentor/Reflection/Php/Interface_.php index f05f8ab8..a38ca067 100644 --- a/src/phpDocumentor/Reflection/Php/Interface_.php +++ b/src/phpDocumentor/Reflection/Php/Interface_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; @@ -22,6 +23,8 @@ /** * Descriptor representing an Interface. + * + * @api */ final class Interface_ implements Element, MetaDataContainerInterface, AttributeContainer { @@ -95,6 +98,7 @@ public function addMethod(Method $method): void /** * Returns the Fqsen of the element. */ + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -103,6 +107,7 @@ public function getFqsen(): Fqsen /** * Returns the name of the element. */ + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/Method.php b/src/phpDocumentor/Reflection/Php/Method.php index be206c1e..d0b2774a 100644 --- a/src/phpDocumentor/Reflection/Php/Method.php +++ b/src/phpDocumentor/Reflection/Php/Method.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; @@ -23,6 +24,8 @@ /** * Descriptor representing a Method in a Class, Interface or Trait. + * + * @api */ final class Method implements Element, MetaDataContainerInterface, AttributeContainer { @@ -131,6 +134,7 @@ public function addArgument(Argument $argument): void /** * Returns the Fqsen of the element. */ + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -139,6 +143,7 @@ public function getFqsen(): Fqsen /** * Returns the name of the element. */ + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/Namespace_.php b/src/phpDocumentor/Reflection/Php/Namespace_.php index 97f048e9..0e8900c8 100644 --- a/src/phpDocumentor/Reflection/Php/Namespace_.php +++ b/src/phpDocumentor/Reflection/Php/Namespace_.php @@ -19,6 +19,8 @@ /** * Represents a namespace and its children for a project. + * + * @api */ // @codingStandardsIgnoreStart final class Namespace_ implements Element, MetaDataContainerInterface @@ -156,6 +158,7 @@ public function addTrait(Fqsen $trait): void /** * Returns the Fqsen of the element. */ + #[\Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -164,6 +167,7 @@ public function getFqsen(): Fqsen /** * Returns the name of the element. */ + #[\Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/NodesFactory.php b/src/phpDocumentor/Reflection/Php/NodesFactory.php index 887fe204..cb877df6 100644 --- a/src/phpDocumentor/Reflection/Php/NodesFactory.php +++ b/src/phpDocumentor/Reflection/Php/NodesFactory.php @@ -14,7 +14,6 @@ namespace phpDocumentor\Reflection\Php; use phpDocumentor\Reflection\NodeVisitor\ElementNameResolver; -use PhpParser\Lexer\Emulative; use PhpParser\Node; use PhpParser\NodeTraverser; use PhpParser\NodeTraverserInterface; @@ -46,18 +45,9 @@ final public function __construct(private readonly Parser $parser, private reado * * @return static */ - public static function createInstance(int $kind = ParserFactory::PREFER_PHP7): self + public static function createInstance(int $kind = 1): self { - $lexer = new Emulative([ - 'usedAttributes' => [ - 'comments', - 'startLine', - 'endLine', - 'startFilePos', - 'endFilePos', - ], - ]); - $parser = (new ParserFactory())->create($kind, $lexer); + $parser = (new ParserFactory())->createForNewestSupportedVersion(); $traverser = new NodeTraverser(); $traverser->addVisitor(new NameResolver()); $traverser->addVisitor(new ElementNameResolver()); diff --git a/src/phpDocumentor/Reflection/Php/Project.php b/src/phpDocumentor/Reflection/Php/Project.php index 9a3bc48b..10041035 100644 --- a/src/phpDocumentor/Reflection/Php/Project.php +++ b/src/phpDocumentor/Reflection/Php/Project.php @@ -13,11 +13,14 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Project as ProjectInterface; /** * Represents the entire project with its files, namespaces and indexes. + * + * @api */ final class Project implements ProjectInterface { @@ -45,6 +48,7 @@ public function __construct(private readonly string $name, private Namespace_|nu /** * Returns the name of this project. */ + #[Override] public function getName(): string { return $this->name; diff --git a/src/phpDocumentor/Reflection/Php/ProjectFactory.php b/src/phpDocumentor/Reflection/Php/ProjectFactory.php index 4c03301f..dd461b76 100644 --- a/src/phpDocumentor/Reflection/Php/ProjectFactory.php +++ b/src/phpDocumentor/Reflection/Php/ProjectFactory.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\Exception; use phpDocumentor\Reflection\File as SourceFile; @@ -77,16 +78,16 @@ public static function createInstance(): self new \phpDocumentor\Reflection\Php\Factory\Namespace_(), new Class_($docblockFactory, [$attributeReducer]), new Enum_($docblockFactory, [$attributeReducer]), - new EnumCase($docblockFactory, new PrettyPrinter()), + new EnumCase($docblockFactory, new PrettyPrinter(), [$attributeReducer]), new Define($docblockFactory, new PrettyPrinter()), new GlobalConstant($docblockFactory, new PrettyPrinter()), - new ClassConstant($docblockFactory, new PrettyPrinter()), + new ClassConstant($docblockFactory, new PrettyPrinter(), [$attributeReducer]), new Factory\File($docblockFactory, NodesFactory::createInstance()), new Function_($docblockFactory, [$attributeReducer, $parameterReducer]), - new Interface_($docblockFactory), + new Interface_($docblockFactory, [$attributeReducer]), $methodStrategy, - new Property($docblockFactory, new PrettyPrinter()), - new Trait_($docblockFactory), + new Property($docblockFactory, new PrettyPrinter(), [$attributeReducer, $parameterReducer]), + new Trait_($docblockFactory, [$attributeReducer]), new IfStatement(), new TraitUse(), @@ -94,7 +95,7 @@ public static function createInstance(): self ); $strategies->addStrategy( - new ConstructorPromotion($methodStrategy, $docblockFactory, new PrettyPrinter()), + new ConstructorPromotion($methodStrategy, $docblockFactory, new PrettyPrinter(), [$attributeReducer, $parameterReducer]), 1100, ); $strategies->addStrategy(new Noop(), -PHP_INT_MAX); @@ -116,6 +117,7 @@ public function addStrategy( * * @throws Exception When no matching strategy was found. */ + #[Override] public function create(string $name, array $files): ProjectInterface { $contextStack = new ContextStack(new Project($name), null); diff --git a/src/phpDocumentor/Reflection/Php/ProjectFactoryStrategies.php b/src/phpDocumentor/Reflection/Php/ProjectFactoryStrategies.php index a434e3a3..00c3af7c 100644 --- a/src/phpDocumentor/Reflection/Php/ProjectFactoryStrategies.php +++ b/src/phpDocumentor/Reflection/Php/ProjectFactoryStrategies.php @@ -14,6 +14,7 @@ namespace phpDocumentor\Reflection\Php; use OutOfBoundsException; +use Override; use phpDocumentor\Reflection\Php\Factory\ContextStack; use SplPriorityQueue; @@ -45,6 +46,7 @@ public function __construct(array $strategies) * * @throws OutOfBoundsException When no matching strategy was found. */ + #[Override] public function findMatching(ContextStack $context, mixed $object): ProjectFactoryStrategy { foreach (clone $this->strategies as $strategy) { diff --git a/src/phpDocumentor/Reflection/Php/Property.php b/src/phpDocumentor/Reflection/Php/Property.php index 0013de93..2f72d5f0 100644 --- a/src/phpDocumentor/Reflection/Php/Property.php +++ b/src/phpDocumentor/Reflection/Php/Property.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; @@ -22,6 +23,8 @@ /** * Descriptor representing a property. + * + * @api */ final class Property implements Element, MetaDataContainerInterface, AttributeContainer { @@ -37,7 +40,10 @@ final class Property implements Element, MetaDataContainerInterface, AttributeCo private readonly Location $endLocation; - /** @param Visibility|null $visibility when null is provided a default 'public' is set. */ + /** + * @param Visibility|null $visibility when null is provided a default 'public' is set. + * @param PropertyHook[] $hooks + */ public function __construct( private readonly Fqsen $fqsen, Visibility|null $visibility = null, @@ -48,6 +54,8 @@ public function __construct( Location|null $endLocation = null, private readonly Type|null $type = null, private readonly bool $readOnly = false, + private readonly array $hooks = [], + private readonly bool $virtual = false, ) { $this->visibility = $visibility ?: new Visibility('public'); $this->location = $location ?: new Location(-1); @@ -99,6 +107,7 @@ public function getVisibility(): Visibility|null /** * Returns the Fqsen of the element. */ + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -107,6 +116,7 @@ public function getFqsen(): Fqsen /** * Returns the name of the element. */ + #[Override] public function getName(): string { return $this->fqsen->getName(); @@ -139,4 +149,20 @@ public function isReadOnly(): bool { return $this->readOnly; } + + /** @return PropertyHook[] */ + public function getHooks(): array + { + return $this->hooks; + } + + /** + * Returns true when this property is virtual (not explicitly backed). + * + * A virtual property is one where no defined hook references the property itself. + */ + public function isVirtual(): bool + { + return $this->virtual; + } } diff --git a/src/phpDocumentor/Reflection/Php/PropertyHook.php b/src/phpDocumentor/Reflection/Php/PropertyHook.php new file mode 100644 index 00000000..9def360b --- /dev/null +++ b/src/phpDocumentor/Reflection/Php/PropertyHook.php @@ -0,0 +1,95 @@ +<?php + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\Php; + +use phpDocumentor\Reflection\DocBlock; +use phpDocumentor\Reflection\Location; +use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; + +/** @api */ +final class PropertyHook implements AttributeContainer, MetaDataContainerInterface +{ + use MetadataContainer; + use HasAttributes; + + /** @var Argument[] */ + private array $arguments = []; + + private readonly Location $location; + + private readonly Location $endLocation; + + public function __construct( + private readonly string $name, + private readonly Visibility $visibility, + private readonly DocBlock|null $docBlock = null, + private readonly bool $final = false, + Location|null $location = null, + Location|null $endLocation = null, + ) { + $this->location = $location ?? new Location(-1); + $this->endLocation = $endLocation ?? new Location(-1); + } + + /** + * Returns true when this hook is final. Otherwise, returns false. + */ + public function isFinal(): bool + { + return $this->final; + } + + /** + * Returns the Visibility of this hook. + */ + public function getVisibility(): Visibility|null + { + return $this->visibility; + } + + /** + * Returns the arguments of this hook. + * + * @return Argument[] + */ + public function getArguments(): array + { + return $this->arguments; + } + + /** + * Add new argument to this hook. + */ + public function addArgument(Argument $argument): void + { + $this->arguments[] = $argument; + } + + /** + * Returns the name of this hook. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Returns the DocBlock of this method if available. + */ + public function getDocBlock(): DocBlock|null + { + return $this->docBlock; + } + + public function getLocation(): Location + { + return $this->location; + } + + public function getEndLocation(): Location + { + return $this->endLocation; + } +} diff --git a/src/phpDocumentor/Reflection/Php/Trait_.php b/src/phpDocumentor/Reflection/Php/Trait_.php index 91fe3747..0e4d80f9 100644 --- a/src/phpDocumentor/Reflection/Php/Trait_.php +++ b/src/phpDocumentor/Reflection/Php/Trait_.php @@ -13,6 +13,7 @@ namespace phpDocumentor\Reflection\Php; +use Override; use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Fqsen; @@ -21,6 +22,8 @@ /** * Descriptor representing a Trait. + * + * @api */ final class Trait_ implements Element, MetaDataContainerInterface, AttributeContainer { @@ -104,6 +107,7 @@ public function addProperty(Property $property): void /** * Returns the Fqsen of the element. */ + #[Override] public function getFqsen(): Fqsen { return $this->fqsen; @@ -112,6 +116,7 @@ public function getFqsen(): Fqsen /** * Returns the name of the element. */ + #[Override] public function getName(): string { return $this->fqsen->getName(); diff --git a/src/phpDocumentor/Reflection/Php/Visibility.php b/src/phpDocumentor/Reflection/Php/Visibility.php index 6b1e3e4b..59d7c523 100644 --- a/src/phpDocumentor/Reflection/Php/Visibility.php +++ b/src/phpDocumentor/Reflection/Php/Visibility.php @@ -14,6 +14,7 @@ namespace phpDocumentor\Reflection\Php; use InvalidArgumentException; +use Override; use Stringable; use function sprintf; @@ -21,8 +22,10 @@ /** * Value object for visibility values of classes, properties, ect. + * + * @api */ -final class Visibility implements Stringable +class Visibility implements Stringable { /** * constant for protected visibility @@ -63,6 +66,7 @@ public function __construct(string $visibility) /** * Will return a string representation of visibility. */ + #[Override] public function __toString(): string { return $this->visibility; diff --git a/src/phpDocumentor/Reflection/Types/NamespaceNodeToContext.php b/src/phpDocumentor/Reflection/Types/NamespaceNodeToContext.php index f4c78f70..a79a6934 100644 --- a/src/phpDocumentor/Reflection/Types/NamespaceNodeToContext.php +++ b/src/phpDocumentor/Reflection/Types/NamespaceNodeToContext.php @@ -33,15 +33,21 @@ public function __invoke(Namespace_|null $namespace): Context private function aliasesToFullyQualifiedNames(Namespace_ $namespace): array { // flatten(flatten(map(stuff))) - return array_merge([], ...array_merge([], ...array_map(static fn ($use): array => array_map(static function (UseUse $useUse) use ($use): array { - if ($use instanceof GroupUse) { - return [ - (string) $useUse->getAlias() => $use->prefix->toString() . '\\' . $useUse->name->toString(), - ]; - } - - return [(string) $useUse->getAlias() => $useUse->name->toString()]; - }, $use->uses), $this->classAlikeUses($namespace)))); + return array_merge([], ...array_merge([], ...array_map( + static fn ($use): array => array_map( + static function (Node\UseItem|UseUse $useUse) use ($use): array { + if ($use instanceof GroupUse) { + return [ + (string) $useUse->getAlias() => $use->prefix->toString() . '\\' . $useUse->name->toString(), + ]; + } + + return [(string) $useUse->getAlias() => $useUse->name->toString()]; + }, + $use->uses, + ), + $this->classAlikeUses($namespace), + ))); } /** @return Use_[]|GroupUse[] */ @@ -52,7 +58,7 @@ private function classAlikeUses(Namespace_ $namespace): array static fn (Node $node): bool => ( $node instanceof Use_ || $node instanceof GroupUse - ) && in_array($node->type, [Use_::TYPE_UNKNOWN, Use_::TYPE_NORMAL], true) + ) && in_array($node->type, [Use_::TYPE_UNKNOWN, Use_::TYPE_NORMAL], true), ); } } diff --git a/tests/integration/AsymmetricAccessorTest.php b/tests/integration/AsymmetricAccessorTest.php new file mode 100644 index 00000000..ee6dfc4f --- /dev/null +++ b/tests/integration/AsymmetricAccessorTest.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); + +namespace phpDocumentor\Reflection; + +use EliasHaeussler\PHPUnitAttributes\Attribute\RequiresPackage; +use phpDocumentor\Reflection\File\LocalFile; +use phpDocumentor\Reflection\Php\ProjectFactory; +use PHPUnit\Framework\TestCase; + +/** @coversNothing */ +#[RequiresPackage('nikic/php-parser', '>= 5.2')] +final class AsymmetricAccessorTest extends TestCase +{ + public function testAsymmetricAccessor(): void + { + $file = __DIR__ . '/data/PHP84/AsymmetricAccessor.php'; + $projectFactory = ProjectFactory::createInstance(); + $project = $projectFactory->create('My project', [new LocalFile($file)]); + + $class = $project->getFiles()[$file]->getClasses()['\AsymmetricAccessor']; + + self::assertEquals( + 'public', + $class->getProperties()['\AsymmetricAccessor::$pizza']->getVisibility()->getReadVisibility(), + ); + self::assertEquals( + 'private', + $class->getProperties()['\AsymmetricAccessor::$pizza']->getVisibility()->getWriteVisibility(), + ); + } + + public function testAsyncPropertyPromotion(): void + { + $file = __DIR__ . '/data/PHP84/AsymmetricPropertyPromotion.php'; + $projectFactory = ProjectFactory::createInstance(); + $project = $projectFactory->create('My project', [new LocalFile($file)]); + + + $class = $project->getFiles()[$file]->getClasses()['\AsymmetricPropertyPromotion']; + + self::assertEquals( + 'public', + $class->getProperties()['\AsymmetricPropertyPromotion::$pizza']->getVisibility()->getReadVisibility(), + ); + self::assertEquals( + 'protected', + $class->getProperties()['\AsymmetricPropertyPromotion::$pizza']->getVisibility()->getWriteVisibility(), + ); + } +} diff --git a/tests/integration/FileDocblockTest.php b/tests/integration/FileDocblockTest.php index 2ac2c05f..d6fa98d6 100644 --- a/tests/integration/FileDocblockTest.php +++ b/tests/integration/FileDocblockTest.php @@ -6,11 +6,13 @@ use phpDocumentor\Reflection\File\LocalFile; use phpDocumentor\Reflection\Php\ProjectFactory; +use PHPUnit\Framework\Attributes\CoversNothing; use PHPUnit\Framework\TestCase; /** * Integration tests to check the correct working of processing a namespace into a project. */ +#[CoversNothing] final class FileDocblockTest extends TestCase { /** @var ProjectFactory */ @@ -37,7 +39,7 @@ public function testFileDocblock(string $fileName) : void ); } - public function fileProvider() : array + public static function fileProvider() : array { return [ [ __DIR__ . '/data/GlobalFiles/empty.php' ], @@ -48,10 +50,6 @@ public function fileProvider() : array ]; } - /** - * @covers \phpDocumentor\Reflection\Php\Factory\File::create - * @covers \phpDocumentor\Reflection\Php\Factory\File::<private> - */ public function testConditionalFunctionDefine() : void { $fileName = __DIR__ . '/data/GlobalFiles/conditional_function.php'; @@ -66,10 +64,6 @@ public function testConditionalFunctionDefine() : void ); } - /** - * @covers \phpDocumentor\Reflection\Php\Factory\File::create - * @covers \phpDocumentor\Reflection\Php\Factory\File::<private> - */ public function testGlobalNamespacedFunctionDefine() : void { $fileName = __DIR__ . '/data/GlobalFiles/global_namspaced_function.php'; @@ -84,10 +78,6 @@ public function testGlobalNamespacedFunctionDefine() : void ); } - /** - * @covers \phpDocumentor\Reflection\Php\Factory\File::create - * @covers \phpDocumentor\Reflection\Php\Factory\File::<private> - */ public function testFileWithInlineFunction() : void { $fileName = __DIR__ . '/data/GlobalFiles/inline_function.php'; diff --git a/tests/integration/Reflection/Metadata/Hook.php b/tests/integration/Metadata/Hook.php similarity index 100% rename from tests/integration/Reflection/Metadata/Hook.php rename to tests/integration/Metadata/Hook.php diff --git a/tests/integration/Reflection/Metadata/HookStrategy.php b/tests/integration/Metadata/HookStrategy.php similarity index 100% rename from tests/integration/Reflection/Metadata/HookStrategy.php rename to tests/integration/Metadata/HookStrategy.php diff --git a/tests/integration/Reflection/Metadata/example.php b/tests/integration/Metadata/example.php similarity index 100% rename from tests/integration/Reflection/Metadata/example.php rename to tests/integration/Metadata/example.php diff --git a/tests/integration/MetadataTest.php b/tests/integration/MetadataTest.php index a15825b0..e9732105 100644 --- a/tests/integration/MetadataTest.php +++ b/tests/integration/MetadataTest.php @@ -15,7 +15,7 @@ */ final class MetadataTest extends TestCase { - const FILE = __DIR__ . '/Reflection/Metadata/example.php'; + const FILE = __DIR__ . '/Metadata/example.php'; public function testCustomMetadata(): void { diff --git a/tests/integration/PHP8/ConstructorPromotionTest.php b/tests/integration/PHP8/ConstructorPromotionTest.php index d14b435a..46e3b84f 100644 --- a/tests/integration/PHP8/ConstructorPromotionTest.php +++ b/tests/integration/PHP8/ConstructorPromotionTest.php @@ -50,8 +50,8 @@ public function testPropertiesAreCreated() : void $class = $file->getClasses()['\\PHP8\\ConstructorPromotion']; $constructor = $this->expectedContructorMethod(); - $constructor->addArgument(new Argument('name', new String_())); - $constructor->addArgument(new Argument('email', new String_(), '\'test@example.com\'')); + $constructor->addArgument(new Argument('name', new String_(), "'default name'")); + $constructor->addArgument(new Argument('email', new Object_(new Fqsen('\\PHP8\\Email')))); $constructor->addArgument(new Argument('birth_date', new Object_(new Fqsen('\\' . \DateTimeImmutable::class)))); self::assertEquals($constructor, $class->getMethods()['\PHP8\ConstructorPromotion::__construct()']); @@ -87,7 +87,7 @@ private function expectedContructorMethod(): Method false, false, new Location(16, 218), - new Location(27, 522) + new Location(27, 517) ); return $constructor; } @@ -105,10 +105,10 @@ private function expectedNameProperty(): Property ], new Context('PHP8', ['DateTimeImmutable' => 'DateTimeImmutable']) ), - null, + "'default name'", false, - new Location(24), - new Location(24), + new Location(24, 393), + new Location(24, 428), new String_() ); return $name; @@ -120,11 +120,11 @@ private function expectedEmailProperty(): Property new Fqsen('\PHP8\ConstructorPromotion::$email'), new Visibility(Visibility::PROTECTED_), null, - '\'test@example.com\'', + null, false, - new Location(25), - new Location(25), - new String_() + new Location(25, 439), + new Location(25, 460), + new Object_(new Fqsen('\\PHP8\\Email')) ); return $email; } @@ -137,8 +137,8 @@ private function expectedBirthDateProperty(): Property null, null, false, - new Location(26), - new Location(26), + new Location(26, 471), + new Location(26, 507), new Object_(new Fqsen('\\' . \DateTimeImmutable::class)) ); return $birthDate; diff --git a/tests/integration/PropertyHookTest.php b/tests/integration/PropertyHookTest.php new file mode 100644 index 00000000..2691595d --- /dev/null +++ b/tests/integration/PropertyHookTest.php @@ -0,0 +1,131 @@ +<?php + +declare(strict_types=1); + +namespace integration; + +use EliasHaeussler\PHPUnitAttributes\Attribute\RequiresPackage; +use phpDocumentor\Reflection\DocBlock; +use phpDocumentor\Reflection\File\LocalFile; +use phpDocumentor\Reflection\Location; +use phpDocumentor\Reflection\Php\Argument; +use phpDocumentor\Reflection\Php\AsymmetricVisibility; +use phpDocumentor\Reflection\Php\Attribute; +use phpDocumentor\Reflection\Php\ProjectFactory; +use phpDocumentor\Reflection\Php\PropertyHook; +use phpDocumentor\Reflection\Php\Visibility; +use phpDocumentor\Reflection\Types\Compound; +use phpDocumentor\Reflection\Types\Integer; +use phpDocumentor\Reflection\Types\String_; +use PHPUnit\Framework\Attributes\CoversNothing; +use PHPUnit\Framework\TestCase; + +#[RequiresPackage('nikic/php-parser', '>= 5.2')] +#[CoversNothing] +final class PropertyHookTest extends TestCase +{ + public function testPropertyHookWithDocblocks(): void + { + $file = __DIR__ . '/data/PHP84/PropertyHook.php'; + $projectFactory = ProjectFactory::createInstance(); + $project = $projectFactory->create('My project', [new LocalFile($file)]); + + $class = $project->getFiles()[$file]->getClasses()['\PropertyHook']; + $hooks = $class->getProperties()['\PropertyHook::$example']->getHooks(); + + $this->assertTrue($class->getProperties()['\PropertyHook::$example']->isVirtual()); + $this->assertCount(2, $hooks); + $this->assertEquals('get', $hooks[0]->getName()); + $this->assertEquals(new Visibility(Visibility::PUBLIC_), $hooks[0]->getVisibility()); + $this->assertCount(1, $hooks[0]->getAttributes()); + $this->assertCount(0, $hooks[0]->getArguments()); + $this->assertSame('Not sure this works, but it gets', $hooks[0]->getDocBlock()->getSummary()); + + $this->assertEquals('set', $hooks[1]->getName()); + $this->assertEquals(new Visibility(Visibility::PUBLIC_), $hooks[1]->getVisibility()); + $this->assertCount(1, $hooks[1]->getAttributes()); + $this->assertCount(1, $hooks[1]->getArguments()); + $this->assertEquals(new Argument( + 'value', + new Compound( + [ + new String_(), + new Integer() + ] + ), + ), $hooks[1]->getArguments()[0]); + $this->assertSame('Not sure this works, but it gets', $hooks[0]->getDocBlock()->getSummary()); + } + + public function testPropertyHookAsymmetric(): void + { + $file = __DIR__ . '/data/PHP84/PropertyHookAsymmetric.php'; + $projectFactory = ProjectFactory::createInstance(); + $project = $projectFactory->create('My project', [new LocalFile($file)]); + + $class = $project->getFiles()[$file]->getClasses()['\PropertyHook']; + $hooks = $class->getProperties()['\PropertyHook::$example']->getHooks(); + + + $this->assertEquals( + new AsymmetricVisibility( + new Visibility(Visibility::PUBLIC_), + new Visibility(Visibility::PRIVATE_) + ), + $class->getProperties()['\PropertyHook::$example']->getVisibility() + ); + $this->assertTrue($class->getProperties()['\PropertyHook::$example']->isVirtual()); + $this->assertCount(2, $hooks); + $this->assertEquals('get', $hooks[0]->getName()); + $this->assertEquals(new Visibility(Visibility::PUBLIC_), $hooks[0]->getVisibility()); + $this->assertCount(0, $hooks[0]->getArguments()); + + $this->assertEquals('set', $hooks[1]->getName()); + $this->assertEquals(new Visibility(Visibility::PRIVATE_), $hooks[1]->getVisibility()); + $this->assertCount(1, $hooks[1]->getArguments()); + $this->assertEquals(new Argument( + 'value', + new Compound( + [ + new String_(), + new Integer() + ] + ), + ), $hooks[1]->getArguments()[0]); + } + + public function testVirtualProperty(): void + { + $file = __DIR__ . '/data/PHP84/PropertyHookVirtual.php'; + $projectFactory = ProjectFactory::createInstance(); + $project = $projectFactory->create('My project', [new LocalFile($file)]); + + $class = $project->getFiles()[$file]->getClasses()['\PropertyHookVirtual']; + + // Test get-only virtual property + $fullNameProperty = $class->getProperties()['\PropertyHookVirtual::$fullName']; + $this->assertTrue($fullNameProperty->isVirtual(), 'Property with getter that doesn\'t reference itself should be virtual'); + $this->assertCount(1, $fullNameProperty->getHooks()); + $this->assertEquals('get', $fullNameProperty->getHooks()[0]->getName()); + + // Test set-only virtual property + $compositeNameProperty = $class->getProperties()['\PropertyHookVirtual::$compositeName']; + $this->assertTrue($compositeNameProperty->isVirtual(), 'Property with setter that doesn\'t reference itself should be virtual'); + $this->assertCount(1, $compositeNameProperty->getHooks()); + $this->assertEquals('set', $compositeNameProperty->getHooks()[0]->getName()); + + // Test property with both get and set hooks that doesn't reference itself + $completeFullNameProperty = $class->getProperties()['\PropertyHookVirtual::$completeFullName']; + $this->assertTrue($completeFullNameProperty->isVirtual(), 'Property with getter and setter that don\'t reference itself should be virtual'); + $this->assertCount(2, $completeFullNameProperty->getHooks()); + + $nonVirtualPropertyWithoutHooks = $class->getProperties()['\PropertyHookVirtual::$firstName']; + $this->assertFalse($nonVirtualPropertyWithoutHooks->isVirtual(), 'Property without hooks should not be virtual'); + $this->assertCount(0, $nonVirtualPropertyWithoutHooks->getHooks()); + + // Test non-virtual property that references itself + $nonVirtualNameProperty = $class->getProperties()['\PropertyHookVirtual::$nonVirtualName']; + $this->assertFalse($nonVirtualNameProperty->isVirtual(), 'Property with hooks that reference itself should not be virtual'); + $this->assertCount(2, $nonVirtualNameProperty->getHooks()); + } +} diff --git a/tests/integration/data/PHP8/ConstructorPromotion.php b/tests/integration/data/PHP8/ConstructorPromotion.php index cc1883c6..494ddbe0 100644 --- a/tests/integration/data/PHP8/ConstructorPromotion.php +++ b/tests/integration/data/PHP8/ConstructorPromotion.php @@ -21,8 +21,8 @@ public function __construct( * * @var string $name property description */ - public string $name, - protected string $email = 'test@example.com', + public string $name = 'default name', + protected Email $email, private DateTimeImmutable $birth_date, ) {} } diff --git a/tests/integration/data/PHP84/AsymmetricAccessor.php b/tests/integration/data/PHP84/AsymmetricAccessor.php new file mode 100644 index 00000000..992145e2 --- /dev/null +++ b/tests/integration/data/PHP84/AsymmetricAccessor.php @@ -0,0 +1,8 @@ +<?php + +declare(strict_types=1); + +class AsymmetricAccessor +{ + private(set) \Pizza $pizza; +} diff --git a/tests/integration/data/PHP84/AsymmetricPropertyPromotion.php b/tests/integration/data/PHP84/AsymmetricPropertyPromotion.php new file mode 100644 index 00000000..0a501d5a --- /dev/null +++ b/tests/integration/data/PHP84/AsymmetricPropertyPromotion.php @@ -0,0 +1,10 @@ +<?php + +declare(strict_types=1); + +class AsymmetricPropertyPromotion +{ + public function __construct( + protected(set) Pizza $pizza, + ) {} +} diff --git a/tests/integration/data/PHP84/PropertyHook.php b/tests/integration/data/PHP84/PropertyHook.php new file mode 100644 index 00000000..a83ff756 --- /dev/null +++ b/tests/integration/data/PHP84/PropertyHook.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +class PropertyHook +{ + private bool $modified = false; + + /** @var string this is my property */ + #[Property(new DateTimeImmutable())] + public string $example = 'default value' { + /** Not sure this works, but it gets */ + #[Getter(new DateTimeImmutable())] + get { + if ($this->modified) { + return $this->foo . ' (modified)'; + } + return $this->foo; + } + /** Not sure this works, but it sets */ + #[Setter(new DateTimeImmutable())] + set(string|int $value) { + $this->foo = strtolower($value); + $this->modified = true; + } + } +} diff --git a/tests/integration/data/PHP84/PropertyHookAsymmetric.php b/tests/integration/data/PHP84/PropertyHookAsymmetric.php new file mode 100644 index 00000000..85253613 --- /dev/null +++ b/tests/integration/data/PHP84/PropertyHookAsymmetric.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +class PropertyHook +{ + private bool $modified = false; + + /** @var string this is my property */ + #[Property(new DateTimeImmutable())] + public private(set) string $example = 'default value' { + get { + if ($this->modified) { + return $this->foo . ' (modified)'; + } + return $this->foo; + } + set(string|int $value) { + $this->foo = strtolower($value); + $this->modified = true; + } + } +} diff --git a/tests/integration/data/PHP84/PropertyHookPromotion.php b/tests/integration/data/PHP84/PropertyHookPromotion.php new file mode 100644 index 00000000..7c933750 --- /dev/null +++ b/tests/integration/data/PHP84/PropertyHookPromotion.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +class PropertyHook +{ + private bool $modified = false; + + /** @param string $example this is my property */ + public function __construct( + /** @var string this is my property */ + #[Property(new DateTimeImmutable())] + public string $example = 'default value' { + /** Not sure this works, but it gets */ + #[Getter(new DateTimeImmutable())] + get { + if ($this->modified) { + return $this->foo . ' (modified)'; + } + return $this->foo; + } + /** Not sure this works, but it sets */ + #[Setter(new DateTimeImmutable())] + set(string|int $value) { + $this->foo = strtolower($value); + $this->modified = true; + } + } + ) + { + } +} diff --git a/tests/integration/data/PHP84/PropertyHookVirtual.php b/tests/integration/data/PHP84/PropertyHookVirtual.php new file mode 100644 index 00000000..7e6f5ec3 --- /dev/null +++ b/tests/integration/data/PHP84/PropertyHookVirtual.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); + +class PropertyHookVirtual +{ + /** + * A virtual property that composes a full name from first and last name + */ + public string $fullName { + // This is a virtual property with a getter + // It doesn't reference $this->fullName + get { + return $this->firstName . ' ' . $this->lastName; + } + } + + /** + * A virtual property that decomposes a full name into first and last name + */ + public string $compositeName { + // This is a virtual property with a setter + // It doesn't reference $this->compositeName + set(string $value) { + [$this->firstName, $this->lastName] = explode(' ', $value, 2); + } + } + + /** + * A virtual property with both getter and setter + */ + public string $completeFullName { + // Getter doesn't reference $this->completeFullName + get { + return $this->firstName . ' ' . $this->lastName; + } + // Setter doesn't reference $this->completeFullName + set(string $value) { + [$this->firstName, $this->lastName] = explode(' ', $value, 2); + } + } + + /** + * A non-virtual property that references itself in its hook + */ + public string $nonVirtualName { + get { + return $this->nonVirtualName ?? $this->firstName; + } + set(string $value) { + $this->nonVirtualName = $value; + } + } + + public function __construct( + private string $firstName = 'John', + private string $lastName = 'Doe' + ) { + } +} diff --git a/tests/unit/phpDocumentor/Reflection/File/LocalFileTest.php b/tests/unit/phpDocumentor/Reflection/File/LocalFileTest.php index 05cd23a1..acfe40cc 100644 --- a/tests/unit/phpDocumentor/Reflection/File/LocalFileTest.php +++ b/tests/unit/phpDocumentor/Reflection/File/LocalFileTest.php @@ -14,38 +14,32 @@ namespace phpDocumentor\Reflection\File; use InvalidArgumentException; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use function md5_file; -/** - * @coversDefaultClass phpDocumentor\Reflection\File\LocalFile - * @covers ::__construct - */ +#[CoversClass(LocalFile::class)] class LocalFileTest extends TestCase { - /** @covers ::getContents */ public function testGetContents(): void { $file = new LocalFile(__FILE__); $this->assertStringEqualsFile(__FILE__, $file->getContents()); } - /** @covers ::md5 */ public function testMd5(): void { $file = new LocalFile(__FILE__); $this->assertEquals(md5_file(__FILE__), $file->md5()); } - /** @covers ::__construct */ public function testNotExistingFileThrowsException(): void { $this->expectException(InvalidArgumentException::class); new LocalFile('aa'); } - /** @covers ::path */ public function testPath(): void { $file = new LocalFile(__FILE__); diff --git a/tests/unit/phpDocumentor/Reflection/Middleware/ChainFactoryTest.php b/tests/unit/phpDocumentor/Reflection/Middleware/ChainFactoryTest.php index 7a7e68f2..e5afad9c 100644 --- a/tests/unit/phpDocumentor/Reflection/Middleware/ChainFactoryTest.php +++ b/tests/unit/phpDocumentor/Reflection/Middleware/ChainFactoryTest.php @@ -14,16 +14,13 @@ namespace phpDocumentor\Reflection\Middleware; use InvalidArgumentException; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use stdClass; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Middleware\ChainFactory - * @covers ::<private> - */ +#[CoversClass(ChainFactory::class)] final class ChainFactoryTest extends TestCase { - /** @covers ::createExecutionChain */ public function testItCreatesAChainOfCallablesThatWillInvokeAllMiddlewares(): void { $exampleCommand = new class implements Command { @@ -46,7 +43,6 @@ static function (): stdClass { $this->assertSame('abc', $chain(new $exampleCommand())->counter); } - /** @covers ::createExecutionChain */ public function testItThrowsAnExceptionIfAnythingOtherThanAMiddlewareIsPassed(): void { $this->expectException(InvalidArgumentException::class); @@ -57,7 +53,7 @@ public function testItThrowsAnExceptionIfAnythingOtherThanAMiddlewareIsPassed(): ChainFactory::createExecutionChain( [$middleware], - static fn (): stdClass => new stdClass() + static fn (): stdClass => new stdClass(), ); } diff --git a/tests/unit/phpDocumentor/Reflection/NodeVisitor/ElementNameResolverTest.php b/tests/unit/phpDocumentor/Reflection/NodeVisitor/ElementNameResolverTest.php index f32d116a..18ceccda 100644 --- a/tests/unit/phpDocumentor/Reflection/NodeVisitor/ElementNameResolverTest.php +++ b/tests/unit/phpDocumentor/Reflection/NodeVisitor/ElementNameResolverTest.php @@ -25,15 +25,12 @@ use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Namespace_; use PhpParser\Node\Stmt\PropertyProperty; +use PhpParser\Node\Stmt\Return_; use PhpParser\NodeTraverser; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -/** - * @uses \phpDocumentor\Reflection\NodeVisitor\ElementNameResolver::beforeTraverse - * - * @coversDefaultClass \phpDocumentor\Reflection\NodeVisitor\ElementNameResolver - * @covers ::<private> - */ +#[CoversClass(ElementNameResolver::class)] class ElementNameResolverTest extends TestCase { private ElementNameResolver $fixture; @@ -44,7 +41,6 @@ protected function setUp(): void $this->fixture->beforeTraverse([]); } - /** @covers ::enterNode */ public function testFunctionWithoutNamespace(): void { $function = new Function_('myFunction'); @@ -53,7 +49,6 @@ public function testFunctionWithoutNamespace(): void $this->assertEquals('\myFunction()', (string) $function->getAttribute('fqsen')); } - /** @covers ::enterNode */ public function testWithClass(): void { $class = new Class_('myClass'); @@ -62,7 +57,6 @@ public function testWithClass(): void $this->assertEquals('\myClass', (string) $class->getAttribute('fqsen')); } - /** @covers ::enterNode */ public function testWithClassMethod(): void { $class = new Class_('myClass'); @@ -74,7 +68,6 @@ public function testWithClassMethod(): void $this->assertEquals('\myClass::method()', (string) $method->getAttribute('fqsen')); } - /** @covers ::enterNode */ public function testWithClassProperty(): void { $class = new Class_('myClass'); @@ -89,8 +82,6 @@ public function testWithClassProperty(): void /** * If anonymous classes were processed, we would obtain a * InvalidArgumentException for an invalid Fqsen. - * - * @covers ::enterNode */ public function testDoesNotEnterAnonymousClass(): void { @@ -101,19 +92,14 @@ public function testDoesNotEnterAnonymousClass(): void ); } - /** - * @link https://github.com/phpDocumentor/Reflection/issues/103 - * - * @covers ::enterNode - * @covers ::leaveNode - */ + /** @link https://github.com/phpDocumentor/Reflection/issues/103 */ public function testAnonymousClassDoesNotPopParts(): void { $anonymousClass = new Class_(null); $new = new New_($anonymousClass); - $namespace = new Namespace_(new Name('ANamespace'), $new); + $namespace = new Namespace_(new Name('ANamespace'), [new Return_($new)]); $this->fixture->enterNode($namespace); $this->fixture->enterNode($new); @@ -125,7 +111,6 @@ public function testAnonymousClassDoesNotPopParts(): void $this->assertTrue(true); } - /** @covers ::enterNode */ public function testClassConstant(): void { $const = new Const_('MY_CLASS', new String_('value')); @@ -139,7 +124,6 @@ public function testClassConstant(): void $this->assertEquals('\\myClass::MY_CLASS', (string) $const->getAttribute('fqsen')); } - /** @covers ::enterNode */ public function testNamespacedConstant(): void { $const = new Const_('MY_CLASS', new String_('value')); @@ -151,7 +135,6 @@ public function testNamespacedConstant(): void $this->assertEquals('\\name\\MY_CLASS', (string) $const->getAttribute('fqsen')); } - /** @covers ::enterNode */ public function testNoNameNamespace(): void { $const = new Const_('MY_CLASS', new String_('value')); @@ -163,7 +146,6 @@ public function testNoNameNamespace(): void $this->assertEquals('\\MY_CLASS', (string) $const->getAttribute('fqsen')); } - /** @covers ::enterNode */ public function testWithEnumWithCase(): void { $enum = new Enum_('myEnum'); diff --git a/tests/unit/phpDocumentor/Reflection/Php/ArgumentTest.php b/tests/unit/phpDocumentor/Reflection/Php/ArgumentTest.php index 14696997..a07de699 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/ArgumentTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/ArgumentTest.php @@ -15,19 +15,15 @@ use phpDocumentor\Reflection\Types\Mixed_; use phpDocumentor\Reflection\Types\String_; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; /** * Tests the functionality for the Argument class. - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Argument - * @covers ::__construct - * @covers ::<private> - * @covers ::<protected> */ +#[CoversClass(Argument::class)] final class ArgumentTest extends TestCase { - /** @covers ::getType */ public function testGetTypes(): void { $argument = new Argument('myArgument', null, 'myDefaultValue', true, true); @@ -43,14 +39,12 @@ public function testGetTypes(): void $this->assertEquals(new String_(), $argument->getType()); } - /** @covers ::getName */ public function testGetName(): void { $argument = new Argument('myArgument', null, 'myDefault', true, true); $this->assertEquals('myArgument', $argument->getName()); } - /** @covers ::getDefault */ public function testGetDefault(): void { $argument = new Argument('myArgument', null, 'myDefaultValue', true, true); @@ -60,7 +54,6 @@ public function testGetDefault(): void $this->assertNull($argument->getDefault()); } - /** @covers ::isByReference */ public function testGetWhetherArgumentIsPassedByReference(): void { $argument = new Argument('myArgument', null, 'myDefaultValue', true, true); @@ -70,7 +63,6 @@ public function testGetWhetherArgumentIsPassedByReference(): void $this->assertFalse($argument->isByReference()); } - /** @covers ::isVariadic */ public function testGetWhetherArgumentisVariadic(): void { $argument = new Argument('myArgument', null, 'myDefaultValue', true, true); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Class_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Class_Test.php index a139b2e4..c3764ef7 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Class_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Class_Test.php @@ -17,23 +17,18 @@ use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; - -/** - * @uses \phpDocumentor\Reflection\Php\Property - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Class_ - * @covers ::__construct - * @covers ::<private> - * @covers ::<protected> - * - * @property Class_ $fixture - */ +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; + +/** @property Class_ $fixture */ +#[CoversClass(Class_::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Property')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] final class Class_Test extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private Fqsen $parent; @@ -58,25 +53,21 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** @covers ::getName */ public function testGettingName(): void { $this->assertSame($this->fqsen->getName(), $this->fixture->getName()); } - /** @covers ::getFqsen */ public function testGettingFqsen(): void { $this->assertSame($this->fqsen, $this->fixture->getFqsen()); } - /** @covers ::getDocBlock */ public function testGettingDocBlock(): void { $this->assertSame($this->docBlock, $this->fixture->getDocBlock()); } - /** @covers ::getParent */ public function testGettingParent(): void { $class = new Class_($this->fqsen, $this->docBlock); @@ -86,10 +77,6 @@ public function testGettingParent(): void $this->assertSame($this->parent, $class->getParent()); } - /** - * @covers ::getInterfaces - * @covers ::AddInterface - */ public function testAddAndGettingInterfaces(): void { $this->assertEmpty($this->fixture->getInterfaces()); @@ -101,10 +88,6 @@ public function testAddAndGettingInterfaces(): void $this->assertSame(['\MyInterface' => $interface], $this->fixture->getInterfaces()); } - /** - * @covers ::getConstants - * @covers ::addConstant - */ public function testAddAndGettingConstants(): void { $this->assertEmpty($this->fixture->getConstants()); @@ -116,10 +99,6 @@ public function testAddAndGettingConstants(): void $this->assertSame(['\MyClass::MY_CONSTANT' => $constant], $this->fixture->getConstants()); } - /** - * @covers ::addProperty - * @covers ::getProperties - */ public function testAddAndGettingProperties(): void { $this->assertEmpty($this->fixture->getProperties()); @@ -131,10 +110,6 @@ public function testAddAndGettingProperties(): void $this->assertSame(['\MyClass::$myProperty' => $property], $this->fixture->getProperties()); } - /** - * @covers ::addMethod - * @covers ::getMethods - */ public function testAddAndGettingMethods(): void { $this->assertEmpty($this->fixture->getMethods()); @@ -146,10 +121,6 @@ public function testAddAndGettingMethods(): void $this->assertSame(['\MyClass::myMethod()' => $method], $this->fixture->getMethods()); } - /** - * @covers ::getUsedTraits - * @covers ::AddUsedTrait - */ public function testAddAndGettingUsedTrait(): void { $this->assertEmpty($this->fixture->getUsedTraits()); @@ -161,7 +132,6 @@ public function testAddAndGettingUsedTrait(): void $this->assertSame(['\MyTrait' => $trait], $this->fixture->getUsedTraits()); } - /** @covers ::isAbstract */ public function testGettingWhetherClassIsAbstract(): void { $class = new Class_($this->fqsen, $this->docBlock); @@ -171,7 +141,6 @@ public function testGettingWhetherClassIsAbstract(): void $this->assertTrue($class->isAbstract()); } - /** @covers ::isFinal */ public function testGettingWhetherClassIsFinal(): void { $class = new Class_($this->fqsen, $this->docBlock); @@ -181,7 +150,6 @@ public function testGettingWhetherClassIsFinal(): void $this->assertTrue($class->isFinal()); } - /** @covers ::isFinal */ public function testGettingWhetherClassIsReadOnly(): void { $class = new Class_($this->fqsen, $this->docBlock); diff --git a/tests/unit/phpDocumentor/Reflection/Php/ConstantTest.php b/tests/unit/phpDocumentor/Reflection/Php/ConstantTest.php index bbd79bb2..0fbed684 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/ConstantTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/ConstantTest.php @@ -17,21 +17,17 @@ use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; - -/** - * @uses \phpDocumentor\Reflection\DocBlock - * @uses \phpDocumentor\Reflection\Php\Visibility - * @uses \phpDocumentor\Reflection\Fqsen - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Constant - * @covers ::__construct - * @covers ::<private> - * - * @property Constant $fixture - */ +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; + +/** @property Constant $fixture */ +#[CoversClass(Constant::class)] +#[UsesClass('\phpDocumentor\Reflection\DocBlock')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Fqsen')] final class ConstantTest extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private Fqsen $fqsen; @@ -54,41 +50,27 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** - * @covers ::getValue - * @covers ::__construct - */ public function testGetValue(): void { $this->assertSame($this->value, $this->fixture->getValue()); } - /** - * @covers ::isFinal - * @covers ::__construct - */ public function testIsFinal(): void { $this->assertFalse($this->fixture->isFinal()); } - /** - * @covers ::getFqsen - * @covers ::getName - */ public function testGetFqsen(): void { $this->assertSame($this->fqsen, $this->fixture->getFqsen()); $this->assertSame($this->fqsen->getName(), $this->fixture->getName()); } - /** @covers ::getDocBlock */ public function testGetDocblock(): void { $this->assertSame($this->docBlock, $this->fixture->getDocBlock()); } - /** @covers ::getVisibility */ public function testGetVisibility(): void { $this->assertEquals(new Visibility(Visibility::PUBLIC_), $this->fixture->getVisibility()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/EnumCaseTest.php b/tests/unit/phpDocumentor/Reflection/Php/EnumCaseTest.php index cbc768ee..11267ac2 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/EnumCaseTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/EnumCaseTest.php @@ -17,17 +17,13 @@ use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\EnumCase - * @covers ::__construct - * @covers ::<private> - * @covers ::<protected> - */ +#[CoversClass(EnumCase::class)] final class EnumCaseTest extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private EnumCase $fixture; @@ -51,31 +47,26 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** @covers ::getName */ public function testGettingName(): void { $this->assertSame($this->fqsen->getName(), $this->fixture->getName()); } - /** @covers ::getFqsen */ public function testGettingFqsen(): void { $this->assertSame($this->fqsen, $this->fixture->getFqsen()); } - /** @covers ::getDocBlock */ public function testGettingDocBlock(): void { $this->assertSame($this->docBlock, $this->fixture->getDocBlock()); } - /** @covers ::getValue */ public function testGetValue(): void { $this->assertNull($this->fixture->getValue()); } - /** @covers ::getLocation */ public function testGetLocationReturnsDefault(): void { self::assertEquals(new Location(-1), $this->fixture->getLocation()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Enum_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Enum_Test.php index 82bb94cb..6ed91334 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Enum_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Enum_Test.php @@ -17,21 +17,16 @@ use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; -/** - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\EnumCase - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Enum_ - * @covers ::__construct - * @covers ::<private> - * @covers ::<protected> - * - * @property Enum_ $fixture - */ +/** @property Enum_ $fixture */ +#[CoversClass(Enum_::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] +#[UsesClass('\phpDocumentor\Reflection\Php\EnumCase')] final class Enum_Test extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private Fqsen $parent; @@ -56,34 +51,26 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** @covers ::getName */ public function testGettingName(): void { $this->assertSame($this->fqsen->getName(), $this->fixture->getName()); } - /** @covers ::getBackedType */ public function testGetBackedWithOutType(): void { $this->assertNull($this->fixture->getBackedType()); } - /** @covers ::getFqsen */ public function testGettingFqsen(): void { $this->assertSame($this->fqsen, $this->fixture->getFqsen()); } - /** @covers ::getDocBlock */ public function testGettingDocBlock(): void { $this->assertSame($this->docBlock, $this->fixture->getDocBlock()); } - /** - * @covers ::getInterfaces - * @covers ::AddInterface - */ public function testAddAndGettingInterfaces(): void { $this->assertEmpty($this->fixture->getInterfaces()); @@ -95,10 +82,6 @@ public function testAddAndGettingInterfaces(): void $this->assertSame(['\MyInterface' => $interface], $this->fixture->getInterfaces()); } - /** - * @covers ::addConstant - * @covers ::getConstants - */ public function testAddAndGettingConstants(): void { $this->assertEmpty($this->fixture->getConstants()); @@ -110,10 +93,6 @@ public function testAddAndGettingConstants(): void $this->assertSame(['\MyClass::MYCONST' => $constant], $this->fixture->getConstants()); } - /** - * @covers ::addMethod - * @covers ::getMethods - */ public function testAddAndGettingMethods(): void { $this->assertEmpty($this->fixture->getMethods()); @@ -125,10 +104,6 @@ public function testAddAndGettingMethods(): void $this->assertSame(['\MyClass::myMethod()' => $method], $this->fixture->getMethods()); } - /** - * @covers ::getUsedTraits - * @covers ::AddUsedTrait - */ public function testAddAndGettingUsedTrait(): void { $this->assertEmpty($this->fixture->getUsedTraits()); @@ -140,10 +115,6 @@ public function testAddAndGettingUsedTrait(): void $this->assertSame(['\MyTrait' => $trait], $this->fixture->getUsedTraits()); } - /** - * @covers ::addCase - * @covers ::getCases - */ public function testAddAndGettingCases(): void { $this->assertEmpty($this->fixture->getCases()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/ClassConstantIteratorTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/ClassConstantIteratorTest.php index cc7661d0..61f5cf7c 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/ClassConstantIteratorTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/ClassConstantIteratorTest.php @@ -20,23 +20,11 @@ use PhpParser\Node\Const_; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Stmt\ClassConst; +use PHPUnit\Framework\Attributes\CoversClass; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\ClassConstantIterator - * @covers ::__construct - * @covers ::<private> - */ +#[CoversClass(ClassConstantIterator::class)] final class ClassConstantIteratorTest extends MockeryTestCase { - /** - * @covers ::current() - * @covers ::next() - * @covers ::valid() - * @covers ::rewind() - * @covers ::getName() - * @covers ::getValue() - * @covers ::getFqsen() - */ public function testIterateProps(): void { $const1 = new Const_('\Space\MyClass::MY_CONST1', new Variable('1')); @@ -55,10 +43,6 @@ public function testIterateProps(): void } } - /** - * @covers ::key() - * @covers ::next() - */ public function testKey(): void { $constantMock = m::mock(ClassConst::class); @@ -70,10 +54,6 @@ public function testKey(): void $this->assertEquals(1, $fixture->key()); } - /** - * @covers ::__construct - * @covers ::getLine - */ public function testProxyMethods(): void { $constantMock = m::mock(ClassConst::class); @@ -84,7 +64,6 @@ public function testProxyMethods(): void $this->assertEquals(10, $fixture->getLine()); } - /** @covers ::getDocComment */ public function testGetDocCommentPropFirst(): void { $const = m::mock(Const_::class); @@ -99,7 +78,6 @@ public function testGetDocCommentPropFirst(): void $this->assertEquals('test', $fixture->getDocComment()->getText()); } - /** @covers ::getDocComment */ public function testGetDocComment(): void { $const = m::mock(Const_::class); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/ClassConstantTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/ClassConstantTest.php index 30945f5d..dec052dc 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/ClassConstantTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/ClassConstantTest.php @@ -30,21 +30,21 @@ use PhpParser\Node\Stmt\Class_ as ClassNode; use PhpParser\Node\Stmt\ClassConst; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use stdClass; use function current; -/** - * @uses \phpDocumentor\Reflection\Php\Factory\ClassConstantIterator - * @uses \phpDocumentor\Reflection\Php\ProjectFactoryStrategies - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers \phpDocumentor\Reflection\Php\Factory\ClassConstant - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - */ +#[CoversClass(ClassConstant::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\ClassConstantIterator')] +#[UsesClass('\phpDocumentor\Reflection\Php\ProjectFactoryStrategies')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] final class ClassConstantTest extends TestCase { use ProphecyTrait; @@ -66,7 +66,7 @@ public function testMatches(): void $this->assertTrue($this->fixture->matches(self::createContext(null), $this->buildConstantIteratorStub())); } - /** @dataProvider visibilityProvider */ + #[DataProvider('visibilityProvider')] public function testCreateWithVisibility(int $input, string $expectedVisibility, bool $isFinal = false): void { $constantStub = $this->buildConstantIteratorStub($input); @@ -79,7 +79,7 @@ public function testCreateWithVisibility(int $input, string $expectedVisibility, } /** @return array<string|int[]> */ - public function visibilityProvider(): array + public static function visibilityProvider(): array { return [ [ diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/Class_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/Class_Test.php index 4642d6d6..82da37ef 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/Class_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/Class_Test.php @@ -26,6 +26,8 @@ use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_ as ClassNode; use PhpParser\Node\Stmt\ClassMethod; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; @@ -33,21 +35,15 @@ use function current; -/** - * @uses \phpDocumentor\Reflection\Php\Class_ - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Property - * @uses \phpDocumentor\Reflection\Php\Visibility - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\Factory\Class_::matches - * @uses \phpDocumentor\Reflection\Php\Factory\ClassConstantIterator - * @uses \phpDocumentor\Reflection\Php\Factory\PropertyIterator - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\Class_ - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - * @covers ::<protected> - * @covers ::<private> - */ +#[CoversClass(Class_::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Class_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Property')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\ClassConstantIterator')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\PropertyIterator')] final class Class_Test extends TestCase { use ProphecyTrait; @@ -60,7 +56,6 @@ protected function setUp(): void $this->fixture = new Class_($this->docblockFactory->reveal()); } - /** @covers ::matches */ public function testMatches(): void { $this->assertFalse($this->fixture->matches(self::createContext(null), new stdClass())); @@ -72,7 +67,6 @@ public function testMatches(): void ); } - /** @covers ::create */ public function testSimpleCreate(): void { $containerMock = m::mock(StrategyContainer::class); @@ -88,13 +82,12 @@ public function testSimpleCreate(): void $this->assertTrue($class->isAbstract()); } - /** @covers ::create */ public function testClassWithParent(): void { $containerMock = m::mock(StrategyContainer::class); $classMock = $this->buildClassMock(); $classMock->shouldReceive('getDocComment')->andReturnNull(); - $classMock->extends = 'Space\MyParent'; + $classMock->extends = new Name('Space\MyParent'); $class = $this->performCreate($classMock, $containerMock); @@ -103,13 +96,12 @@ public function testClassWithParent(): void $this->assertEquals('\Space\MyParent', (string) $class->getParent()); } - /** @covers ::create */ public function testClassImplementingInterface(): void { $containerMock = m::mock(StrategyContainer::class); $classMock = $this->buildClassMock(); $classMock->shouldReceive('getDocComment')->andReturnNull(); - $classMock->extends = 'Space\MyParent'; + $classMock->extends = new Name('Space\MyParent'); $classMock->implements = [ new Name('MyInterface'), ]; @@ -125,7 +117,6 @@ public function testClassImplementingInterface(): void ); } - /** @covers ::create */ public function testIteratesStatements(): void { $method1 = new ClassMethod('MyClass::method1'); @@ -157,7 +148,6 @@ public function testIteratesStatements(): void ); } - /** @covers ::create */ public function testCreateWithDocBlock(): void { $doc = new Doc('Text'); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/ConstructorPromotionTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/ConstructorPromotionTest.php index 9777ff3e..bb63942d 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/ConstructorPromotionTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/ConstructorPromotionTest.php @@ -22,6 +22,8 @@ use PhpParser\Node\Stmt\Class_ as ClassNode; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\PrettyPrinter\Standard; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; @@ -29,7 +31,7 @@ use function current; -/** @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\ConstructorPromotion */ +#[CoversClass(ConstructorPromotion::class)] final class ConstructorPromotionTest extends TestCase { use ProphecyTrait; @@ -51,18 +53,14 @@ protected function setUp(): void ); } - /** - * @dataProvider objectProvider - * @covers ::__construct - * @covers ::matches - */ + #[DataProvider('objectProvider')] public function testMatches(ContextStack $context, object $object, bool $expected): void { self::assertEquals($expected, $this->fixture->matches($context, $object)); } /** @return mixed[][] */ - public function objectProvider(): array + public static function objectProvider(): array { $context = new ContextStack(new Project('test')); @@ -90,13 +88,7 @@ public function objectProvider(): array ]; } - /** - * @covers ::buildPropertyVisibilty - * @covers ::doCreate - * @covers ::promoteParameterToProperty - * @covers ::readOnly - * @dataProvider visibilityProvider - */ + #[DataProvider('visibilityProvider')] public function testCreateWithProperty(int $flags, string $visibility, bool $readOnly = false): void { $methodNode = new ClassMethod('__construct'); @@ -141,7 +133,7 @@ public function testCreateWithProperty(int $flags, string $visibility, bool $rea } /** @return mixed[][] */ - public function visibilityProvider(): array + public static function visibilityProvider(): array { return [ [ diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/ContextStackTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/ContextStackTest.php index cd094f08..68af0687 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/ContextStackTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/ContextStackTest.php @@ -10,16 +10,12 @@ use phpDocumentor\Reflection\Php\Method; use phpDocumentor\Reflection\Php\Project; use phpDocumentor\Reflection\Types\Context; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase as PHPUnitTestCase; -/** @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\ContextStack */ +#[CoversClass(ContextStack::class)] final class ContextStackTest extends PHPUnitTestCase { - /** - * @covers ::__construct - * @covers ::getTypeContext - * @covers ::getProject - */ public function testCreate(): void { $project = new Project('myProject'); @@ -30,10 +26,6 @@ public function testCreate(): void self::assertSame($typeContext, $context->getTypeContext()); } - /** - * @covers ::__construct - * @covers ::peek - */ public function testPeekThowsWhenEmpty(): void { $this->expectException(OutOfBoundsException::class); @@ -44,14 +36,6 @@ public function testPeekThowsWhenEmpty(): void $context->peek(); } - /** - * @covers ::__construct - * @covers ::peek - * @covers ::push - * @covers ::getTypeContext - * @covers ::getProject - * @covers ::createFromSelf - */ public function testPeekReturnsTopOfStack(): void { $class = new ClassElement(new Fqsen('\MyClass')); @@ -66,15 +50,6 @@ public function testPeekReturnsTopOfStack(): void self::assertSame($typeContext, $context->getTypeContext()); } - /** - * @covers ::__construct - * @covers ::withTypeContext - * @covers ::peek - * @covers ::push - * @covers ::getTypeContext - * @covers ::getProject - * @covers ::createFromSelf - */ public function testCreateWithTypeContext(): void { $class = new ClassElement(new Fqsen('\MyClass')); @@ -89,10 +64,6 @@ public function testCreateWithTypeContext(): void self::assertSame($typeContext, $context->getTypeContext()); } - /** - * @covers ::__construct - * @covers ::search - */ public function testSearchEmptyStackResultsInNull(): void { $project = new Project('myProject'); @@ -101,10 +72,6 @@ public function testSearchEmptyStackResultsInNull(): void self::assertNull($context->search(ClassElement::class)); } - /** - * @covers ::__construct - * @covers ::search - */ public function testSearchStackForExistingElementTypeWillReturnTheFirstHit(): void { $class = new ClassElement(new Fqsen('\MyClass')); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/DefineTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/DefineTest.php index 83e62d8a..c0668641 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/DefineTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/DefineTest.php @@ -27,20 +27,19 @@ use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Expression; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use stdClass; use function current; -/** - * @uses \phpDocumentor\Reflection\Php\ProjectFactoryStrategies - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers \phpDocumentor\Reflection\Php\Factory\Define - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - */ +#[CoversClass(Define::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\ProjectFactoryStrategies')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] final class DefineTest extends TestCase { use ProphecyTrait; diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/EnumCaseTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/EnumCaseTest.php index f33306f6..0193d8b0 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/EnumCaseTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/EnumCaseTest.php @@ -22,17 +22,13 @@ use phpDocumentor\Reflection\Php\StrategyContainer; use PhpParser\Node\Stmt\EnumCase as EnumCaseNode; use PhpParser\PrettyPrinter\Standard; +use PHPUnit\Framework\Attributes\CoversClass; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use stdClass; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\EnumCase - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - * @covers ::__construct - * @covers ::<protected> - * @covers ::<private> - */ +#[CoversClass(EnumCase::class)] +#[CoversClass(AbstractFactory::class)] final class EnumCaseTest extends TestCase { use ProphecyTrait; @@ -45,7 +41,6 @@ protected function setUp(): void $this->fixture = new EnumCase($this->docblockFactory->reveal(), new Standard()); } - /** @covers ::matches */ public function testMatches(): void { self::assertFalse($this->fixture->matches(self::createContext(null), new stdClass())); @@ -57,7 +52,6 @@ public function testMatches(): void ); } - /** @covers ::create */ public function testSimpleCreate(): void { $containerMock = $this->prophesize(StrategyContainer::class)->reveal(); @@ -92,6 +86,7 @@ private function performCreate(EnumCaseNode $enumCase): EnumElement private function buildEnumCaseMock(): ObjectProphecy { $enumMock = $this->prophesize(EnumCaseNode::class); + $enumMock->expr = null; $enumMock->getAttribute('fqsen')->willReturn(new Fqsen('\Space\MyEnum::VALUE')); $enumMock->getLine()->willReturn(1); $enumMock->getEndLine()->willReturn(2); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/Enum_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/Enum_Test.php index 11d27a5a..6a66d257 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/Enum_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/Enum_Test.php @@ -29,6 +29,8 @@ use PhpParser\Node\Stmt\Class_ as ClassNode; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Enum_ as EnumNode; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; @@ -36,17 +38,11 @@ use function current; -/** - * @uses \phpDocumentor\Reflection\Php\Enum_ - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\Factory\Enum_::matches - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\Enum_ - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - * @covers ::<protected> - * @covers ::<private> - */ +#[CoversClass(Enum_::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Enum_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] final class Enum_Test extends TestCase { use ProphecyTrait; @@ -59,7 +55,6 @@ protected function setUp(): void $this->fixture = new Enum_($this->docblockFactory->reveal()); } - /** @covers ::matches */ public function testMatches(): void { self::assertFalse($this->fixture->matches(self::createContext(null), new stdClass())); @@ -71,7 +66,6 @@ public function testMatches(): void ); } - /** @covers ::create */ public function testSimpleCreate(): void { $containerMock = m::mock(StrategyContainer::class); @@ -84,7 +78,6 @@ public function testSimpleCreate(): void self::assertEquals('\Space\MyEnum', (string) $result->getFqsen()); } - /** @covers ::create */ public function testBackedEnumTypeIsSet(): void { $containerMock = m::mock(StrategyContainer::class); @@ -99,7 +92,6 @@ public function testBackedEnumTypeIsSet(): void self::assertEquals(new String_(), $result->getBackedType()); } - /** @covers ::create */ public function testClassImplementingInterface(): void { $containerMock = m::mock(StrategyContainer::class); @@ -121,7 +113,6 @@ public function testClassImplementingInterface(): void ); } - /** @covers ::create */ public function testIteratesStatements(): void { $method1 = new ClassMethod('MyEnum::method1'); @@ -153,7 +144,6 @@ public function testIteratesStatements(): void ); } - /** @covers ::create */ public function testCreateWithDocBlock(): void { $doc = new Doc('Text'); @@ -171,6 +161,7 @@ public function testCreateWithDocBlock(): void private function buildEnumMock(): m\MockInterface|ClassNode { $enumMock = m::mock(EnumNode::class); + $enumMock->scalarType = null; $enumMock->shouldReceive('getAttribute')->andReturn(new Fqsen('\Space\MyEnum')); $enumMock->implements = []; $enumMock->stmts = []; diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/File/CreateCommandTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/File/CreateCommandTest.php index 7ed26d97..d6df9cdd 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/File/CreateCommandTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/File/CreateCommandTest.php @@ -17,15 +17,13 @@ use phpDocumentor\Reflection\Php\Factory\ContextStack; use phpDocumentor\Reflection\Php\Project; use phpDocumentor\Reflection\Php\ProjectFactoryStrategies; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; -/** - * @uses phpDocumentor\Reflection\File\LocalFile - * @uses phpDocumentor\Reflection\Php\ProjectFactoryStrategies - * - * @coversDefaultClass phpDocumentor\Reflection\Php\Factory\File\CreateCommand - * @covers ::__construct - */ +#[CoversClass(CreateCommand::class)] +#[UsesClass('phpDocumentor\Reflection\File\LocalFile')] +#[UsesClass('phpDocumentor\Reflection\Php\ProjectFactoryStrategies')] class CreateCommandTest extends TestCase { private CreateCommand $fixture; @@ -45,13 +43,11 @@ protected function setUp(): void ); } - /** @covers ::getFile */ public function testGetFile(): void { $this->assertSame($this->file, $this->fixture->getFile()); } - /** @covers ::getStrategies */ public function testGetStrategies(): void { $this->assertSame($this->strategies, $this->fixture->getStrategies()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/FileTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/FileTest.php index b3026112..7e7fdd94 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/FileTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/FileTest.php @@ -30,6 +30,9 @@ use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_ as ClassNode; use PhpParser\Node\Stmt\Namespace_ as NamespaceNode; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; @@ -38,27 +41,20 @@ use function current; use function file_get_contents; -/** - * @uses \phpDocumentor\Reflection\Php\File - * @uses \phpDocumentor\Reflection\Php\Factory\File::matches - * @uses \phpDocumentor\Reflection\File\LocalFile - * @uses \phpDocumentor\Reflection\Middleware\ChainFactory - * @uses \phpDocumentor\Reflection\Php\Class_ - * @uses \phpDocumentor\Reflection\Php\Trait_ - * @uses \phpDocumentor\Reflection\Php\Interface_ - * @uses \phpDocumentor\Reflection\Php\Function_ - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Visibility - * @uses \phpDocumentor\Reflection\Php\Factory\GlobalConstantIterator - * @uses \phpDocumentor\Reflection\Types\NamespaceNodeToContext - * @uses \phpDocumentor\Reflection\Php\Factory\File\CreateCommand - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\File - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - * @covers ::__construct - * @covers ::<protected> - * @covers ::<private> - */ +#[CoversClass(File::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\File')] +#[UsesClass('\phpDocumentor\Reflection\File\LocalFile')] +#[UsesClass('\phpDocumentor\Reflection\Middleware\ChainFactory')] +#[UsesClass('\phpDocumentor\Reflection\Php\Class_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Trait_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Interface_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Function_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\GlobalConstantIterator')] +#[UsesClass('\phpDocumentor\Reflection\Types\NamespaceNodeToContext')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\File\CreateCommand')] final class FileTest extends TestCase { use ProphecyTrait; @@ -74,14 +70,12 @@ protected function setUp(): void $this->fixture = new File($this->docBlockFactory->reveal(), $this->nodesFactoryMock->reveal()); } - /** @covers ::matches */ public function testMatches(): void { $this->assertFalse($this->fixture->matches(self::createContext(null), new stdClass())); $this->assertTrue($this->fixture->matches(self::createContext(null), m::mock(SourceFile::class))); } - /** @covers ::create */ public function testMiddlewareIsExecuted(): void { $file = new FileElement('aa', __FILE__); @@ -108,10 +102,7 @@ public function testMiddlewareIsChecked(): void new File($this->docBlockFactory->reveal(), $this->nodesFactoryMock->reveal(), [new stdClass()]); } - /** - * @covers ::create - * @dataProvider nodeProvider - */ + #[DataProvider('nodeProvider')] public function testFileGetsCommentFromFirstNode(Node $node, DocBlockDescriptor $docblock): void { $this->nodesFactoryMock->create(file_get_contents(__FILE__))->willReturn([$node]); @@ -132,7 +123,7 @@ public function testFileGetsCommentFromFirstNode(Node $node, DocBlockDescriptor } /** @return array<string, mixed[]> */ - public function nodeProvider(): array + public static function nodeProvider(): array { $docBlockNode = new DocBlockNode('Text'); $namespaceNode = new NamespaceNode(new Name('mySpace')); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/Function_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/Function_Test.php index e96ff0ea..cd41c748 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/Function_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/Function_Test.php @@ -24,6 +24,8 @@ use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Name; use PhpParser\Node\Stmt\Expression; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; @@ -31,17 +33,11 @@ use function current; -/** - * @uses \phpDocumentor\Reflection\Php\Factory\Function_::matches - * @uses \phpDocumentor\Reflection\Php\Function_ - * @uses \phpDocumentor\Reflection\Php\Argument - * @uses \phpDocumentor\Reflection\Php\Factory\Type - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\Function_ - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - * @covers ::<private> - * @covers ::<protected> - */ +#[CoversClass(Function_::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Function_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Argument')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Type')] final class Function_Test extends TestCase { use ProphecyTrait; @@ -54,7 +50,6 @@ protected function setUp(): void $this->fixture = new Function_($this->docBlockFactory->reveal()); } - /** @covers ::matches */ public function testMatches(): void { $this->assertFalse($this->fixture->matches(self::createContext(null), new stdClass())); @@ -64,10 +59,11 @@ public function testMatches(): void )); } - /** @covers ::create */ public function testCreateWithoutParameters(): void { $functionMock = $this->prophesize(\PhpParser\Node\Stmt\Function_::class); + $functionMock->byRef = false; + $functionMock->stmts = []; $functionMock->getAttribute('fqsen')->willReturn(new Fqsen('\SomeSpace::function()')); $functionMock->params = []; $functionMock->getDocComment()->willReturn(null); @@ -85,11 +81,12 @@ public function testCreateWithoutParameters(): void $this->assertEquals('\SomeSpace::function()', (string) $function->getFqsen()); } - /** @covers ::create */ public function testCreateWithDocBlock(): void { $doc = new Doc('Text'); $functionMock = $this->prophesize(\PhpParser\Node\Stmt\Function_::class); + $functionMock->byRef = false; + $functionMock->stmts = []; $functionMock->getAttribute('fqsen')->willReturn(new Fqsen('\SomeSpace::function()')); $functionMock->params = []; $functionMock->getDocComment()->willReturn($doc); @@ -110,11 +107,12 @@ public function testCreateWithDocBlock(): void $this->assertSame($docBlock, $function->getDocBlock()); } - /** @covers ::create */ public function testIteratesStatements(): void { $doc = new Doc('Text'); $functionMock = $this->prophesize(\PhpParser\Node\Stmt\Function_::class); + $functionMock->byRef = false; + $functionMock->stmts = []; $functionMock->getAttribute('fqsen')->willReturn(new Fqsen('\SomeSpace::function()')); $functionMock->params = []; $functionMock->getDocComment()->willReturn(null); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/GlobalConstantIteratorTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/GlobalConstantIteratorTest.php index 4af9acb6..971a6054 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/GlobalConstantIteratorTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/GlobalConstantIteratorTest.php @@ -19,22 +19,11 @@ use PhpParser\Node\Const_; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Stmt\Const_ as ConstStatement; +use PHPUnit\Framework\Attributes\CoversClass; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\GlobalConstantIterator - * @covers ::__construct - * @covers ::<private> - */ +#[CoversClass(GlobalConstantIterator::class)] final class GlobalConstantIteratorTest extends m\Adapter\Phpunit\MockeryTestCase { - /** - * @covers ::current() - * @covers ::next() - * @covers ::valid() - * @covers ::rewind() - * @covers ::getName() - * @covers ::getFqsen() - */ public function testIterateProps(): void { $const1 = new Const_('\Space\MY_CONST1', new Variable('a')); @@ -53,10 +42,6 @@ public function testIterateProps(): void } } - /** - * @covers ::key() - * @covers ::next() - */ public function testKey(): void { $constant = m::mock(ConstStatement::class); @@ -68,10 +53,6 @@ public function testKey(): void $this->assertEquals(1, $fixture->key()); } - /** - * @covers ::__construct - * @covers ::getLine - */ public function testProxyMethods(): void { $constant = m::mock(ConstStatement::class); @@ -82,7 +63,6 @@ public function testProxyMethods(): void $this->assertEquals(10, $fixture->getLine()); } - /** @covers ::getDocComment */ public function testGetDocCommentPropFirst(): void { $const = m::mock(Const_::class); @@ -97,7 +77,6 @@ public function testGetDocCommentPropFirst(): void $this->assertEquals('test', $fixture->getDocComment()->getText()); } - /** @covers ::getDocComment */ public function testGetDocComment(): void { $const = m::mock(Const_::class); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/GlobalConstantTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/GlobalConstantTest.php index 4c2d26a4..533c18f6 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/GlobalConstantTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/GlobalConstantTest.php @@ -26,21 +26,20 @@ use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Const_ as ConstStatement; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use stdClass; use function current; -/** - * @uses \phpDocumentor\Reflection\Php\Factory\GlobalConstantIterator - * @uses \phpDocumentor\Reflection\Php\ProjectFactoryStrategies - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers \phpDocumentor\Reflection\Php\Factory\GlobalConstant - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - */ +#[CoversClass(GlobalConstant::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\GlobalConstantIterator')] +#[UsesClass('\phpDocumentor\Reflection\Php\ProjectFactoryStrategies')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] final class GlobalConstantTest extends TestCase { use ProphecyTrait; diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/Interface_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/Interface_Test.php index 91d29db2..91d40920 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/Interface_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/Interface_Test.php @@ -25,6 +25,8 @@ use PhpParser\Comment\Doc; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Interface_ as InterfaceNode; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; @@ -32,19 +34,13 @@ use function current; -/** - * @uses \phpDocumentor\Reflection\Php\Interface_ - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\Visibility - * @uses \phpDocumentor\Reflection\Php\Factory\Interface_::matches - * @uses \phpDocumentor\Reflection\Php\Factory\ClassConstantIterator - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\Interface_ - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - * @covers ::<private> - * @covers ::<protected> - */ +#[CoversClass(Interface_::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Interface_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\ClassConstantIterator')] class Interface_Test extends TestCase { use ProphecyTrait; @@ -57,14 +53,12 @@ protected function setUp(): void $this->fixture = new Interface_($this->docBlockFactory->reveal()); } - /** @covers ::matches */ public function testMatches(): void { $this->assertFalse($this->fixture->matches(self::createContext(null), new stdClass())); $this->assertTrue($this->fixture->matches(self::createContext(null), m::mock(InterfaceNode::class))); } - /** @covers ::create */ public function testSimpleCreate(): void { $interfaceMock = $this->buildClassMock(); @@ -77,7 +71,6 @@ public function testSimpleCreate(): void $this->assertEquals('\Space\MyInterface', (string) $interface->getFqsen()); } - /** @covers ::create */ public function testCreateWithDocBlock(): void { $doc = new Doc('Text'); @@ -93,7 +86,6 @@ public function testCreateWithDocBlock(): void $this->assertSame($docBlock, $interface->getDocBlock()); } - /** @covers ::create */ public function testIteratesStatements(): void { $method1 = new ClassMethod('MyClass::method1'); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/MethodTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/MethodTest.php index ddfc7e2b..2e6ab447 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/MethodTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/MethodTest.php @@ -24,9 +24,12 @@ use phpDocumentor\Reflection\Php\StrategyContainer; use PhpParser\Comment\Doc; use PhpParser\Node\Expr\FuncCall; +use PhpParser\Node\Identifier; use PhpParser\Node\Name; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Expression; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; @@ -34,18 +37,12 @@ use function current; -/** - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\Argument - * @uses \phpDocumentor\Reflection\Php\Visibility - * @uses \phpDocumentor\Reflection\Php\Factory\Method::matches - * @uses \phpDocumentor\Reflection\Php\Factory\Type - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\Method - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - * @covers ::<protected> - * @covers ::<private> - */ +#[CoversClass(Method::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] +#[UsesClass('\phpDocumentor\Reflection\Php\Argument')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Type')] class MethodTest extends TestCase { use ProphecyTrait; @@ -58,14 +55,12 @@ protected function setUp(): void $this->fixture = new Method($this->docBlockFactory->reveal()); } - /** @covers ::matches */ public function testMatches(): void { $this->assertFalse($this->fixture->matches(self::createContext(null), new stdClass())); $this->assertTrue($this->fixture->matches(self::createContext(null), m::mock(ClassMethod::class))); } - /** @covers ::create */ public function testCreateWithoutParameters(): void { $classMethodMock = $this->buildClassMethodMock(); @@ -87,7 +82,6 @@ public function testCreateWithoutParameters(): void $this->assertEquals('public', (string) $method->getVisibility()); } - /** @covers ::create */ public function testCreateProtectedMethod(): void { $classMethodMock = $this->buildClassMethodMock(); @@ -109,7 +103,6 @@ public function testCreateProtectedMethod(): void $this->assertEquals('protected', (string) $method->getVisibility()); } - /** @covers ::create */ public function testCreateWithDocBlock(): void { $doc = new Doc('Text'); @@ -136,7 +129,9 @@ public function testCreateWithDocBlock(): void private function buildClassMethodMock(): MockInterface { $methodMock = m::mock(ClassMethod::class); - $methodMock->name = 'function'; + $methodMock->name = new Identifier('function'); + $methodMock->byRef = false; + $methodMock->stmts = []; $methodMock->shouldReceive('getAttribute')->andReturn(new Fqsen('\SomeSpace\Class::function()')); $methodMock->params = []; @@ -151,7 +146,6 @@ private function buildClassMethodMock(): MockInterface return $methodMock; } - /** @covers ::create */ public function testIteratesStatements(): void { $method1 = $this->buildClassMethodMock(); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/Namespace_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/Namespace_Test.php index ffef61e5..2e45e06c 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/Namespace_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/Namespace_Test.php @@ -13,13 +13,14 @@ use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_ as ClassNode; use PhpParser\Node\Stmt\Namespace_ as NamespaceNode; +use PHPUnit\Framework\Attributes\CoversClass; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use stdClass; use function current; -/** @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\Namespace_ */ +#[CoversClass(Namespace_::class)] final class Namespace_Test extends TestCase { use ProphecyTrait; @@ -29,7 +30,6 @@ protected function setUp(): void $this->fixture = new Namespace_(); } - /** @covers ::matches */ public function testMatches(): void { $this->assertFalse($this->fixture->matches(self::createContext(null), new stdClass())); @@ -39,7 +39,6 @@ public function testMatches(): void )); } - /** @covers ::create */ public function testCreateThrowsException(): void { $this->expectException(InvalidArgumentException::class); @@ -50,7 +49,6 @@ public function testCreateThrowsException(): void ); } - /** @covers ::create */ public function testIteratesStatements(): void { $class = new ClassNode('\MyClass'); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyBuilderTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyBuilderTest.php new file mode 100644 index 00000000..297734a1 --- /dev/null +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyBuilderTest.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\Php\Factory; + +use phpDocumentor\Reflection\DocBlockFactoryInterface; +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\Location; +use phpDocumentor\Reflection\Php\StrategyContainer; +use phpDocumentor\Reflection\Php\Visibility; +use PhpParser\Node\Stmt\Property as PropertyNode; +use PhpParser\Node\Stmt\PropertyProperty; +use PhpParser\PrettyPrinter; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\TestCase; + +#[CoversClass(PropertyBuilder::class)] +class PropertyBuilderTest extends TestCase +{ + public function testBuildsPropertyElementWithCorrectAttributes(): void + { + $fqsen = new Fqsen('\MyClass::$property'); + $visibility = new Visibility(Visibility::PUBLIC_); + $startLocation = new Location(10); + $endLocation = new Location(20); + + $docBlockFactory = $this->createMock(DocBlockFactoryInterface::class); + $valueConverter = $this->createMock(PrettyPrinter\Standard::class); + $strategies = $this->createMock(StrategyContainer::class); + $reducers = []; + + $prop1 = new PropertyProperty('prop1'); + $propertyNode = new PropertyNode(1, [$prop1]); + $properties = new PropertyIterator($propertyNode); + + $builder = PropertyBuilder::create($valueConverter, $docBlockFactory, $strategies, $reducers); + $builder->fqsen($fqsen) + ->visibility($properties) + ->docblock($properties->getDocComment()) + ->default($properties->getDefault()) + ->static(true) + ->startLocation($startLocation) + ->endLocation($endLocation) + ->type($properties->getType()) + ->readOnly(true) + ->hooks($properties->getHooks()); + + $context = \phpDocumentor\Reflection\Php\Factory\TestCase::createContext(); + $property = $builder->build($context); + + $this->assertSame($fqsen, $property->getFqsen()); + $this->assertEquals($visibility, $property->getVisibility()); + $this->assertNull($property->getDocBlock()); + $this->assertNull($property->getDefault()); + $this->assertTrue($property->isStatic()); + $this->assertSame($startLocation, $property->getLocation()); + $this->assertSame($endLocation, $property->getEndLocation()); + $this->assertNull($property->getType()); + $this->assertTrue($property->isReadOnly()); + } +} diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyIteratorTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyIteratorTest.php index 99a6e21e..a97feaa8 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyIteratorTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyIteratorTest.php @@ -16,23 +16,14 @@ use Mockery as m; use Mockery\Adapter\Phpunit\MockeryTestCase; use PhpParser\Comment\Doc; +use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Property as PropertyNode; use PhpParser\Node\Stmt\PropertyProperty; +use PHPUnit\Framework\Attributes\CoversClass; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\PropertyIterator - * @covers ::__construct - * @covers ::<private> - */ +#[CoversClass(PropertyIterator::class)] class PropertyIteratorTest extends MockeryTestCase { - /** - * @covers ::current() - * @covers ::next() - * @covers ::valid() - * @covers ::rewind() - * @covers ::getName() - */ public function testIterateProps(): void { $prop1 = new PropertyProperty('prop1'); @@ -47,10 +38,6 @@ public function testIterateProps(): void } } - /** - * @covers ::key() - * @covers ::next() - */ public function testKey(): void { $propertyMock = m::mock(PropertyNode::class); @@ -62,15 +49,6 @@ public function testKey(): void $this->assertEquals(1, $fixture->key()); } - /** - * @covers ::__construct - * @covers ::isPublic - * @covers ::isProtected - * @covers ::isPrivate - * @covers ::isStatic - * @covers ::isReadOnly - * @covers ::getLine - */ public function testProxyMethods(): void { $propertyMock = m::mock(PropertyNode::class); @@ -91,22 +69,17 @@ public function testProxyMethods(): void $this->assertEquals(10, $fixture->getLine()); } - /** - * @covers ::__construct - * @covers ::getDefault - */ public function testGetDefault(): void { $prop = m::mock(PropertyProperty::class); - $prop->default = 'myDefault'; + $prop->default = new String_('myDefault'); $property = new PropertyNode(1, [$prop]); $fixture = new PropertyIterator($property); - $this->assertEquals('myDefault', $fixture->getDefault()); + $this->assertEquals(new String_('myDefault'), $fixture->getDefault()); } - /** @covers ::getDocComment */ public function testGetDocCommentPropFirst(): void { $prop = m::mock(PropertyProperty::class); @@ -121,7 +94,6 @@ public function testGetDocCommentPropFirst(): void $this->assertEquals('test', $fixture->getDocComment()->getText()); } - /** @covers ::getDocComment */ public function testGetDocComment(): void { $prop = m::mock(PropertyProperty::class); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyTest.php index 3c375eff..42c5a722 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/PropertyTest.php @@ -25,6 +25,9 @@ use PhpParser\Node\Stmt\Property as PropertyNode; use PhpParser\Node\Stmt\PropertyProperty; use PhpParser\PrettyPrinter\Standard as PrettyPrinter; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; use stdClass; @@ -32,16 +35,13 @@ use function current; use function next; -/** - * @uses \phpDocumentor\Reflection\Php\Factory\PropertyIterator - * @uses \phpDocumentor\Reflection\Php\Property - * @uses \phpDocumentor\Reflection\Php\Visibility - * @uses \phpDocumentor\Reflection\Php\ProjectFactoryStrategies - * @uses \phpDocumentor\Reflection\Php\Factory\Type - * - * @covers \phpDocumentor\Reflection\Php\Factory\Property - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - */ +#[CoversClass(Property::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\PropertyIterator')] +#[UsesClass('\phpDocumentor\Reflection\Php\Property')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Php\ProjectFactoryStrategies')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Type')] final class PropertyTest extends TestCase { use ProphecyTrait; @@ -60,7 +60,7 @@ public function testMatches(): void $this->assertTrue($this->fixture->matches(self::createContext(null), new PropertyNode(1, []))); } - /** @dataProvider visibilityProvider */ + #[DataProvider('visibilityProvider')] public function testCreateWithVisibility(int $input, string $expectedVisibility): void { $constantStub = $this->buildPropertyMock($input); @@ -72,7 +72,7 @@ public function testCreateWithVisibility(int $input, string $expectedVisibility) } /** @return array<string|int[]> */ - public function visibilityProvider(): array + public static function visibilityProvider(): array { return [ [ diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/TestCase.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/TestCase.php index 442a8bb2..36acc0a4 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/TestCase.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/TestCase.php @@ -20,11 +20,13 @@ use phpDocumentor\Reflection\Php\ProjectFactoryStrategy; use phpDocumentor\Reflection\Php\StrategyContainer; use phpDocumentor\Reflection\Types\Context; +use PHPUnit\Framework\Attributes\CoversClass; use stdClass; /** * Base test case for all strategies, to be sure that they check if the can handle objects before handeling them. */ +#[CoversClass(AbstractFactory::class)] abstract class TestCase extends MockeryTestCase { protected ProjectFactoryStrategy $fixture; @@ -37,7 +39,6 @@ public static function createContext(Context|null $typeContext = null): ContextS ); } - /** @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory::create */ public function testCreateThrowsException(): void { $this->expectException(InvalidArgumentException::class); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/TraitUseTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/TraitUseTest.php index 184a58a2..78414df2 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/TraitUseTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/TraitUseTest.php @@ -14,15 +14,15 @@ use phpDocumentor\Reflection\Php\Trait_ as Trait_Element; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\TraitUse as TraitUseNode; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\TraitUse - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - */ +#[CoversClass(TraitUse::class)] +#[CoversClass(AbstractFactory::class)] final class TraitUseTest extends TestCase { /** @return mixed[][] */ - public function consumerProvider(): array + public static function consumerProvider(): array { return [ [new Class_Element(new Fqsen('\MyClass'))], @@ -36,7 +36,6 @@ protected function setUp(): void $this->fixture = new TraitUse(); } - /** @covers ::matches */ public function testMatchesOnlyTraitUseNode(): void { self::assertTrue( @@ -47,7 +46,6 @@ public function testMatchesOnlyTraitUseNode(): void ); } - /** @covers ::create */ public function testCreateThrowsExceptionWhenStackDoesNotContainClass(): void { $this->expectException(InvalidArgumentException::class); @@ -56,12 +54,8 @@ public function testCreateThrowsExceptionWhenStackDoesNotContainClass(): void $this->fixture->create($context, $this->givenTraitUse(), new ProjectFactoryStrategies([])); } - /** - * @param Class_Element|Trait_Element $traitConsumer - * - * @covers ::create - * @dataProvider consumerProvider - */ + /** @param Class_Element|Trait_Element $traitConsumer */ + #[DataProvider('consumerProvider')] public function testCreateWillAddUsedTraitToContextTop(Element $traitConsumer): void { $context = self::createContext()->push($traitConsumer); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/Trait_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/Trait_Test.php index 7acbe604..89cc74f8 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/Trait_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/Trait_Test.php @@ -25,6 +25,8 @@ use PhpParser\Comment\Doc; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Trait_ as TraitNode; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; @@ -32,17 +34,14 @@ use function current; -/** - * @uses \phpDocumentor\Reflection\Php\Trait_ - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\Visibility - * @uses \phpDocumentor\Reflection\Php\Property - * @uses \phpDocumentor\Reflection\Php\Factory\PropertyIterator - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\Trait_ - * @covers \phpDocumentor\Reflection\Php\Factory\Trait_ - * @covers \phpDocumentor\Reflection\Php\Factory\AbstractFactory - */ +#[CoversClass(Trait_::class)] +#[CoversClass(Trait_::class)] +#[CoversClass(AbstractFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Trait_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Php\Property')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\PropertyIterator')] final class Trait_Test extends TestCase { use ProphecyTrait; @@ -61,10 +60,6 @@ public function testMatches(): void $this->assertTrue($this->fixture->matches(self::createContext(null), m::mock(TraitNode::class))); } - /** - * @covers ::create - * @covers ::doCreate - */ public function testSimpleCreate(): void { $containerMock = m::mock(StrategyContainer::class); @@ -77,10 +72,6 @@ public function testSimpleCreate(): void $this->assertEquals('\Space\MyTrait', (string) $trait->getFqsen()); } - /** - * @covers ::create - * @covers ::doCreate - */ public function testIteratesStatements(): void { $method1 = new ClassMethod('\Space\MyTrait::method1'); @@ -111,7 +102,6 @@ public function testIteratesStatements(): void ); } - /** @covers ::create */ public function testCreateWithDocBlock(): void { $doc = new Doc('Text'); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Factory/TypeTest.php b/tests/unit/phpDocumentor/Reflection/Php/Factory/TypeTest.php index 037da55e..be914b6d 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Factory/TypeTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Factory/TypeTest.php @@ -24,15 +24,12 @@ use PhpParser\Node\Name; use PhpParser\Node\NullableType; use PhpParser\Node\UnionType; +use PHPUnit\Framework\Attributes\CoversClass; use PhpUnit\Framework\TestCase as PhpUnitTestCase; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\Factory\Type - * @covers ::<private> - */ +#[CoversClass(Type::class)] final class TypeTest extends PhpUnitTestCase { - /** @covers ::fromPhpParser */ public function testReturnsNullWhenNoTypeIsPassed(): void { $factory = new Type(); @@ -42,7 +39,6 @@ public function testReturnsNullWhenNoTypeIsPassed(): void $this->assertNull($result); } - /** @covers ::fromPhpParser */ public function testReturnsReflectedType(): void { $factory = new Type(); @@ -54,11 +50,10 @@ public function testReturnsReflectedType(): void $this->assertEquals($expected, $result); } - /** @covers ::fromPhpParser */ public function testReturnsNullableTypeWhenPassedAPhpParserNullable(): void { $factory = new Type(); - $given = new NullableType('integer'); + $given = new NullableType(new Identifier('integer')); $expected = new Nullable(new Integer()); $result = $factory->fromPhpParser($given); @@ -66,7 +61,6 @@ public function testReturnsNullableTypeWhenPassedAPhpParserNullable(): void $this->assertEquals($expected, $result); } - /** @covers ::fromPhpParser */ public function testReturnsUnion(): void { $factory = new Type(); @@ -78,7 +72,6 @@ public function testReturnsUnion(): void $this->assertEquals($expected, $result); } - /** @covers ::fromPhpParser */ public function testReturnsUnionGivenVariousTypes(): void { $factory = new Type(); @@ -90,7 +83,6 @@ public function testReturnsUnionGivenVariousTypes(): void $this->assertEquals($expected, $result); } - /** @covers ::fromPhpParser */ public function testReturnsInterseptionType(): void { $factory = new Type(); diff --git a/tests/unit/phpDocumentor/Reflection/Php/FileTest.php b/tests/unit/phpDocumentor/Reflection/Php/FileTest.php index 287dc8bc..9cdf0d3a 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/FileTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/FileTest.php @@ -16,23 +16,21 @@ use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; -/** - * @uses \phpDocumentor\Reflection\Php\Trait_ - * @uses \phpDocumentor\Reflection\Php\Interface_ - * @uses \phpDocumentor\Reflection\Php\Class_ - * @uses \phpDocumentor\Reflection\Php\Namespace_ - * @uses \phpDocumentor\Reflection\Php\Function_ - * @uses \phpDocumentor\Reflection\Php\Constant - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\File - * @covers ::__construct - * @covers ::<private> - */ +#[CoversClass(File::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Trait_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Interface_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Class_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Namespace_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Function_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] final class FileTest extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; public const EXAMPLE_HASH = 'a-hash-string'; @@ -61,10 +59,6 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** - * @covers ::getClasses - * @covers ::AddClass - */ public function testAddAndGetClasses(): void { $this->assertEmpty($this->fixture->getClasses()); @@ -75,12 +69,6 @@ public function testAddAndGetClasses(): void $this->assertEquals(['\MySpace\MyClass' => $class], $this->fixture->getClasses()); } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::getConstants - * @covers ::addConstant - */ public function testAddAndGetConstants(): void { $this->assertEmpty($this->fixture->getConstants()); @@ -91,10 +79,6 @@ public function testAddAndGetConstants(): void $this->assertEquals(['\MySpace::MY_CONSTANT' => $constant], $this->fixture->getConstants()); } - /** - * @covers ::getFunctions - * @covers ::addFunction - */ public function testAddAndGetFunctions(): void { $this->assertEmpty($this->fixture->getFunctions()); @@ -105,10 +89,6 @@ public function testAddAndGetFunctions(): void $this->assertEquals(['\MySpace::MyFunction()' => $function], $this->fixture->getFunctions()); } - /** - * @covers ::getInterfaces - * @covers ::addInterface - */ public function testAddAndGetInterfaces(): void { $this->assertEmpty($this->fixture->getInterfaces()); @@ -119,10 +99,6 @@ public function testAddAndGetInterfaces(): void $this->assertEquals(['\MySpace\MyInterface' => $interface], $this->fixture->getInterfaces()); } - /** - * @covers ::getTraits - * @covers ::addTrait - */ public function testAddAndGetTraits(): void { $this->assertEmpty($this->fixture->getTraits()); @@ -133,10 +109,6 @@ public function testAddAndGetTraits(): void $this->assertEquals(['\MySpace\MyTrait' => $trait], $this->fixture->getTraits()); } - /** - * @covers ::getEnums - * @covers ::addEnum - */ public function testAddAndGetEnums(): void { $this->assertEmpty($this->fixture->getEnums()); @@ -147,40 +119,31 @@ public function testAddAndGetEnums(): void $this->assertEquals(['\MySpace\MyEnum' => $enum], $this->fixture->getEnums()); } - /** @covers ::getDocBlock */ public function testGetDocBlock(): void { $this->assertSame($this->docBlock, $this->fixture->getDocBlock()); } - /** @covers ::getHash */ public function testGetHash(): void { $this->assertSame(self::EXAMPLE_HASH, $this->fixture->getHash()); } - /** @covers ::getName */ public function testGetName(): void { $this->assertSame(self::EXAMPLE_NAME, $this->fixture->getName()); } - /** @covers ::getPath */ public function testSetAndGetPath(): void { $this->assertSame(self::EXAMPLE_PATH, $this->fixture->getPath()); } - /** @covers ::getSource */ public function testSetAndGetSource(): void { $this->assertSame(self::EXAMPLE_SOURCE, $this->fixture->getSource()); } - /** - * @covers ::addNamespace - * @covers ::getNamespaces - */ public function testSetAndGetNamespaceAliases(): void { $this->assertEmpty($this->fixture->getNamespaces()); @@ -190,10 +153,6 @@ public function testSetAndGetNamespaceAliases(): void $this->assertEquals(['\MyNamepace\Foo' => new Fqsen('\MyNamepace\Foo')], $this->fixture->getNamespaces()); } - /** - * @covers ::getIncludes - * @covers ::addInclude - */ public function testAddAndGetIncludes(): void { $this->assertEmpty($this->fixture->getIncludes()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Function_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Function_Test.php index 6ca038e8..fbbdf7d0 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Function_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Function_Test.php @@ -19,21 +19,17 @@ use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; use phpDocumentor\Reflection\Types\Mixed_; use phpDocumentor\Reflection\Types\String_; - -/** - * @uses \phpDocumentor\Reflection\Php\Argument - * @uses \phpDocumentor\Reflection\DocBlock - * @uses \phpDocumentor\Reflection\Fqsen - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Function_ - * @covers ::__construct - * @covers ::<private> - * - * @property Function_ $fixture - */ +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; + +/** @property Function_ $fixture */ +#[CoversClass(Function_::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Argument')] +#[UsesClass('\phpDocumentor\Reflection\DocBlock')] +#[UsesClass('\phpDocumentor\Reflection\Fqsen')] final class Function_Test extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private Fqsen $fqsen; @@ -54,16 +50,11 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** @covers ::getName */ public function testGetName(): void { $this->assertEquals('MyFunction', $this->fixture->getName()); } - /** - * @covers ::addArgument - * @covers ::getArguments - */ public function testAddAndGetArguments(): void { $argument = new Argument('firstArgument'); @@ -72,26 +63,22 @@ public function testAddAndGetArguments(): void $this->assertEquals([$argument], $this->fixture->getArguments()); } - /** @covers ::getFqsen */ public function testGetFqsen(): void { $this->assertSame($this->fqsen, $this->fixture->getFqsen()); } - /** @covers ::getDocBlock */ public function testGetDocblock(): void { $this->assertSame($this->docBlock, $this->fixture->getDocBlock()); } - /** @covers ::getReturnType */ public function testGetDefaultReturnType(): void { $function = new Function_($this->fqsen); $this->assertEquals(new Mixed_(), $function->getReturnType()); } - /** @covers ::getReturnType */ public function testGetReturnTypeFromConstructor(): void { $returnType = new String_(); @@ -100,14 +87,12 @@ public function testGetReturnTypeFromConstructor(): void $this->assertSame($returnType, $function->getReturnType()); } - /** @covers ::getHasReturnByReference */ public function testGetHasReturnByReference(): void { $function = new Function_($this->fqsen); $this->assertSame(false, $function->getHasReturnByReference()); } - /** @covers ::getHasReturnByReference */ public function testGetHasReturnByReferenceFromConstructor(): void { $function = new Function_($this->fqsen, null, null, null, null, true); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Interface_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Interface_Test.php index d5d1ccee..2d63f04f 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Interface_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Interface_Test.php @@ -18,23 +18,19 @@ use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; - -/** - * @uses \phpDocumentor\Reflection\DocBlock - * @uses \phpDocumentor\Reflection\Fqsen - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Interface_ - * @covers ::__construct - * @covers ::<private> - * - * @property Interface_ $fixture - */ +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; + +/** @property Interface_ $fixture */ +#[CoversClass(Interface_::class)] +#[UsesClass('\phpDocumentor\Reflection\DocBlock')] +#[UsesClass('\phpDocumentor\Reflection\Fqsen')] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] final class Interface_Test extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private Fqsen $fqsen; @@ -63,28 +59,21 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** @covers ::getName */ public function testGetName(): void { $this->assertSame($this->fqsen->getName(), $this->fixture->getName()); } - /** @covers ::getFqsen */ public function testGetFqsen(): void { $this->assertSame($this->fqsen, $this->fixture->getFqsen()); } - /** @covers ::getDocBlock */ public function testGetDocblock(): void { $this->assertSame($this->docBlock, $this->fixture->getDocBlock()); } - /** - * @covers ::addConstant - * @covers ::getConstants - */ public function testSettingAndGettingConstants(): void { $this->assertEquals([], $this->fixture->getConstants()); @@ -96,10 +85,6 @@ public function testSettingAndGettingConstants(): void $this->assertEquals(['\MySpace\MyInterface::MY_CONSTANT' => $constant], $this->fixture->getConstants()); } - /** - * @covers ::addMethod - * @covers ::getMethods - */ public function testSettingAndGettingMethods(): void { $this->assertEquals([], $this->fixture->getMethods()); @@ -111,7 +96,6 @@ public function testSettingAndGettingMethods(): void $this->assertEquals(['\MySpace\MyInterface::myMethod()' => $method], $this->fixture->getMethods()); } - /** @covers ::getParents */ public function testReturningTheParentsOfThisInterface(): void { $this->assertSame($this->exampleParents, $this->fixture->getParents()); @@ -123,7 +107,6 @@ public function testLineAndColumnNumberIsReturnedWhenALocationIsProvided(): void $this->assertLineAndColumnNumberIsReturnedWhenALocationIsProvided($fixture); } - /** @covers ::__construct */ public function testArrayWithParentsMustBeFqsenObjects(): void { $this->expectException(InvalidArgumentException::class); diff --git a/tests/unit/phpDocumentor/Reflection/Php/MetadataContainerTest.php b/tests/unit/phpDocumentor/Reflection/Php/MetadataContainerTestHelper.php similarity index 85% rename from tests/unit/phpDocumentor/Reflection/Php/MetadataContainerTest.php rename to tests/unit/phpDocumentor/Reflection/Php/MetadataContainerTestHelper.php index db3cfdd4..fc444117 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/MetadataContainerTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/MetadataContainerTestHelper.php @@ -7,12 +7,8 @@ use phpDocumentor\Reflection\Exception; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; -trait MetadataContainerTest +trait MetadataContainerTestHelper { - /** - * @covers ::addMetadata - * @covers ::getMetadata - */ public function testSetMetaDataForNonExistingKey(): void { $stub = new MetadataStub('stub'); @@ -22,7 +18,6 @@ public function testSetMetaDataForNonExistingKey(): void self::assertSame(['stub' => $stub], $this->getFixture()->getMetadata()); } - /** @covers ::addMetadata */ public function testSetMetaDataWithExistingKeyThrows(): void { self::expectException(Exception::class); diff --git a/tests/unit/phpDocumentor/Reflection/Php/MethodTest.php b/tests/unit/phpDocumentor/Reflection/Php/MethodTest.php index 3798bc5a..c72b5fc3 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/MethodTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/MethodTest.php @@ -19,19 +19,16 @@ use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; use phpDocumentor\Reflection\Types\Mixed_; use phpDocumentor\Reflection\Types\String_; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; -/** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Method - * @covers ::__construct - * @covers ::<private> - * - * @property Method $fixture - */ +/** @property Method $fixture */ +#[CoversClass(Method::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Php\Argument')] final class MethodTest extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private Fqsen $fqsen; @@ -52,10 +49,6 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** - * @covers ::getFqsen - * @covers ::getName - */ public function testGetFqsenAndGetName(): void { $method = new Method($this->fqsen); @@ -64,7 +57,6 @@ public function testGetFqsenAndGetName(): void $this->assertEquals($this->fqsen->getName(), $method->getName()); } - /** @covers ::getDocblock */ public function testGetDocBlock(): void { $method = new Method($this->fqsen, $this->visibility, $this->docblock); @@ -72,12 +64,6 @@ public function testGetDocBlock(): void $this->assertSame($this->docblock, $method->getDocBlock()); } - /** - * @uses \phpDocumentor\Reflection\Php\Argument - * - * @covers ::getArguments - * @covers ::addArgument - */ public function testAddingAndGettingArguments(): void { $method = new Method($this->fqsen); @@ -89,7 +75,6 @@ public function testAddingAndGettingArguments(): void $this->assertEquals([$argument], $method->getArguments()); } - /** @covers ::isAbstract */ public function testGettingWhetherMethodIsAbstract(): void { $method = new Method($this->fqsen, $this->visibility, $this->docblock, false); @@ -99,7 +84,6 @@ public function testGettingWhetherMethodIsAbstract(): void $this->assertTrue($method->isAbstract()); } - /** @covers ::isFinal */ public function testGettingWhetherMethodIsFinal(): void { $method = new Method($this->fqsen, $this->visibility, $this->docblock, false, false, false); @@ -109,7 +93,6 @@ public function testGettingWhetherMethodIsFinal(): void $this->assertTrue($method->isFinal()); } - /** @covers ::isStatic */ public function testGettingWhetherMethodIsStatic(): void { $method = new Method($this->fqsen, $this->visibility, $this->docblock, false, false, false); @@ -119,28 +102,24 @@ public function testGettingWhetherMethodIsStatic(): void $this->assertTrue($method->isStatic()); } - /** @covers ::getVisibility */ public function testGettingVisibility(): void { $method = new Method($this->fqsen, $this->visibility, $this->docblock, false, false, false); $this->assertSame($this->visibility, $method->getVisibility()); } - /** @covers ::getVisibility */ public function testGetDefaultVisibility(): void { $method = new Method($this->fqsen); $this->assertEquals(new Visibility('public'), $method->getVisibility()); } - /** @covers ::getReturnType */ public function testGetDefaultReturnType(): void { $method = new Method($this->fqsen); $this->assertEquals(new Mixed_(), $method->getReturnType()); } - /** @covers ::getReturnType */ public function testGetReturnTypeFromConstructor(): void { $returnType = new String_(); @@ -159,14 +138,12 @@ public function testGetReturnTypeFromConstructor(): void $this->assertSame($returnType, $method->getReturnType()); } - /** @covers ::getHasReturnByReference */ public function testGetHasReturnByReference(): void { $method = new Method($this->fqsen); $this->assertSame(false, $method->getHasReturnByReference()); } - /** @covers ::getHasReturnByReference */ public function testGetHasReturnByReferenceFromConstructor(): void { $method = new Method($this->fqsen, null, null, false, false, false, null, null, null, true); diff --git a/tests/unit/phpDocumentor/Reflection/Php/Namespace_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Namespace_Test.php index 7179d2db..3ed7d211 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Namespace_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Namespace_Test.php @@ -16,18 +16,18 @@ use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; /** * Tests the functionality for the Namespace_ class. - * - * @coversDefaultClass phpDocumentor\Reflection\Php\Namespace_ */ // @codingStandardsIgnoreStart +#[CoversClass(Namespace_::class)] class Namespace_Test extends TestCase // @codingStandardsIgnoreEnd { - use MetadataContainerTest; + use MetadataContainerTestHelper; protected Namespace_ $fixture; @@ -51,11 +51,6 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** - * @covers ::__construct - * @covers ::getClasses - * @covers ::AddClass - */ public function testAddAndGetClasses(): void { $this->assertEmpty($this->fixture->getClasses()); @@ -66,11 +61,6 @@ public function testAddAndGetClasses(): void $this->assertEquals(['\MySpace\MyClass' => $class], $this->fixture->getClasses()); } - /** - * @covers ::__construct - * @covers ::getConstants - * @covers ::addConstant - */ public function testAddAndGetConstants(): void { $this->assertEmpty($this->fixture->getConstants()); @@ -81,11 +71,6 @@ public function testAddAndGetConstants(): void $this->assertEquals(['\MySpace::MY_CONSTANT' => $constant], $this->fixture->getConstants()); } - /** - * @covers ::__construct - * @covers ::getFunctions - * @covers ::addFunction - */ public function testAddAndGetFunctions(): void { $this->assertEmpty($this->fixture->getFunctions()); @@ -96,11 +81,6 @@ public function testAddAndGetFunctions(): void $this->assertEquals(['\MySpace\MyFunction()' => $function], $this->fixture->getFunctions()); } - /** - * @covers ::__construct - * @covers ::getInterfaces - * @covers ::addInterface - */ public function testAddAndGetInterfaces(): void { $this->assertEmpty($this->fixture->getInterfaces()); @@ -111,11 +91,6 @@ public function testAddAndGetInterfaces(): void $this->assertEquals(['\MySpace\MyInterface' => $interface], $this->fixture->getInterfaces()); } - /** - * @covers ::__construct - * @covers ::getTraits - * @covers ::addTrait - */ public function testAddAndGetTraits(): void { $this->assertEmpty($this->fixture->getTraits()); @@ -126,11 +101,6 @@ public function testAddAndGetTraits(): void $this->assertEquals(['\MySpace\MyTrait' => $trait], $this->fixture->getTraits()); } - /** - * @covers ::__construct - * @covers ::getFqsen - * @covers ::getName - */ public function testGetFqsen(): void { $this->assertSame($this->fqsen, $this->fixture->getFqsen()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/NodesFactoryTest.php b/tests/unit/phpDocumentor/Reflection/Php/NodesFactoryTest.php index b7d69a80..1854ff0d 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/NodesFactoryTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/NodesFactoryTest.php @@ -14,20 +14,16 @@ namespace phpDocumentor\Reflection\Php; use phpDocumentor\Reflection\NodeVisitor\ElementNameResolver; -use PhpParser\Lexer\Emulative; use PhpParser\NodeTraverser; use PhpParser\NodeTraverserInterface; use PhpParser\NodeVisitor\NameResolver; use PhpParser\Parser; use PhpParser\ParserFactory; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\NodesFactory - * @covers ::__construct - * @covers ::<private> - */ +#[CoversClass(NodesFactory::class)] final class NodesFactoryTest extends TestCase { use ProphecyTrait; @@ -37,8 +33,6 @@ final class NodesFactoryTest extends TestCase * * Unfortunately, we cannot actually inspect whether all recommended items were instantiated, so I create an example * NodesFactory containing what I expected and this test will verify that no regression took place. - * - * @covers ::createInstance */ public function testThatAFactoryWithRecommendedComponentsCanBeInstantiated(): void { @@ -48,7 +42,6 @@ public function testThatAFactoryWithRecommendedComponentsCanBeInstantiated(): vo $this->assertEquals($this->givenTheExpectedDefaultNodesFactory(), $factory); } - /** @covers ::create */ public function testThatCodeGetsConvertedIntoNodes(): void { $parser = $this->prophesize(Parser::class); @@ -66,16 +59,7 @@ public function testThatCodeGetsConvertedIntoNodes(): void private function givenTheExpectedDefaultNodesFactory(): NodesFactory { - $lexer = new Emulative([ - 'usedAttributes' => [ - 'comments', - 'startLine', - 'endLine', - 'startFilePos', - 'endFilePos', - ], - ]); - $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7, $lexer); + $parser = (new ParserFactory())->createForNewestSupportedVersion(); $traverser = new NodeTraverser(); $traverser->addVisitor(new NameResolver()); $traverser->addVisitor(new ElementNameResolver()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/ProjectFactoryStrategiesTest.php b/tests/unit/phpDocumentor/Reflection/Php/ProjectFactoryStrategiesTest.php index ce1b20ef..e8a332d0 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/ProjectFactoryStrategiesTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/ProjectFactoryStrategiesTest.php @@ -17,29 +17,22 @@ use phpDocumentor\Reflection\Php\Factory\ContextStack; use phpDocumentor\Reflection\Php\Factory\DummyFactoryStrategy; use phpDocumentor\Reflection\Types\Context; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use stdClass; /** * Test case for ProjectFactoryStrategies - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\ProjectFactoryStrategies - * @covers ::__construct - * @covers ::<private> */ +#[CoversClass(ProjectFactoryStrategies::class)] class ProjectFactoryStrategiesTest extends TestCase { - /** @covers ::addStrategy */ public function testStrategiesAreChecked(): void { new ProjectFactoryStrategies([new DummyFactoryStrategy()]); $this->assertTrue(true); } - /** - * @covers ::findMatching - * @covers ::addStrategy - */ public function testFindMatching(): void { $strategy = new DummyFactoryStrategy(); @@ -52,7 +45,6 @@ public function testFindMatching(): void $this->assertSame($strategy, $actual); } - /** @covers ::findMatching */ public function testCreateThrowsExceptionWhenStrategyNotFound(): void { $this->expectException(OutOfBoundsException::class); diff --git a/tests/unit/phpDocumentor/Reflection/Php/ProjectFactoryTest.php b/tests/unit/phpDocumentor/Reflection/Php/ProjectFactoryTest.php index ed1e5736..67da45f4 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/ProjectFactoryTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/ProjectFactoryTest.php @@ -19,6 +19,8 @@ use phpDocumentor\Reflection\File\LocalFile; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Php\Factory\ContextStack; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use Prophecy\Argument as ProphesizeArgument; use Prophecy\PhpUnit\ProphecyTrait; @@ -28,57 +30,37 @@ use function key; use function md5; -/** - * @uses \phpDocumentor\Reflection\Php\Project - * @uses \phpDocumentor\Reflection\Php\Namespace_ - * @uses \phpDocumentor\Reflection\Php\Class_ - * @uses \phpDocumentor\Reflection\Php\Interface_ - * @uses \phpDocumentor\Reflection\Php\Trait_ - * @uses \phpDocumentor\Reflection\Php\Constant - * @uses \phpDocumentor\Reflection\Php\File - * @uses \phpDocumentor\Reflection\Php\Function_ - * @uses \phpDocumentor\Reflection\Php\ProjectFactoryStrategies - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\ProjectFactory - * @covers ::__construct - * @covers ::<private> - */ +#[CoversClass(ProjectFactory::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Project')] +#[UsesClass('\phpDocumentor\Reflection\Php\Namespace_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Class_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Interface_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Trait_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Constant')] +#[UsesClass('\phpDocumentor\Reflection\Php\File')] +#[UsesClass('\phpDocumentor\Reflection\Php\Function_')] +#[UsesClass('\phpDocumentor\Reflection\Php\ProjectFactoryStrategies')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Middleware\ChainFactory')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Property')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Method')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Class_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Interface_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\ClassConstant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Define')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\GlobalConstant')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\Trait_')] +#[UsesClass('\phpDocumentor\Reflection\Php\Factory\File')] +#[UsesClass('\phpDocumentor\Reflection\Php\NodesFactory')] final class ProjectFactoryTest extends MockeryTestCase { use ProphecyTrait; - /** - * Tests whether a factory can be instantiated using recommended factories. - * - * This test is unable to test which exact factories are instantiated because that is not exposed by - * the factory. Even using assertEquals to do a regression test against a pre-populated factory does not - * work because there is a piece of randomness inside one of the properties; causing the tests to fail when - * you try to do it like that. - * - * @uses \phpDocumentor\Reflection\Middleware\ChainFactory - * @uses \phpDocumentor\Reflection\Php\Factory\Property - * @uses \phpDocumentor\Reflection\Php\Factory\Argument - * @uses \phpDocumentor\Reflection\Php\Factory\Method - * @uses \phpDocumentor\Reflection\Php\Factory\Class_ - * @uses \phpDocumentor\Reflection\Php\Factory\Interface_ - * @uses \phpDocumentor\Reflection\Php\Factory\ClassConstant - * @uses \phpDocumentor\Reflection\Php\Factory\Define - * @uses \phpDocumentor\Reflection\Php\Factory\GlobalConstant - * @uses \phpDocumentor\Reflection\Php\Factory\Argument - * @uses \phpDocumentor\Reflection\Php\Factory\Trait_ - * @uses \phpDocumentor\Reflection\Php\Factory\DocBlock - * @uses \phpDocumentor\Reflection\Php\Factory\File - * @uses \phpDocumentor\Reflection\Php\NodesFactory - * - * @covers ::createInstance - */ public function testCreatingAnInstanceInstantiatesItWithTheRecommendedStrategies(): void { $this->assertInstanceOf(ProjectFactory::class, ProjectFactory::createInstance()); } - /** @covers ::create */ public function testCreate(): void { $expected = ['some/file.php', 'some/other.php']; @@ -125,7 +107,6 @@ public function testCreate(): void $this->assertEquals(['some/file.php', 'some/other.php'], $projectFilePaths); } - /** @covers ::create */ public function testCreateThrowsExceptionWhenStrategyNotFound(): void { $this->expectException(OutOfBoundsException::class); @@ -133,7 +114,6 @@ public function testCreateThrowsExceptionWhenStrategyNotFound(): void $projectFactory->create('MyProject', ['aa']); } - /** @covers ::create */ public function testCreateProjectFromFileWithNamespacedClass(): void { $file = new File(md5('some/file.php'), 'some/file.php'); @@ -150,7 +130,6 @@ public function testCreateProjectFromFileWithNamespacedClass(): void $this->assertEquals('\mySpace\MyClass', key($mySpace->getClasses())); } - /** @covers ::create */ public function testWithNamespacedInterface(): void { $file = new File(md5('some/file.php'), 'some/file.php'); @@ -165,7 +144,6 @@ public function testWithNamespacedInterface(): void $this->assertEquals('\mySpace\MyInterface', key($mySpace->getInterfaces())); } - /** @covers ::create */ public function testWithNamespacedFunction(): void { $file = new File(md5('some/file.php'), 'some/file.php'); @@ -180,7 +158,6 @@ public function testWithNamespacedFunction(): void $this->assertEquals('\mySpace\function()', key($mySpace->getFunctions())); } - /** @covers ::create */ public function testWithNamespacedConstant(): void { $file = new File(md5('some/file.php'), 'some/file.php'); @@ -195,7 +172,6 @@ public function testWithNamespacedConstant(): void $this->assertEquals('\mySpace::MY_CONST', key($mySpace->getConstants())); } - /** @covers ::create */ public function testWithNamespacedTrait(): void { $file = new File(md5('some/file.php'), 'some/file.php'); @@ -210,7 +186,6 @@ public function testWithNamespacedTrait(): void $this->assertEquals('\mySpace\MyTrait', key($mySpace->getTraits())); } - /** @covers ::create */ public function testNamespaceSpreadOverMultipleFiles(): void { $someFile = new File(md5('some/file.php'), 'some/file.php'); @@ -227,7 +202,6 @@ public function testNamespaceSpreadOverMultipleFiles(): void $this->assertCount(2, current($namespaces)->getClasses()); } - /** @covers ::create */ public function testSingleFileMultipleNamespaces(): void { $someFile = new File(md5('some/file.php'), 'some/file.php'); diff --git a/tests/unit/phpDocumentor/Reflection/Php/ProjectTest.php b/tests/unit/phpDocumentor/Reflection/Php/ProjectTest.php index 8df072bf..724a996c 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/ProjectTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/ProjectTest.php @@ -14,15 +14,16 @@ namespace phpDocumentor\Reflection\Php; use phpDocumentor\Reflection\Fqsen; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; /** * Tests the functionality for the Project class. - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Project - * @covers ::__construct - * @covers ::<private> */ +#[CoversClass(Project::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Namespace_')] +#[UsesClass('\phpDocumentor\Reflection\Php\File')] class ProjectTest extends TestCase { final public const EXAMPLE_NAME = 'Initial name'; @@ -37,23 +38,11 @@ protected function setUp(): void $this->fixture = new Project(self::EXAMPLE_NAME); } - /** - * @uses \phpDocumentor\Reflection\Php\Namespace_ - * - * @covers ::getName - */ public function testGetSetName(): void { $this->assertEquals(self::EXAMPLE_NAME, $this->fixture->getName()); } - /** - * @uses \phpDocumentor\Reflection\Php\Namespace_ - * @uses \phpDocumentor\Reflection\Php\File - * - * @covers ::getFiles - * @covers ::addFile - */ public function testGetAddFiles(): void { $this->assertEmpty($this->fixture->getFiles()); @@ -64,11 +53,6 @@ public function testGetAddFiles(): void $this->assertSame(['foo/bar' => $include], $this->fixture->getFiles()); } - /** - * @uses \phpDocumentor\Reflection\Php\Namespace_ - * - * @covers ::getRootNamespace - */ public function testGetRootNamespace(): void { $this->assertInstanceOf(Namespace_::class, $this->fixture->getRootNamespace()); @@ -79,12 +63,6 @@ public function testGetRootNamespace(): void $this->assertSame($namespaceDescriptor, $project->getRootNamespace()); } - /** - * @uses \phpDocumentor\Reflection\Php\Namespace_ - * - * @covers ::getNamespaces - * @covers ::addNamespace - */ public function testGetAddNamespace(): void { $this->assertEmpty($this->fixture->getNamespaces()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/PropertyTest.php b/tests/unit/phpDocumentor/Reflection/Php/PropertyTest.php index 5f8b319d..44a7d5ef 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/PropertyTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/PropertyTest.php @@ -18,18 +18,20 @@ use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; use phpDocumentor\Reflection\Types\Integer; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; /** * Tests the functionality for the Property class. * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Property - * @covers ::__construct - * @covers ::<private> * @property Property $fixture */ +#[CoversClass(Property::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Types\Integer')] final class PropertyTest extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private Fqsen $fqsen; @@ -50,12 +52,6 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::getFqsen - * @covers ::getName - */ public function testGetFqsenAndGetName(): void { $property = new Property($this->fqsen); @@ -64,12 +60,6 @@ public function testGetFqsenAndGetName(): void $this->assertEquals($this->fqsen->getName(), $property->getName()); } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::isStatic - * @covers ::__construct - */ public function testGettingWhetherPropertyIsStatic(): void { $property = new Property($this->fqsen, $this->visibility, $this->docBlock, null, false); @@ -79,12 +69,6 @@ public function testGettingWhetherPropertyIsStatic(): void $this->assertTrue($property->isStatic()); } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::isReadOnly - * @covers ::__construct - */ public function testGettingWhetherPropertyIsReadOnly(): void { $property = new Property($this->fqsen, $this->visibility, $this->docBlock, null); @@ -105,12 +89,6 @@ public function testGettingWhetherPropertyIsReadOnly(): void $this->assertTrue($property->isReadOnly()); } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::getVisibility - * @covers ::__construct - */ public function testGettingVisibility(): void { $property = new Property($this->fqsen, $this->visibility, $this->docBlock, null, true); @@ -118,12 +96,6 @@ public function testGettingVisibility(): void $this->assertSame($this->visibility, $property->getVisibility()); } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::getTypes - * @covers ::addType - */ public function testSetAndGetTypes(): void { $property = new Property($this->fqsen, $this->visibility, $this->docBlock, null, true); @@ -133,11 +105,6 @@ public function testSetAndGetTypes(): void $this->assertEquals(['a'], $property->getTypes()); } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::getDefault - */ public function testGetDefault(): void { $property = new Property($this->fqsen, $this->visibility, $this->docBlock, null, false); @@ -147,11 +114,6 @@ public function testGetDefault(): void $this->assertEquals('a', $property->getDefault()); } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::getDocBlock - */ public function testGetDocBlock(): void { $property = new Property($this->fqsen, $this->visibility, $this->docBlock, null, false); @@ -164,12 +126,6 @@ public function testLineAndColumnNumberIsReturnedWhenALocationIsProvided(): void $this->assertLineAndColumnNumberIsReturnedWhenALocationIsProvided($fixture); } - /** - * @uses \phpDocumentor\Reflection\Php\Visibility - * @uses \phpDocumentor\Reflection\Types\Integer - * - * @covers ::getType - */ public function testGetType(): void { $type = new Integer(); diff --git a/tests/unit/phpDocumentor/Reflection/Php/TestCase.php b/tests/unit/phpDocumentor/Reflection/Php/TestCase.php index 9be46c68..75712494 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/TestCase.php +++ b/tests/unit/phpDocumentor/Reflection/Php/TestCase.php @@ -15,19 +15,20 @@ use phpDocumentor\Reflection\Element; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; +use PHPUnit\Framework\Attributes\CoversFunction; +use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase as BaseTestCase; /** * Base test case for all elements. */ +#[CoversFunction('getLocation')] +#[CoversFunction('getEndLocation')] +#[UsesClass('\phpDocumentor\Reflection\Location')] abstract class TestCase extends BaseTestCase { protected Element|MetaDataContainerInterface $fixture; - /** - * @covers ::getLocation - * @covers ::getEndLocation - */ public function testLineNumberIsMinusOneWhenNoneIsProvided(): void { $this->assertSame(-1, $this->fixture->getLocation()->getLineNumber()); @@ -37,12 +38,6 @@ public function testLineNumberIsMinusOneWhenNoneIsProvided(): void $this->assertSame(0, $this->fixture->getEndLocation()->getColumnNumber()); } - /** - * @uses \phpDocumentor\Reflection\Location - * - * @covers ::getLocation - * @covers ::getEndLocation - */ public function testLineAndColumnNumberIsReturnedWhenALocationIsProvided(): void { } diff --git a/tests/unit/phpDocumentor/Reflection/Php/Trait_Test.php b/tests/unit/phpDocumentor/Reflection/Php/Trait_Test.php index 72f5ddd3..afddb001 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/Trait_Test.php +++ b/tests/unit/phpDocumentor/Reflection/Php/Trait_Test.php @@ -17,16 +17,17 @@ use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Location; use phpDocumentor\Reflection\Metadata\MetaDataContainer as MetaDataContainerInterface; - -/** - * @coversDefaultClass \phpDocumentor\Reflection\Php\Trait_ - * @covers ::__construct - * @covers ::<private> - * @property Trait_ $fixture - */ +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\UsesClass; + +/** @property Trait_ $fixture */ +#[CoversClass(Trait_::class)] +#[UsesClass('\phpDocumentor\Reflection\Php\Property')] +#[UsesClass('\phpDocumentor\Reflection\Php\Visibility')] +#[UsesClass('\phpDocumentor\Reflection\Php\Method')] final class Trait_Test extends TestCase { - use MetadataContainerTest; + use MetadataContainerTestHelper; private Fqsen $fqsen; @@ -47,23 +48,12 @@ private function getFixture(): MetaDataContainerInterface return $this->fixture; } - /** - * @covers ::getFqsen - * @covers ::getName - */ public function testGetFqsenAndGetName(): void { $this->assertSame($this->fqsen, $this->fixture->getFqsen()); $this->assertEquals($this->fqsen->getName(), $this->fixture->getName()); } - /** - * @uses \phpDocumentor\Reflection\Php\Property - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::addProperty - * @covers ::getProperties - */ public function testAddAndGettingProperties(): void { $this->assertEquals([], $this->fixture->getProperties()); @@ -75,13 +65,6 @@ public function testAddAndGettingProperties(): void $this->assertEquals(['\MyTrait::$myProperty' => $property], $this->fixture->getProperties()); } - /** - * @uses \phpDocumentor\Reflection\Php\Method - * @uses \phpDocumentor\Reflection\Php\Visibility - * - * @covers ::addMethod - * @covers ::getMethods - */ public function testAddAndGettingMethods(): void { $this->assertEquals([], $this->fixture->getMethods()); @@ -93,10 +76,6 @@ public function testAddAndGettingMethods(): void $this->assertEquals(['\MyTrait::myMethod()' => $method], $this->fixture->getMethods()); } - /** - * @covers ::getUsedTraits - * @covers ::AddUsedTrait - */ public function testAddAndGettingUsedTrait(): void { $this->assertEmpty($this->fixture->getUsedTraits()); @@ -108,10 +87,6 @@ public function testAddAndGettingUsedTrait(): void $this->assertSame(['\MyTrait' => $trait], $this->fixture->getUsedTraits()); } - /** - * @covers ::getConstants - * @covers ::addConstant - */ public function testAddAndGettingConstants(): void { $this->assertEmpty($this->fixture->getConstants()); @@ -123,7 +98,6 @@ public function testAddAndGettingConstants(): void $this->assertSame(['\MyClass::MY_CONSTANT' => $constant], $this->fixture->getConstants()); } - /** @covers ::getDocBlock */ public function testGetDocblock(): void { $this->assertSame($this->docBlock, $this->fixture->getDocBlock()); diff --git a/tests/unit/phpDocumentor/Reflection/Php/ValueEvaluator/ConstantEvaluatorTest.php b/tests/unit/phpDocumentor/Reflection/Php/ValueEvaluator/ConstantEvaluatorTest.php index ea96ce1d..7c5754d0 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/ValueEvaluator/ConstantEvaluatorTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/ValueEvaluator/ConstantEvaluatorTest.php @@ -10,14 +10,12 @@ use PhpParser\ConstExprEvaluationException; use PhpParser\Node\Expr\ShellExec; use PhpParser\Node\Scalar\MagicConst\Namespace_; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -/** @coversDefaultClass \phpDocumentor\Reflection\Php\ValueEvaluator\ConstantEvaluator */ +#[CoversClass(ConstantEvaluator::class)] final class ConstantEvaluatorTest extends TestCase { - /** @covers ::evaluate */ - - /** @covers ::evaluateFallback */ public function testEvaluateThrowsWhenTypeContextIsNotSet(): void { $this->expectException(ConstExprEvaluationException::class); @@ -26,9 +24,6 @@ public function testEvaluateThrowsWhenTypeContextIsNotSet(): void $evaluator->evaluate(new Namespace_(), new ContextStack(new Project('test'))); } - /** @covers ::evaluate */ - - /** @covers ::evaluateFallback */ public function testEvaluateThrowsOnUnknownExpression(): void { $this->expectException(ConstExprEvaluationException::class); @@ -37,9 +32,6 @@ public function testEvaluateThrowsOnUnknownExpression(): void $result = $evaluator->evaluate(new ShellExec([]), new ContextStack(new Project('test'), new Context('Test'))); } - /** @covers ::evaluate */ - - /** @covers ::evaluateFallback */ public function testEvaluateReturnsNamespaceFromContext(): void { $evaluator = new ConstantEvaluator(); diff --git a/tests/unit/phpDocumentor/Reflection/Php/VisibilityTest.php b/tests/unit/phpDocumentor/Reflection/Php/VisibilityTest.php index 609d644f..17cf1e34 100644 --- a/tests/unit/phpDocumentor/Reflection/Php/VisibilityTest.php +++ b/tests/unit/phpDocumentor/Reflection/Php/VisibilityTest.php @@ -14,20 +14,17 @@ namespace phpDocumentor\Reflection\Php; use InvalidArgumentException; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; /** * Test case for Visibility - * - * @coversDefaultClass \phpDocumentor\Reflection\Php\Visibility */ +#[CoversClass(Visibility::class)] class VisibilityTest extends TestCase { - /** - * @dataProvider visibilityProvider - * @covers ::__construct - * @covers ::__toString - */ + #[DataProvider('visibilityProvider')] public function testVisibility(string $input, string $expected): void { $visibility = new Visibility($input); @@ -36,7 +33,7 @@ public function testVisibility(string $input, string $expected): void } /** @return string[][] */ - public function visibilityProvider(): array + public static function visibilityProvider(): array { return [ ['public', 'public'], @@ -46,7 +43,6 @@ public function visibilityProvider(): array ]; } - /** @covers ::__construct */ public function testVisibilityChecksInput(): void { $this->expectException(InvalidArgumentException::class); diff --git a/tests/unit/phpDocumentor/Reflection/Types/NamespaceNodeToContextTest.php b/tests/unit/phpDocumentor/Reflection/Types/NamespaceNodeToContextTest.php index afe924fc..dd058a31 100644 --- a/tests/unit/phpDocumentor/Reflection/Types/NamespaceNodeToContextTest.php +++ b/tests/unit/phpDocumentor/Reflection/Types/NamespaceNodeToContextTest.php @@ -11,25 +11,21 @@ use PhpParser\Node\Stmt\Namespace_; use PhpParser\Node\Stmt\Use_ as UseStatement; use PhpParser\Node\Stmt\UseUse; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -/** - * @coversDefaultClass \phpDocumentor\Reflection\Types\NamespaceNodeToContext - * @covers ::<private> - */ +#[CoversClass(NamespaceNodeToContext::class)] final class NamespaceNodeToContextTest extends TestCase { - /** - * @dataProvider expectedContextsProvider - * @covers ::__invoke - */ + #[DataProvider('expectedContextsProvider')] public function testConversion(Namespace_|null $namespace, Context $expectedContext): void { $this->assertEquals($expectedContext, (new NamespaceNodeToContext())->__invoke($namespace)); } /** @return (Namespace|Context|null)[][] */ - public function expectedContextsProvider(): array + public static function expectedContextsProvider(): array { $namespaceWithImports = new Namespace_( new Name('With\\Imports'),