From a2528466b788d1a32a5145d8b09a24ac9f156fe9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Dec 2023 15:57:07 +0100 Subject: [PATCH 001/508] Open 2.0.x-dev --- .github/workflows/backward-compatibility.yml | 2 +- .github/workflows/build-issue-bot.yml | 2 +- .github/workflows/changelog-generator.yml | 2 +- .github/workflows/checksum-phar.yml | 2 +- .github/workflows/e2e-tests.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/phar.yml | 26 +++++++++++++++++-- .../workflows/pr-base-on-previous-branch.yml | 2 +- .github/workflows/reflection-golden-test.yml | 2 +- .github/workflows/spelling.yml | 2 +- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 2 +- 12 files changed, 35 insertions(+), 13 deletions(-) diff --git a/.github/workflows/backward-compatibility.yml b/.github/workflows/backward-compatibility.yml index 0233e1e422..d7651c9202 100644 --- a/.github/workflows/backward-compatibility.yml +++ b/.github/workflows/backward-compatibility.yml @@ -6,7 +6,7 @@ on: pull_request: push: branches: - - "1.12.x" + - "2.0.x" paths: - 'src/**' - '.github/workflows/backward-compatibility.yml' diff --git a/.github/workflows/build-issue-bot.yml b/.github/workflows/build-issue-bot.yml index 278470b466..0e541ca5b1 100644 --- a/.github/workflows/build-issue-bot.yml +++ b/.github/workflows/build-issue-bot.yml @@ -9,7 +9,7 @@ on: - '.github/workflows/build-issue-bot.yml' push: branches: - - "1.12.x" + - "2.0.x" paths: - 'issue-bot/**' - '.github/workflows/build-issue-bot.yml' diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index 21971571f3..bda67d4725 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -9,7 +9,7 @@ on: - '.github/workflows/changelog-generator.yml' push: branches: - - "1.12.x" + - "2.0.x" paths: - 'changelog-generator/**' - '.github/workflows/changelog-generator.yml' diff --git a/.github/workflows/checksum-phar.yml b/.github/workflows/checksum-phar.yml index 47256373d0..994f11ba06 100644 --- a/.github/workflows/checksum-phar.yml +++ b/.github/workflows/checksum-phar.yml @@ -12,7 +12,7 @@ on: - '.github/workflows/checksum-phar.yml' push: branches: - - "1.12.x" + - "2.0.x" paths: - 'compiler/**' - '.github/workflows/checksum-phar.yml' diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 53fded3322..239a5e3781 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -11,7 +11,7 @@ on: - 'issue-bot/**' push: branches: - - "1.12.x" + - "2.0.x" paths-ignore: - 'compiler/**' - 'apigen/**' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 03420615cd..105fff7588 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,7 +6,7 @@ on: pull_request: push: branches: - - "1.12.x" + - "2.0.x" env: COMPOSER_ROOT_VERSION: "1.12.x-dev" diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index c6c4934b44..723e8a93be 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -6,9 +6,9 @@ on: pull_request: push: branches: - - "1.12.x" + - "2.0.x" tags: - - '1.12.*' + - '2.0.*' concurrency: group: phar-${{ github.ref }} # will be canceled on subsequent pushes in both branches and pull requests @@ -107,25 +107,43 @@ jobs: integration-tests: if: github.event_name == 'pull_request' needs: compiler-tests +<<<<<<< HEAD uses: phpstan/phpstan/.github/workflows/integration-tests.yml@1.12.x with: ref: 1.12.x +======= + uses: phpstan/phpstan/.github/workflows/integration-tests.yml@2.0.x + with: + ref: 2.0.x +>>>>>>> 264ce7a58b (Open 2.0.x-dev) phar-checksum: ${{needs.compiler-tests.outputs.checksum}} extension-tests: if: github.event_name == 'pull_request' needs: compiler-tests +<<<<<<< HEAD uses: phpstan/phpstan/.github/workflows/extension-tests.yml@1.12.x with: ref: 1.12.x +======= + uses: phpstan/phpstan/.github/workflows/extension-tests.yml@2.0.x + with: + ref: 2.0.x +>>>>>>> 264ce7a58b (Open 2.0.x-dev) phar-checksum: ${{needs.compiler-tests.outputs.checksum}} other-tests: if: github.event_name == 'pull_request' needs: compiler-tests +<<<<<<< HEAD uses: phpstan/phpstan/.github/workflows/other-tests.yml@1.12.x with: ref: 1.12.x +======= + uses: phpstan/phpstan/.github/workflows/other-tests.yml@2.0.x + with: + ref: 2.0.x +>>>>>>> 264ce7a58b (Open 2.0.x-dev) phar-checksum: ${{needs.compiler-tests.outputs.checksum}} commit: @@ -152,7 +170,11 @@ jobs: repository: phpstan/phpstan path: phpstan-dist token: ${{ secrets.PHPSTAN_BOT_TOKEN }} +<<<<<<< HEAD ref: 1.12.x +======= + ref: 2.0.x +>>>>>>> 264ce7a58b (Open 2.0.x-dev) - name: "Get previous pushed dist commit" id: previous-commit diff --git a/.github/workflows/pr-base-on-previous-branch.yml b/.github/workflows/pr-base-on-previous-branch.yml index 85b8974449..f522ea446e 100644 --- a/.github/workflows/pr-base-on-previous-branch.yml +++ b/.github/workflows/pr-base-on-previous-branch.yml @@ -19,6 +19,6 @@ jobs: - name: Comment PR uses: peter-evans/create-or-update-comment@v4 with: - body: "You've opened the pull request against the latest branch 2.0.x. If your code is relevant on 1.12.x and you want it to be released sooner, please rebase your pull request and change its target to 1.12.x." + body: "You've opened the pull request against the latest branch 2.0.x. PHPStan 2.0 is not going to be released for months. If your code is relevant on 1.12.x and you want it to be released sooner, please rebase your pull request and change its target to 1.12.x." token: ${{ secrets.PHPSTAN_BOT_TOKEN }} issue-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/reflection-golden-test.yml b/.github/workflows/reflection-golden-test.yml index 6d16f21aaa..d996728a38 100644 --- a/.github/workflows/reflection-golden-test.yml +++ b/.github/workflows/reflection-golden-test.yml @@ -11,7 +11,7 @@ on: - 'issue-bot/**' push: branches: - - "1.12.x" + - "2.0.x" paths-ignore: - 'compiler/**' - 'apigen/**' diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index d91ab1ff1f..4304d27005 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -6,7 +6,7 @@ on: pull_request: push: branches: - - "1.12.x" + - "2.0.x" jobs: typos: diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index b19b6c10f7..fb498cd9bc 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -9,7 +9,7 @@ on: - 'apigen/**' push: branches: - - "1.12.x" + - "2.0.x" paths-ignore: - 'compiler/**' - 'apigen/**' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 59d834e9c7..0080b3d697 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,7 @@ on: - 'issue-bot/**' push: branches: - - "1.12.x" + - "2.0.x" paths-ignore: - 'compiler/**' - 'apigen/**' From 4d7f976728e6f4e012d0396a8d090a39b3f69a96 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Dec 2023 16:01:14 +0100 Subject: [PATCH 002/508] Drop support for PHP 7.2 and 7.3 --- .github/workflows/lint.yml | 2 - .github/workflows/reflection-golden-test.yml | 1 - .github/workflows/static-analysis.yml | 20 +++------ .github/workflows/tests.yml | 44 -------------------- 4 files changed, 6 insertions(+), 61 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 105fff7588..bdc15d968a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -25,8 +25,6 @@ jobs: fail-fast: false matrix: php-version: - - "7.2" - - "7.3" - "7.4" - "8.0" - "8.1" diff --git a/.github/workflows/reflection-golden-test.yml b/.github/workflows/reflection-golden-test.yml index d996728a38..2bf67cb14f 100644 --- a/.github/workflows/reflection-golden-test.yml +++ b/.github/workflows/reflection-golden-test.yml @@ -65,7 +65,6 @@ jobs: fail-fast: false matrix: php-version: - - "7.3" - "7.4" - "8.0" - "8.1" diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index fb498cd9bc..24760de756 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -31,8 +31,6 @@ jobs: fail-fast: false matrix: php-version: - - "7.2" - - "7.3" - "7.4" - "8.0" - "8.1" @@ -61,18 +59,12 @@ jobs: shell: bash run: "vendor/bin/simple-downgrade downgrade -c build/downgrade.php ${{ matrix.php-version }}" - - name: "Paratest patch" - if: matrix.php-version == '7.2' - run: composer config extra.patches.brianium/paratest --json --merge '["patches/paratest.patch"]' - shell: bash - - - name: "Downgrade PHPUnit" - if: matrix.php-version == '7.2' - run: "composer require --dev phpunit/phpunit:^8.5.31 brianium/paratest:^4.0 composer/semver:^1.2 --update-with-dependencies --ignore-platform-reqs" - - - name: "Update PHPUnit" - if: matrix.php-version != '7.2' && matrix.php-version != '7.3' - run: "composer update phpunit/phpunit -W" + - name: "Upload transformed sources" + if: matrix.php-version == '7.4' + uses: actions/upload-artifact@v3 + with: + name: transformed-src + path: src - name: "PHPStan" run: "make phpstan" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0080b3d697..75f5de1627 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -35,7 +35,6 @@ jobs: fail-fast: false matrix: php-version: - - "7.3" - "7.4" - "8.0" - "8.1" @@ -162,46 +161,3 @@ jobs: - name: "Tests" run: "${{ matrix.script }}" - - tests-old-phpunit: - name: "Tests with old PHPUnit" - runs-on: ${{ matrix.operating-system }} - timeout-minutes: 60 - - strategy: - fail-fast: false - matrix: - php-version: - - "7.2" - operating-system: [ ubuntu-latest ] - - steps: - - name: "Checkout" - uses: actions/checkout@v4 - - - name: "Install PHP" - uses: "shivammathur/setup-php@v2" - with: - coverage: "none" - php-version: "${{ matrix.php-version }}" - tools: pecl - extensions: ds,mbstring - ini-file: development - ini-values: memory_limit=2G - - - name: "Install dependencies" - run: "composer install --no-interaction --no-progress" - - - name: "Transform source code" - shell: bash - run: "vendor/bin/simple-downgrade downgrade -c build/downgrade.php ${{ matrix.php-version }}" - - - name: "Paratest patch" - run: composer config extra.patches.brianium/paratest --json --merge '["patches/paratest.patch"]' - shell: bash - - - name: "Downgrade PHPUnit" - run: "composer require --dev phpunit/phpunit:^8.5.31 brianium/paratest:^4.0 composer/semver:^1.2 --update-with-dependencies --ignore-platform-reqs" - - - name: "Tests" - run: "make tests-coverage" From 5c68a148c88ef4df22ec825d76b23a3931f0cabf Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 22 Dec 2023 08:42:44 +0100 Subject: [PATCH 003/508] Update nikic/php-parser to v5 --- composer.json | 7 ++-- composer.lock | 112 +++++++++++++++++++++++++------------------------- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/composer.json b/composer.json index f6cb9c01db..7e859b19e4 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,9 @@ "nette/php-generator": "3.6.9", "nette/schema": "^1.2.2", "nette/utils": "^3.2.5", - "nikic/php-parser": "^4.17.1", + "nikic/php-parser": "^5.1.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.25.0.17", + "ondrejmirtes/better-reflection": "6.42.0.3", "phpstan/php-8-stubs": "0.3.101", "phpstan/phpdoc-parser": "1.30.0", "psr/http-message": "^1.1", @@ -55,8 +55,7 @@ "require-dev": { "brianium/paratest": "^6.5", "cweagans/composer-patches": "^1.7.3", - "nette/finder": "^2.5", - "ondrejmirtes/simple-downgrader": "^1.0", + "ondrejmirtes/simple-downgrader": "^2.0", "php-parallel-lint/php-parallel-lint": "^1.2.0", "phpstan/phpstan-deprecation-rules": "^1.2", "phpstan/phpstan-nette": "^1.0", diff --git a/composer.lock b/composer.lock index 71beaf624c..aba98b1475 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f5af1898ab9d95520d1511334b2000c0", + "content-hash": "6ecf16b4614aa87f10e85e795af26169", "packages": [ { "name": "clue/ndjson-react", @@ -1474,7 +1474,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-07-24T19:11:43+00:00" + "time": "2024-09-01T14:35:14+00:00" }, { "name": "nette/bootstrap", @@ -1963,25 +1963,26 @@ }, { "name": "nette/utils", - "version": "v3.2.7", + "version": "v3.2.10", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "0af4e3de4df9f1543534beab255ccf459e7a2c99" + "reference": "a4175c62652f2300c8017fb7e640f9ccb11648d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/0af4e3de4df9f1543534beab255ccf459e7a2c99", - "reference": "0af4e3de4df9f1543534beab255ccf459e7a2c99", + "url": "https://api.github.com/repos/nette/utils/zipball/a4175c62652f2300c8017fb7e640f9ccb11648d2", + "reference": "a4175c62652f2300c8017fb7e640f9ccb11648d2", "shasum": "" }, "require": { - "php": ">=7.2 <8.2" + "php": ">=7.2 <8.4" }, "conflict": { "nette/di": "<3.0.6" }, "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", "nette/tester": "~2.0", "phpstan/phpstan": "^1.0", "tracy/tracy": "^2.3" @@ -2042,31 +2043,33 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v3.2.7" + "source": "https://github.com/nette/utils/tree/v3.2.10" }, - "time": "2022-01-24T11:29:14+00:00" + "time": "2023-07-30T15:38:18+00:00" }, { "name": "nikic/php-parser", - "version": "v4.19.1", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b" + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" }, "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/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", "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" @@ -2074,7 +2077,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2098,9 +2101,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.1.0" }, - "time": "2024-03-17T08:10:35+00:00" + "time": "2024-07-01T20:03:41+00:00" }, { "name": "ondram/ci-detector", @@ -2176,23 +2179,23 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.25.0.17", + "version": "6.42.0.3", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "2c9cf932ab3306e0fcb90471f3b63fa3190bf7b2" + "reference": "bdb626a5e2fb52bfe3fec1d367a9c72e48550954" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/2c9cf932ab3306e0fcb90471f3b63fa3190bf7b2", - "reference": "2c9cf932ab3306e0fcb90471f3b63fa3190bf7b2", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/bdb626a5e2fb52bfe3fec1d367a9c72e48550954", + "reference": "bdb626a5e2fb52bfe3fec1d367a9c72e48550954", "shasum": "" }, "require": { "ext-json": "*", "jetbrains/phpstorm-stubs": "dev-master#217ed9356d07ef89109d3cd7d8c5df10aab4b0d4", - "nikic/php-parser": "^4.18.0", - "php": "^7.2 || ^8.0" + "nikic/php-parser": "^5.1.0", + "php": "^7.4 || ^8.0" }, "conflict": { "thecodingmachine/safe": "<1.1.3" @@ -2201,9 +2204,8 @@ "doctrine/coding-standard": "^12.0.0", "phpstan/phpstan": "^1.10.60", "phpstan/phpstan-phpunit": "^1.3.16", - "phpunit/phpunit": "^10.5.12", - "rector/rector": "0.14.3", - "vimeo/psalm": "5.23.0" + "phpunit/phpunit": "^11.3.2", + "rector/rector": "0.14.3" }, "suggest": { "composer/composer": "Required to use the ComposerSourceLocator" @@ -2242,9 +2244,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.25.0.17" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.42.0.3" }, - "time": "2024-08-26T20:47:13+00:00" + "time": "2024-09-04T11:06:34+00:00" }, { "name": "phpstan/php-8-stubs", @@ -3168,16 +3170,16 @@ }, { "name": "symfony/console", - "version": "v5.4.41", + "version": "v5.4.43", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6473d441a913cb997123b59ff2dbe3d1cf9e11ba" + "reference": "e86f8554de667c16dde8aeb89a3990cfde924df9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6473d441a913cb997123b59ff2dbe3d1cf9e11ba", - "reference": "6473d441a913cb997123b59ff2dbe3d1cf9e11ba", + "url": "https://api.github.com/repos/symfony/console/zipball/e86f8554de667c16dde8aeb89a3990cfde924df9", + "reference": "e86f8554de667c16dde8aeb89a3990cfde924df9", "shasum": "" }, "require": { @@ -3247,7 +3249,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.41" + "source": "https://github.com/symfony/console/tree/v5.4.43" }, "funding": [ { @@ -3263,7 +3265,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T07:48:55+00:00" + "time": "2024-08-13T16:31:56+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3334,16 +3336,16 @@ }, { "name": "symfony/finder", - "version": "v5.4.40", + "version": "v5.4.43", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "f51cff4687547641c7d8180d74932ab40b2205ce" + "reference": "ae25a9145a900764158d439653d5630191155ca0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/f51cff4687547641c7d8180d74932ab40b2205ce", - "reference": "f51cff4687547641c7d8180d74932ab40b2205ce", + "url": "https://api.github.com/repos/symfony/finder/zipball/ae25a9145a900764158d439653d5630191155ca0", + "reference": "ae25a9145a900764158d439653d5630191155ca0", "shasum": "" }, "require": { @@ -3377,7 +3379,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.40" + "source": "https://github.com/symfony/finder/tree/v5.4.43" }, "funding": [ { @@ -3393,7 +3395,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:33:22+00:00" + "time": "2024-08-13T14:03:51+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4169,16 +4171,16 @@ }, { "name": "symfony/string", - "version": "v5.4.41", + "version": "v5.4.43", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "065a9611e0b1fd2197a867e1fb7f2238191b7096" + "reference": "8be1d484951ff5ca995eaf8edcbcb8b9a5888450" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/065a9611e0b1fd2197a867e1fb7f2238191b7096", - "reference": "065a9611e0b1fd2197a867e1fb7f2238191b7096", + "url": "https://api.github.com/repos/symfony/string/zipball/8be1d484951ff5ca995eaf8edcbcb8b9a5888450", + "reference": "8be1d484951ff5ca995eaf8edcbcb8b9a5888450", "shasum": "" }, "require": { @@ -4235,7 +4237,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.41" + "source": "https://github.com/symfony/string/tree/v5.4.43" }, "funding": [ { @@ -4251,7 +4253,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:20:55+00:00" + "time": "2024-08-01T10:24:28+00:00" } ], "packages-dev": [ @@ -4586,22 +4588,22 @@ }, { "name": "ondrejmirtes/simple-downgrader", - "version": "1.0.2", + "version": "2.x-dev", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/simple-downgrader.git", - "reference": "832aaae53dcfe358f63180494de8734244773d46" + "reference": "dbbf56fab0bc71310ff3766ea204d84f019e99b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/simple-downgrader/zipball/832aaae53dcfe358f63180494de8734244773d46", - "reference": "832aaae53dcfe358f63180494de8734244773d46", + "url": "https://api.github.com/repos/ondrejmirtes/simple-downgrader/zipball/dbbf56fab0bc71310ff3766ea204d84f019e99b7", + "reference": "dbbf56fab0bc71310ff3766ea204d84f019e99b7", "shasum": "" }, "require": { "nette/utils": "^3.2.5", - "nikic/php-parser": "^4.18", - "php": "^7.2|^8.0", + "nikic/php-parser": "^5.0", + "php": "^7.4|^8.0", "phpstan/phpdoc-parser": "^1.24.5", "symfony/console": "^5.4", "symfony/finder": "^5.4" @@ -4629,9 +4631,9 @@ "description": "Simple Downgrader", "support": { "issues": "https://github.com/ondrejmirtes/simple-downgrader/issues", - "source": "https://github.com/ondrejmirtes/simple-downgrader/tree/1.0.2" + "source": "https://github.com/ondrejmirtes/simple-downgrader/tree/2.x" }, - "time": "2024-02-12T19:22:32+00:00" + "time": "2024-02-12T19:24:54+00:00" }, { "name": "phar-io/manifest", From 31742d125d2cae20a869429730b878e0bc9dfabf Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Dec 2023 16:10:06 +0100 Subject: [PATCH 004/508] Compatibility with PHP-Parser v5 --- conf/config.neon | 4 ++-- src/Parser/LexerFactory.php | 11 +++-------- src/Parser/PhpParserDecorator.php | 5 +++++ src/Parser/RichParser.php | 25 ++++++++++--------------- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index 255be78dc2..dac1e96e5f 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -2045,7 +2045,7 @@ services: autowired: false currentPhpVersionPhpParser: - class: PhpParser\Parser\Php7 + class: PhpParser\Parser\Php8 # todo use factory and create Php7/Php8 arguments: lexer: @currentPhpVersionLexer autowired: false @@ -2161,7 +2161,7 @@ services: autowired: false php8PhpParser: - class: PhpParser\Parser\Php7 + class: PhpParser\Parser\Php8 arguments: lexer: @php8Lexer autowired: false diff --git a/src/Parser/LexerFactory.php b/src/Parser/LexerFactory.php index 5fa801ddec..e02bc5ed2c 100644 --- a/src/Parser/LexerFactory.php +++ b/src/Parser/LexerFactory.php @@ -9,27 +9,22 @@ final class LexerFactory { - private const OPTIONS = ['usedAttributes' => ['comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos', 'startFilePos', 'endFilePos']]; - public function __construct(private PhpVersion $phpVersion) { } public function create(): Lexer { - $options = self::OPTIONS; if ($this->phpVersion->getVersionId() === PHP_VERSION_ID) { - return new Lexer($options); + return new Lexer(); } - $options['phpVersion'] = $this->phpVersion->getVersionString(); - - return new Lexer\Emulative($options); + return new Lexer\Emulative(\PhpParser\PhpVersion::fromString($this->phpVersion->getVersionString())); } public function createEmulative(): Lexer\Emulative { - return new Lexer\Emulative(self::OPTIONS); + return new Lexer\Emulative(); } } diff --git a/src/Parser/PhpParserDecorator.php b/src/Parser/PhpParserDecorator.php index 14c462c39f..d4e00547a0 100644 --- a/src/Parser/PhpParserDecorator.php +++ b/src/Parser/PhpParserDecorator.php @@ -31,4 +31,9 @@ public function parse(string $code, ?ErrorHandler $errorHandler = null): array } } + public function getTokens(): array + { + return $this->wrappedParser->getTokens(); + } + } diff --git a/src/Parser/RichParser.php b/src/Parser/RichParser.php index b5863a4b80..e3f2a5e310 100644 --- a/src/Parser/RichParser.php +++ b/src/Parser/RichParser.php @@ -7,6 +7,7 @@ use PhpParser\Node; use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\NameResolver; +use PhpParser\Token; use PHPStan\Analyser\Ignore\IgnoreLexer; use PHPStan\Analyser\Ignore\IgnoreParseException; use PHPStan\DependencyInjection\Container; @@ -17,7 +18,6 @@ use function count; use function implode; use function in_array; -use function is_string; use function preg_match_all; use function sprintf; use function str_contains; @@ -72,8 +72,7 @@ public function parseString(string $sourceCode): array $errorHandler = new Collecting(); $nodes = $this->parser->parse($sourceCode, $errorHandler); - /** @var list $tokens */ - $tokens = $this->lexer->getTokens(); + $tokens = $this->parser->getTokens(); if ($errorHandler->hasErrors()) { throw new ParserErrorsException($errorHandler->getErrors(), null); } @@ -109,7 +108,7 @@ public function parseString(string $sourceCode): array } /** - * @param list $tokens + * @param Token[] $tokens * @return array{lines: array|null>, errors: array>} */ private function getLinesToIgnore(array $tokens): array @@ -119,12 +118,8 @@ private function getLinesToIgnore(array $tokens): array $pendingToken = null; $errors = []; foreach ($tokens as $token) { - if (is_string($token)) { - continue; - } - - $type = $token[0]; - $line = $token[2]; + $type = $token->id; + $line = $token->line; if ($type !== T_COMMENT && $type !== T_DOC_COMMENT) { if ($type !== T_WHITESPACE) { if ($pendingToken !== null) { @@ -155,7 +150,7 @@ private function getLinesToIgnore(array $tokens): array continue; } - $text = $token[1]; + $text = $token->text; $isNextLine = str_contains($text, '@phpstan-ignore-next-line'); $isCurrentLine = str_contains($text, '@phpstan-ignore-line'); @@ -204,20 +199,20 @@ private function getLinesToIgnore(array $tokens): array $ignoreLine = substr_count(substr($text, 0, $ignorePos), "\n") - 1; - if ($previousToken !== null && $previousToken[2] === $line) { + if ($previousToken !== null && $previousToken->line === $line) { try { foreach ($this->parseIdentifiers($text, $ignorePos) as $identifier) { $lines[$line][] = $identifier; } } catch (IgnoreParseException $e) { - $errors[] = [$token[2] + $e->getPhpDocLine() + $ignoreLine, $e->getMessage()]; + $errors[] = [$token->line + $e->getPhpDocLine() + $ignoreLine, $e->getMessage()]; } continue; } - $line += substr_count($token[1], "\n"); - $pendingToken = [$text, $ignorePos, $token[2] + $ignoreLine, $line]; + $line += substr_count($token->text, "\n"); + $pendingToken = [$text, $ignorePos, $token->line + $ignoreLine, $line]; } if ($pendingToken !== null) { From 038f0ca7d5910e510e4ec2135e7bfd753700d46d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Dec 2023 16:19:24 +0100 Subject: [PATCH 005/508] PHP-Parser 5 - compiler --- compiler/src/Console/PrepareCommand.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/compiler/src/Console/PrepareCommand.php b/compiler/src/Console/PrepareCommand.php index f7f2b6cdf6..7bef8b99db 100644 --- a/compiler/src/Console/PrepareCommand.php +++ b/compiler/src/Console/PrepareCommand.php @@ -16,6 +16,7 @@ use function file_get_contents; use function file_put_contents; use function implode; +use function in_array; use function is_dir; use function json_decode; use function json_encode; @@ -184,6 +185,20 @@ private function buildPreloadScript(): void if ($realPath === false) { return; } + if (in_array($realPath, [ + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php', + $vendorDir . '/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php', + ], true)) { + continue; + } $path = substr($realPath, strlen($root)); $output .= 'require_once __DIR__ . ' . var_export($path, true) . ';' . "\n"; } From e7e3dfdb8451918138007dacf61264bcc25fde11 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 22 Dec 2023 13:39:40 +0100 Subject: [PATCH 006/508] Scope changes --- src/Analyser/MutatingScope.php | 19 +++++++-------- src/Analyser/NodeScopeResolver.php | 38 +++++++++++++----------------- 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index cb4dd6b858..3a251908c9 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -21,10 +21,10 @@ use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\Variable; +use PhpParser\Node\InterpolatedStringPart; use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Scalar\DNumber; -use PhpParser\Node\Scalar\EncapsedStringPart; use PhpParser\Node\Scalar\LNumber; use PhpParser\Node\Scalar\String_; use PhpParser\NodeFinder; @@ -1129,16 +1129,16 @@ private function resolveType(string $exprString, Expr $node): Type return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); } elseif ($node instanceof String_) { return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); - } elseif ($node instanceof Node\Scalar\Encapsed) { + } elseif ($node instanceof Node\Scalar\InterpolatedString) { $resultType = null; - foreach ($node->parts as $part) { - $partType = $part instanceof EncapsedStringPart - ? new ConstantStringType($part->value) - : $this->getType($part)->toString(); + if ($part instanceof InterpolatedStringPart) { + $partType = new ConstantStringType($part->value); + } else { + $partType = $this->getType($part); + } if ($resultType === null) { $resultType = $partType; - continue; } @@ -3455,9 +3455,6 @@ private function enterAnonymousFunctionWithoutReflection( continue; } foreach ($variables as $variable) { - if (!$variable instanceof Variable) { - continue 2; - } if (!is_string($variable->name)) { continue 2; } @@ -4785,7 +4782,7 @@ private function processFinallyScopeVariableTypeHolders( } /** - * @param Expr\ClosureUse[] $byRefUses + * @param Node\ClosureUse[] $byRefUses */ public function processClosureScope( self $closureScope, diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index b22d651f99..e7b3a0abab 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -6,13 +6,13 @@ use Closure; use DivisionByZeroError; use PhpParser\Comment\Doc; +use PhpParser\Modifiers; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\AttributeGroup; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\ArrayDimFetch; -use PhpParser\Node\Expr\ArrayItem; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\AssignRef; use PhpParser\Node\Expr\BinaryOp; @@ -48,7 +48,6 @@ use PhpParser\Node\Stmt\Return_; use PhpParser\Node\Stmt\Static_; use PhpParser\Node\Stmt\Switch_; -use PhpParser\Node\Stmt\Throw_; use PhpParser\Node\Stmt\TryCatch; use PhpParser\Node\Stmt\Unset_; use PhpParser\Node\Stmt\While_; @@ -474,7 +473,10 @@ private function processStmtNode( } $stmtScope = $scope; - if ($stmt instanceof Throw_ || $stmt instanceof Return_) { + if ($stmt instanceof Node\Stmt\Expression && $stmt->expr instanceof Expr\Throw_) { + $stmtScope = $this->processStmtVarAnnotation($scope, $stmt, $stmt->expr->expr, $nodeCallback); + } + if ($stmt instanceof Return_) { $stmtScope = $this->processStmtVarAnnotation($scope, $stmt, $stmt->expr, $nodeCallback); } @@ -922,14 +924,6 @@ private function processStmtNode( if ($stmt->type !== null) { $nodeCallback($stmt->type, $scope); } - } elseif ($stmt instanceof Throw_) { - $result = $this->processExprNode($stmt, $stmt->expr, $scope, $nodeCallback, ExpressionContext::createDeep()); - $throwPoints = $result->getThrowPoints(); - $throwPoints[] = ThrowPoint::createExplicit($result->getScope(), $scope->getType($stmt->expr), $stmt, false); - $impurePoints = $result->getImpurePoints(); - return new StatementResult($result->getScope(), $result->hasYield(), true, [ - new StatementExitPoint($stmt, $scope), - ], $throwPoints, $impurePoints); } elseif ($stmt instanceof If_) { $conditionType = ($this->treatPhpDocTypesAsCertain ? $scope->getType($stmt->cond) : $scope->getNativeType($stmt->cond))->toBoolean(); $ifAlwaysTrue = $conditionType->isTrue()->yes(); @@ -1506,7 +1500,7 @@ private function processStmtNode( } foreach ($branchScopeResult->getExitPoints() as $exitPoint) { $finallyExitPoints[] = $exitPoint; - if ($exitPoint->getStatement() instanceof Throw_) { + if ($exitPoint->getStatement() instanceof Node\Stmt\Expression && $exitPoint->getStatement()->expr instanceof Expr\Throw_) { continue; } if ($finallyScope !== null) { @@ -1668,7 +1662,7 @@ private function processStmtNode( } foreach ($catchScopeResult->getExitPoints() as $exitPoint) { $finallyExitPoints[] = $exitPoint; - if ($exitPoint->getStatement() instanceof Throw_) { + if ($exitPoint->getStatement() instanceof Node\Stmt\Expression && $exitPoint->getStatement()->expr instanceof Expr\Throw_) { continue; } if ($finallyScope !== null) { @@ -2037,7 +2031,7 @@ private function lookForExpressionCallback(MutatingScope $scope, Expr $expr, Clo $scope = $this->lookForExpressionCallback($scope, $expr->var, $callback); } elseif ($expr instanceof StaticPropertyFetch && $expr->class instanceof Expr) { $scope = $this->lookForExpressionCallback($scope, $expr->class, $callback); - } elseif ($expr instanceof Array_ || $expr instanceof List_) { + } elseif ($expr instanceof List_) { foreach ($expr->items as $item) { if ($item === null) { continue; @@ -2942,11 +2936,14 @@ static function (): void { $impurePoints = array_merge($impurePoints, $result->getImpurePoints()); $scope = $result->getScope(); } - } elseif ($expr instanceof Node\Scalar\Encapsed) { + } elseif ($expr instanceof Node\Scalar\InterpolatedString) { $hasYield = false; $throwPoints = []; $impurePoints = []; foreach ($expr->parts as $part) { + if (!$part instanceof Expr) { + continue; + } $result = $this->processExprNode($stmt, $part, $scope, $nodeCallback, $context->enterDeep()); $hasYield = $hasYield || $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); @@ -3630,7 +3627,7 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void { } else { $items = []; foreach ($filteringExprs as $filteringExpr) { - $items[] = new ArrayItem($filteringExpr); + $items[] = new Node\ArrayItem($filteringExpr); } $filteringExpr = new FuncCall( new Name\FullyQualified('in_array'), @@ -4113,7 +4110,7 @@ private function getAssignedVariables(Expr $expr): array return []; } - if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) { + if ($expr instanceof Expr\List_) { $names = []; foreach ($expr->items as $item) { if ($item === null) { @@ -5271,7 +5268,7 @@ static function (): void { $nodeCallback(new PropertyAssignNode($var, $assignedExpr, $isAssignOp), $scope); $scope = $scope->assignExpression($var, $assignedExprType, $scope->getNativeType($assignedExpr)); } - } elseif ($var instanceof List_ || $var instanceof Array_) { + } elseif ($var instanceof List_) { $result = $processExprCallback($scope); $hasYield = $result->hasYield(); $throwPoints = array_merge($throwPoints, $result->getThrowPoints()); @@ -5778,7 +5775,7 @@ private function processNodesForTraitUse($node, ClassReflection $traitReflection $methodAst = clone $stmt; $stmts[$i] = $methodAst; if (array_key_exists($methodName, $methodModifiers)) { - $methodAst->flags = ($methodAst->flags & ~ Node\Stmt\Class_::VISIBILITY_MODIFIER_MASK) | $methodModifiers[$methodName]; + $methodAst->flags = ($methodAst->flags & ~ Modifiers::VISIBILITY_MASK) | $methodModifiers[$methodName]; } if (!array_key_exists($methodName, $methodNames)) { @@ -5867,9 +5864,6 @@ private function processCalledMethod(MethodReflection $methodReflection): ?Mutat foreach ($returnStatement->getExecutionEnds() as $executionEnd) { $statementResult = $executionEnd->getStatementResult(); $endNode = $executionEnd->getNode(); - if ($endNode instanceof Node\Stmt\Throw_) { - continue; - } if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); if ($exprType instanceof NeverType && $exprType->isExplicit()) { From eb0162f72e48b7e914ffc260e88f7a041dea5dfe Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Dec 2023 16:20:31 +0100 Subject: [PATCH 007/508] Rest of src/ changes --- phpstan-baseline.neon | 16 ++++++++++++++++ src/Dependency/DependencyResolver.php | 4 ---- src/Node/ClassPropertiesNode.php | 3 --- src/Node/ClassPropertyNode.php | 14 +++++++------- src/Node/ClassStatementsGatherer.php | 3 --- src/Node/LiteralArrayItem.php | 2 +- src/Parser/LastConditionVisitor.php | 6 +++++- src/Reflection/InitializerExprTypeResolver.php | 4 ---- src/Rules/Arrays/ArrayDestructuringRule.php | 7 +++---- src/Rules/Arrays/ArrayUnpackingRule.php | 2 +- src/Rules/Arrays/EmptyArrayItemRule.php | 1 + src/Rules/Arrays/InvalidKeyInArrayItemRule.php | 4 ++-- .../Cast/InvalidPartOfEncapsedStringRule.php | 6 +++--- src/Rules/Functions/UnusedClosureUsesRule.php | 2 +- src/Rules/NullsafeCheck.php | 2 +- src/Rules/Operators/InvalidAssignVarRule.php | 2 +- .../PhpDoc/WrongVariableNameInVarTagRule.php | 2 +- src/Rules/UnusedFunctionParametersCheck.php | 2 +- src/Type/FileTypeMapper.php | 1 - ...IsCallableFunctionTypeSpecifyingExtension.php | 4 ---- 20 files changed, 44 insertions(+), 43 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 77ff81fd1a..cdbd956fa2 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1835,3 +1835,19 @@ parameters: message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" count: 1 path: tests/PHPStan/Type/IterableTypeTest.php + + - + message: """ + #^Instantiation of deprecated class PHPStan\\\\Rules\\\\Arrays\\\\EmptyArrayItemRule\\: + Since PHP\\-Parser 5\\.0 this is a parse error\\.$# + """ + count: 1 + path: tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php + + - + message: """ + #^Return type of method PHPStan\\\\Rules\\\\Arrays\\\\EmptyArrayItemRuleTest\\:\\:getRule\\(\\) has typehint with deprecated class PHPStan\\\\Rules\\\\Arrays\\\\EmptyArrayItemRule\\: + Since PHP\\-Parser 5\\.0 this is a parse error\\.$# + """ + count: 1 + path: tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php diff --git a/src/Dependency/DependencyResolver.php b/src/Dependency/DependencyResolver.php index 57a80a5a2e..2c7d3f581a 100644 --- a/src/Dependency/DependencyResolver.php +++ b/src/Dependency/DependencyResolver.php @@ -479,10 +479,6 @@ private function considerArrayForCallableTest(Scope $scope, Array_ $arrayNode): return false; } - if ($items[0] === null) { - return false; - } - $itemType = $scope->getType($items[0]->value); return $itemType->isClassStringType()->yes(); } diff --git a/src/Node/ClassPropertiesNode.php b/src/Node/ClassPropertiesNode.php index 7afc4bc874..0707a5bc6d 100644 --- a/src/Node/ClassPropertiesNode.php +++ b/src/Node/ClassPropertiesNode.php @@ -271,9 +271,6 @@ private function collectUninitializedProperties(array $constructors, array $unin $statementResult = $executionEnd->getStatementResult(); $endNode = $executionEnd->getNode(); if ($statementResult->isAlwaysTerminating()) { - if ($endNode instanceof Node\Stmt\Throw_) { - continue; - } if ($endNode instanceof Node\Stmt\Expression) { $exprType = $statementResult->getScope()->getType($endNode->expr); if ($exprType instanceof NeverType && $exprType->isExplicit()) { diff --git a/src/Node/ClassPropertyNode.php b/src/Node/ClassPropertyNode.php index d8aaea6218..f0ad86ff8c 100644 --- a/src/Node/ClassPropertyNode.php +++ b/src/Node/ClassPropertyNode.php @@ -2,11 +2,11 @@ namespace PHPStan\Node; +use PhpParser\Modifiers; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Identifier; use PhpParser\Node\Name; -use PhpParser\Node\Stmt\Class_; use PhpParser\NodeAbstract; use PHPStan\Reflection\ClassReflection; use PHPStan\Type\Type; @@ -75,28 +75,28 @@ public function getPhpDocType(): ?Type public function isPublic(): bool { - return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 - || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + return ($this->flags & Modifiers::PUBLIC) !== 0 + || ($this->flags & Modifiers::VISIBILITY_MASK) === 0; } public function isProtected(): bool { - return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + return (bool) ($this->flags & Modifiers::PROTECTED); } public function isPrivate(): bool { - return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + return (bool) ($this->flags & Modifiers::PRIVATE); } public function isStatic(): bool { - return (bool) ($this->flags & Class_::MODIFIER_STATIC); + return (bool) ($this->flags & Modifiers::STATIC); } public function isReadOnly(): bool { - return (bool) ($this->flags & Class_::MODIFIER_READONLY) || $this->isReadonlyClass; + return (bool) ($this->flags & Modifiers::READONLY) || $this->isReadonlyClass; } public function isReadOnlyByPhpDoc(): bool diff --git a/src/Node/ClassStatementsGatherer.php b/src/Node/ClassStatementsGatherer.php index 55ef907799..7fb27f8351 100644 --- a/src/Node/ClassStatementsGatherer.php +++ b/src/Node/ClassStatementsGatherer.php @@ -221,9 +221,6 @@ private function gatherNodes(Node $node, Scope $scope): void $this->propertyUsages[] = new PropertyWrite($node->expr, $scope, false); return; } - if ($node instanceof Node\Scalar\EncapsedStringPart) { - return; - } if ($node instanceof FunctionCallableNode) { $node = $node->getOriginalNode(); } elseif ($node instanceof InstantiationCallableNode) { diff --git a/src/Node/LiteralArrayItem.php b/src/Node/LiteralArrayItem.php index ea9be27be6..1ba0c04ef5 100644 --- a/src/Node/LiteralArrayItem.php +++ b/src/Node/LiteralArrayItem.php @@ -2,7 +2,7 @@ namespace PHPStan\Node; -use PhpParser\Node\Expr\ArrayItem; +use PhpParser\Node\ArrayItem; use PHPStan\Analyser\Scope; /** diff --git a/src/Parser/LastConditionVisitor.php b/src/Parser/LastConditionVisitor.php index ce21f571fd..d4c4b53ac3 100644 --- a/src/Parser/LastConditionVisitor.php +++ b/src/Parser/LastConditionVisitor.php @@ -18,7 +18,11 @@ public function enterNode(Node $node): ?Node $lastElseIf = count($node->elseifs) - 1; $elseIsMissingOrThrowing = $node->else === null - || (count($node->else->stmts) === 1 && $node->else->stmts[0] instanceof Node\Stmt\Throw_); + || ( + count($node->else->stmts) === 1 + && $node->else->stmts[0] instanceof Node\Stmt\Expression + && $node->else->stmts[0]->expr instanceof Node\Expr\Throw_ + ); foreach ($node->elseifs as $i => $elseif) { $isLast = $i === $lastElseIf && $elseIsMissingOrThrowing; diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index dae4e11140..2f1aaa96a0 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -525,10 +525,6 @@ public function getArrayType(Expr\Array_ $expr, callable $getTypeCallback): Type $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); $isList = null; foreach ($expr->items as $arrayItem) { - if ($arrayItem === null) { - continue; - } - $valueType = $getTypeCallback($arrayItem->value); if ($arrayItem->unpack) { $constantArrays = $valueType->getConstantArrays(); diff --git a/src/Rules/Arrays/ArrayDestructuringRule.php b/src/Rules/Arrays/ArrayDestructuringRule.php index ab83f1d019..d8281b1d88 100644 --- a/src/Rules/Arrays/ArrayDestructuringRule.php +++ b/src/Rules/Arrays/ArrayDestructuringRule.php @@ -40,7 +40,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if (!$node->var instanceof Node\Expr\List_ && !$node->var instanceof Node\Expr\Array_) { + if (!$node->var instanceof Node\Expr\List_) { return []; } @@ -52,10 +52,9 @@ public function processNode(Node $node, Scope $scope): array } /** - * @param Node\Expr\List_|Node\Expr\Array_ $var * @return list */ - private function getErrors(Scope $scope, Expr $var, Expr $expr): array + private function getErrors(Scope $scope, Node\Expr\List_ $var, Expr $expr): array { $exprTypeResult = $this->ruleLevelHelper->findTypeToCheck( $scope, @@ -100,7 +99,7 @@ private function getErrors(Scope $scope, Expr $var, Expr $expr): array ); $errors = array_merge($errors, $itemErrors); - if (!$item->value instanceof Node\Expr\List_ && !$item->value instanceof Node\Expr\Array_) { + if (!$item->value instanceof Node\Expr\List_) { $i++; continue; } diff --git a/src/Rules/Arrays/ArrayUnpackingRule.php b/src/Rules/Arrays/ArrayUnpackingRule.php index 4be69c0ac0..f1573bec6d 100644 --- a/src/Rules/Arrays/ArrayUnpackingRule.php +++ b/src/Rules/Arrays/ArrayUnpackingRule.php @@ -3,7 +3,7 @@ namespace PHPStan\Rules\Arrays; use PhpParser\Node; -use PhpParser\Node\Expr\ArrayItem; +use PhpParser\Node\ArrayItem; use PHPStan\Analyser\Scope; use PHPStan\Node\Expr\GetIterableKeyTypeExpr; use PHPStan\Php\PhpVersion; diff --git a/src/Rules/Arrays/EmptyArrayItemRule.php b/src/Rules/Arrays/EmptyArrayItemRule.php index 0bfcebf956..dfe2a48d4b 100644 --- a/src/Rules/Arrays/EmptyArrayItemRule.php +++ b/src/Rules/Arrays/EmptyArrayItemRule.php @@ -9,6 +9,7 @@ use PHPStan\Rules\RuleErrorBuilder; /** + * @deprecated Since PHP-Parser 5.0 this is a parse error. * @implements Rule */ final class EmptyArrayItemRule implements Rule diff --git a/src/Rules/Arrays/InvalidKeyInArrayItemRule.php b/src/Rules/Arrays/InvalidKeyInArrayItemRule.php index 5b5f3545a9..fb4ab23162 100644 --- a/src/Rules/Arrays/InvalidKeyInArrayItemRule.php +++ b/src/Rules/Arrays/InvalidKeyInArrayItemRule.php @@ -11,7 +11,7 @@ use function sprintf; /** - * @implements Rule + * @implements Rule */ final class InvalidKeyInArrayItemRule implements Rule { @@ -22,7 +22,7 @@ public function __construct(private bool $reportMaybes) public function getNodeType(): string { - return Node\Expr\ArrayItem::class; + return Node\ArrayItem::class; } public function processNode(Node $node, Scope $scope): array diff --git a/src/Rules/Cast/InvalidPartOfEncapsedStringRule.php b/src/Rules/Cast/InvalidPartOfEncapsedStringRule.php index 5cf96d8ad2..a2c04dc054 100644 --- a/src/Rules/Cast/InvalidPartOfEncapsedStringRule.php +++ b/src/Rules/Cast/InvalidPartOfEncapsedStringRule.php @@ -14,7 +14,7 @@ use function sprintf; /** - * @implements Rule + * @implements Rule */ final class InvalidPartOfEncapsedStringRule implements Rule { @@ -28,14 +28,14 @@ public function __construct( public function getNodeType(): string { - return Node\Scalar\Encapsed::class; + return Node\Scalar\InterpolatedString::class; } public function processNode(Node $node, Scope $scope): array { $messages = []; foreach ($node->parts as $part) { - if ($part instanceof Node\Scalar\EncapsedStringPart) { + if ($part instanceof Node\InterpolatedStringPart) { continue; } diff --git a/src/Rules/Functions/UnusedClosureUsesRule.php b/src/Rules/Functions/UnusedClosureUsesRule.php index 1494208b5b..c019d69240 100644 --- a/src/Rules/Functions/UnusedClosureUsesRule.php +++ b/src/Rules/Functions/UnusedClosureUsesRule.php @@ -34,7 +34,7 @@ public function processNode(Node $node, Scope $scope): array return $this->check->getUnusedParameters( $scope, - array_map(static function (Node\Expr\ClosureUse $use): string { + array_map(static function (Node\ClosureUse $use): string { if (!is_string($use->var->name)) { throw new ShouldNotHappenException(); } diff --git a/src/Rules/NullsafeCheck.php b/src/Rules/NullsafeCheck.php index b8ff7713bf..a4424b69ac 100644 --- a/src/Rules/NullsafeCheck.php +++ b/src/Rules/NullsafeCheck.php @@ -36,7 +36,7 @@ public function containsNullSafe(Expr $expr): bool return $this->containsNullSafe($expr->class); } - if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) { + if ($expr instanceof Expr\List_) { foreach ($expr->items as $item) { if ($item === null) { continue; diff --git a/src/Rules/Operators/InvalidAssignVarRule.php b/src/Rules/Operators/InvalidAssignVarRule.php index 7b24c91c52..a5ae2ac291 100644 --- a/src/Rules/Operators/InvalidAssignVarRule.php +++ b/src/Rules/Operators/InvalidAssignVarRule.php @@ -85,7 +85,7 @@ private function containsNonAssignableExpression(Expr $expr): bool return false; } - if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) { + if ($expr instanceof Expr\List_) { foreach ($expr->items as $item) { if ($item === null) { continue; diff --git a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php index 9e4fc3ebf1..b7021dfe92 100644 --- a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php +++ b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php @@ -195,7 +195,7 @@ private function getAssignedVariables(Expr $expr): array return []; } - if ($expr instanceof Expr\List_ || $expr instanceof Expr\Array_) { + if ($expr instanceof Expr\List_) { $names = []; foreach ($expr->items as $item) { if ($item === null) { diff --git a/src/Rules/UnusedFunctionParametersCheck.php b/src/Rules/UnusedFunctionParametersCheck.php index b85150e267..4fbe76d20d 100644 --- a/src/Rules/UnusedFunctionParametersCheck.php +++ b/src/Rules/UnusedFunctionParametersCheck.php @@ -69,7 +69,7 @@ private function getUsedVariables(Scope $scope, $node): array if ($node instanceof Node\Expr\Variable && is_string($node->name) && $node->name !== 'this') { return [$node->name]; } - if ($node instanceof Node\Expr\ClosureUse && is_string($node->var->name)) { + if ($node instanceof Node\ClosureUse && is_string($node->var->name)) { return [$node->var->name]; } if ( diff --git a/src/Type/FileTypeMapper.php b/src/Type/FileTypeMapper.php index edd8d3eef6..db5d8983f5 100644 --- a/src/Type/FileTypeMapper.php +++ b/src/Type/FileTypeMapper.php @@ -519,7 +519,6 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun $node instanceof Node\Stmt && !$node instanceof Node\Stmt\Namespace_ && !$node instanceof Node\Stmt\Declare_ - && !$node instanceof Node\Stmt\DeclareDeclare && !$node instanceof Node\Stmt\Use_ && !$node instanceof Node\Stmt\UseUse && !$node instanceof Node\Stmt\GroupUse diff --git a/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php index 472683ffb1..a571338e18 100644 --- a/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php @@ -51,10 +51,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n && $valueType->isConstantArray()->yes() && !$valueType->isCallable()->no() ) { - if ($value->items[0] === null || $value->items[1] === null) { - throw new ShouldNotHappenException(); - } - $functionCall = new FuncCall(new Name('method_exists'), [ new Arg($value->items[0]->value), new Arg($value->items[1]->value), From a0122ff9469572777d8fa5ca62ff1896641362e7 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Dec 2023 16:20:13 +0100 Subject: [PATCH 008/508] Tests changes --- tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php b/tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php index 51ba629e16..df14e33493 100644 --- a/tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php @@ -20,7 +20,7 @@ public function testRule(): void { $this->analyse([__DIR__ . '/data/empty-array-item.php'], [ [ - 'Literal array contains empty item.', + 'Cannot use empty array elements in arrays on line 5', 5, ], ]); From 357905ed33f9efbac067e99d48c554ef2ad9799d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Dec 2023 16:32:08 +0100 Subject: [PATCH 009/508] Fixes --- src/Analyser/MutatingScope.php | 2 +- .../BetterReflection/SourceLocator/AutoloadSourceLocator.php | 1 + src/Type/Constant/OversizedArrayBuilder.php | 5 +++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 3a251908c9..36eedbe816 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -1837,7 +1837,7 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu } else { $items = []; foreach ($arm->conds as $filteringExpr) { - $items[] = new Expr\ArrayItem($filteringExpr); + $items[] = new Node\ArrayItem($filteringExpr); } $filteringExpr = new FuncCall( new Name\FullyQualified('in_array'), diff --git a/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php b/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php index 7506682426..2edde64fbc 100644 --- a/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php +++ b/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php @@ -114,6 +114,7 @@ public function locateIdentifier(Reflector $reflector, Identifier $identifier): 'startFilePos' => 1, 'endFilePos' => 4, ]), + null, new LocatedSource('getIterableValueType()), new TypeExpr($valueType->getIterableKeyType()), )]); From 5909dd1c1a7213bce79232caf9a60296f1bd948a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Dec 2023 16:46:18 +0100 Subject: [PATCH 010/508] Fix deprecations --- src/Dependency/ExportedNodeVisitor.php | 4 ++-- .../BetterReflection/SourceLocator/CachingVisitor.php | 10 +++++----- src/Rules/Whitespace/FileWhitespaceRule.php | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Dependency/ExportedNodeVisitor.php b/src/Dependency/ExportedNodeVisitor.php index 90df53887b..34dfd1efe1 100644 --- a/src/Dependency/ExportedNodeVisitor.php +++ b/src/Dependency/ExportedNodeVisitor.php @@ -3,7 +3,7 @@ namespace PHPStan\Dependency; use PhpParser\Node; -use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; use PHPStan\ShouldNotHappenException; @@ -52,7 +52,7 @@ public function enterNode(Node $node): ?int || $node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\Trait_ ) { - return NodeTraverser::DONT_TRAVERSE_CHILDREN; + return NodeVisitor::DONT_TRAVERSE_CHILDREN; } return null; diff --git a/src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php b/src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php index 3a6d194395..6eb1f57604 100644 --- a/src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php +++ b/src/Reflection/BetterReflection/SourceLocator/CachingVisitor.php @@ -4,7 +4,7 @@ use PhpParser\Node; use PhpParser\Node\Stmt\Namespace_; -use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; use PHPStan\BetterReflection\Reflection\Exception\InvalidConstantNode; use PHPStan\BetterReflection\SourceLocator\Located\LocatedSource; @@ -51,7 +51,7 @@ public function enterNode(Node $node): ?int ); } - return NodeTraverser::DONT_TRAVERSE_CHILDREN; + return NodeVisitor::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Stmt\Function_) { @@ -64,7 +64,7 @@ public function enterNode(Node $node): ?int ); } - return NodeTraverser::DONT_TRAVERSE_CHILDREN; + return NodeVisitor::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Stmt\Const_) { @@ -80,7 +80,7 @@ public function enterNode(Node $node): ?int ); } - return NodeTraverser::DONT_TRAVERSE_CHILDREN; + return NodeVisitor::DONT_TRAVERSE_CHILDREN; } if ($node instanceof Node\Expr\FuncCall) { @@ -101,7 +101,7 @@ public function enterNode(Node $node): ?int ); $this->constantNodes[ConstantNameHelper::normalize($constantName)][] = $constantNode; - return NodeTraverser::DONT_TRAVERSE_CHILDREN; + return NodeVisitor::DONT_TRAVERSE_CHILDREN; } return null; diff --git a/src/Rules/Whitespace/FileWhitespaceRule.php b/src/Rules/Whitespace/FileWhitespaceRule.php index d234baa6b1..3fb3cbf239 100644 --- a/src/Rules/Whitespace/FileWhitespaceRule.php +++ b/src/Rules/Whitespace/FileWhitespaceRule.php @@ -5,6 +5,7 @@ use Nette\Utils\Strings; use PhpParser\Node; use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor; use PhpParser\NodeVisitorAbstract; use PHPStan\Analyser\Scope; use PHPStan\Node\FileNode; @@ -61,7 +62,7 @@ public function enterNode(Node $node) } return null; } - return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; + return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } /** From c6acbe9c905e47a6ce49c26f7800e01e0b6040e5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 22 Dec 2023 14:46:05 +0100 Subject: [PATCH 011/508] Fix phar.yml --- .github/workflows/phar.yml | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index 723e8a93be..f2f75906b3 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -10,6 +10,9 @@ on: tags: - '2.0.*' +env: + COMPOSER_ROOT_VERSION: "1.12.x-dev" + concurrency: group: phar-${{ github.ref }} # will be canceled on subsequent pushes in both branches and pull requests cancel-in-progress: true @@ -76,15 +79,12 @@ jobs: - name: "Composer dump" run: "composer install --no-interaction --no-progress" - env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" - name: "Compile PHAR for checksum" working-directory: "compiler/build" run: "php box.phar compile --no-parallel" env: PHAR_CHECKSUM: "1" - COMPOSER_ROOT_VERSION: "1.12.x-dev" - name: "Re-sign PHAR" run: "php compiler/build/resign.php tmp/phpstan.phar" @@ -107,43 +107,25 @@ jobs: integration-tests: if: github.event_name == 'pull_request' needs: compiler-tests -<<<<<<< HEAD - uses: phpstan/phpstan/.github/workflows/integration-tests.yml@1.12.x - with: - ref: 1.12.x -======= uses: phpstan/phpstan/.github/workflows/integration-tests.yml@2.0.x with: ref: 2.0.x ->>>>>>> 264ce7a58b (Open 2.0.x-dev) phar-checksum: ${{needs.compiler-tests.outputs.checksum}} extension-tests: if: github.event_name == 'pull_request' needs: compiler-tests -<<<<<<< HEAD - uses: phpstan/phpstan/.github/workflows/extension-tests.yml@1.12.x - with: - ref: 1.12.x -======= uses: phpstan/phpstan/.github/workflows/extension-tests.yml@2.0.x with: ref: 2.0.x ->>>>>>> 264ce7a58b (Open 2.0.x-dev) phar-checksum: ${{needs.compiler-tests.outputs.checksum}} other-tests: if: github.event_name == 'pull_request' needs: compiler-tests -<<<<<<< HEAD - uses: phpstan/phpstan/.github/workflows/other-tests.yml@1.12.x - with: - ref: 1.12.x -======= uses: phpstan/phpstan/.github/workflows/other-tests.yml@2.0.x with: ref: 2.0.x ->>>>>>> 264ce7a58b (Open 2.0.x-dev) phar-checksum: ${{needs.compiler-tests.outputs.checksum}} commit: @@ -170,11 +152,7 @@ jobs: repository: phpstan/phpstan path: phpstan-dist token: ${{ secrets.PHPSTAN_BOT_TOKEN }} -<<<<<<< HEAD - ref: 1.12.x -======= ref: 2.0.x ->>>>>>> 264ce7a58b (Open 2.0.x-dev) - name: "Get previous pushed dist commit" id: previous-commit From 8bfffef61f1b44761c1d361c01f3bd64c7ab456b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 29 Dec 2023 10:01:35 +0100 Subject: [PATCH 012/508] Fix ThrowExprTypeRuleTest --- .../Rules/Exceptions/ThrowExprTypeRuleTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/PHPStan/Rules/Exceptions/ThrowExprTypeRuleTest.php b/tests/PHPStan/Rules/Exceptions/ThrowExprTypeRuleTest.php index 8ef6277fe1..9ece8025a0 100644 --- a/tests/PHPStan/Rules/Exceptions/ThrowExprTypeRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/ThrowExprTypeRuleTest.php @@ -23,16 +23,16 @@ public function testRule(): void $this->analyse( [__DIR__ . '/data/throw-values.php'], [ - /*[ + [ 'Invalid type int to throw.', 29, ], [ - 'Invalid type ThrowValues\InvalidException to throw.', + 'Invalid type ThrowExprValues\InvalidException to throw.', 32, ], [ - 'Invalid type ThrowValues\InvalidInterfaceException to throw.', + 'Invalid type ThrowExprValues\InvalidInterfaceException to throw.', 35, ], [ @@ -40,10 +40,10 @@ public function testRule(): void 38, ], [ - 'Throwing object of an unknown class ThrowValues\NonexistentClass.', + 'Throwing object of an unknown class ThrowExprValues\NonexistentClass.', 44, 'Learn more at https://phpstan.org/user-guide/discovering-symbols', - ],*/ + ], [ 'Invalid type int to throw.', 65, @@ -64,10 +64,10 @@ public function testRuleWithNullsafeVariant(): void } $this->analyse([__DIR__ . '/data/throw-values-nullsafe.php'], [ - /*[ + [ 'Invalid type Exception|null to throw.', 17, - ],*/ + ], ]); } From 2ac47f1fe19fe3d00709a6d5d22de792886343db Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 29 Dec 2023 10:02:00 +0100 Subject: [PATCH 013/508] Remove obsolete ThrowTypeRule because it targeted Stmt\Throw_ --- conf/config.level3.neon | 1 - src/Rules/Variables/ThrowTypeRule.php | 62 ---------------- .../Rules/Variables/ThrowTypeRuleTest.php | 70 ------------------- .../Variables/data/throw-class-exists.php | 19 ----- .../Variables/data/throw-values-nullsafe.php | 18 ----- .../Rules/Variables/data/throw-values.php | 62 ---------------- 6 files changed, 232 deletions(-) delete mode 100644 src/Rules/Variables/ThrowTypeRule.php delete mode 100644 tests/PHPStan/Rules/Variables/ThrowTypeRuleTest.php delete mode 100644 tests/PHPStan/Rules/Variables/data/throw-class-exists.php delete mode 100644 tests/PHPStan/Rules/Variables/data/throw-values-nullsafe.php delete mode 100644 tests/PHPStan/Rules/Variables/data/throw-values.php diff --git a/conf/config.level3.neon b/conf/config.level3.neon index 5540500714..f205db23b6 100644 --- a/conf/config.level3.neon +++ b/conf/config.level3.neon @@ -30,7 +30,6 @@ rules: - PHPStan\Rules\Properties\ReadOnlyPropertyAssignRule - PHPStan\Rules\Properties\ReadOnlyPropertyAssignRefRule - PHPStan\Rules\Properties\TypesAssignedToPropertiesRule - - PHPStan\Rules\Variables\ThrowTypeRule - PHPStan\Rules\Variables\VariableCloningRule parameters: diff --git a/src/Rules/Variables/ThrowTypeRule.php b/src/Rules/Variables/ThrowTypeRule.php deleted file mode 100644 index 03a80e73bf..0000000000 --- a/src/Rules/Variables/ThrowTypeRule.php +++ /dev/null @@ -1,62 +0,0 @@ - - */ -final class ThrowTypeRule implements Rule -{ - - public function __construct( - private RuleLevelHelper $ruleLevelHelper, - ) - { - } - - public function getNodeType(): string - { - return Node\Stmt\Throw_::class; - } - - public function processNode(Node $node, Scope $scope): array - { - $throwableType = new ObjectType(Throwable::class); - $typeResult = $this->ruleLevelHelper->findTypeToCheck( - $scope, - $node->expr, - 'Throwing object of an unknown class %s.', - static fn (Type $type): bool => $throwableType->isSuperTypeOf($type)->yes(), - ); - - $foundType = $typeResult->getType(); - if ($foundType instanceof ErrorType) { - return $typeResult->getUnknownClassErrors(); - } - - $isSuperType = $throwableType->isSuperTypeOf($foundType); - if ($isSuperType->yes()) { - return []; - } - - return [ - RuleErrorBuilder::message(sprintf( - 'Invalid type %s to throw.', - $foundType->describe(VerbosityLevel::typeOnly()), - ))->identifier('throw.notThrowable')->build(), - ]; - } - -} diff --git a/tests/PHPStan/Rules/Variables/ThrowTypeRuleTest.php b/tests/PHPStan/Rules/Variables/ThrowTypeRuleTest.php deleted file mode 100644 index 020f713708..0000000000 --- a/tests/PHPStan/Rules/Variables/ThrowTypeRuleTest.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ -class ThrowTypeRuleTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new ThrowTypeRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false)); - } - - public function testRule(): void - { - $this->analyse( - [__DIR__ . '/data/throw-values.php'], - [ - [ - 'Invalid type int to throw.', - 29, - ], - [ - 'Invalid type ThrowValues\InvalidException to throw.', - 32, - ], - [ - 'Invalid type ThrowValues\InvalidInterfaceException to throw.', - 35, - ], - [ - 'Invalid type Exception|null to throw.', - 38, - ], - [ - 'Throwing object of an unknown class ThrowValues\NonexistentClass.', - 44, - 'Learn more at https://phpstan.org/user-guide/discovering-symbols', - ], - ], - ); - } - - public function testClassExists(): void - { - $this->analyse([__DIR__ . '/data/throw-class-exists.php'], []); - } - - public function testRuleWithNullsafeVariant(): void - { - if (PHP_VERSION_ID < 80000) { - $this->markTestSkipped('Test requires PHP 8.0.'); - } - - $this->analyse([__DIR__ . '/data/throw-values-nullsafe.php'], [ - [ - 'Invalid type Exception|null to throw.', - 17, - ], - ]); - } - -} diff --git a/tests/PHPStan/Rules/Variables/data/throw-class-exists.php b/tests/PHPStan/Rules/Variables/data/throw-class-exists.php deleted file mode 100644 index f819307398..0000000000 --- a/tests/PHPStan/Rules/Variables/data/throw-class-exists.php +++ /dev/null @@ -1,19 +0,0 @@ -= 8.0 - -namespace ThrowValuesNullsafe; - -class Bar -{ - - function doException(): \Exception - { - return new \Exception(); - } - -} - -function doFoo(?Bar $bar) -{ - throw $bar?->doException(); -} diff --git a/tests/PHPStan/Rules/Variables/data/throw-values.php b/tests/PHPStan/Rules/Variables/data/throw-values.php deleted file mode 100644 index 5582923fa2..0000000000 --- a/tests/PHPStan/Rules/Variables/data/throw-values.php +++ /dev/null @@ -1,62 +0,0 @@ - $genericExceptionClassName - * @param T $genericException - */ -function test($genericExceptionClassName, $genericException) { - /** @var ValidInterfaceException $validInterface */ - $validInterface = new \Exception(); - /** @var InvalidInterfaceException $invalidInterface */ - $invalidInterface = new \Exception(); - /** @var \Exception|null $nullableException */ - $nullableException = new \Exception(); - - if (rand(0, 1)) { - throw new \Exception(); - } - if (rand(0, 1)) { - throw $validInterface; - } - if (rand(0, 1)) { - throw 123; - } - if (rand(0, 1)) { - throw new InvalidException(); - } - if (rand(0, 1)) { - throw $invalidInterface; - } - if (rand(0, 1)) { - throw $nullableException; - } - if (rand(0, 1)) { - throw foo(); - } - if (rand(0, 1)) { - throw new NonexistentClass(); - } - if (rand(0, 1)) { - throw new $genericExceptionClassName; - } - if (rand(0, 1)) { - throw $genericException; - } -} - -function (\stdClass $foo) { - /** @var \Exception $foo */ - throw $foo; -}; - -function (\stdClass $foo) { - /** @var \Exception */ - throw $foo; -}; From 03bef7e630ad3fff8bfb6aca18d746629959e251 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 17:07:57 +0100 Subject: [PATCH 014/508] Fix ThrowExpressionRule --- conf/config.neon | 5 ++++ src/Parser/StandaloneThrowExprVisitor.php | 28 ++++++++++++++++++++ src/Rules/Exceptions/ThrowExpressionRule.php | 5 ++++ 3 files changed, 38 insertions(+) create mode 100644 src/Parser/StandaloneThrowExprVisitor.php diff --git a/conf/config.neon b/conf/config.neon index dac1e96e5f..4558955396 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -372,6 +372,11 @@ services: tags: - phpstan.parser.richParserNodeVisitor + - + class: PHPStan\Parser\StandaloneThrowExprVisitor + tags: + - phpstan.parser.richParserNodeVisitor + - class: PHPStan\Parser\TryCatchTypeVisitor tags: diff --git a/src/Parser/StandaloneThrowExprVisitor.php b/src/Parser/StandaloneThrowExprVisitor.php new file mode 100644 index 0000000000..e108246128 --- /dev/null +++ b/src/Parser/StandaloneThrowExprVisitor.php @@ -0,0 +1,28 @@ +expr instanceof Node\Expr\Throw_) { + return null; + } + + $node->expr->setAttribute(self::ATTRIBUTE_NAME, true); + + return $node; + } + +} diff --git a/src/Rules/Exceptions/ThrowExpressionRule.php b/src/Rules/Exceptions/ThrowExpressionRule.php index 5d3c7c2576..9fcc9c9e88 100644 --- a/src/Rules/Exceptions/ThrowExpressionRule.php +++ b/src/Rules/Exceptions/ThrowExpressionRule.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\Parser\StandaloneThrowExprVisitor; use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -29,6 +30,10 @@ public function processNode(Node $node, Scope $scope): array return []; } + if ($node->getAttribute(StandaloneThrowExprVisitor::ATTRIBUTE_NAME) === true) { + return []; + } + return [ RuleErrorBuilder::message('Throw expression is supported only on PHP 8.0 and later.')->nonIgnorable() ->identifier('throw.notSupported') From 89bc1e6e4d2ff8f23466cbceeec65d5696b97e6c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 17:14:46 +0100 Subject: [PATCH 015/508] Fixes --- src/Analyser/MutatingScope.php | 10 ++++------ src/Analyser/NodeScopeResolver.php | 1 - src/Dependency/ExportedNodeResolver.php | 2 +- src/Reflection/InitializerExprTypeResolver.php | 8 ++++---- src/Rules/Namespaces/ExistingNamesInUseRule.php | 8 ++++---- src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php | 1 - src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php | 1 - src/Type/FileTypeMapper.php | 1 - 8 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 36eedbe816..c3f58e1c92 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -24,8 +24,6 @@ use PhpParser\Node\InterpolatedStringPart; use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified; -use PhpParser\Node\Scalar\DNumber; -use PhpParser\Node\Scalar\LNumber; use PhpParser\Node\Scalar\String_; use PhpParser\NodeFinder; use PHPStan\Node\ExecutionEndNode; @@ -1125,7 +1123,7 @@ private function resolveType(string $exprString, Expr $node): Type return $this->getType($node->expr); } - if ($node instanceof LNumber) { + if ($node instanceof Node\Scalar\Int_) { return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); } elseif ($node instanceof String_) { return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); @@ -1149,7 +1147,7 @@ private function resolveType(string $exprString, Expr $node): Type } return $resultType ?? new ConstantStringType(''); - } elseif ($node instanceof DNumber) { + } elseif ($node instanceof Node\Scalar\Float_) { return $this->initializerExprTypeResolver->getType($node, InitializerExprContext::fromScope($this)); } elseif ($node instanceof Expr\CallLike && $node->isFirstClassCallable()) { if ($node instanceof FuncCall) { @@ -1707,10 +1705,10 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu } if ($node instanceof Expr\PreInc) { - return $this->getType(new BinaryOp\Plus($node->var, new LNumber(1))); + return $this->getType(new BinaryOp\Plus($node->var, new Node\Scalar\Int_(1))); } - return $this->getType(new BinaryOp\Minus($node->var, new LNumber(1))); + return $this->getType(new BinaryOp\Minus($node->var, new Node\Scalar\Int_(1))); } elseif ($node instanceof Expr\Yield_) { $functionReflection = $this->getFunction(); if ($functionReflection === null) { diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index e7b3a0abab..e11eeff70a 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -444,7 +444,6 @@ private function processStmtNode( && !$stmt instanceof Foreach_ && !$stmt instanceof Node\Stmt\Global_ && !$stmt instanceof Node\Stmt\Property - && !$stmt instanceof Node\Stmt\PropertyProperty && !$stmt instanceof Node\Stmt\ClassConst && !$stmt instanceof Node\Stmt\Const_ ) { diff --git a/src/Dependency/ExportedNodeResolver.php b/src/Dependency/ExportedNodeResolver.php index c9a0c52154..36a752735d 100644 --- a/src/Dependency/ExportedNodeResolver.php +++ b/src/Dependency/ExportedNodeResolver.php @@ -336,7 +336,7 @@ private function exportClassStatement(Node\Stmt $node, string $fileName, string $docComment = $node->getDocComment(); return new ExportedPropertiesNode( - array_map(static fn (Node\Stmt\PropertyProperty $prop): string => $prop->name->toString(), $node->props), + array_map(static fn (Node\PropertyItem $prop): string => $prop->name->toString(), $node->props), $this->exportPhpDocNode( $fileName, $namespacedName, diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 2f1aaa96a0..6013737759 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -11,8 +11,8 @@ use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Identifier; use PhpParser\Node\Name; -use PhpParser\Node\Scalar\DNumber; -use PhpParser\Node\Scalar\LNumber; +use PhpParser\Node\Scalar\Float_; +use PhpParser\Node\Scalar\Int_; use PhpParser\Node\Scalar\MagicConst; use PhpParser\Node\Scalar\MagicConst\Dir; use PhpParser\Node\Scalar\MagicConst\File; @@ -113,10 +113,10 @@ public function getType(Expr $expr, InitializerExprContext $context): Type if ($expr instanceof TypeExpr) { return $expr->getExprType(); } - if ($expr instanceof LNumber) { + if ($expr instanceof Int_) { return new ConstantIntegerType($expr->value); } - if ($expr instanceof DNumber) { + if ($expr instanceof Float_) { return new ConstantFloatType($expr->value); } if ($expr instanceof String_) { diff --git a/src/Rules/Namespaces/ExistingNamesInUseRule.php b/src/Rules/Namespaces/ExistingNamesInUseRule.php index 381a2e1de6..b93db1ea45 100644 --- a/src/Rules/Namespaces/ExistingNamesInUseRule.php +++ b/src/Rules/Namespaces/ExistingNamesInUseRule.php @@ -58,7 +58,7 @@ public function processNode(Node $node, Scope $scope): array } /** - * @param Node\Stmt\UseUse[] $uses + * @param Node\UseItem[] $uses * @return list */ private function checkConstants(array $uses): array @@ -80,7 +80,7 @@ private function checkConstants(array $uses): array } /** - * @param Node\Stmt\UseUse[] $uses + * @param Node\UseItem[] $uses * @return list */ private function checkFunctions(array $uses): array @@ -117,13 +117,13 @@ private function checkFunctions(array $uses): array } /** - * @param Node\Stmt\UseUse[] $uses + * @param Node\UseItem[] $uses * @return list */ private function checkClasses(array $uses): array { return $this->classCheck->checkClassNames( - array_map(static fn (Node\Stmt\UseUse $use): ClassNameNodePair => new ClassNameNodePair((string) $use->name, $use->name), $uses), + array_map(static fn (Node\UseItem $use): ClassNameNodePair => new ClassNameNodePair((string) $use->name, $use->name), $uses), ); } diff --git a/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php b/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php index 4a227ffd07..81b4296100 100644 --- a/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php +++ b/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php @@ -48,7 +48,6 @@ public function processNode(Node $node, Scope $scope): array { if ( $node instanceof Node\Stmt\Property - || $node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Stmt\ClassConst || $node instanceof Node\Stmt\Const_ ) { diff --git a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php index b7021dfe92..5ff12a4206 100644 --- a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php +++ b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php @@ -51,7 +51,6 @@ public function processNode(Node $node, Scope $scope): array { if ( $node instanceof Node\Stmt\Property - || $node instanceof Node\Stmt\PropertyProperty || $node instanceof Node\Stmt\ClassConst || $node instanceof Node\Stmt\Const_ || ($node instanceof VirtualNode && !$node instanceof InFunctionNode && !$node instanceof InClassMethodNode && !$node instanceof InClassNode) diff --git a/src/Type/FileTypeMapper.php b/src/Type/FileTypeMapper.php index db5d8983f5..a0af548147 100644 --- a/src/Type/FileTypeMapper.php +++ b/src/Type/FileTypeMapper.php @@ -520,7 +520,6 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun && !$node instanceof Node\Stmt\Namespace_ && !$node instanceof Node\Stmt\Declare_ && !$node instanceof Node\Stmt\Use_ - && !$node instanceof Node\Stmt\UseUse && !$node instanceof Node\Stmt\GroupUse && !$node instanceof Node\Stmt\TraitUse && !$node instanceof Node\Stmt\TraitUseAdaptation From 8dafccb4bc6075bfd63b9ab31042c6cd1c6752d1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 17:26:02 +0100 Subject: [PATCH 016/508] ParserFactory to correctly create Php7/Php8 --- conf/config.neon | 6 +++++- src/Parser/PhpParserFactory.php | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/Parser/PhpParserFactory.php diff --git a/conf/config.neon b/conf/config.neon index 4558955396..d1b5182fe0 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -2050,7 +2050,11 @@ services: autowired: false currentPhpVersionPhpParser: - class: PhpParser\Parser\Php8 # todo use factory and create Php7/Php8 + factory: @currentPhpVersionPhpParserFactory::create() + autowired: false + + currentPhpVersionPhpParserFactory: + class: PHPStan\Parser\PhpParserFactory arguments: lexer: @currentPhpVersionLexer autowired: false diff --git a/src/Parser/PhpParserFactory.php b/src/Parser/PhpParserFactory.php new file mode 100644 index 0000000000..dee78b35d2 --- /dev/null +++ b/src/Parser/PhpParserFactory.php @@ -0,0 +1,28 @@ +phpVersion->getVersionString()); + if ($this->phpVersion->getVersionId() >= 80000) { + return new Php8($this->lexer, $phpVersion); + } + + return new Php7($this->lexer, $phpVersion); + } + +} From 503fe0ce4f12f2a515974d75513c92b32f733dd1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 17:31:15 +0100 Subject: [PATCH 017/508] This hack is no longer needed because there is now clear separation between Name and Identifier --- src/Type/TypehintHelper.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Type/TypehintHelper.php b/src/Type/TypehintHelper.php index 8f9f5616f3..dbfb14973a 100644 --- a/src/Type/TypehintHelper.php +++ b/src/Type/TypehintHelper.php @@ -16,7 +16,6 @@ use function get_class; use function is_string; use function sprintf; -use function str_ends_with; use function strtolower; final class TypehintHelper @@ -132,20 +131,6 @@ public static function decideTypeFromReflection( } $reflectionTypeString = $reflectionType->getName(); - $loweredReflectionTypeString = strtolower($reflectionTypeString); - if (str_ends_with($loweredReflectionTypeString, '\\object')) { - $reflectionTypeString = 'object'; - } elseif (str_ends_with($loweredReflectionTypeString, '\\mixed')) { - $reflectionTypeString = 'mixed'; - } elseif (str_ends_with($loweredReflectionTypeString, '\\true')) { - $reflectionTypeString = 'true'; - } elseif (str_ends_with($loweredReflectionTypeString, '\\false')) { - $reflectionTypeString = 'false'; - } elseif (str_ends_with($loweredReflectionTypeString, '\\null')) { - $reflectionTypeString = 'null'; - } elseif (str_ends_with($loweredReflectionTypeString, '\\never')) { - $reflectionTypeString = 'never'; - } $type = self::getTypeObjectFromTypehint($reflectionTypeString, $selfClass); if ($reflectionType->allowsNull()) { From 201fca1458f7bcea325de003cdc4e099fb64e462 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 17:39:24 +0100 Subject: [PATCH 018/508] Fix NeverRuleHelper --- src/Rules/Playground/NeverRuleHelper.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Rules/Playground/NeverRuleHelper.php b/src/Rules/Playground/NeverRuleHelper.php index 520b426424..9865d3d1ce 100644 --- a/src/Rules/Playground/NeverRuleHelper.php +++ b/src/Rules/Playground/NeverRuleHelper.php @@ -26,10 +26,17 @@ public function shouldReturnNever(ReturnStatementsNode $node, Type $returnType): $other = []; foreach ($node->getExecutionEnds() as $executionEnd) { if ($executionEnd->getStatementResult()->isAlwaysTerminating()) { - if (!$executionEnd->getNode() instanceof Node\Stmt\Throw_) { + $executionEndNode = $executionEnd->getNode(); + if (!$executionEndNode instanceof Node\Stmt\Expression) { $other[] = $executionEnd->getNode(); + continue; } + if ($executionEndNode->expr instanceof Node\Expr\Throw_) { + continue; + } + + $other[] = $executionEnd->getNode(); continue; } From 23060238dda22589a5497b2437a568c7d990df96 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 17:41:45 +0100 Subject: [PATCH 019/508] Get rid of more Stmt\Throw_ instances --- src/Parser/LastConditionVisitor.php | 8 +++++++- .../Exceptions/OverwrittenExitPointByFinallyRule.php | 2 +- src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Parser/LastConditionVisitor.php b/src/Parser/LastConditionVisitor.php index d4c4b53ac3..d20a8f4b90 100644 --- a/src/Parser/LastConditionVisitor.php +++ b/src/Parser/LastConditionVisitor.php @@ -68,7 +68,13 @@ public function enterNode(Node $node): ?Node return null; } - if (!$statements[$statementCount - 1] instanceof Node\Stmt\Throw_) { + $lastStatement = $statements[$statementCount - 1]; + + if (!$lastStatement instanceof Node\Stmt\Expression) { + return null; + } + + if (!$lastStatement->expr instanceof Node\Expr\Throw_) { return null; } diff --git a/src/Rules/Exceptions/OverwrittenExitPointByFinallyRule.php b/src/Rules/Exceptions/OverwrittenExitPointByFinallyRule.php index f4a6e17499..74fa2eb0ae 100644 --- a/src/Rules/Exceptions/OverwrittenExitPointByFinallyRule.php +++ b/src/Rules/Exceptions/OverwrittenExitPointByFinallyRule.php @@ -51,7 +51,7 @@ private function describeExitPoint(Node\Stmt $stmt): string return 'return'; } - if ($stmt instanceof Node\Stmt\Throw_) { + if ($stmt instanceof Node\Stmt\Expression && $stmt->expr instanceof Node\Expr\Throw_) { return 'throw'; } diff --git a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php index 5ff12a4206..87784c71d6 100644 --- a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php +++ b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php @@ -89,10 +89,13 @@ public function processNode(Node $node, Scope $scope): array } if ($node instanceof Node\Stmt\Expression) { + if ($node->expr instanceof Expr\Throw_) { + return $this->processStmt($scope, $varTags, $node->expr); + } return $this->processExpression($scope, $node->expr, $varTags); } - if ($node instanceof Node\Stmt\Throw_ || $node instanceof Node\Stmt\Return_) { + if ($node instanceof Node\Stmt\Return_) { return $this->processStmt($scope, $varTags, $node->expr); } From 9c177958fc2eda3615967a24504196a7848627aa Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 17:44:34 +0100 Subject: [PATCH 020/508] Fixes --- src/Analyser/NodeScopeResolver.php | 4 ++-- src/Analyser/StatementResult.php | 10 +++++----- src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.php | 4 ++-- src/Reflection/InitializerExprTypeResolver.php | 2 +- src/Rules/Arrays/ArrayDestructuringRule.php | 2 +- src/Rules/Classes/EnumSanityRule.php | 2 +- .../Comparison/DoWhileLoopConstantConditionRule.php | 4 ++-- .../Comparison/WhileLoopAlwaysTrueConditionRule.php | 4 ++-- src/Rules/Keywords/ContinueBreakInLoopRule.php | 2 +- src/Rules/Keywords/DeclareStrictTypesRule.php | 2 +- src/Rules/PhpDoc/VarTagTypeRuleHelper.php | 2 +- .../Php/ArraySumFunctionDynamicReturnTypeExtension.php | 4 ++-- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index e11eeff70a..a15060536b 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -494,7 +494,7 @@ private function processStmtNode( $nodeCallback($declare->value, $scope); if ( $declare->key->name !== 'strict_types' - || !($declare->value instanceof Node\Scalar\LNumber) + || !($declare->value instanceof Node\Scalar\Int_) || $declare->value->value !== 1 ) { continue; @@ -5298,7 +5298,7 @@ static function (): void { $impurePoints = array_merge($impurePoints, $valueResult->getImpurePoints()); if ($arrayItem->key === null) { - $dimExpr = new Node\Scalar\LNumber($i); + $dimExpr = new Node\Scalar\Int_($i); } else { $dimExpr = $arrayItem->key; } diff --git a/src/Analyser/StatementResult.php b/src/Analyser/StatementResult.php index bb9ae78f2e..985777317e 100644 --- a/src/Analyser/StatementResult.php +++ b/src/Analyser/StatementResult.php @@ -2,7 +2,7 @@ namespace PHPStan\Analyser; -use PhpParser\Node\Scalar\LNumber; +use PhpParser\Node\Scalar\Int_; use PhpParser\Node\Stmt; /** @@ -58,7 +58,7 @@ public function filterOutLoopExitPoints(): self } $num = $statement->num; - if (!$num instanceof LNumber) { + if (!$num instanceof Int_) { return new self($this->scope, $this->hasYield, false, $this->exitPoints, $this->throwPoints, $this->impurePoints); } @@ -99,7 +99,7 @@ public function getExitPointsByType(string $stmtClass): array continue; } - if (!$value instanceof LNumber) { + if (!$value instanceof Int_) { $exitPoints[] = $exitPoint; continue; } @@ -130,7 +130,7 @@ public function getExitPointsForOuterLoop(): array if ($statement->num === null) { continue; } - if (!$statement->num instanceof LNumber) { + if (!$statement->num instanceof Int_) { continue; } $value = $statement->num->value; @@ -140,7 +140,7 @@ public function getExitPointsForOuterLoop(): array $newNode = null; if ($value > 2) { - $newNode = new LNumber($value - 1); + $newNode = new Int_($value - 1); } if ($statement instanceof Stmt\Continue_) { $newStatement = new Stmt\Continue_($newNode); diff --git a/src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.php b/src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.php index 48722eeca5..b57afc5fba 100644 --- a/src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.php +++ b/src/Parser/RemoveUnusedCodeByPhpVersionIdVisitor.php @@ -77,7 +77,7 @@ public function enterNode(Node $node): ?Node private function getOperands(Node\Expr $left, Node\Expr $right): ?array { if ( - $left instanceof Node\Scalar\LNumber + $left instanceof Node\Scalar\Int_ && $right instanceof Node\Expr\ConstFetch && $right->name->toString() === 'PHP_VERSION_ID' ) { @@ -85,7 +85,7 @@ private function getOperands(Node\Expr $left, Node\Expr $right): ?array } if ( - $right instanceof Node\Scalar\LNumber + $right instanceof Node\Scalar\Int_ && $left instanceof Node\Expr\ConstFetch && $left->name->toString() === 'PHP_VERSION_ID' ) { diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 6013737759..174adae5c1 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -2044,7 +2044,7 @@ public function getUnaryMinusType(Expr $expr, callable $getTypeCallback): Type } if ($type instanceof IntegerRangeType) { - return $getTypeCallback(new Expr\BinaryOp\Mul($expr, new LNumber(-1))); + return $getTypeCallback(new Expr\BinaryOp\Mul($expr, new Int_(-1))); } return $type; diff --git a/src/Rules/Arrays/ArrayDestructuringRule.php b/src/Rules/Arrays/ArrayDestructuringRule.php index d8281b1d88..1d9537d274 100644 --- a/src/Rules/Arrays/ArrayDestructuringRule.php +++ b/src/Rules/Arrays/ArrayDestructuringRule.php @@ -85,7 +85,7 @@ private function getErrors(Scope $scope, Node\Expr\List_ $var, Expr $expr): arra $keyExpr = null; if ($item->key === null) { $keyType = new ConstantIntegerType($i); - $keyExpr = new Node\Scalar\LNumber($i); + $keyExpr = new Node\Scalar\Int_($i); } else { $keyType = $scope->getType($item->key); $keyExpr = new TypeExpr($keyType); diff --git a/src/Rules/Classes/EnumSanityRule.php b/src/Rules/Classes/EnumSanityRule.php index 2d193095d4..51c07fdfd8 100644 --- a/src/Rules/Classes/EnumSanityRule.php +++ b/src/Rules/Classes/EnumSanityRule.php @@ -143,7 +143,7 @@ public function processNode(Node $node, Scope $scope): array } $caseName = $stmt->name->name; - if ($stmt->expr instanceof Node\Scalar\LNumber || $stmt->expr instanceof Node\Scalar\String_) { + if ($stmt->expr instanceof Node\Scalar\Int_ || $stmt->expr instanceof Node\Scalar\String_) { if ($enumNode->scalarType === null) { $errors[] = RuleErrorBuilder::message(sprintf( 'Enum %s is not backed, but case %s has value %s.', diff --git a/src/Rules/Comparison/DoWhileLoopConstantConditionRule.php b/src/Rules/Comparison/DoWhileLoopConstantConditionRule.php index 3777b5d6e5..4b43745923 100644 --- a/src/Rules/Comparison/DoWhileLoopConstantConditionRule.php +++ b/src/Rules/Comparison/DoWhileLoopConstantConditionRule.php @@ -3,7 +3,7 @@ namespace PHPStan\Rules\Comparison; use PhpParser\Node; -use PhpParser\Node\Scalar\LNumber; +use PhpParser\Node\Scalar\Int_; use PhpParser\Node\Stmt\Break_; use PhpParser\Node\Stmt\Continue_; use PHPStan\Analyser\Scope; @@ -47,7 +47,7 @@ public function processNode(Node $node, Scope $scope): array if ($statement->num === null) { continue; } - if (!$statement->num instanceof LNumber) { + if (!$statement->num instanceof Int_) { continue; } $value = $statement->num->value; diff --git a/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php b/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php index 68ac27fbf2..505c57d7c6 100644 --- a/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php +++ b/src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php @@ -3,7 +3,7 @@ namespace PHPStan\Rules\Comparison; use PhpParser\Node; -use PhpParser\Node\Scalar\LNumber; +use PhpParser\Node\Scalar\Int_; use PhpParser\Node\Stmt\Break_; use PhpParser\Node\Stmt\Continue_; use PHPStan\Analyser\Scope; @@ -46,7 +46,7 @@ public function processNode( if ($statement->num === null) { continue; } - if (!$statement->num instanceof LNumber) { + if (!$statement->num instanceof Int_) { continue; } $value = $statement->num->value; diff --git a/src/Rules/Keywords/ContinueBreakInLoopRule.php b/src/Rules/Keywords/ContinueBreakInLoopRule.php index d8e8b00fcb..75657f232f 100644 --- a/src/Rules/Keywords/ContinueBreakInLoopRule.php +++ b/src/Rules/Keywords/ContinueBreakInLoopRule.php @@ -28,7 +28,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - if (!$node->num instanceof Node\Scalar\LNumber) { + if (!$node->num instanceof Node\Scalar\Int_) { $value = 1; } else { $value = $node->num->value; diff --git a/src/Rules/Keywords/DeclareStrictTypesRule.php b/src/Rules/Keywords/DeclareStrictTypesRule.php index b0b364030a..66aaa94026 100644 --- a/src/Rules/Keywords/DeclareStrictTypesRule.php +++ b/src/Rules/Keywords/DeclareStrictTypesRule.php @@ -40,7 +40,7 @@ public function processNode(Node $node, Scope $scope): array } if ( - !$declare->value instanceof Node\Scalar\LNumber + !$declare->value instanceof Node\Scalar\Int_ || !in_array($declare->value->value, [0, 1], true) ) { return [ diff --git a/src/Rules/PhpDoc/VarTagTypeRuleHelper.php b/src/Rules/PhpDoc/VarTagTypeRuleHelper.php index 0070554896..67bcd8f88a 100644 --- a/src/Rules/PhpDoc/VarTagTypeRuleHelper.php +++ b/src/Rules/PhpDoc/VarTagTypeRuleHelper.php @@ -53,7 +53,7 @@ public function checkVarType(Scope $scope, Node\Expr $var, Node\Expr $expr, arra continue; } if ($arrayItem->key === null) { - $dimExpr = new Node\Scalar\LNumber($i); + $dimExpr = new Node\Scalar\Int_($i); } else { $dimExpr = $arrayItem->key; } diff --git a/src/Type/Php/ArraySumFunctionDynamicReturnTypeExtension.php b/src/Type/Php/ArraySumFunctionDynamicReturnTypeExtension.php index b60730e828..5185fbccc1 100644 --- a/src/Type/Php/ArraySumFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/ArraySumFunctionDynamicReturnTypeExtension.php @@ -5,7 +5,7 @@ use PhpParser\Node\Expr\BinaryOp\Mul; use PhpParser\Node\Expr\BinaryOp\Plus; use PhpParser\Node\Expr\FuncCall; -use PhpParser\Node\Scalar\LNumber; +use PhpParser\Node\Scalar\Int_; use PHPStan\Analyser\Scope; use PHPStan\Node\Expr\TypeExpr; use PHPStan\Reflection\FunctionReflection; @@ -35,7 +35,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, if (count($argType->getConstantArrays()) > 0) { foreach ($argType->getConstantArrays() as $constantArray) { - $node = new LNumber(0); + $node = new Int_(0); foreach ($constantArray->getValueTypes() as $i => $type) { if ($constantArray->isOptionalKey($i)) { From 05d4303e71f48c97da8a892052a5942902ec6760 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 17:47:49 +0100 Subject: [PATCH 021/508] Fixes --- conf/config.neon | 1 - src/Parser/RichParser.php | 2 -- tests/PHPStan/Analyser/AnalyserTest.php | 3 +-- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index d1b5182fe0..4d897a4587 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -2015,7 +2015,6 @@ services: class: PHPStan\Parser\RichParser arguments: parser: @currentPhpVersionPhpParser - lexer: @currentPhpVersionLexer enableIgnoreErrorsWithinPhpDocs: %featureToggles.enableIgnoreErrorsWithinPhpDocs% autowired: no diff --git a/src/Parser/RichParser.php b/src/Parser/RichParser.php index e3f2a5e310..ed0f1840a0 100644 --- a/src/Parser/RichParser.php +++ b/src/Parser/RichParser.php @@ -3,7 +3,6 @@ namespace PHPStan\Parser; use PhpParser\ErrorHandler\Collecting; -use PhpParser\Lexer; use PhpParser\Node; use PhpParser\NodeTraverser; use PhpParser\NodeVisitor\NameResolver; @@ -42,7 +41,6 @@ final class RichParser implements Parser public function __construct( private \PhpParser\Parser $parser, - private Lexer $lexer, private NameResolver $nameResolver, private Container $container, private IgnoreLexer $ignoreLexer, diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index f820c64aff..d59549b9da 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -745,13 +745,12 @@ private function createAnalyser(bool $enableIgnoreErrorsWithinPhpDocs): Analyser self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], self::getContainer()->getParameter('featureToggles')['explicitThrow'], ); - $lexer = new Lexer(['usedAttributes' => ['comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos']]); + $lexer = new Lexer(); $fileAnalyser = new FileAnalyser( $this->createScopeFactory($reflectionProvider, $typeSpecifier), $nodeScopeResolver, new RichParser( new Php7($lexer), - $lexer, new NameResolver(), self::getContainer(), new IgnoreLexer(), From 7981c5daade0d5b646dc4d1ac8a1cfdb68ee156a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 20:38:56 +0100 Subject: [PATCH 022/508] Simplify TypehintHelper and use ParserNodeTypeToPHPStanType --- src/Type/TypehintHelper.php | 96 ++++++++----------------------------- 1 file changed, 19 insertions(+), 77 deletions(-) diff --git a/src/Type/TypehintHelper.php b/src/Type/TypehintHelper.php index dbfb14973a..5538370ccb 100644 --- a/src/Type/TypehintHelper.php +++ b/src/Type/TypehintHelper.php @@ -2,95 +2,25 @@ namespace PHPStan\Type; +use PhpParser\Node\Identifier; +use PhpParser\Node\Name\FullyQualified; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Generic\TemplateTypeHelper; -use ReflectionIntersectionType; -use ReflectionNamedType; use ReflectionType; -use ReflectionUnionType; use function array_map; use function count; use function get_class; use function is_string; use function sprintf; -use function strtolower; final class TypehintHelper { - private static function getTypeObjectFromTypehint(string $typeString, ClassReflection|string|null $selfClass): Type - { - switch (strtolower($typeString)) { - case 'int': - return new IntegerType(); - case 'bool': - return new BooleanType(); - case 'false': - return new ConstantBooleanType(false); - case 'true': - return new ConstantBooleanType(true); - case 'string': - return new StringType(); - case 'float': - return new FloatType(); - case 'array': - return new ArrayType(new MixedType(), new MixedType()); - case 'iterable': - return new IterableType(new MixedType(), new MixedType()); - case 'callable': - return new CallableType(); - case 'void': - return new VoidType(); - case 'object': - return new ObjectWithoutClassType(); - case 'mixed': - return new MixedType(true); - case 'self': - if ($selfClass instanceof ClassReflection) { - $selfClass = $selfClass->getName(); - } - return $selfClass !== null ? new ObjectType($selfClass) : new ErrorType(); - case 'parent': - $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); - if (is_string($selfClass)) { - if ($reflectionProvider->hasClass($selfClass)) { - $selfClass = $reflectionProvider->getClass($selfClass); - } else { - $selfClass = null; - } - } - if ($selfClass !== null) { - if ($selfClass->getParentClass() !== null) { - return new ObjectType($selfClass->getParentClass()->getName()); - } - } - return new NonexistentParentClassType(); - case 'static': - $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); - if (is_string($selfClass)) { - if ($reflectionProvider->hasClass($selfClass)) { - $selfClass = $reflectionProvider->getClass($selfClass); - } else { - $selfClass = null; - } - } - if ($selfClass !== null) { - return new StaticType($selfClass); - } - - return new ErrorType(); - case 'null': - return new NullType(); - case 'never': - return new NonAcceptingNeverType(); - default: - return new ObjectType($typeString); - } - } - /** @api */ public static function decideTypeFromReflection( ?ReflectionType $reflectionType, @@ -130,9 +60,21 @@ public static function decideTypeFromReflection( throw new ShouldNotHappenException(sprintf('Unexpected type: %s', get_class($reflectionType))); } - $reflectionTypeString = $reflectionType->getName(); + if ($reflectionType->isIdentifier()) { + $typeNode = new Identifier($reflectionType->getName()); + } else { + $typeNode = new FullyQualified($reflectionType->getName()); + } - $type = self::getTypeObjectFromTypehint($reflectionTypeString, $selfClass); + if (is_string($selfClass)) { + $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); + if ($reflectionProvider->hasClass($selfClass)) { + $selfClass = $reflectionProvider->getClass($selfClass); + } else { + $selfClass = null; + } + } + $type = ParserNodeTypeToPHPStanType::resolve($typeNode, $selfClass); if ($reflectionType->allowsNull()) { $type = TypeCombinator::addNull($type); } elseif ($phpDocType !== null) { From f0709245a0b4a6edad2e377e054b93a4d767854f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 30 Dec 2023 20:58:53 +0100 Subject: [PATCH 023/508] Stub validator - always use latest PHP 8 parser --- conf/config.stubValidator.neon | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/conf/config.stubValidator.neon b/conf/config.stubValidator.neon index 1645698a92..ae22e5ccdc 100644 --- a/conf/config.stubValidator.neon +++ b/conf/config.stubValidator.neon @@ -13,7 +13,7 @@ services: arguments: php8Parser: @php8PhpParser - nodeScopeResolverClassReflector: + nodeScopeResolverReflector: factory: @stubReflector stubBetterReflectionProvider: @@ -38,3 +38,11 @@ services: factory: @stubBetterReflectionProvider autowired: - PHPStan\Reflection\ReflectionProvider + + currentPhpVersionLexer: + factory: @php8Lexer + autowired: false + + currentPhpVersionPhpParser: + factory: @php8PhpParser + autowired: false From dbf06b62f1a2ec7ed3ec28cb45e293aee6b42c30 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 1 Jan 2024 14:31:39 +0100 Subject: [PATCH 024/508] Fix PHPStan errors --- phpstan-baseline.neon | 52 ++++--------------- src/Analyser/NodeScopeResolver.php | 5 +- src/Parser/PhpParserDecorator.php | 3 +- src/Type/Constant/OversizedArrayBuilder.php | 6 --- ...InArrayFunctionTypeSpecifyingExtension.php | 3 -- 5 files changed, 13 insertions(+), 56 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index cdbd956fa2..fbfeafa608 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -70,7 +70,7 @@ parameters: path: src/Analyser/NodeScopeResolver.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 1 path: src/Analyser/NodeScopeResolver.php @@ -276,7 +276,7 @@ parameters: path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php @@ -286,17 +286,17 @@ parameters: path: src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 2 path: src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php @@ -1799,43 +1799,6 @@ parameters: count: 1 path: tests/PHPStan/Rules/Arrays/AppendedArrayKeyTypeRuleTest.php - - - message: """ - #^Instantiation of deprecated class PHPStan\\\\Rules\\\\DeadCode\\\\NoopRule\\: - Replaced by PHPStan\\\\Rules\\\\DeadCode\\\\BetterNoopRule$# - """ - count: 1 - path: tests/PHPStan/Rules/DeadCode/NoopRuleTest.php - - - - message: """ - #^Return type of method PHPStan\\\\Rules\\\\DeadCode\\\\NoopRuleTest\\:\\:getRule\\(\\) has typehint with deprecated class PHPStan\\\\Rules\\\\DeadCode\\\\NoopRule\\: - Replaced by PHPStan\\\\Rules\\\\DeadCode\\\\BetterNoopRule$# - """ - count: 1 - path: tests/PHPStan/Rules/DeadCode/NoopRuleTest.php - - - - message: """ - #^Instantiation of deprecated class PHPStan\\\\Rules\\\\Functions\\\\ImplodeFunctionRule\\: - Replaced by PHPStan\\\\Rules\\\\Functions\\\\ImplodeParameterCastableToStringRuleTest$# - """ - count: 1 - path: tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php - - - - message: """ - #^Return type of method PHPStan\\\\Rules\\\\Functions\\\\ImplodeFunctionRuleTest\\:\\:getRule\\(\\) has typehint with deprecated class PHPStan\\\\Rules\\\\Functions\\\\ImplodeFunctionRule\\: - Replaced by PHPStan\\\\Rules\\\\Functions\\\\ImplodeParameterCastableToStringRuleTest$# - """ - count: 1 - path: tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php - - - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" - count: 1 - path: tests/PHPStan/Type/IterableTypeTest.php - - message: """ #^Instantiation of deprecated class PHPStan\\\\Rules\\\\Arrays\\\\EmptyArrayItemRule\\: @@ -1851,3 +1814,8 @@ parameters: """ count: 1 path: tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php + + - + message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" + count: 1 + path: tests/PHPStan/Type/IterableTypeTest.php diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index a15060536b..345a323d03 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1689,7 +1689,7 @@ private function processStmtNode( $finallyScope = $finallyScope->mergeWith($throwPoint->getScope()); } - if ($finallyScope !== null && $stmt->finally !== null) { + if ($finallyScope !== null) { $originalFinallyScope = $finallyScope; $finallyResult = $this->processStmtNodes($stmt->finally, $stmt->finally->stmts, $finallyScope, $nodeCallback, $context); $alwaysTerminating = $alwaysTerminating || $finallyResult->isAlwaysTerminating(); @@ -2973,9 +2973,6 @@ static function (): void { $impurePoints = []; foreach ($expr->items as $arrayItem) { $itemNodes[] = new LiteralArrayItem($scope, $arrayItem); - if ($arrayItem === null) { - continue; - } $nodeCallback($arrayItem, $scope); if ($arrayItem->key !== null) { $keyResult = $this->processExprNode($stmt, $arrayItem->key, $scope, $nodeCallback, $context->enterDeep()); diff --git a/src/Parser/PhpParserDecorator.php b/src/Parser/PhpParserDecorator.php index d4e00547a0..7481574450 100644 --- a/src/Parser/PhpParserDecorator.php +++ b/src/Parser/PhpParserDecorator.php @@ -6,6 +6,7 @@ use PhpParser\ErrorHandler; use PhpParser\Node; use PhpParser\Parser; +use PHPStan\ShouldNotHappenException; use function sprintf; final class PhpParserDecorator implements Parser @@ -33,7 +34,7 @@ public function parse(string $code, ?ErrorHandler $errorHandler = null): array public function getTokens(): array { - return $this->wrappedParser->getTokens(); + throw new ShouldNotHappenException('PhpParserDecorator::getTokens() should not be called'); } } diff --git a/src/Type/Constant/OversizedArrayBuilder.php b/src/Type/Constant/OversizedArrayBuilder.php index c365e0581f..e6ac71ded5 100644 --- a/src/Type/Constant/OversizedArrayBuilder.php +++ b/src/Type/Constant/OversizedArrayBuilder.php @@ -34,9 +34,6 @@ public function build(Array_ $expr, callable $getTypeCallback): Type $items = $expr->items; for ($i = 0; $i < count($items); $i++) { $item = $items[$i]; - if ($item === null) { - continue; - } if (!$item->unpack) { continue; } @@ -64,9 +61,6 @@ public function build(Array_ $expr, callable $getTypeCallback): Type } } foreach ($items as $item) { - if ($item === null) { - continue; - } if ($item->unpack) { throw new ShouldNotHappenException(); } diff --git a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php index df1bf3499a..1c4436ca46 100644 --- a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php @@ -65,9 +65,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n if ($arrayExpr instanceof Array_) { $types = null; foreach ($arrayExpr->items as $item) { - if ($item === null) { - continue; - } if ($item->unpack) { $types = null; break; From a2df219c86d6f52ecd5cc5a0752adecbd26335e2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 1 Jan 2024 14:42:54 +0100 Subject: [PATCH 025/508] Fix --- src/Analyser/MutatingScope.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index c3f58e1c92..b6a38997a8 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -1133,7 +1133,7 @@ private function resolveType(string $exprString, Expr $node): Type if ($part instanceof InterpolatedStringPart) { $partType = new ConstantStringType($part->value); } else { - $partType = $this->getType($part); + $partType = $this->getType($part)->toString(); } if ($resultType === null) { $resultType = $partType; From 92a9288581c38c08a2b00213351173a26610f614 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 09:39:07 +0200 Subject: [PATCH 026/508] Fix --- .../BetterReflection/SourceLocator/AutoloadSourceLocator.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php b/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php index 2edde64fbc..7506682426 100644 --- a/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php +++ b/src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php @@ -114,7 +114,6 @@ public function locateIdentifier(Reflector $reflector, Identifier $identifier): 'startFilePos' => 1, 'endFilePos' => 4, ]), - null, new LocatedSource(' Date: Wed, 4 Sep 2024 11:16:22 +0200 Subject: [PATCH 027/508] Handle Block statement --- src/Analyser/NodeScopeResolver.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 345a323d03..0b7133e631 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1895,6 +1895,8 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void { $impurePoints = [ new ImpurePoint($scope, $stmt, 'betweenPhpTags', 'output between PHP opening and closing tags', true), ]; + } elseif ($stmt instanceof Node\Stmt\Block) { + return $this->processStmtNodes($stmt, $stmt->stmts, $scope, $nodeCallback, $context); } elseif ($stmt instanceof Node\Stmt\Nop) { $hasYield = false; $throwPoints = $overridingThrowPoints ?? []; From 21402088feb881170161283a5c08b8b0e8ce297a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 11:19:37 +0200 Subject: [PATCH 028/508] Fix standalone Throw_ expr handling --- src/Analyser/NodeScopeResolver.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 0b7133e631..f32e3345b7 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -791,6 +791,9 @@ private function processStmtNode( new StatementExitPoint($stmt, $scope), ], $overridingThrowPoints ?? $throwPoints, $impurePoints); } elseif ($stmt instanceof Node\Stmt\Expression) { + if ($stmt->expr instanceof Expr\Throw_) { + $scope = $stmtScope; + } $earlyTerminationExpr = $this->findEarlyTerminatingExpr($stmt->expr, $scope); $hasAssign = false; $currentScope = $scope; From 9b7a8f41612f9716368935196f4fcb42464dbf5a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 11:36:07 +0200 Subject: [PATCH 029/508] Remove obsolete NoBleedingEdge tests --- .../CallMethodsRuleNoBleedingEdgeTest.php | 61 -------- .../PhpDoc/InvalidPHPStanDocTagRuleTest.php | 25 +-- ...idPhpDocTagValueRuleNoBleedingEdgeTest.php | 146 ------------------ .../PhpDoc/InvalidPhpDocTagValueRuleTest.php | 28 +--- ...gnedToPropertiesRuleNoBleedingEdgeTest.php | 50 ------ 5 files changed, 8 insertions(+), 302 deletions(-) delete mode 100644 tests/PHPStan/Rules/Methods/CallMethodsRuleNoBleedingEdgeTest.php delete mode 100644 tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleNoBleedingEdgeTest.php delete mode 100644 tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleNoBleedingEdgeTest.php diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleNoBleedingEdgeTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleNoBleedingEdgeTest.php deleted file mode 100644 index 71678d99ff..0000000000 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleNoBleedingEdgeTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ -class CallMethodsRuleNoBleedingEdgeTest extends RuleTestCase -{ - - private bool $checkExplicitMixed; - - protected function getRule(): Rule - { - $reflectionProvider = $this->createReflectionProvider(); - $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, $this->checkExplicitMixed, false, true, false); - return new CallMethodsRule( - new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true), - new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion(PHP_VERSION_ID), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, false), - ); - } - - public function testGenericsInferCollection(): void - { - $this->checkExplicitMixed = true; - $this->analyse([__DIR__ . '/data/generics-infer-collection.php'], [ - [ - 'Parameter #1 $c of method GenericsInferCollection\Foo::doBar() expects GenericsInferCollection\ArrayCollection, GenericsInferCollection\ArrayCollection given.', - 43, - ], - ]); - } - - public function testGenericsInferCollectionLevel8(): void - { - $this->checkExplicitMixed = false; - $this->analyse([__DIR__ . '/data/generics-infer-collection.php'], [ - [ - 'Parameter #1 $c of method GenericsInferCollection\Foo::doBar() expects GenericsInferCollection\ArrayCollection, GenericsInferCollection\ArrayCollection given.', - 43, - ], - ]); - } - - public static function getAdditionalConfigFiles(): array - { - // no bleeding edge - return []; - } - -} diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php index 7995c696f4..e3e82da0ff 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php @@ -6,7 +6,6 @@ use PHPStan\PhpDocParser\Parser\PhpDocParser; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use function array_merge; /** * @extends RuleTestCase @@ -14,20 +13,18 @@ class InvalidPHPStanDocTagRuleTest extends RuleTestCase { - private bool $checkAllInvalidPhpDocs; - protected function getRule(): Rule { return new InvalidPHPStanDocTagRule( self::getContainer()->getByType(Lexer::class), self::getContainer()->getByType(PhpDocParser::class), - $this->checkAllInvalidPhpDocs, + true, ); } - public function dataRule(): iterable + public function testRule(): void { - $errors = [ + $this->analyse([__DIR__ . '/data/invalid-phpstan-doc.php'], [ [ 'Unknown PHPDoc tag: @phpstan-extens', 6, @@ -44,29 +41,15 @@ public function dataRule(): iterable 'Unknown PHPDoc tag: @phpstan-varr', 46, ], - ]; - yield [false, $errors]; - yield [true, array_merge($errors, [ [ 'Unknown PHPDoc tag: @phpstan-varr', 56, ], - ])]; - } - - /** - * @dataProvider dataRule - * @param list $expectedErrors - */ - public function testRule(bool $checkAllInvalidPhpDocs, array $expectedErrors): void - { - $this->checkAllInvalidPhpDocs = $checkAllInvalidPhpDocs; - $this->analyse([__DIR__ . '/data/invalid-phpstan-doc.php'], $expectedErrors); + ]); } public function testBug8697(): void { - $this->checkAllInvalidPhpDocs = true; $this->analyse([__DIR__ . '/data/bug-8697.php'], []); } diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleNoBleedingEdgeTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleNoBleedingEdgeTest.php deleted file mode 100644 index b0bb271349..0000000000 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleNoBleedingEdgeTest.php +++ /dev/null @@ -1,146 +0,0 @@ - - */ -class InvalidPhpDocTagValueRuleNoBleedingEdgeTest extends RuleTestCase -{ - - private bool $checkAllInvalidPhpDocs; - - protected function getRule(): Rule - { - return new InvalidPhpDocTagValueRule( - self::getContainer()->getByType(Lexer::class), - self::getContainer()->getByType(PhpDocParser::class), - $this->checkAllInvalidPhpDocs, - false, - ); - } - - public function dataRule(): iterable - { - $errors = [ - [ - 'PHPDoc tag @param has invalid value (): Unexpected token "\n * ", expected type at offset 13', - 25, - ], - [ - 'PHPDoc tag @param has invalid value (A & B | C $paramNameA): Unexpected token "|", expected variable at offset 72', - 25, - ], - [ - 'PHPDoc tag @param has invalid value ((A & B $paramNameB): Unexpected token "$paramNameB", expected \')\' at offset 105', - 25, - ], - [ - 'PHPDoc tag @param has invalid value (~A & B $paramNameC): Unexpected token "~A", expected type at offset 127', - 25, - ], - [ - 'PHPDoc tag @var has invalid value (): Unexpected token "\n * ", expected type at offset 156', - 25, - ], - [ - 'PHPDoc tag @var has invalid value ($invalid): Unexpected token "$invalid", expected type at offset 165', - 25, - ], - [ - 'PHPDoc tag @var has invalid value ($invalid Foo): Unexpected token "$invalid", expected type at offset 182', - 25, - ], - [ - 'PHPDoc tag @return has invalid value (): Unexpected token "\n * ", expected type at offset 208', - 25, - ], - [ - 'PHPDoc tag @return has invalid value ([int, string]): Unexpected token "[", expected type at offset 220', - 25, - ], - [ - 'PHPDoc tag @return has invalid value (A & B | C): Unexpected token "|", expected TOKEN_OTHER at offset 251', - 25, - ], - [ - 'PHPDoc tag @var has invalid value (\\\Foo|\Bar $test): Unexpected token "\\\\\\\Foo|\\\Bar", expected type at offset 9', - 29, - ], - [ - 'PHPDoc tag @var has invalid value ((Foo|Bar): Unexpected token "*/", expected \')\' at offset 18', - 62, - ], - [ - 'PHPDoc tag @throws has invalid value ((\Exception): Unexpected token "*/", expected \')\' at offset 24', - 72, - ], - [ - 'PHPDoc tag @var has invalid value ((Foo|Bar): Unexpected token "*/", expected \')\' at offset 18', - 81, - ], - [ - 'PHPDoc tag @var has invalid value ((Foo&): Unexpected token "*/", expected type at offset 15', - 89, - ], - [ - 'PHPDoc tag @var has invalid value ((Foo&): Unexpected token "*/", expected type at offset 15', - 92, - ], - ]; - - yield [false, $errors]; - yield [true, array_merge($errors, [ - [ - 'PHPDoc tag @var has invalid value ((Foo&): Unexpected token "*/", expected type at offset 15', - 102, - ], - ])]; - } - - /** - * @dataProvider dataRule - * @param list $expectedErrors - */ - public function testRule(bool $checkAllInvalidPhpDocs, array $expectedErrors): void - { - $this->checkAllInvalidPhpDocs = $checkAllInvalidPhpDocs; - $this->analyse([__DIR__ . '/data/invalid-phpdoc.php'], $expectedErrors); - } - - public function testBug4731(): void - { - $this->checkAllInvalidPhpDocs = true; - $this->analyse([__DIR__ . '/data/bug-4731.php'], []); - } - - public function testBug4731WithoutFirstTag(): void - { - $this->checkAllInvalidPhpDocs = true; - $this->analyse([__DIR__ . '/data/bug-4731-no-first-tag.php'], []); - } - - public function testInvalidTypeInTypeAlias(): void - { - $this->checkAllInvalidPhpDocs = true; - $this->analyse([__DIR__ . '/data/invalid-type-type-alias.php'], [ - [ - 'PHPDoc tag @phpstan-type InvalidFoo has invalid value: Unexpected token "{", expected TOKEN_PHPDOC_EOL at offset 65', - 15, - ], - ]); - } - - public static function getAdditionalConfigFiles(): array - { - // reset bleedingEdge - return []; - } - -} diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php index c726559432..a82880302d 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php @@ -6,7 +6,6 @@ use PHPStan\PhpDocParser\Parser\PhpDocParser; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use function array_merge; /** * @extends RuleTestCase @@ -14,21 +13,19 @@ class InvalidPhpDocTagValueRuleTest extends RuleTestCase { - private bool $checkAllInvalidPhpDocs; - protected function getRule(): Rule { return new InvalidPhpDocTagValueRule( self::getContainer()->getByType(Lexer::class), self::getContainer()->getByType(PhpDocParser::class), - $this->checkAllInvalidPhpDocs, + true, true, ); } - public function dataRule(): iterable + public function testRule(): void { - $errors = [ + $this->analyse([__DIR__ . '/data/invalid-phpdoc.php'], [ [ 'PHPDoc tag @param has invalid value (): Unexpected token "\n * ", expected type at offset 13 on line 2', 6, @@ -97,42 +94,25 @@ public function dataRule(): iterable 'PHPDoc tag @var has invalid value ((Foo&): Unexpected token "*/", expected type at offset 15 on line 1', 91, ], - ]; - - yield [false, $errors]; - yield [true, array_merge($errors, [ [ 'PHPDoc tag @var has invalid value ((Foo&): Unexpected token "*/", expected type at offset 15 on line 1', 101, ], - ])]; - } - - /** - * @dataProvider dataRule - * @param list $expectedErrors - */ - public function testRule(bool $checkAllInvalidPhpDocs, array $expectedErrors): void - { - $this->checkAllInvalidPhpDocs = $checkAllInvalidPhpDocs; - $this->analyse([__DIR__ . '/data/invalid-phpdoc.php'], $expectedErrors); + ]); } public function testBug4731(): void { - $this->checkAllInvalidPhpDocs = true; $this->analyse([__DIR__ . '/data/bug-4731.php'], []); } public function testBug4731WithoutFirstTag(): void { - $this->checkAllInvalidPhpDocs = true; $this->analyse([__DIR__ . '/data/bug-4731-no-first-tag.php'], []); } public function testInvalidTypeInTypeAlias(): void { - $this->checkAllInvalidPhpDocs = true; $this->analyse([__DIR__ . '/data/invalid-type-type-alias.php'], [ [ 'PHPDoc tag @phpstan-type InvalidFoo has invalid value: Unexpected token "{", expected TOKEN_PHPDOC_EOL at offset 65 on line 3', diff --git a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleNoBleedingEdgeTest.php b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleNoBleedingEdgeTest.php deleted file mode 100644 index 9b0aaf913d..0000000000 --- a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleNoBleedingEdgeTest.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ -class TypesAssignedToPropertiesRuleNoBleedingEdgeTest extends RuleTestCase -{ - - private bool $checkExplicitMixed = false; - - protected function getRule(): Rule - { - return new TypesAssignedToPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, false, true, false), new PropertyReflectionFinder()); - } - - public function testGenericObjectWithUnspecifiedTemplateTypes(): void - { - $this->checkExplicitMixed = true; - $this->analyse([__DIR__ . '/data/generic-object-unspecified-template-types.php'], [ - [ - 'Property GenericObjectUnspecifiedTemplateTypes\Bar::$ints (GenericObjectUnspecifiedTemplateTypes\ArrayCollection) does not accept GenericObjectUnspecifiedTemplateTypes\ArrayCollection.', - 67, - ], - ]); - } - - public function testGenericObjectWithUnspecifiedTemplateTypesLevel8(): void - { - $this->checkExplicitMixed = false; - $this->analyse([__DIR__ . '/data/generic-object-unspecified-template-types.php'], [ - [ - 'Property GenericObjectUnspecifiedTemplateTypes\Bar::$ints (GenericObjectUnspecifiedTemplateTypes\ArrayCollection) does not accept GenericObjectUnspecifiedTemplateTypes\ArrayCollection.', - 67, - ], - ]); - } - - public static function getAdditionalConfigFiles(): array - { - // no bleeding edge - return []; - } - -} From cc4bff635ebae19b010b81130360155692283ac6 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 11:38:31 +0200 Subject: [PATCH 030/508] Fix detecting invalid PHPDocs --- conf/bleedingEdge.neon | 1 - conf/config.level2.neon | 3 -- conf/config.neon | 2 +- conf/parametersSchema.neon | 1 - src/PhpDoc/StubValidator.php | 13 +++----- src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php | 32 +++++-------------- .../PhpDoc/InvalidPhpDocTagValueRule.php | 32 +++++-------------- .../PhpDoc/InvalidPHPStanDocTagRuleTest.php | 1 - .../PhpDoc/InvalidPhpDocTagValueRuleTest.php | 1 - 9 files changed, 21 insertions(+), 65 deletions(-) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 8fb6e4da6a..12694539ae 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -39,7 +39,6 @@ parameters: newRuleLevelHelper: true instanceofType: true paramOutVariance: true - allInvalidPhpDocs: true strictStaticMethodTemplateTypeVariance: true propertyVariance: true genericPrototypeMessage: true diff --git a/conf/config.level2.neon b/conf/config.level2.neon index 1399394032..d7a7cc943b 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -146,7 +146,6 @@ services: - class: PHPStan\Rules\PhpDoc\InvalidPhpDocTagValueRule arguments: - checkAllInvalidPhpDocs: %featureToggles.allInvalidPhpDocs% invalidPhpDocTagLine: %featureToggles.invalidPhpDocTagLine% tags: - phpstan.rules.rule @@ -159,8 +158,6 @@ services: - phpstan.rules.rule - class: PHPStan\Rules\PhpDoc\InvalidPHPStanDocTagRule - arguments: - checkAllInvalidPhpDocs: %featureToggles.allInvalidPhpDocs% tags: - phpstan.rules.rule - diff --git a/conf/config.neon b/conf/config.neon index 4d897a4587..ae411edcca 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -74,7 +74,7 @@ parameters: newRuleLevelHelper: false instanceofType: false paramOutVariance: false - allInvalidPhpDocs: false + strictStaticMethodTemplateTypeVariance: false propertyVariance: false genericPrototypeMessage: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 05d6d79f0c..8b986b0442 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -69,7 +69,6 @@ parametersSchema: newRuleLevelHelper: bool() instanceofType: bool() paramOutVariance: bool() - allInvalidPhpDocs: bool() strictStaticMethodTemplateTypeVariance: bool() propertyVariance: bool() genericPrototypeMessage: bool() diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index 43ecfdd0a5..7260542411 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -217,12 +217,15 @@ private function getRuleRegistry(Container $container): RuleRegistry new InvalidPhpDocTagValueRule( $container->getByType(Lexer::class), $container->getByType(PhpDocParser::class), - $container->getParameter('featureToggles')['allInvalidPhpDocs'], $container->getParameter('featureToggles')['invalidPhpDocTagLine'], ), new IncompatibleParamImmediatelyInvokedCallableRule($fileTypeMapper), new IncompatibleSelfOutTypeRule($unresolvableTypeHelper, $genericObjectTypeCheck), new IncompatibleClassConstantPhpDocTypeRule($genericObjectTypeCheck, $unresolvableTypeHelper), + new InvalidPHPStanDocTagRule( + $container->getByType(Lexer::class), + $container->getByType(PhpDocParser::class), + ), new InvalidThrowsPhpDocValueRule($fileTypeMapper), // level 6 @@ -240,14 +243,6 @@ private function getRuleRegistry(Container $container): RuleRegistry $rules[] = new DuplicateFunctionDeclarationRule($reflector, $relativePathHelper); } - if ((bool) $container->getParameter('featureToggles')['allInvalidPhpDocs']) { - $rules[] = new InvalidPHPStanDocTagRule( - $container->getByType(Lexer::class), - $container->getByType(PhpDocParser::class), - true, - ); - } - if ((bool) $container->getParameter('featureToggles')['absentTypeChecks']) { $rules[] = new MissingMethodSelfOutTypeRule($missingTypehintCheck); diff --git a/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php b/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php index 923d65e143..51b22dd564 100644 --- a/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php +++ b/src/Rules/PhpDoc/InvalidPHPStanDocTagRule.php @@ -15,7 +15,7 @@ use function str_starts_with; /** - * @implements Rule + * @implements Rule */ final class InvalidPHPStanDocTagRule implements Rule { @@ -63,39 +63,23 @@ final class InvalidPHPStanDocTagRule implements Rule public function __construct( private Lexer $phpDocLexer, private PhpDocParser $phpDocParser, - private bool $checkAllInvalidPhpDocs, ) { } public function getNodeType(): string { - return Node::class; + return Node\Stmt::class; } public function processNode(Node $node, Scope $scope): array { - if (!$this->checkAllInvalidPhpDocs) { - if ( - !$node instanceof Node\Stmt\ClassLike - && !$node instanceof Node\FunctionLike - && !$node instanceof Node\Stmt\Foreach_ - && !$node instanceof Node\Stmt\Property - && !$node instanceof Node\Expr\Assign - && !$node instanceof Node\Expr\AssignRef - && !$node instanceof Node\Stmt\ClassConst - ) { - return []; - } - } else { - // mirrored with InvalidPhpDocTagValueRule - if ($node instanceof VirtualNode) { - return []; - } - if ($node instanceof Node\Stmt\Expression) { - return []; - } - if ($node instanceof Node\Expr && !$node instanceof Node\Expr\Assign && !$node instanceof Node\Expr\AssignRef) { + // mirrored with InvalidPhpDocTagValueRule + if ($node instanceof VirtualNode) { + return []; + } + if ($node instanceof Node\Stmt\Expression) { + if (!$node->expr instanceof Node\Expr\Assign && !$node->expr instanceof Node\Expr\AssignRef) { return []; } } diff --git a/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php b/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php index fe40a1bd61..569c776df3 100644 --- a/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php +++ b/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php @@ -18,7 +18,7 @@ use function str_starts_with; /** - * @implements Rule + * @implements Rule */ final class InvalidPhpDocTagValueRule implements Rule { @@ -26,7 +26,6 @@ final class InvalidPhpDocTagValueRule implements Rule public function __construct( private Lexer $phpDocLexer, private PhpDocParser $phpDocParser, - private bool $checkAllInvalidPhpDocs, private bool $invalidPhpDocTagLine, ) { @@ -34,32 +33,17 @@ public function __construct( public function getNodeType(): string { - return Node::class; + return Node\Stmt::class; } public function processNode(Node $node, Scope $scope): array { - if (!$this->checkAllInvalidPhpDocs) { - if ( - !$node instanceof Node\Stmt\ClassLike - && !$node instanceof Node\FunctionLike - && !$node instanceof Node\Stmt\Foreach_ - && !$node instanceof Node\Stmt\Property - && !$node instanceof Node\Expr\Assign - && !$node instanceof Node\Expr\AssignRef - && !$node instanceof Node\Stmt\ClassConst - ) { - return []; - } - } else { - // mirrored with InvalidPHPStanDocTagRule - if ($node instanceof VirtualNode) { - return []; - } - if ($node instanceof Node\Stmt\Expression) { - return []; - } - if ($node instanceof Node\Expr && !$node instanceof Node\Expr\Assign && !$node instanceof Node\Expr\AssignRef) { + // mirrored with InvalidPHPStanDocTagRule + if ($node instanceof VirtualNode) { + return []; + } + if ($node instanceof Node\Stmt\Expression) { + if (!$node->expr instanceof Node\Expr\Assign && !$node->expr instanceof Node\Expr\AssignRef) { return []; } } diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php index e3e82da0ff..c664e1658a 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPHPStanDocTagRuleTest.php @@ -18,7 +18,6 @@ protected function getRule(): Rule return new InvalidPHPStanDocTagRule( self::getContainer()->getByType(Lexer::class), self::getContainer()->getByType(PhpDocParser::class), - true, ); } diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php index a82880302d..542b38f13f 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php @@ -19,7 +19,6 @@ protected function getRule(): Rule self::getContainer()->getByType(Lexer::class), self::getContainer()->getByType(PhpDocParser::class), true, - true, ); } From cd5504c091f33071c843f681d9de3414ff4f8a2e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 11:45:44 +0200 Subject: [PATCH 031/508] Fix minor change --- tests/PHPStan/Parser/RichParserTest.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/PHPStan/Parser/RichParserTest.php b/tests/PHPStan/Parser/RichParserTest.php index 103eb129b4..69fc99cbab 100644 --- a/tests/PHPStan/Parser/RichParserTest.php +++ b/tests/PHPStan/Parser/RichParserTest.php @@ -193,7 +193,17 @@ public function dataLinesToIgnore(): iterable PHP_EOL . '/** @phpstan-ignore test */' . PHP_EOL, [ - 3 => ['test'], + 4 => ['test'], + ], + ]; + + yield [ + ' ['test'], ], ]; From 9bf85519da8fae2eaf737e4ed15ae83a2c752158 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 12:48:43 +0200 Subject: [PATCH 032/508] Fix baseline --- phpstan-baseline.neon | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index fbfeafa608..7bbba41b08 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -70,7 +70,7 @@ parameters: path: src/Analyser/NodeScopeResolver.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 1 path: src/Analyser/NodeScopeResolver.php @@ -276,7 +276,7 @@ parameters: path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php @@ -286,17 +286,17 @@ parameters: path: src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Expression\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 2 path: src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php From d7c7266e877c5371eed0c7d81ae4d91eaef673f2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 13:11:59 +0200 Subject: [PATCH 033/508] Preparing PHAR - fix php constraint --- compiler/src/Console/PrepareCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/Console/PrepareCommand.php b/compiler/src/Console/PrepareCommand.php index 7bef8b99db..6d23dde7a6 100644 --- a/compiler/src/Console/PrepareCommand.php +++ b/compiler/src/Console/PrepareCommand.php @@ -65,7 +65,7 @@ private function fixComposerJson(string $buildDir): void unset($json['replace']); $json['name'] = 'phpstan/phpstan'; - $json['require']['php'] = '^7.2|^8.0'; + $json['require']['php'] = '^7.4|^8.0'; // simplify autoload (remove not packed build directory] $json['autoload']['psr-4']['PHPStan\\'] = 'src/'; From 084f3ec0e2535b2853cc588fa64d4f4f8f5291fd Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 13:16:03 +0200 Subject: [PATCH 034/508] Fix tests --- .../ExistingClassesInTypehintsRuleTest.php | 17 +++++---- .../ExistingClassesInTypehintsRuleTest.php | 36 ++++++++++++------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php b/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php index 78415d4616..056740ed99 100644 --- a/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php @@ -421,13 +421,18 @@ public function dataTrueTypes(): array ]; } - /** - * @dataProvider dataTrueTypes - * @param list $errors - */ - public function testTrueTypehint(int $phpVersion, array $errors): void + public function testTrueTypehint(): void { - $this->phpVersionId = $phpVersion; + if (PHP_VERSION_ID >= 80200) { + $errors = []; + } else { + $errors = [ + [ + 'Function NativeTrueType\alwaysTrue() has invalid return type NativeTrueType\true.', + 5, + ], + ]; + } $this->analyse([__DIR__ . '/data/true-typehint.php'], $errors); } diff --git a/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php b/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php index b86302f453..df40cbac04 100644 --- a/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php @@ -429,20 +429,30 @@ public function testEnums(): void ]); } - public function dataTrueTypes(): array + public function testTrueTypehint(): void { - return [ - [80200, []], - ]; - } - - /** - * @dataProvider dataTrueTypes - * @param list $errors - */ - public function testTrueTypehint(int $phpVersion, array $errors): void - { - $this->phpVersionId = $phpVersion; + if (PHP_VERSION_ID >= 80200) { + $errors = []; + } else { + $errors = [ + [ + 'Parameter $v of method NativeTrueType\Truthy::foo() has invalid type NativeTrueType\true.', + 10, + ], + [ + 'Method NativeTrueType\Truthy::foo() has invalid return type NativeTrueType\true.', + 10, + ], + [ + 'Parameter $trueUnion of method NativeTrueType\Truthy::trueUnion() has invalid type NativeTrueType\true.', + 14, + ], + [ + 'Method NativeTrueType\Truthy::trueUnionReturn() has invalid return type NativeTrueType\true.', + 31, + ], + ]; + } $this->analyse([__DIR__ . '/data/true-typehint.php'], $errors); } From 4aed8e4b77021953ea84ef31f2f170d58fe826c1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 13:35:21 +0200 Subject: [PATCH 035/508] Update PHPUnit --- .github/workflows/static-analysis.yml | 3 - .github/workflows/tests.yml | 4 - composer.json | 2 +- composer.lock | 270 ++++++++++++++------------ 4 files changed, 142 insertions(+), 137 deletions(-) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 24760de756..a0c08f6171 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -99,9 +99,6 @@ jobs: - name: "Install dependencies" run: "composer install --no-interaction --no-progress" - - name: "Update PHPUnit" - run: "composer update phpunit/phpunit -W" - - name: "Cache Result cache" uses: actions/cache@v4 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 75f5de1627..5533bd7e6a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -65,10 +65,6 @@ jobs: shell: bash run: "vendor/bin/simple-downgrade downgrade -c build/downgrade.php ${{ matrix.php-version }}" - - name: "Update PHPUnit" - if: matrix.php-version != '7.3' - run: "composer update phpunit/phpunit -W" - - name: "Tests" run: "make tests" diff --git a/composer.json b/composer.json index 7e859b19e4..64c143fd28 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,7 @@ "phpstan/phpstan-nette": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "^9.5.4", + "phpunit/phpunit": "^9.6", "shipmonk/composer-dependency-analyser": "^1.5", "shipmonk/name-collision-detector": "^2.0" }, diff --git a/composer.lock b/composer.lock index aba98b1475..6ef0c6b966 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6ecf16b4614aa87f10e85e795af26169", + "content-hash": "b0a75f027cffe40f37c639ade2ee9361", "packages": [ { "name": "clue/ndjson-react", @@ -4400,30 +4400,30 @@ }, { "name": "doctrine/instantiator", - "version": "1.4.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -4450,7 +4450,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -4466,7 +4466,7 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "jean85/pretty-package-versions", @@ -4529,16 +4529,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -4546,11 +4546,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "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", @@ -4576,7 +4577,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -4584,7 +4585,7 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "ondrejmirtes/simple-downgrader", @@ -4637,20 +4638,21 @@ }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "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", @@ -4691,9 +4693,15 @@ "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.3" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -5018,35 +5026,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.30", + "version": "9.2.32", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.19.1 || ^5.1.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" + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -5055,7 +5063,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -5084,7 +5092,7 @@ "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.30" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -5092,7 +5100,7 @@ "type": "github" } ], - "time": "2023-12-22T06:47:57+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", @@ -5337,50 +5345,50 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.23", + "version": "9.6.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "888556852e7e9bbeeedb9656afe46118765ade34" + "reference": "49d7820565836236411f5dc002d16dd689cde42f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/888556852e7e9bbeeedb9656afe46118765ade34", - "reference": "888556852e7e9bbeeedb9656afe46118765ade34", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f", + "reference": "49d7820565836236411f5dc002d16dd689cde42f", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.5.0 || ^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", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.31", + "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -5388,7 +5396,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -5419,7 +5427,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.23" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20" }, "funding": [ { @@ -5429,22 +5438,26 @@ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2022-08-22T14:01:36+00:00" + "time": "2024-07-10T11:45:39+00:00" }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { @@ -5479,7 +5492,7 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" }, "funding": [ { @@ -5487,7 +5500,7 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2024-03-02T06:27:43+00:00" }, { "name": "sebastian/code-unit", @@ -5602,16 +5615,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -5664,7 +5677,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -5672,7 +5685,7 @@ "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", @@ -5733,16 +5746,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", "shasum": "" }, "require": { @@ -5787,7 +5800,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -5795,7 +5808,7 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", @@ -5862,16 +5875,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.4", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { @@ -5927,7 +5940,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -5935,20 +5948,20 @@ "type": "github" } ], - "time": "2021-11-11T14:18:36+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { @@ -5991,7 +6004,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -5999,7 +6012,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { "name": "sebastian/lines-of-code", @@ -6172,16 +6185,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -6220,10 +6233,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -6231,20 +6244,20 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { @@ -6256,7 +6269,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -6277,8 +6290,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -6286,20 +6298,20 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", - "version": "3.0.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -6311,7 +6323,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -6334,7 +6346,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -6342,7 +6354,7 @@ "type": "github" } ], - "time": "2022-03-15T09:54:48+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -6523,16 +6535,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -6561,7 +6573,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -6569,7 +6581,7 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], From 078eeab53ced7dd6677068f7b13190d4e542ec3c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 13:43:12 +0200 Subject: [PATCH 036/508] Fix anonymous class --- src/Reflection/BetterReflection/BetterReflectionProvider.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Reflection/BetterReflection/BetterReflectionProvider.php b/src/Reflection/BetterReflection/BetterReflectionProvider.php index 6ae28ec9c6..54b26ec9f8 100644 --- a/src/Reflection/BetterReflection/BetterReflectionProvider.php +++ b/src/Reflection/BetterReflection/BetterReflectionProvider.php @@ -204,6 +204,7 @@ public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $ $scopeFile, ); $classNode->name = new Node\Identifier($className); + $classNode->namespacedName = null; if (isset(self::$anonymousClasses[$className])) { return self::$anonymousClasses[$className]; From 0e689a325434ab2658d0c23215a27f13b0ad1357 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 13:46:03 +0200 Subject: [PATCH 037/508] Fix RichParser --- src/Parser/RichParser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Parser/RichParser.php b/src/Parser/RichParser.php index ed0f1840a0..14ade510c3 100644 --- a/src/Parser/RichParser.php +++ b/src/Parser/RichParser.php @@ -183,7 +183,7 @@ private function getLinesToIgnore(array $tokens): array $line++; } if ($isNextLine || $isCurrentLine) { - $line += substr_count($token[1], "\n"); + $line += substr_count($token->text, "\n"); $lines[$line] = null; continue; From 9cdcd737698ba6c561451e938d3243974a5fc2b0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 13:49:37 +0200 Subject: [PATCH 038/508] Fix --- tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php index 542b38f13f..405e3668a8 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php @@ -122,7 +122,6 @@ public function testInvalidTypeInTypeAlias(): void public function testIgnoreWithinPhpDoc(): void { - $this->checkAllInvalidPhpDocs = true; $this->analyse([__DIR__ . '/data/ignore-line-within-phpdoc.php'], []); } From e2440242863fc43bf2bffc82f2763ae0ee307081 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 13:56:24 +0200 Subject: [PATCH 039/508] Fixes --- src/Analyser/NodeScopeResolver.php | 6 +----- src/Parser/PhpParserFactory.php | 2 +- src/Parser/StandaloneThrowExprVisitor.php | 2 +- src/Rules/ClassForbiddenNameCheck.php | 2 +- src/Rules/FunctionDefinitionCheck.php | 2 +- src/Rules/Names/UsedNamesRule.php | 9 ++++----- src/Rules/PhpDoc/PhpDocLineHelper.php | 2 +- src/Rules/Variables/ParameterOutExecutionEndTypeRule.php | 3 --- src/Testing/TypeInferenceTestCase.php | 4 ++-- src/Type/FileTypeMapper.php | 4 ---- 10 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index f32e3345b7..8a992f5c13 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1556,8 +1556,7 @@ private function processStmtNode( } $throwNode = $throwPoint->getNode(); if ( - !$throwNode instanceof Throw_ - && !$throwNode instanceof Expr\Throw_ + !$throwNode instanceof Expr\Throw_ && !($throwNode instanceof Node\Stmt\Expression && $throwNode->expr instanceof Expr\Throw_) ) { $onlyExplicitIsThrow = false; @@ -1858,9 +1857,6 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void { if ($const->namespacedName !== null) { $constantName = new Name\FullyQualified($const->namespacedName->toString()); } else { - if ($const->name->toString() === '') { - throw new ShouldNotHappenException('Constant cannot have a empty name'); - } $constantName = new Name\FullyQualified($const->name->toString()); } $scope = $scope->assignExpression(new ConstFetch($constantName), $scope->getType($const->value), $scope->getNativeType($const->value)); diff --git a/src/Parser/PhpParserFactory.php b/src/Parser/PhpParserFactory.php index dee78b35d2..3a1f2cb4ea 100644 --- a/src/Parser/PhpParserFactory.php +++ b/src/Parser/PhpParserFactory.php @@ -8,7 +8,7 @@ use PhpParser\ParserAbstract; use PHPStan\Php\PhpVersion; -class PhpParserFactory +final class PhpParserFactory { public function __construct(private Lexer $lexer, private PhpVersion $phpVersion) diff --git a/src/Parser/StandaloneThrowExprVisitor.php b/src/Parser/StandaloneThrowExprVisitor.php index e108246128..772a3a1c43 100644 --- a/src/Parser/StandaloneThrowExprVisitor.php +++ b/src/Parser/StandaloneThrowExprVisitor.php @@ -5,7 +5,7 @@ use PhpParser\Node; use PhpParser\NodeVisitorAbstract; -class StandaloneThrowExprVisitor extends NodeVisitorAbstract +final class StandaloneThrowExprVisitor extends NodeVisitorAbstract { public const ATTRIBUTE_NAME = 'standaloneThrowExpr'; diff --git a/src/Rules/ClassForbiddenNameCheck.php b/src/Rules/ClassForbiddenNameCheck.php index c7658440ab..f1f9f032a3 100644 --- a/src/Rules/ClassForbiddenNameCheck.php +++ b/src/Rules/ClassForbiddenNameCheck.php @@ -73,7 +73,7 @@ public function checkClassNames(array $pairs): array $projectName, $className, )) - ->line($pair->getNode()->getLine()) + ->line($pair->getNode()->getStartLine()) ->identifier('class.prefixed') ->nonIgnorable(); diff --git a/src/Rules/FunctionDefinitionCheck.php b/src/Rules/FunctionDefinitionCheck.php index 19a76e042c..a9ea3ff521 100644 --- a/src/Rules/FunctionDefinitionCheck.php +++ b/src/Rules/FunctionDefinitionCheck.php @@ -204,7 +204,7 @@ public function checkAnonymousFunction( foreach ($returnType->getReferencedClasses() as $returnTypeClass) { if (!$this->reflectionProvider->hasClass($returnTypeClass)) { $errors[] = RuleErrorBuilder::message(sprintf($returnMessage, $returnTypeClass)) - ->line($returnTypeNode->getLine()) + ->line($returnTypeNode->getStartLine()) ->identifier('class.notFound') ->build(); continue; diff --git a/src/Rules/Names/UsedNamesRule.php b/src/Rules/Names/UsedNamesRule.php index a1afbb742b..5462137e5d 100644 --- a/src/Rules/Names/UsedNamesRule.php +++ b/src/Rules/Names/UsedNamesRule.php @@ -10,7 +10,6 @@ use PhpParser\Node\Stmt\Namespace_; use PhpParser\Node\Stmt\Trait_; use PhpParser\Node\Stmt\Use_; -use PhpParser\Node\Stmt\UseUse; use PHPStan\Analyser\Scope; use PHPStan\Node\FileNode; use PHPStan\Rules\IdentifierRuleError; @@ -100,7 +99,7 @@ private function findErrorsForNode(Node $node, string $namespace, array &$usedNa $namespace !== '' ? $namespace . '\\' . $node->name->toString() : $node->name->toString(), )) ->identifier(sprintf('%s.nameInUse', $type)) - ->line($node->getLine()) + ->line($node->getStartLine()) ->nonIgnorable() ->build(), ]; @@ -113,7 +112,7 @@ private function findErrorsForNode(Node $node, string $namespace, array &$usedNa } /** - * @param UseUse[] $uses + * @param Node\UseItem[] $uses * @param array $usedNames * @return list */ @@ -132,7 +131,7 @@ private function findErrorsInUses(array $uses, string $useGroupPrefix, string $l $use->getAlias()->toString(), )) ->identifier('use.nameInUse') - ->line($use->getLine()) + ->line($use->getStartLine()) ->nonIgnorable() ->build(); continue; @@ -142,7 +141,7 @@ private function findErrorsInUses(array $uses, string $useGroupPrefix, string $l return $errors; } - private function shouldBeIgnored(Use_|GroupUse|UseUse $use): bool + private function shouldBeIgnored(Use_|GroupUse|Node\UseItem $use): bool { return in_array($use->type, [Use_::TYPE_FUNCTION, Use_::TYPE_CONSTANT], true); } diff --git a/src/Rules/PhpDoc/PhpDocLineHelper.php b/src/Rules/PhpDoc/PhpDocLineHelper.php index b008e63470..a7894f762f 100644 --- a/src/Rules/PhpDoc/PhpDocLineHelper.php +++ b/src/Rules/PhpDoc/PhpDocLineHelper.php @@ -19,7 +19,7 @@ public static function detectLine(PhpParserNode $node, PhpDocNode $phpDocNode): $phpDoc = $node->getDocComment(); if ($phpDocTagLine === null || $phpDoc === null) { - return $node->getLine(); + return $node->getStartLine(); } return $phpDoc->getStartLine() + $phpDocTagLine - 1; diff --git a/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php b/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php index 177079ac6c..9b42e1909e 100644 --- a/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php +++ b/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php @@ -57,9 +57,6 @@ public function processNode(Node $node, Scope $scope): array return []; } } - if ($endNode instanceof Node\Stmt\Throw_) { - return []; - } $variant = ParametersAcceptorSelector::selectSingle($inFunction->getVariants()); $parameters = $variant->getParameters(); diff --git a/src/Testing/TypeInferenceTestCase.php b/src/Testing/TypeInferenceTestCase.php index 4194d4f4d3..874b601156 100644 --- a/src/Testing/TypeInferenceTestCase.php +++ b/src/Testing/TypeInferenceTestCase.php @@ -178,7 +178,7 @@ public static function gatherAssertTypes(string $file): array 'Expected type must be a literal string, %s given in %s on line %d.', $expectedType->describe(VerbosityLevel::precise()), $relativePathHelper->getRelativePath($file), - $node->getLine(), + $node->getStartLine(), )); } $actualType = $scope->getType($node->getArgs()[1]->value); @@ -190,7 +190,7 @@ public static function gatherAssertTypes(string $file): array 'Expected type must be a literal string, %s given in %s on line %d.', $expectedType->describe(VerbosityLevel::precise()), $relativePathHelper->getRelativePath($file), - $node->getLine(), + $node->getStartLine(), )); } diff --git a/src/Type/FileTypeMapper.php b/src/Type/FileTypeMapper.php index a0af548147..9a14e3aec4 100644 --- a/src/Type/FileTypeMapper.php +++ b/src/Type/FileTypeMapper.php @@ -482,10 +482,6 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun $functionName = $functionStack[count($functionStack) - 1] ?? null; $nameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, $functionName); - if ($namespace === '') { - throw new ShouldNotHappenException('Namespace cannot be empty.'); - } - if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) { if (array_key_exists($nameScopeKey, $phpDocNodeMap)) { $phpDocNode = $phpDocNodeMap[$nameScopeKey]; From baaf9d9fa2474e5b06bf7066a66b5d8862dd6a65 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 13:56:51 +0200 Subject: [PATCH 040/508] Remove deprecated rule NoopRule --- conf/config.level4.neon | 7 -- src/Rules/DeadCode/NoopRule.php | 73 --------------- tests/PHPStan/Rules/DeadCode/NoopRuleTest.php | 93 ------------------- 3 files changed, 173 deletions(-) delete mode 100644 src/Rules/DeadCode/NoopRule.php delete mode 100644 tests/PHPStan/Rules/DeadCode/NoopRuleTest.php diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 8f3ecc86bc..421cafcd9e 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -96,13 +96,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\DeadCode\NoopRule - arguments: - better: %featureToggles.betterNoop% - tags: - - phpstan.rules.rule - - class: PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule diff --git a/src/Rules/DeadCode/NoopRule.php b/src/Rules/DeadCode/NoopRule.php deleted file mode 100644 index ff0d6eb8e7..0000000000 --- a/src/Rules/DeadCode/NoopRule.php +++ /dev/null @@ -1,73 +0,0 @@ - - */ -final class NoopRule implements Rule -{ - - public function __construct(private ExprPrinter $exprPrinter, private bool $better) - { - } - - public function getNodeType(): string - { - return Node\Stmt\Expression::class; - } - - public function processNode(Node $node, Scope $scope): array - { - if ($this->better) { - // disabled in bleeding edge - return []; - } - $originalExpr = $node->expr; - $expr = $originalExpr; - if ( - $expr instanceof Node\Expr\Cast - || $expr instanceof Node\Expr\UnaryMinus - || $expr instanceof Node\Expr\UnaryPlus - || $expr instanceof Node\Expr\ErrorSuppress - ) { - $expr = $expr->expr; - } - - if (!$this->isNoopExpr($expr)) { - return []; - } - - return [ - RuleErrorBuilder::message(sprintf( - 'Expression "%s" on a separate line does not do anything.', - $this->exprPrinter->printExpr($originalExpr), - ))->line($expr->getStartLine()) - ->identifier('expr.resultUnused') - ->build(), - ]; - } - - public function isNoopExpr(Node\Expr $expr): bool - { - return $expr instanceof Node\Expr\Variable - || $expr instanceof Node\Expr\PropertyFetch - || $expr instanceof Node\Expr\StaticPropertyFetch - || $expr instanceof Node\Expr\NullsafePropertyFetch - || $expr instanceof Node\Expr\ArrayDimFetch - || $expr instanceof Node\Scalar - || $expr instanceof Node\Expr\Isset_ - || $expr instanceof Node\Expr\Empty_ - || $expr instanceof Node\Expr\ConstFetch - || $expr instanceof Node\Expr\ClassConstFetch; - } - -} diff --git a/tests/PHPStan/Rules/DeadCode/NoopRuleTest.php b/tests/PHPStan/Rules/DeadCode/NoopRuleTest.php deleted file mode 100644 index edffaa5b9a..0000000000 --- a/tests/PHPStan/Rules/DeadCode/NoopRuleTest.php +++ /dev/null @@ -1,93 +0,0 @@ - - */ -class NoopRuleTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new NoopRule(new ExprPrinter(new Printer()), false); - } - - public function testRule(): void - { - $this->analyse([__DIR__ . '/data/noop.php'], [ - [ - 'Expression "$arr" on a separate line does not do anything.', - 9, - ], - [ - 'Expression "$arr[\'test\']" on a separate line does not do anything.', - 10, - ], - [ - 'Expression "$foo::$test" on a separate line does not do anything.', - 11, - ], - [ - 'Expression "$foo->test" on a separate line does not do anything.', - 12, - ], - [ - 'Expression "\'foo\'" on a separate line does not do anything.', - 14, - ], - [ - 'Expression "1" on a separate line does not do anything.', - 15, - ], - [ - 'Expression "@\'foo\'" on a separate line does not do anything.', - 17, - ], - [ - 'Expression "+1" on a separate line does not do anything.', - 18, - ], - [ - 'Expression "-1" on a separate line does not do anything.', - 19, - ], - [ - 'Expression "isset($test)" on a separate line does not do anything.', - 25, - ], - [ - 'Expression "empty($test)" on a separate line does not do anything.', - 26, - ], - [ - 'Expression "true" on a separate line does not do anything.', - 27, - ], - [ - 'Expression "\DeadCodeNoop\Foo::TEST" on a separate line does not do anything.', - 28, - ], - [ - 'Expression "(string) 1" on a separate line does not do anything.', - 30, - ], - ]); - } - - public function testNullsafe(): void - { - $this->analyse([__DIR__ . '/data/nullsafe-property-fetch-noop.php'], [ - [ - 'Expression "$ref?->name" on a separate line does not do anything.', - 10, - ], - ]); - } - -} From 7501f2f73be42279fe769bb9908da30f1ffdd8e2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 14:01:09 +0200 Subject: [PATCH 041/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 64c143fd28..e4e61cd532 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.1.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.42.0.3", + "ondrejmirtes/better-reflection": "6.42.0.6", "phpstan/php-8-stubs": "0.3.101", "phpstan/phpdoc-parser": "1.30.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 6ef0c6b966..0aba247c22 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b0a75f027cffe40f37c639ade2ee9361", + "content-hash": "bba4725ca58df1d370b5aa291335076d", "packages": [ { "name": "clue/ndjson-react", @@ -2179,16 +2179,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.42.0.3", + "version": "6.42.0.6", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "bdb626a5e2fb52bfe3fec1d367a9c72e48550954" + "reference": "955eefa555a862d35c298c69042a176bb39f88e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/bdb626a5e2fb52bfe3fec1d367a9c72e48550954", - "reference": "bdb626a5e2fb52bfe3fec1d367a9c72e48550954", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/955eefa555a862d35c298c69042a176bb39f88e2", + "reference": "955eefa555a862d35c298c69042a176bb39f88e2", "shasum": "" }, "require": { @@ -2244,9 +2244,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.42.0.3" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.42.0.6" }, - "time": "2024-09-04T11:06:34+00:00" + "time": "2024-09-04T11:59:59+00:00" }, { "name": "phpstan/php-8-stubs", From ba66abe0a16e1c98f6241009acec756781d7e9a1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 14:07:14 +0200 Subject: [PATCH 042/508] Fix --- src/Parser/StandaloneThrowExprVisitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Parser/StandaloneThrowExprVisitor.php b/src/Parser/StandaloneThrowExprVisitor.php index 772a3a1c43..386c903281 100644 --- a/src/Parser/StandaloneThrowExprVisitor.php +++ b/src/Parser/StandaloneThrowExprVisitor.php @@ -10,7 +10,7 @@ final class StandaloneThrowExprVisitor extends NodeVisitorAbstract public const ATTRIBUTE_NAME = 'standaloneThrowExpr'; - public function enterNode(Node $node) + public function enterNode(Node $node): ?Node\Stmt\Expression { if (!$node instanceof Node\Stmt\Expression) { return null; From d0824eb2fd777dd668e93d9db3e3cfa5b43d5f1f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 14:07:39 +0200 Subject: [PATCH 043/508] Remove deprecated rule ImplodeFunctionRule --- conf/config.level5.neon | 6 -- src/Rules/Functions/ImplodeFunctionRule.php | 84 ------------------- .../Functions/ImplodeFunctionRuleTest.php | 61 -------------- 3 files changed, 151 deletions(-) delete mode 100644 src/Rules/Functions/ImplodeFunctionRule.php delete mode 100644 tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php diff --git a/conf/config.level5.neon b/conf/config.level5.neon index 184cee83b8..470689b7c2 100644 --- a/conf/config.level5.neon +++ b/conf/config.level5.neon @@ -42,12 +42,6 @@ services: - class: PHPStan\Rules\Functions\CallUserFuncRule - - - class: PHPStan\Rules\Functions\ImplodeFunctionRule - arguments: - disabled: %featureToggles.checkParameterCastableToStringFunctions% - tags: - - phpstan.rules.rule - class: PHPStan\Rules\Functions\ParameterCastableToStringRule - diff --git a/src/Rules/Functions/ImplodeFunctionRule.php b/src/Rules/Functions/ImplodeFunctionRule.php deleted file mode 100644 index 93ade0dafc..0000000000 --- a/src/Rules/Functions/ImplodeFunctionRule.php +++ /dev/null @@ -1,84 +0,0 @@ - - */ -final class ImplodeFunctionRule implements Rule -{ - - public function __construct( - private ReflectionProvider $reflectionProvider, - private RuleLevelHelper $ruleLevelHelper, - private bool $disabled, - ) - { - } - - public function getNodeType(): string - { - return FuncCall::class; - } - - public function processNode(Node $node, Scope $scope): array - { - if ($this->disabled) { - return []; - } - - if (!($node->name instanceof Node\Name)) { - return []; - } - - $functionName = $this->reflectionProvider->resolveFunctionName($node->name, $scope); - if (!in_array($functionName, ['implode', 'join'], true)) { - return []; - } - - $args = $node->getArgs(); - if (count($args) === 1) { - $arrayArg = $args[0]->value; - $paramNo = 1; - } elseif (count($args) === 2) { - $arrayArg = $args[1]->value; - $paramNo = 2; - } else { - return []; - } - - $typeResult = $this->ruleLevelHelper->findTypeToCheck( - $scope, - $arrayArg, - '', - static fn (Type $type): bool => !$type->getIterableValueType()->toString() instanceof ErrorType, - ); - - if ($typeResult->getType() instanceof ErrorType - || !$typeResult->getType()->getIterableValueType()->toString() instanceof ErrorType) { - return []; - } - - return [ - RuleErrorBuilder::message( - sprintf('Parameter #%d $array of function %s expects array, %s given.', $paramNo, $functionName, $typeResult->getType()->describe(VerbosityLevel::typeOnly())), - )->identifier('argument.type')->build(), - ]; - } - -} diff --git a/tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php b/tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php deleted file mode 100644 index 44755df63d..0000000000 --- a/tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ -class ImplodeFunctionRuleTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - $broker = $this->createReflectionProvider(); - return new ImplodeFunctionRule($broker, new RuleLevelHelper($broker, true, false, true, false, false, true, false), false); - } - - public function testFile(): void - { - $this->analyse([__DIR__ . '/data/implode.php'], [ - [ - 'Parameter #2 $array of function implode expects array, array|string> given.', - 9, - ], - [ - 'Parameter #1 $array of function implode expects array, array> given.', - 11, - ], - [ - 'Parameter #1 $array of function implode expects array, array> given.', - 12, - ], - [ - 'Parameter #1 $array of function implode expects array, array> given.', - 13, - ], - [ - 'Parameter #2 $array of function implode expects array, array> given.', - 15, - ], - [ - 'Parameter #2 $array of function join expects array, array> given.', - 16, - ], - ]); - } - - public function testBug6000(): void - { - $this->analyse([__DIR__ . '/../Arrays/data/bug-6000.php'], []); - } - - public function testBug8467a(): void - { - $this->analyse([__DIR__ . '/../Arrays/data/bug-8467a.php'], []); - } - -} From 507fdcae01c19aa03f7bd8109c9a08f50553694a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 14:16:04 +0200 Subject: [PATCH 044/508] Fix tests --- .../Functions/ArrowFunctionReturnTypeRuleTest.php | 13 ++++++++++++- ...ingClassesInArrowFunctionTypehintsRuleTest.php | 9 ++++++++- .../data/arrow-function-never-return.php | 15 +++++++++++++++ .../data/arrow-functions-return-type.php | 12 ------------ .../Rules/Playground/FunctionNeverRuleTest.php | 5 +++++ .../Rules/Playground/MethodNeverRuleTest.php | 5 +++++ 6 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 tests/PHPStan/Rules/Functions/data/arrow-function-never-return.php diff --git a/tests/PHPStan/Rules/Functions/ArrowFunctionReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ArrowFunctionReturnTypeRuleTest.php index bf46cd56a6..8e530c62aa 100644 --- a/tests/PHPStan/Rules/Functions/ArrowFunctionReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ArrowFunctionReturnTypeRuleTest.php @@ -39,9 +39,20 @@ public function testRule(): void 'Anonymous function should return int but returns string.', 14, ], + + ]); + } + + public function testRuleNever(): void + { + if (PHP_VERSION_ID < 80100) { + self::markTestSkipped('Test requires PHP 8.1.'); + } + + $this->analyse([__DIR__ . '/data/arrow-function-never-return.php'], [ [ 'Anonymous function should never return but return statement found.', - 44, + 12, ], ]); } diff --git a/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php b/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php index 2417944d1a..e670804dcd 100644 --- a/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php @@ -289,7 +289,14 @@ public function testIntersectionTypes(int $phpVersion, array $errors): void public function testNever(): void { $errors = []; - if (PHP_VERSION_ID < 80200) { + if (PHP_VERSION_ID < 80100) { + $errors = [ + [ + 'Anonymous function has invalid return type ArrowFunctionNever\never.', + 6, + ], + ]; + } elseif (PHP_VERSION_ID < 80200) { $errors = [ [ 'Never return type in arrow function is supported only on PHP 8.2 and later.', diff --git a/tests/PHPStan/Rules/Functions/data/arrow-function-never-return.php b/tests/PHPStan/Rules/Functions/data/arrow-function-never-return.php new file mode 100644 index 0000000000..5a9641fb06 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/arrow-function-never-return.php @@ -0,0 +1,15 @@ += 8.1 + +namespace ArrowFunctionNeverReturn; + +class Baz +{ + + public function doFoo(): void + { + $f = fn () => throw new \Exception(); + $g = fn (): never => throw new \Exception(); + $g = fn (): never => 1; + } + +} diff --git a/tests/PHPStan/Rules/Functions/data/arrow-functions-return-type.php b/tests/PHPStan/Rules/Functions/data/arrow-functions-return-type.php index 552bf901c6..4a18708fba 100644 --- a/tests/PHPStan/Rules/Functions/data/arrow-functions-return-type.php +++ b/tests/PHPStan/Rules/Functions/data/arrow-functions-return-type.php @@ -33,15 +33,3 @@ public function doBar(): void } static fn (int $value): iterable => yield $value; - -class Baz -{ - - public function doFoo(): void - { - $f = fn () => throw new \Exception(); - $g = fn (): never => throw new \Exception(); - $g = fn (): never => 1; - } - -} diff --git a/tests/PHPStan/Rules/Playground/FunctionNeverRuleTest.php b/tests/PHPStan/Rules/Playground/FunctionNeverRuleTest.php index a75b82f714..2f580113f5 100644 --- a/tests/PHPStan/Rules/Playground/FunctionNeverRuleTest.php +++ b/tests/PHPStan/Rules/Playground/FunctionNeverRuleTest.php @@ -4,6 +4,7 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -18,6 +19,10 @@ protected function getRule(): Rule public function testRule(): void { + if (PHP_VERSION_ID < 80100) { + self::markTestSkipped('Test requires PHP 8.1 or greater.'); + } + $this->analyse([__DIR__ . '/data/function-never.php'], [ [ 'Function FunctionNever\doBar() always throws an exception, it should have return type "never".', diff --git a/tests/PHPStan/Rules/Playground/MethodNeverRuleTest.php b/tests/PHPStan/Rules/Playground/MethodNeverRuleTest.php index 583c6a5a5f..83e315479d 100644 --- a/tests/PHPStan/Rules/Playground/MethodNeverRuleTest.php +++ b/tests/PHPStan/Rules/Playground/MethodNeverRuleTest.php @@ -4,6 +4,7 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -18,6 +19,10 @@ protected function getRule(): Rule public function testRule(): void { + if (PHP_VERSION_ID < 80100) { + self::markTestSkipped('Test requires PHP 8.1 or greater.'); + } + $this->analyse([__DIR__ . '/data/method-never.php'], [ [ 'Method MethodNever\Foo::doBar() always throws an exception, it should have return type "never".', From 7cb1f1bda8ba1ca3f75a1e2c1fb5834a35291092 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 14:40:27 +0200 Subject: [PATCH 045/508] Skip `mixed` tests on PHP < 8.0 --- ...namicReturnTypeExtensionTypeInferenceTest.php | 2 +- .../Analyser/LegacyNodeScopeResolverTest.php | 2 +- tests/PHPStan/Analyser/nsrt/abs.php | 4 +++- tests/PHPStan/Analyser/nsrt/array-key-exists.php | 2 +- .../PHPStan/Analyser/nsrt/assert-conditional.php | 2 +- tests/PHPStan/Analyser/nsrt/assert-docblock.php | 2 +- tests/PHPStan/Analyser/nsrt/assert-empty.php | 2 +- .../PHPStan/Analyser/nsrt/assert-inheritance.php | 2 +- .../PHPStan/Analyser/nsrt/assert-intersected.php | 2 +- tests/PHPStan/Analyser/nsrt/assert-invariant.php | 4 +++- tests/PHPStan/Analyser/nsrt/bug-10037.php | 4 +++- tests/PHPStan/Analyser/nsrt/bug-10254.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-10473.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-6293.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-7141.php | 4 +++- tests/PHPStan/Analyser/nsrt/bug-7788.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-7944.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-8249.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-8803.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-9062.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-9086.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-9341.php | 4 +++- tests/PHPStan/Analyser/nsrt/bug-9472.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-9764.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-9867.php | 2 +- tests/PHPStan/Analyser/nsrt/class-implements.php | 2 +- .../nsrt/conditional-types-inference.php | 2 +- tests/PHPStan/Analyser/nsrt/ctype-digit.php | 4 +++- tests/PHPStan/Analyser/nsrt/enum_exists.php | 2 +- tests/PHPStan/Analyser/nsrt/falsy-isset.php | 2 +- .../PHPStan/Analyser/nsrt/filter-input-array.php | 4 +++- tests/PHPStan/Analyser/nsrt/filter-var-array.php | 2 +- .../PHPStan/Analyser/nsrt/generic-callables.php | 2 +- .../Analyser/nsrt/generic-method-tags.php | 2 +- tests/PHPStan/Analyser/nsrt/key-exists.php | 2 +- tests/PHPStan/Analyser/nsrt/mixed-typehint.php | 2 +- tests/PHPStan/Analyser/nsrt/offset-access.php | 2 +- tests/PHPStan/Reflection/MixedTypeTest.php | 5 +++++ .../Rules/Arrays/IterableInForeachRuleTest.php | 4 ++++ .../NonexistentOffsetInArrayDimFetchRuleTest.php | 4 ++++ .../Arrays/UnpackIterableInArrayRuleTest.php | 4 ++++ tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php | 4 ++++ .../ExistingClassInInstanceOfRuleTest.php | 5 +++++ .../ImpossibleCheckTypeFunctionCallRuleTest.php | 16 ++++++++++++++++ .../ImpossibleCheckTypeMethodCallRuleTest.php | 5 +++++ .../CallToFunctionParametersRuleTest.php | 12 ++++++++++++ ...ngClassesInArrowFunctionTypehintsRuleTest.php | 4 ++++ ...ExistingClassesInClosureTypehintsRuleTest.php | 4 ++++ .../Rules/Functions/ReturnTypeRuleTest.php | 4 ++++ .../Rules/Methods/CallMethodsRuleTest.php | 12 ++++++++++++ .../Rules/Methods/CallStaticMethodsRuleTest.php | 4 ++++ .../ExistingClassesInTypehintsRuleTest.php | 12 ++++++++++++ .../IncompatibleDefaultParameterTypeRuleTest.php | 5 +++++ .../Rules/Methods/OverridingMethodRuleTest.php | 4 ++++ .../Rules/Missing/MissingReturnRuleTest.php | 8 ++++++++ .../Operators/InvalidBinaryOperationRuleTest.php | 4 ++++ .../Operators/InvalidIncDecOperationRuleTest.php | 5 +++++ .../Operators/InvalidUnaryOperationRuleTest.php | 5 +++++ 58 files changed, 181 insertions(+), 37 deletions(-) diff --git a/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php b/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php index 59ebef356e..c76ca0ebca 100644 --- a/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php +++ b/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php @@ -14,10 +14,10 @@ public function dataAsserts(): iterable if (PHP_VERSION_ID >= 80000) { yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-types-named-args.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-getsingle-conditional.php'); } yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-compound-types.php'); - yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-getsingle-conditional.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7344.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7391b.php'); } diff --git a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php index 1d17f9ee48..f75730744d 100644 --- a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php @@ -6431,7 +6431,7 @@ public function dataMisleadingTypes(): array '$foo->misleadingIntReturnType()', ], [ - 'mixed', + PHP_VERSION_ID >= 80000 ? 'mixed' : 'MisleadingTypes\mixed', '$foo->misleadingMixedReturnType()', ], ]; diff --git a/tests/PHPStan/Analyser/nsrt/abs.php b/tests/PHPStan/Analyser/nsrt/abs.php index eb644eb4bd..506f436c02 100644 --- a/tests/PHPStan/Analyser/nsrt/abs.php +++ b/tests/PHPStan/Analyser/nsrt/abs.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types = 1); namespace Abs; diff --git a/tests/PHPStan/Analyser/nsrt/array-key-exists.php b/tests/PHPStan/Analyser/nsrt/array-key-exists.php index ed6f552d15..17e49019c7 100644 --- a/tests/PHPStan/Analyser/nsrt/array-key-exists.php +++ b/tests/PHPStan/Analyser/nsrt/array-key-exists.php @@ -1,4 +1,4 @@ -= 8.0 namespace ArrayKeyExistsExtension; diff --git a/tests/PHPStan/Analyser/nsrt/assert-conditional.php b/tests/PHPStan/Analyser/nsrt/assert-conditional.php index 4e52490066..4a8567a2db 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-conditional.php +++ b/tests/PHPStan/Analyser/nsrt/assert-conditional.php @@ -1,4 +1,4 @@ -= 8.0 namespace AssertConditional; diff --git a/tests/PHPStan/Analyser/nsrt/assert-docblock.php b/tests/PHPStan/Analyser/nsrt/assert-docblock.php index 1b094a1cd7..b6391d651a 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-docblock.php +++ b/tests/PHPStan/Analyser/nsrt/assert-docblock.php @@ -1,4 +1,4 @@ -= 8.0 namespace AssertDocblock; diff --git a/tests/PHPStan/Analyser/nsrt/assert-empty.php b/tests/PHPStan/Analyser/nsrt/assert-empty.php index 12176791a3..73f15aade7 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-empty.php +++ b/tests/PHPStan/Analyser/nsrt/assert-empty.php @@ -1,4 +1,4 @@ -= 8.0 namespace AssertEmpty; diff --git a/tests/PHPStan/Analyser/nsrt/assert-inheritance.php b/tests/PHPStan/Analyser/nsrt/assert-inheritance.php index b9b362172e..ffc9552321 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-inheritance.php +++ b/tests/PHPStan/Analyser/nsrt/assert-inheritance.php @@ -1,4 +1,4 @@ -= 8.0 namespace AssertInheritance; diff --git a/tests/PHPStan/Analyser/nsrt/assert-intersected.php b/tests/PHPStan/Analyser/nsrt/assert-intersected.php index a39ffe1436..17aa63957a 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-intersected.php +++ b/tests/PHPStan/Analyser/nsrt/assert-intersected.php @@ -1,4 +1,4 @@ -= 8.0 namespace AssertIntersected; diff --git a/tests/PHPStan/Analyser/nsrt/assert-invariant.php b/tests/PHPStan/Analyser/nsrt/assert-invariant.php index b7368f06e9..4efe160b18 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-invariant.php +++ b/tests/PHPStan/Analyser/nsrt/assert-invariant.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types = 1); namespace AssertInvariant; diff --git a/tests/PHPStan/Analyser/nsrt/bug-10037.php b/tests/PHPStan/Analyser/nsrt/bug-10037.php index 58adb961c1..56c49c331b 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-10037.php +++ b/tests/PHPStan/Analyser/nsrt/bug-10037.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types = 1); namespace Bug10037; diff --git a/tests/PHPStan/Analyser/nsrt/bug-10254.php b/tests/PHPStan/Analyser/nsrt/bug-10254.php index 3299015ca0..a16ed81f04 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-10254.php +++ b/tests/PHPStan/Analyser/nsrt/bug-10254.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug10254; diff --git a/tests/PHPStan/Analyser/nsrt/bug-10473.php b/tests/PHPStan/Analyser/nsrt/bug-10473.php index d07a7f6804..bad001bea0 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-10473.php +++ b/tests/PHPStan/Analyser/nsrt/bug-10473.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug10473; diff --git a/tests/PHPStan/Analyser/nsrt/bug-6293.php b/tests/PHPStan/Analyser/nsrt/bug-6293.php index 0a5c8548be..993f7b470e 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-6293.php +++ b/tests/PHPStan/Analyser/nsrt/bug-6293.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug6239; diff --git a/tests/PHPStan/Analyser/nsrt/bug-7141.php b/tests/PHPStan/Analyser/nsrt/bug-7141.php index 277b00d9e6..2cf34a5733 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7141.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7141.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types = 1); namespace Bug7141; diff --git a/tests/PHPStan/Analyser/nsrt/bug-7788.php b/tests/PHPStan/Analyser/nsrt/bug-7788.php index 944d10e7e4..fa5c6a73af 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7788.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7788.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug7788; diff --git a/tests/PHPStan/Analyser/nsrt/bug-7944.php b/tests/PHPStan/Analyser/nsrt/bug-7944.php index 737ab3dcb8..0d219b40b3 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7944.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7944.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug7944; diff --git a/tests/PHPStan/Analyser/nsrt/bug-8249.php b/tests/PHPStan/Analyser/nsrt/bug-8249.php index 960126723d..46964dc0ad 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-8249.php +++ b/tests/PHPStan/Analyser/nsrt/bug-8249.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug8249; diff --git a/tests/PHPStan/Analyser/nsrt/bug-8803.php b/tests/PHPStan/Analyser/nsrt/bug-8803.php index a1d9ad568b..88af4df14d 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-8803.php +++ b/tests/PHPStan/Analyser/nsrt/bug-8803.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug8803; diff --git a/tests/PHPStan/Analyser/nsrt/bug-9062.php b/tests/PHPStan/Analyser/nsrt/bug-9062.php index a4c8cc6251..7280c8634c 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9062.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9062.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug9062; diff --git a/tests/PHPStan/Analyser/nsrt/bug-9086.php b/tests/PHPStan/Analyser/nsrt/bug-9086.php index db0110f2f4..e099f4eec1 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9086.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9086.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug9086; diff --git a/tests/PHPStan/Analyser/nsrt/bug-9341.php b/tests/PHPStan/Analyser/nsrt/bug-9341.php index 2c1a90f5bd..3265c4a7b0 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9341.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9341.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types = 1); namespace Bug9341; diff --git a/tests/PHPStan/Analyser/nsrt/bug-9472.php b/tests/PHPStan/Analyser/nsrt/bug-9472.php index 923c0534e6..e81f67b7ea 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9472.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9472.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug9472; diff --git a/tests/PHPStan/Analyser/nsrt/bug-9764.php b/tests/PHPStan/Analyser/nsrt/bug-9764.php index 15807d0b1e..f24b810fe8 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9764.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9764.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug9764; diff --git a/tests/PHPStan/Analyser/nsrt/bug-9867.php b/tests/PHPStan/Analyser/nsrt/bug-9867.php index 7c677aa8d6..6ab9515b87 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9867.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9867.php @@ -1,4 +1,4 @@ -= 8.0 declare(strict_types=1); diff --git a/tests/PHPStan/Analyser/nsrt/class-implements.php b/tests/PHPStan/Analyser/nsrt/class-implements.php index acd6a616ae..316c8e8ed4 100644 --- a/tests/PHPStan/Analyser/nsrt/class-implements.php +++ b/tests/PHPStan/Analyser/nsrt/class-implements.php @@ -1,4 +1,4 @@ -= 8.0 namespace ClassImplements; diff --git a/tests/PHPStan/Analyser/nsrt/conditional-types-inference.php b/tests/PHPStan/Analyser/nsrt/conditional-types-inference.php index 55335c6e2e..89bfa50a22 100644 --- a/tests/PHPStan/Analyser/nsrt/conditional-types-inference.php +++ b/tests/PHPStan/Analyser/nsrt/conditional-types-inference.php @@ -1,4 +1,4 @@ -= 8.0 namespace ConditionalTypesInference; diff --git a/tests/PHPStan/Analyser/nsrt/ctype-digit.php b/tests/PHPStan/Analyser/nsrt/ctype-digit.php index 835ba4fdcc..00a803d52d 100644 --- a/tests/PHPStan/Analyser/nsrt/ctype-digit.php +++ b/tests/PHPStan/Analyser/nsrt/ctype-digit.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types=1); namespace CtypeDigit; diff --git a/tests/PHPStan/Analyser/nsrt/enum_exists.php b/tests/PHPStan/Analyser/nsrt/enum_exists.php index 33f1200924..37809016ad 100644 --- a/tests/PHPStan/Analyser/nsrt/enum_exists.php +++ b/tests/PHPStan/Analyser/nsrt/enum_exists.php @@ -1,4 +1,4 @@ -= 8.0 namespace EnumExists; diff --git a/tests/PHPStan/Analyser/nsrt/falsy-isset.php b/tests/PHPStan/Analyser/nsrt/falsy-isset.php index bce229826a..eb11c5254d 100644 --- a/tests/PHPStan/Analyser/nsrt/falsy-isset.php +++ b/tests/PHPStan/Analyser/nsrt/falsy-isset.php @@ -1,4 +1,4 @@ -= 8.0 namespace FalsyIsset; diff --git a/tests/PHPStan/Analyser/nsrt/filter-input-array.php b/tests/PHPStan/Analyser/nsrt/filter-input-array.php index 706a300680..d773c237f8 100644 --- a/tests/PHPStan/Analyser/nsrt/filter-input-array.php +++ b/tests/PHPStan/Analyser/nsrt/filter-input-array.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types=1); namespace FilterVarArray; diff --git a/tests/PHPStan/Analyser/nsrt/filter-var-array.php b/tests/PHPStan/Analyser/nsrt/filter-var-array.php index 52261b0e8a..38db914722 100644 --- a/tests/PHPStan/Analyser/nsrt/filter-var-array.php +++ b/tests/PHPStan/Analyser/nsrt/filter-var-array.php @@ -1,4 +1,4 @@ -= 8.0 namespace FilterVarArray; diff --git a/tests/PHPStan/Analyser/nsrt/generic-callables.php b/tests/PHPStan/Analyser/nsrt/generic-callables.php index 94bb3238a2..9fde822894 100644 --- a/tests/PHPStan/Analyser/nsrt/generic-callables.php +++ b/tests/PHPStan/Analyser/nsrt/generic-callables.php @@ -1,4 +1,4 @@ -= 8.0 namespace GenericCallables; diff --git a/tests/PHPStan/Analyser/nsrt/generic-method-tags.php b/tests/PHPStan/Analyser/nsrt/generic-method-tags.php index 92fdfaef5c..0aab6ea591 100644 --- a/tests/PHPStan/Analyser/nsrt/generic-method-tags.php +++ b/tests/PHPStan/Analyser/nsrt/generic-method-tags.php @@ -1,4 +1,4 @@ -= 8.0 namespace GenericMethodTags; diff --git a/tests/PHPStan/Analyser/nsrt/key-exists.php b/tests/PHPStan/Analyser/nsrt/key-exists.php index 11c2ed6a2a..0c98f24b2b 100644 --- a/tests/PHPStan/Analyser/nsrt/key-exists.php +++ b/tests/PHPStan/Analyser/nsrt/key-exists.php @@ -1,4 +1,4 @@ -= 8.0 namespace KeyExists; diff --git a/tests/PHPStan/Analyser/nsrt/mixed-typehint.php b/tests/PHPStan/Analyser/nsrt/mixed-typehint.php index 8d7ce4ad16..5b3c17cbb1 100644 --- a/tests/PHPStan/Analyser/nsrt/mixed-typehint.php +++ b/tests/PHPStan/Analyser/nsrt/mixed-typehint.php @@ -1,4 +1,4 @@ -= 8.0 namespace MixedTypehint; diff --git a/tests/PHPStan/Analyser/nsrt/offset-access.php b/tests/PHPStan/Analyser/nsrt/offset-access.php index 505557b452..593dd799ab 100644 --- a/tests/PHPStan/Analyser/nsrt/offset-access.php +++ b/tests/PHPStan/Analyser/nsrt/offset-access.php @@ -1,4 +1,4 @@ -= 8.0 namespace OffsetAccess; diff --git a/tests/PHPStan/Reflection/MixedTypeTest.php b/tests/PHPStan/Reflection/MixedTypeTest.php index f6c511df33..869f3c2bf8 100644 --- a/tests/PHPStan/Reflection/MixedTypeTest.php +++ b/tests/PHPStan/Reflection/MixedTypeTest.php @@ -6,12 +6,17 @@ use PhpParser\Node\Name; use PHPStan\Testing\PHPStanTestCase; use PHPStan\Type\MixedType; +use const PHP_VERSION_ID; class MixedTypeTest extends PHPStanTestCase { public function testMixedType(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $reflectionProvider = $this->createReflectionProvider(); $class = $reflectionProvider->getClass(Foo::class); $propertyType = $class->getNativeProperty('fooProp')->getNativeType(); diff --git a/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php b/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php index dbb64b29ca..31407e99be 100644 --- a/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php @@ -135,6 +135,10 @@ public function dataMixed(): array */ public function testMixed(bool $checkExplicitMixed, bool $checkImplicitMixed, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixed = $checkExplicitMixed; $this->checkImplicitMixed = $checkImplicitMixed; $this->analyse([__DIR__ . '/data/foreach-mixed.php'], $errors); diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index ffc6aa26d5..bde2d1100e 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -762,6 +762,10 @@ public function testBug10926(): void public function testMixed(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixed = true; $this->checkImplicitMixed = true; $this->analyse([__DIR__ . '/data/offset-access-mixed.php'], [ diff --git a/tests/PHPStan/Rules/Arrays/UnpackIterableInArrayRuleTest.php b/tests/PHPStan/Rules/Arrays/UnpackIterableInArrayRuleTest.php index 32d4900686..c7de4bc7bf 100644 --- a/tests/PHPStan/Rules/Arrays/UnpackIterableInArrayRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/UnpackIterableInArrayRuleTest.php @@ -107,6 +107,10 @@ public function dataMixed(): array */ public function testMixed(bool $checkExplicitMixed, bool $checkImplicitMixed, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixed = $checkExplicitMixed; $this->checkImplicitMixed = $checkImplicitMixed; $this->analyse([__DIR__ . '/data/unpack-mixed.php'], $errors); diff --git a/tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php b/tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php index 5734b47928..bc7cd35acb 100644 --- a/tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php +++ b/tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php @@ -163,6 +163,10 @@ public function dataMixed(): array */ public function testMixed(bool $checkExplicitMixed, bool $checkImplicitMixed, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkImplicitMixed = $checkImplicitMixed; $this->checkExplicitMixed = $checkExplicitMixed; $this->analyse([__DIR__ . '/data/mixed-cast.php'], $errors); diff --git a/tests/PHPStan/Rules/Classes/ExistingClassInInstanceOfRuleTest.php b/tests/PHPStan/Rules/Classes/ExistingClassInInstanceOfRuleTest.php index 4018d2ca62..0e6d0b066f 100644 --- a/tests/PHPStan/Rules/Classes/ExistingClassInInstanceOfRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ExistingClassInInstanceOfRuleTest.php @@ -7,6 +7,7 @@ use PHPStan\Rules\ClassNameCheck; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -67,6 +68,10 @@ public function testClassExists(): void public function testBug7720(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/bug-7720.php'], [ [ 'Instanceof between mixed and trait Bug7720\FooBar will always evaluate to false.', diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index 88d9315d84..38d61a57dd 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -46,6 +46,10 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool public function testImpossibleCheckTypeFunctionCall(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse( @@ -274,6 +278,10 @@ public function testBug7898(): void public function testImpossibleCheckTypeFunctionCallWithoutAlwaysTrue(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkAlwaysTrueCheckTypeFunctionCall = false; $this->treatPhpDocTypesAsCertain = true; $this->analyse( @@ -610,6 +618,10 @@ public function testBug7079(): void public function testConditionalTypesInference(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/conditional-types-inference.php'], [ @@ -645,6 +657,10 @@ public function testBug6697(): void public function testBug6443(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-6443.php'], []); diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php index 7a697e6ffa..6504b21a6a 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php @@ -4,6 +4,7 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -199,6 +200,10 @@ public function testReportPhpDoc(): void public function testBug8169(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-8169.php'], [ [ diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index d49987e3c5..174f8ece4a 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -1417,6 +1417,10 @@ public function testBug2508(): void public function testBug6175(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/bug-6175.php'], []); } @@ -1600,6 +1604,10 @@ public function testBug9580(): void public function testBug7283(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/bug-7283.php'], []); } @@ -1670,6 +1678,10 @@ public function testParamClosureThis(): void public function testBug10297(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/bug-10297.php'], []); } diff --git a/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php b/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php index e670804dcd..a409df4391 100644 --- a/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php @@ -243,6 +243,10 @@ public function dataRequiredParameterAfterOptional(): array */ public function testRequiredParameterAfterOptional(int $phpVersionId, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->phpVersionId = $phpVersionId; $this->analyse([__DIR__ . '/data/required-parameter-after-optional-arrow.php'], $errors); } diff --git a/tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php b/tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php index 86f8725573..9b1c1c329d 100644 --- a/tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php @@ -287,6 +287,10 @@ public function dataRequiredParameterAfterOptional(): array */ public function testRequiredParameterAfterOptional(int $phpVersionId, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->phpVersionId = $phpVersionId; $this->analyse([__DIR__ . '/data/required-parameter-after-optional-closures.php'], $errors); } diff --git a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php index f16d288869..53476ec81b 100644 --- a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php @@ -257,6 +257,10 @@ public function testBug8683(): void public function testBug7984(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixed = true; $this->checkNullables = true; $this->analyse([__DIR__ . '/data/bug-7984.php'], []); diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 3f29976a12..b5565f4d40 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -1595,6 +1595,10 @@ public function dataExplicitMixed(): array */ public function testExplicitMixed(bool $checkExplicitMixed, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkThisOnly = false; $this->checkNullables = true; $this->checkUnionTypes = true; @@ -2708,6 +2712,10 @@ public function testBug1517(): void public function testBug7593(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkThisOnly = false; $this->checkNullables = true; $this->checkUnionTypes = true; @@ -3088,6 +3096,10 @@ public function testObjectShapes(): void public function testBug9951(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkThisOnly = false; $this->checkNullables = true; $this->checkUnionTypes = true; diff --git a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php index 27718dc9c7..d46969bdf3 100644 --- a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php @@ -758,6 +758,10 @@ public function dataMixed(): array */ public function testMixed(bool $checkExplicitMixed, bool $checkImplicitMixed, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkThisOnly = false; $this->checkExplicitMixed = $checkExplicitMixed; $this->checkImplicitMixed = $checkImplicitMixed; diff --git a/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php b/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php index df40cbac04..07ea2260ee 100644 --- a/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php @@ -362,6 +362,10 @@ public function dataRequiredParameterAfterOptional(): array */ public function testRequiredParameterAfterOptional(int $phpVersionId, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->phpVersionId = $phpVersionId; $this->analyse([__DIR__ . '/data/required-parameter-after-optional.php'], $errors); } @@ -459,6 +463,10 @@ public function testTrueTypehint(): void public function testConditionalReturnType(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/conditional-return-type.php'], [ [ 'Template type T of method MethodConditionalReturnType\Container::notGet() is not referenced in a parameter.', @@ -474,6 +482,10 @@ public function testBug7519(): void public function testTemplateInParamOut(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/param-out.php'], [ [ 'Template type T of method ParamOutTemplate\FooBar::uselessLocalTemplate() is not referenced in a parameter.', diff --git a/tests/PHPStan/Rules/Methods/IncompatibleDefaultParameterTypeRuleTest.php b/tests/PHPStan/Rules/Methods/IncompatibleDefaultParameterTypeRuleTest.php index e55eb6eede..0f6d5b81f1 100644 --- a/tests/PHPStan/Rules/Methods/IncompatibleDefaultParameterTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/IncompatibleDefaultParameterTypeRuleTest.php @@ -4,6 +4,7 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -75,6 +76,10 @@ public function testDefaultValueForPromotedProperty(): void public function testBug10956(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/bug-10956.php'], []); } diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index 826586689a..75f9465e74 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -238,6 +238,10 @@ public function testParameterContravariance( array $expectedErrors, ): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->phpVersionId = $phpVersion; $this->analyse([$file], $expectedErrors); } diff --git a/tests/PHPStan/Rules/Missing/MissingReturnRuleTest.php b/tests/PHPStan/Rules/Missing/MissingReturnRuleTest.php index ad9fc94be5..533ad774eb 100644 --- a/tests/PHPStan/Rules/Missing/MissingReturnRuleTest.php +++ b/tests/PHPStan/Rules/Missing/MissingReturnRuleTest.php @@ -265,6 +265,10 @@ public function dataCheckPhpDocMissingReturn(): array */ public function testCheckPhpDocMissingReturn(bool $checkPhpDocMissingReturn, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixedMissingReturn = true; $this->checkPhpDocMissingReturn = $checkPhpDocMissingReturn; $this->analyse([__DIR__ . '/data/check-phpdoc-missing-return.php'], $errors); @@ -287,6 +291,10 @@ public function dataModelMixin(): array */ public function testModelMixin(bool $checkExplicitMixedMissingReturn): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixedMissingReturn = $checkExplicitMixedMissingReturn; $this->checkPhpDocMissingReturn = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/model-mixin.php'], [ diff --git a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php index 41c947e937..190b83798b 100644 --- a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php @@ -306,6 +306,10 @@ public function testBug5309(): void public function testBinaryMixed(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixed = true; $this->checkImplicitMixed = true; $this->analyse([__DIR__ . '/data/invalid-binary-mixed.php'], [ diff --git a/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php index 5042bb336c..a70d03a6e7 100644 --- a/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php @@ -5,6 +5,7 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -69,6 +70,10 @@ public function testRule(): void public function testMixed(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixed = true; $this->checkImplicitMixed = true; $this->analyse([__DIR__ . '/data/invalid-inc-dec-mixed.php'], [ diff --git a/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php index 2475fa3a80..ddc41ed337 100644 --- a/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php @@ -5,6 +5,7 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -96,6 +97,10 @@ public function testRule(): void public function testMixed(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkImplicitMixed = true; $this->checkExplicitMixed = true; $this->analyse([__DIR__ . '/data/invalid-unary-mixed.php'], [ From e0ee68d5cf0b6d3b3d66eff598a12dd67e93b02d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 15:01:24 +0200 Subject: [PATCH 046/508] Fix lint --- build/composer-dependency-analyser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/composer-dependency-analyser.php b/build/composer-dependency-analyser.php index 723a3ece2e..7502680e13 100644 --- a/build/composer-dependency-analyser.php +++ b/build/composer-dependency-analyser.php @@ -33,7 +33,7 @@ ) ->ignoreErrorsOnPackage('phpunit/phpunit', [ErrorType::DEV_DEPENDENCY_IN_PROD]) // prepared test tooling ->ignoreErrorsOnPackage('jetbrains/phpstorm-stubs', [ErrorType::PROD_DEPENDENCY_ONLY_IN_DEV]) // there is no direct usage, but we need newer version then required by ondrejmirtes/BetterReflection - ->ignoreErrorsOnPath(__DIR__ . '/../tests', [ErrorType::UNKNOWN_CLASS, ErrorType::UNKNOWN_FUNCTION]) // to be able to test invalid symbols + ->ignoreErrorsOnPath(__DIR__ . '/../tests', [ErrorType::UNKNOWN_CLASS, ErrorType::UNKNOWN_FUNCTION, ErrorType::SHADOW_DEPENDENCY]) // to be able to test invalid symbols ->ignoreUnknownClasses([ 'JetBrains\PhpStorm\Pure', // not present on composer's classmap 'PHPStan\ExtensionInstaller\GeneratedConfig', // generated From 8b43cfaace4371163aca9d21295e68d065fbfaea Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 15:08:50 +0200 Subject: [PATCH 047/508] Skip more `mixed` tests --- .../Analyser/AnalyserIntegrationTest.php | 12 +++++++ .../Analyser/NodeScopeResolverTest.php | 5 ++- tests/PHPStan/Analyser/nsrt/bug-10131.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-7607.php | 4 ++- tests/PHPStan/Analyser/nsrt/bug-7685.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-9105.php | 2 +- .../Analyser/nsrt/falsey-isset-certainty.php | 2 +- .../nsrt/falsey-ternary-certainty.php | 2 +- .../PHPStan/Analyser/nsrt/in_array_loose.php | 2 +- .../ImpossibleCheckTypeMethodCallRuleTest.php | 6 ++-- .../Rules/Comparison/data/bug-8169.php | 4 ++- .../ExistingClassesInTypehintsRuleTest.php | 12 +++++++ .../ExistingClassesInTypehintsRuleTest.php | 35 +++++++++++++++++++ .../Rules/Methods/ReturnTypeRuleTest.php | 31 ++++++++++++++++ .../data/method-misleading-mixed-return.php | 21 +++++++++++ .../Rules/Methods/data/returnTypes.php | 4 +-- .../NullsafePropertyFetchRuleTest.php | 4 +++ 17 files changed, 136 insertions(+), 14 deletions(-) create mode 100644 tests/PHPStan/Rules/Methods/data/method-misleading-mixed-return.php diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index b84ff5feb0..e3a3997bf3 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -827,6 +827,10 @@ public function testBug7094(): void public function testOffsetAccess(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $errors = $this->runAnalyse(__DIR__ . '/nsrt/offset-access.php'); $this->assertCount(1, $errors); $this->assertSame('PHPDoc tag @return contains unresolvable type.', $errors[0]->getMessage()); @@ -1063,6 +1067,10 @@ public function testBug8376(): void public function testAssertDocblock(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $errors = $this->runAnalyse(__DIR__ . '/nsrt/assert-docblock.php'); $this->assertCount(4, $errors); $this->assertSame('Call to method AssertDocblock\A::testInt() with string will always evaluate to false.', $errors[0]->getMessage()); @@ -1396,6 +1404,10 @@ public function testBug11147(): void public function testBug11283(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $errors = $this->runAnalyse(__DIR__ . '/data/bug-11283.php'); $this->assertNoErrors($errors); } diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index ec6abc47e7..56017066d1 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -152,7 +152,10 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Properties/data/bug-7839.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Classes/data/bug-5333.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/bug-8174.php'); - yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-8169.php'); + + if (PHP_VERSION_ID >= 80000) { + yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-8169.php'); + } yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Functions/data/bug-8280.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-8277.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Variables/data/bug-8113.php'); diff --git a/tests/PHPStan/Analyser/nsrt/bug-10131.php b/tests/PHPStan/Analyser/nsrt/bug-10131.php index d78066e232..11088d2e44 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-10131.php +++ b/tests/PHPStan/Analyser/nsrt/bug-10131.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug10131; diff --git a/tests/PHPStan/Analyser/nsrt/bug-7607.php b/tests/PHPStan/Analyser/nsrt/bug-7607.php index b88d6e5c02..e8d6aa5911 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7607.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7607.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types = 1); namespace Bug7607; diff --git a/tests/PHPStan/Analyser/nsrt/bug-7685.php b/tests/PHPStan/Analyser/nsrt/bug-7685.php index 580ad7f33f..e5674250b4 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7685.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7685.php @@ -1,4 +1,4 @@ -= 8.0 namespace bug7685; diff --git a/tests/PHPStan/Analyser/nsrt/bug-9105.php b/tests/PHPStan/Analyser/nsrt/bug-9105.php index 956d53f055..296baba23d 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9105.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9105.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug9105; diff --git a/tests/PHPStan/Analyser/nsrt/falsey-isset-certainty.php b/tests/PHPStan/Analyser/nsrt/falsey-isset-certainty.php index 1fbb9547ac..484d0363e3 100644 --- a/tests/PHPStan/Analyser/nsrt/falsey-isset-certainty.php +++ b/tests/PHPStan/Analyser/nsrt/falsey-isset-certainty.php @@ -1,4 +1,4 @@ -= 8.0 namespace FalseyIssetCertainty; diff --git a/tests/PHPStan/Analyser/nsrt/falsey-ternary-certainty.php b/tests/PHPStan/Analyser/nsrt/falsey-ternary-certainty.php index 01045e25f9..cc831b87a4 100644 --- a/tests/PHPStan/Analyser/nsrt/falsey-ternary-certainty.php +++ b/tests/PHPStan/Analyser/nsrt/falsey-ternary-certainty.php @@ -1,4 +1,4 @@ -= 8.0 namespace FalseyTernaryCertainty; diff --git a/tests/PHPStan/Analyser/nsrt/in_array_loose.php b/tests/PHPStan/Analyser/nsrt/in_array_loose.php index 4600ae0a13..78d2899b8c 100644 --- a/tests/PHPStan/Analyser/nsrt/in_array_loose.php +++ b/tests/PHPStan/Analyser/nsrt/in_array_loose.php @@ -1,4 +1,4 @@ -= 8.0 namespace InArrayLoose; diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php index 6504b21a6a..29f63a6bf2 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php @@ -208,15 +208,15 @@ public function testBug8169(): void $this->analyse([__DIR__ . '/data/bug-8169.php'], [ [ 'Call to method Bug8169\HelloWorld::assertString() with string will always evaluate to true.', - 19, + 21, ], [ 'Call to method Bug8169\HelloWorld::assertString() with string will always evaluate to true.', - 26, + 28, ], [ 'Call to method Bug8169\HelloWorld::assertString() with int will always evaluate to false.', - 33, + 35, ], ]); } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-8169.php b/tests/PHPStan/Rules/Comparison/data/bug-8169.php index a6c4d33025..e3ee4aa5a5 100644 --- a/tests/PHPStan/Rules/Comparison/data/bug-8169.php +++ b/tests/PHPStan/Rules/Comparison/data/bug-8169.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types = 1); namespace Bug8169; diff --git a/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php b/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php index 056740ed99..06957666f5 100644 --- a/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php @@ -368,6 +368,10 @@ public function dataRequiredParameterAfterOptional(): array */ public function testRequiredParameterAfterOptional(int $phpVersionId, array $errors): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->phpVersionId = $phpVersionId; $this->analyse([__DIR__ . '/data/required-parameter-after-optional.php'], $errors); } @@ -439,6 +443,10 @@ public function testTrueTypehint(): void public function testConditionalReturnType(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/conditional-return-type.php'], [ [ 'Template type T of function FunctionConditionalReturnType\notGet() is not referenced in a parameter.', @@ -449,6 +457,10 @@ public function testConditionalReturnType(): void public function testTemplateInParamOut(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/param-out.php'], [ [ 'Template type S of function ParamOutTemplate\uselessGeneric() is not referenced in a parameter.', diff --git a/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php b/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php index 07ea2260ee..8c9fc563e3 100644 --- a/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php @@ -437,6 +437,25 @@ public function testTrueTypehint(): void { if (PHP_VERSION_ID >= 80200) { $errors = []; + } elseif (PHP_VERSION_ID >= 80000) { + $errors = [ + [ + 'Parameter $v of method NativeTrueType\Truthy::foo() has invalid type NativeTrueType\true.', + 10, + ], + [ + 'Method NativeTrueType\Truthy::foo() has invalid return type NativeTrueType\true.', + 10, + ], + [ + 'Parameter $trueUnion of method NativeTrueType\Truthy::trueUnion() has invalid type NativeTrueType\true.', + 14, + ], + [ + 'Method NativeTrueType\Truthy::trueUnionReturn() has invalid return type NativeTrueType\true.', + 31, + ], + ]; } else { $errors = [ [ @@ -447,14 +466,30 @@ public function testTrueTypehint(): void 'Method NativeTrueType\Truthy::foo() has invalid return type NativeTrueType\true.', 10, ], + [ + "Method NativeTrueType\Truthy::trueUnion() uses native union types but they're supported only on PHP 8.0 and later.", + 14, + ], [ 'Parameter $trueUnion of method NativeTrueType\Truthy::trueUnion() has invalid type NativeTrueType\true.', 14, ], + [ + 'Parameter $trueUnion of method NativeTrueType\Truthy::trueUnion() has invalid type NativeTrueType\null.', + 14, + ], + [ + "Method NativeTrueType\Truthy::trueUnionReturn() uses native union types but they're supported only on PHP 8.0 and later.", + 31, + ], [ 'Method NativeTrueType\Truthy::trueUnionReturn() has invalid return type NativeTrueType\true.', 31, ], + [ + 'Method NativeTrueType\Truthy::trueUnionReturn() has invalid return type NativeTrueType\null.', + 31, + ], ]; } diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index 6303bdcdc4..f080bd4be8 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -283,8 +283,31 @@ public function testReturnTypeRule(): void ]); } + public function testMisleadingMixedType(): void + { + if (PHP_VERSION_ID >= 80000) { + $errors = []; + } else { + $errors = [ + [ + 'Method MethodMisleadingMixedReturn\Foo::misleadingMixedReturnType() should return MethodMisleadingMixedReturn\mixed but returns int.', + 11, + ], + [ + 'Method MethodMisleadingMixedReturn\Foo::misleadingMixedReturnType() should return MethodMisleadingMixedReturn\mixed but returns true.', + 14, + ], + ]; + } + $this->analyse([__DIR__ . '/data/method-misleading-mixed-return.php'], $errors); + } + public function testMisleadingTypehintsInClassWithoutNamespace(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/misleadingTypehints.php'], [ [ 'Method FooWithoutNamespace::misleadingBoolReturnType() should return boolean but returns true.', @@ -522,6 +545,10 @@ public function testBug2573(): void public function testBug4603(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/bug-4603.php'], []); } @@ -774,6 +801,10 @@ public function testBug6358(): void public function testBug8071(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->checkExplicitMixed = true; $this->analyse([__DIR__ . '/data/bug-8071.php'], [ [ diff --git a/tests/PHPStan/Rules/Methods/data/method-misleading-mixed-return.php b/tests/PHPStan/Rules/Methods/data/method-misleading-mixed-return.php new file mode 100644 index 0000000000..e7c1b2141a --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/method-misleading-mixed-return.php @@ -0,0 +1,21 @@ +analyse([__DIR__ . '/../../Analyser/nsrt/bug-9105.php'], []); } From f9af7116d067e64697de231eb7aa155323581c78 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 15:21:19 +0200 Subject: [PATCH 048/508] Compile and commit PHAR on 2.0.x --- .github/workflows/checksum-phar.yml | 2 +- .github/workflows/phar.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/checksum-phar.yml b/.github/workflows/checksum-phar.yml index 994f11ba06..b5dc04f6dc 100644 --- a/.github/workflows/checksum-phar.yml +++ b/.github/workflows/checksum-phar.yml @@ -37,7 +37,7 @@ jobs: with: repository: phpstan/phpstan path: phpstan-dist - ref: 1.12.x + ref: 2.0.x - name: "Get info" id: info diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index f2f75906b3..c6534ecd7b 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -130,7 +130,7 @@ jobs: commit: name: "Commit PHAR" - if: "github.repository_owner == 'phpstan' && (github.ref == 'refs/heads/1.12.x' || startsWith(github.ref, 'refs/tags/'))" + if: "github.repository_owner == 'phpstan' && (github.ref == 'refs/heads/2.0.x' || startsWith(github.ref, 'refs/tags/'))" needs: compiler-tests runs-on: "ubuntu-latest" timeout-minutes: 60 From 154d6723cc626e74f9736fa0aaca3b34a1ad6cfc Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 15:36:01 +0200 Subject: [PATCH 049/508] Fix apiref.yml --- .github/workflows/apiref.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/apiref.yml b/.github/workflows/apiref.yml index 9375c12fc2..32c7417841 100644 --- a/.github/workflows/apiref.yml +++ b/.github/workflows/apiref.yml @@ -13,6 +13,9 @@ on: - 'apigen/**' - '.github/workflows/apiref.yml' +env: + COMPOSER_ROOT_VERSION: "1.12.x-dev" + concurrency: group: apigen-${{ github.ref }} # will be canceled on subsequent pushes in branch cancel-in-progress: true From a6be9826f0e1d6e4b38f4db9d0cad0264d311d69 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 16:07:13 +0200 Subject: [PATCH 050/508] Get rid of JetBrains PhpStorm attributes in nette/utils Because the PHP-Scoper collapses the code to a single line, it breaks the signature on PHP < 8.0 because it "comments" the rest of the line --- compiler/build/scoper.inc.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/build/scoper.inc.php b/compiler/build/scoper.inc.php index 0ea6df31ec..5b4a21c5b2 100644 --- a/compiler/build/scoper.inc.php +++ b/compiler/build/scoper.inc.php @@ -218,6 +218,16 @@ function (string $filePath, string $prefix, string $content): string { return str_replace(sprintf('use %s\\PhpParser;', $prefix), 'use PhpParser;', $content); }, + function (string $filePath, string $prefix, string $content): string { + if ( + $filePath !== 'vendor/nette/utils/src/Utils/Strings.php' + && $filePath !== 'vendor/nette/utils/src/Utils/Arrays.php' + ) { + return $content; + } + + return str_replace('#[\\JetBrains\\PhpStorm\\Language(\'RegExp\')] ', '', $content); + }, ], 'exclude-namespaces' => [ 'PHPStan', From cbdc65275fa8f9372eebe460b9b67c661923cfef Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 16:08:45 +0200 Subject: [PATCH 051/508] Get rid of old E2E test --- .github/workflows/e2e-tests.yml | 30 - tests/e2e/ResultCacheEndToEndTest.php | 208 --- tests/e2e/baseline.neon | 172 -- tests/e2e/phpstan.neon | 7 - tests/e2e/phpstan_resultcachepath.neon | 7 - tests/e2e/resultCache_1.php | 2019 ----------------------- tests/e2e/resultCache_2.php | 2023 ------------------------ tests/e2e/resultCache_3.php | 2016 ----------------------- 8 files changed, 6482 deletions(-) delete mode 100644 tests/e2e/ResultCacheEndToEndTest.php delete mode 100644 tests/e2e/baseline.neon delete mode 100644 tests/e2e/phpstan.neon delete mode 100644 tests/e2e/phpstan_resultcachepath.neon delete mode 100644 tests/e2e/resultCache_1.php delete mode 100644 tests/e2e/resultCache_2.php delete mode 100644 tests/e2e/resultCache_3.php diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 239a5e3781..dd8a44e406 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -26,36 +26,6 @@ concurrency: cancel-in-progress: true jobs: - result-cache-php-parser-e2e: - name: "Result cache PHP-Parser E2E test" - - runs-on: ${{ matrix.operating-system }} - timeout-minutes: 60 - - strategy: - fail-fast: false - matrix: - operating-system: [ubuntu-latest, windows-latest] - - steps: - - name: "Checkout" - uses: actions/checkout@v4 - - - name: "Install PHP" - uses: "shivammathur/setup-php@v2" - with: - coverage: "none" - php-version: "8.1" - extensions: mbstring - ini-values: memory_limit=256M - - - name: "Install dependencies" - run: "composer install --no-interaction --no-progress" - - - name: "Tests" - run: | - git clone https://github.com/nikic/PHP-Parser.git tests/e2e/PHP-Parser && git -C tests/e2e/PHP-Parser checkout v3.1.5 && composer install --working-dir tests/e2e/PHP-Parser && vendor/bin/phpunit tests/e2e/ResultCacheEndToEndTest.php - result-cache-e2e-tests: name: "Result cache E2E tests" runs-on: ubuntu-latest diff --git a/tests/e2e/ResultCacheEndToEndTest.php b/tests/e2e/ResultCacheEndToEndTest.php deleted file mode 100644 index 1117af27b0..0000000000 --- a/tests/e2e/ResultCacheEndToEndTest.php +++ /dev/null @@ -1,208 +0,0 @@ -&1', escapeshellarg(__DIR__ . '/PHP-Parser')), $outputLines, $exitCode); - if ($exitCode === 0) { - return; - } - - $this->fail(implode("\n", $outputLines)); - } - - public function testResultCache(): void - { - $this->runPhpstan(0); - $this->assertResultCache(__DIR__ . '/resultCache_1.php'); - - $this->runPhpstan(0); - $this->assertResultCache(__DIR__ . '/resultCache_1.php'); - - $lexerPath = __DIR__ . '/PHP-Parser/lib/PhpParser/Lexer.php'; - $lexerCode = FileReader::read($lexerPath); - $originalLexerCode = $lexerCode; - - $lexerCode = str_replace('@param string $code', '', $lexerCode); - $lexerCode = str_replace('public function startLexing($code', 'public function startLexing(\\PhpParser\\Node\\Expr\\MethodCall $code', $lexerCode); - file_put_contents($lexerPath, $lexerCode); - - $errorHandlerPath = __DIR__ . '/PHP-Parser/lib/PhpParser/ErrorHandler.php'; - $errorHandlerContents = FileReader::read($errorHandlerPath); - $errorHandlerContents .= "\n\n"; - file_put_contents($errorHandlerPath, $errorHandlerContents); - - $bootstrapPath = __DIR__ . '/PHP-Parser/lib/bootstrap.php'; - $originalBootstrapContents = FileReader::read($bootstrapPath); - file_put_contents($bootstrapPath, "\n\n echo ['foo'];", FILE_APPEND); - - $this->runPhpstanWithErrors(); - $this->runPhpstanWithErrors(); - - file_put_contents($lexerPath, $originalLexerCode); - - unlink($bootstrapPath); - $this->runPhpstan(0); - $this->assertResultCache(__DIR__ . '/resultCache_3.php'); - - file_put_contents($bootstrapPath, $originalBootstrapContents); - $this->runPhpstan(0); - $this->assertResultCache(__DIR__ . '/resultCache_1.php'); - } - - private function runPhpstanWithErrors(): void - { - $result = $this->runPhpstan(1); - $this->assertIsArray($result['totals']); - $this->assertSame(3, $result['totals']['file_errors']); - $this->assertSame(0, $result['totals']['errors']); - - $fileHelper = new FileHelper(__DIR__); - - $this->assertSame('Parameter #1 $code of function token_get_all expects string, PhpParser\Node\Expr\MethodCall given.', $result['files'][$fileHelper->normalizePath(__DIR__ . '/PHP-Parser/lib/PhpParser/Lexer.php')]['messages'][0]['message']); - $this->assertSame('Parameter #1 $code of method PhpParser\Lexer::startLexing() expects PhpParser\Node\Expr\MethodCall, string given.', $result['files'][$fileHelper->normalizePath(__DIR__ . '/PHP-Parser/lib/PhpParser/ParserAbstract.php')]['messages'][0]['message']); - $this->assertSame('Parameter #1 (array{\'foo\'}) of echo cannot be converted to string.', $result['files'][$fileHelper->normalizePath(__DIR__ . '/PHP-Parser/lib/bootstrap.php')]['messages'][0]['message']); - $this->assertResultCache(__DIR__ . '/resultCache_2.php'); - } - - public function testResultCacheDeleteFile(): void - { - $this->runPhpstan(0); - $this->assertResultCache(__DIR__ . '/resultCache_1.php'); - - $serializerPath = __DIR__ . '/PHP-Parser/lib/PhpParser/Serializer.php'; - $serializerCode = FileReader::read($serializerPath); - $originalSerializerCode = $serializerCode; - unlink($serializerPath); - - $fileHelper = new FileHelper(__DIR__); - - $result = $this->runPhpstan(1); - $this->assertIsArray($result['totals']); - $this->assertSame(1, $result['totals']['file_errors'], Json::encode($result)); - $this->assertSame(0, $result['totals']['errors'], Json::encode($result)); - - $message = $result['files'][$fileHelper->normalizePath(__DIR__ . '/PHP-Parser/lib/PhpParser/Serializer/XML.php')]['messages'][0]['message']; - $this->assertSame('Class PhpParser\\Serializer\\XML implements unknown interface PhpParser\\Serializer.', $message); - - file_put_contents($serializerPath, $originalSerializerCode); - $this->runPhpstan(0); - $this->assertResultCache(__DIR__ . '/resultCache_1.php'); - } - - public function testResultCachePath(): void - { - $this->runPhpstan(0, __DIR__ . '/phpstan_resultcachepath.neon'); - - $this->assertFileExists(sys_get_temp_dir() . '/phpstan/myResultCacheFile.php'); - $this->assertResultCache(__DIR__ . '/resultCache_1.php', sys_get_temp_dir() . '/phpstan/myResultCacheFile.php'); - } - - /** - * @return mixed[] - */ - private function runPhpstan(int $expectedExitCode, string $phpstanConfigPath = __DIR__ . '/phpstan.neon'): array - { - exec(sprintf( - '%s %s analyse -c %s -l 5 --no-progress --error-format json lib 2>&1', - escapeshellarg(PHP_BINARY), - escapeshellarg(__DIR__ . '/../../bin/phpstan'), - escapeshellarg($phpstanConfigPath), - ), $outputLines, $exitCode); - $output = implode("\n", $outputLines); - - try { - $json = Json::decode($output, Json::FORCE_ARRAY); - $this->assertIsArray($json); - } catch (JsonException $e) { - $this->fail(sprintf('%s: %s', $e->getMessage(), $output)); - } - - if ($exitCode !== $expectedExitCode) { - $this->fail($output); - } - - return $json; - } - - /** - * @param mixed[] $resultCache - * @return array> - */ - private function transformResultCache(array $resultCache): array - { - $new = []; - $this->assertIsArray($resultCache['dependencies']); - foreach ($resultCache['dependencies'] as $file => $data) { - $this->assertIsString($file); - $this->assertIsArray($data); - $this->assertIsArray($data['dependentFiles']); - - $files = []; - foreach ($data['dependentFiles'] as $filePath) { - $this->assertIsString($filePath); - $files[] = $this->relativizePath($filePath); - } - sort($files); - $new[$this->relativizePath($file)] = $files; - } - - ksort($new); - - return $new; - } - - private function relativizePath(string $path): string - { - $path = str_replace('\\', '/', $path); - $helper = new SimpleRelativePathHelper(str_replace('\\', '/', __DIR__ . '/PHP-Parser')); - return $helper->getRelativePath($path); - } - - private function assertResultCache(string $expectedCachePath, string $actualCachePath = __DIR__ . '/tmp/resultCache.php'): void - { - $resultCache = $this->transformResultCache(require $actualCachePath); - $expectedResultCachePath = require $expectedCachePath; - $this->assertSame($expectedResultCachePath, $resultCache); - } - -} diff --git a/tests/e2e/baseline.neon b/tests/e2e/baseline.neon deleted file mode 100644 index aad958b3b5..0000000000 --- a/tests/e2e/baseline.neon +++ /dev/null @@ -1,172 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^PHPDoc tag @param references unknown parameter\\: \\$interfaces$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Builder/Class_.php - - - - message: "#^Access to an undefined property PhpParser\\\\Node\\:\\:\\$stmts\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Builder/Interface_.php - - - - message: "#^PHPDoc tag @param references unknown parameter\\: \\$interfaces$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Builder/Interface_.php - - - - message: "#^Access to an undefined property PhpParser\\\\BuilderAbstract\\:\\:\\$flags\\.$#" - count: 2 - path: PHP-Parser/lib/PhpParser/BuilderAbstract.php - - - - message: "#^Method PhpParser\\\\BuilderAbstract\\:\\:normalizeValue\\(\\) should return PhpParser\\\\Node\\\\Expr but returns PhpParser\\\\Node\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/BuilderAbstract.php - - - - message: "#^PHPDoc tag @param has invalid value \\(string\\|Node\\\\Name Name to alias\\)\\: Unexpected token \"Name\", expected variable at offset 88$#" - count: 1 - path: PHP-Parser/lib/PhpParser/BuilderFactory.php - - - - message: "#^Expression \"@\\$undefinedVariable\" on a separate line does not do anything\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Lexer.php - - - - message: "#^Undefined variable\\: \\$undefinedVariable$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Lexer.php - - - - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Lexer.php - - - - message: "#^Empty array passed to foreach\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Lexer/Emulative.php - - - - message: "#^Method PhpParser\\\\Node\\\\Expr\\\\Closure\\:\\:getStmts\\(\\) should return array\\ but returns array\\\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Node/Expr/Closure.php - - - - message: "#^Unsafe usage of new static\\(\\)\\.$#" - count: 4 - path: PHP-Parser/lib/PhpParser/Node/Name.php - - - - message: "#^Method PhpParser\\\\Node\\\\Stmt\\\\ClassMethod\\:\\:getStmts\\(\\) should return array\\ but returns array\\\\|null\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Node/Stmt/ClassMethod.php - - - - message: "#^Method PhpParser\\\\Node\\\\Stmt\\\\Function_\\:\\:getStmts\\(\\) should return array\\ but returns array\\\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Node/Stmt/Function_.php - - - - message: "#^PHPDoc tag @param for parameter \\$attributes with type array\\|null is not subtype of native type array\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Node/Stmt/TryCatch.php - - - - message: "#^Access to an undefined property PhpParser\\\\Node\\:\\:\\$name\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/NodeVisitor/NameResolver.php - - - - message: "#^Access to an undefined property PhpParser\\\\Node\\:\\:\\$namespacedName\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/NodeVisitor/NameResolver.php - - - - message: "#^Method PhpParser\\\\NodeVisitor\\\\NameResolver\\:\\:beforeTraverse\\(\\) should return array\\\\|null but return statement is missing\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/NodeVisitor/NameResolver.php - - - - message: "#^Method PhpParser\\\\NodeVisitor\\\\NameResolver\\:\\:enterNode\\(\\) should return int\\|PhpParser\\\\Node\\|null but return statement is missing\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/NodeVisitor/NameResolver.php - - - - message: "#^Method PhpParser\\\\NodeVisitorAbstract\\:\\:afterTraverse\\(\\) should return array\\\\|null but return statement is missing\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/NodeVisitorAbstract.php - - - - message: "#^Method PhpParser\\\\NodeVisitorAbstract\\:\\:beforeTraverse\\(\\) should return array\\\\|null but return statement is missing\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/NodeVisitorAbstract.php - - - - message: "#^Method PhpParser\\\\NodeVisitorAbstract\\:\\:enterNode\\(\\) should return int\\|PhpParser\\\\Node\\|null but return statement is missing\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/NodeVisitorAbstract.php - - - - message: "#^Method PhpParser\\\\NodeVisitorAbstract\\:\\:leaveNode\\(\\) should return array\\\\|int\\|PhpParser\\\\Node\\|false\\|null but return statement is missing\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/NodeVisitorAbstract.php - - - - message: "#^Access to an undefined property PhpParser\\\\Node\\\\Expr\\:\\:\\$class\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Parser/Php5.php - - - - message: "#^Access to an undefined property PhpParser\\\\Node\\\\Expr\\:\\:\\$name\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Parser/Php5.php - - - - message: "#^Variable \\$s might not be defined\\.$#" - count: 3 - path: PHP-Parser/lib/PhpParser/Parser/Php5.php - - - - message: "#^Variable \\$s might not be defined\\.$#" - count: 3 - path: PHP-Parser/lib/PhpParser/Parser/Php7.php - - - - message: "#^Comparison operation \"\\<\" between \\(array\\|float\\|int\\<0, max\\>\\) and int results in an error\\.$#" - count: 3 - path: PHP-Parser/lib/PhpParser/ParserAbstract.php - - - - message: "#^Comparison operation \"\\>\\=\" between \\(array\\|float\\|int\\) and 0 results in an error\\.$#" - count: 3 - path: PHP-Parser/lib/PhpParser/ParserAbstract.php - - - - message: "#^Property PhpParser\\\\ParserAbstract\\:\\:\\$endAttributeStack \\(array\\\\) does not accept array\\\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/ParserAbstract.php - - - - message: "#^Property PhpParser\\\\ParserAbstract\\:\\:\\$endAttributes \\(array\\) does not accept string\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/ParserAbstract.php - - - - message: "#^Variable \\$action might not be defined\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/ParserAbstract.php - - - - message: "#^Variable \\$tokenValue might not be defined\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/ParserAbstract.php - - - - message: "#^Argument of an invalid type PhpParser\\\\Node supplied for foreach, only iterables are supported\\.$#" - count: 1 - path: PHP-Parser/lib/PhpParser/Serializer/XML.php - diff --git a/tests/e2e/phpstan.neon b/tests/e2e/phpstan.neon deleted file mode 100644 index b9fe1cd9c1..0000000000 --- a/tests/e2e/phpstan.neon +++ /dev/null @@ -1,7 +0,0 @@ -includes: - - baseline.neon - -parameters: - phpVersion: 80000 - tmpDir: tmp - treatPhpDocTypesAsCertain: false diff --git a/tests/e2e/phpstan_resultcachepath.neon b/tests/e2e/phpstan_resultcachepath.neon deleted file mode 100644 index 3ad1d1a3b1..0000000000 --- a/tests/e2e/phpstan_resultcachepath.neon +++ /dev/null @@ -1,7 +0,0 @@ -includes: - - baseline.neon - -parameters: - phpVersion: 80000 - resultCachePath: %tmpDir%/myResultCacheFile.php - treatPhpDocTypesAsCertain: false diff --git a/tests/e2e/resultCache_1.php b/tests/e2e/resultCache_1.php deleted file mode 100644 index fd17dda8f2..0000000000 --- a/tests/e2e/resultCache_1.php +++ /dev/null @@ -1,2019 +0,0 @@ - - array ( - 0 => 'lib/bootstrap.php', - ), - 'lib/PhpParser/Builder.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Declaration.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderAbstract.php', - 12 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Class_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Declaration.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Trait_.php', - 7 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/FunctionLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Function_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Interface_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Method.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Param.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Property.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Trait_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Use_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/BuilderAbstract.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Declaration.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/BuilderFactory.php' => - array ( - ), - 'lib/PhpParser/Comment.php' => - array ( - 0 => 'lib/PhpParser/Builder/Declaration.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Comment/Doc.php', - 4 => 'lib/PhpParser/Lexer.php', - 5 => 'lib/PhpParser/Node.php', - 6 => 'lib/PhpParser/NodeAbstract.php', - 7 => 'lib/PhpParser/NodeDumper.php', - 8 => 'lib/PhpParser/PrettyPrinterAbstract.php', - 9 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Comment/Doc.php' => - array ( - 0 => 'lib/PhpParser/Builder/Declaration.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Comment.php', - 4 => 'lib/PhpParser/Lexer.php', - 5 => 'lib/PhpParser/Node.php', - 6 => 'lib/PhpParser/NodeAbstract.php', - 7 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Error.php' => - array ( - 0 => 'lib/PhpParser/ErrorHandler.php', - 1 => 'lib/PhpParser/ErrorHandler/Collecting.php', - 2 => 'lib/PhpParser/ErrorHandler/Throwing.php', - 3 => 'lib/PhpParser/Lexer.php', - 4 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 5 => 'lib/PhpParser/Node/Scalar/String_.php', - 6 => 'lib/PhpParser/Node/Stmt/Class_.php', - 7 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 8 => 'lib/PhpParser/Parser/Multiple.php', - 9 => 'lib/PhpParser/Parser/Php5.php', - 10 => 'lib/PhpParser/Parser/Php7.php', - 11 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/ErrorHandler.php' => - array ( - 0 => 'lib/PhpParser/ErrorHandler/Collecting.php', - 1 => 'lib/PhpParser/ErrorHandler/Throwing.php', - 2 => 'lib/PhpParser/Lexer.php', - 3 => 'lib/PhpParser/Lexer/Emulative.php', - 4 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 5 => 'lib/PhpParser/Parser.php', - 6 => 'lib/PhpParser/Parser/Multiple.php', - 7 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/ErrorHandler/Collecting.php' => - array ( - ), - 'lib/PhpParser/ErrorHandler/Throwing.php' => - array ( - 0 => 'lib/PhpParser/Lexer.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Multiple.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/Lexer.php' => - array ( - 0 => 'lib/PhpParser/Lexer/Emulative.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Lexer/Emulative.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Node.php' => - array ( - 0 => 'lib/PhpParser/Builder.php', - 1 => 'lib/PhpParser/Builder/Class_.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderAbstract.php', - 12 => 'lib/PhpParser/BuilderFactory.php', - 13 => 'lib/PhpParser/Node/Arg.php', - 14 => 'lib/PhpParser/Node/Const_.php', - 15 => 'lib/PhpParser/Node/Expr.php', - 16 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 17 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 18 => 'lib/PhpParser/Node/Expr/Array_.php', - 19 => 'lib/PhpParser/Node/Expr/Assign.php', - 20 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 22 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 23 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 24 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 25 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 26 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 27 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 28 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 29 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 30 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 31 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 32 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 33 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 34 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 51 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 52 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 53 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 54 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 55 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 56 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 57 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 58 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 59 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 60 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 61 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 62 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 63 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 64 => 'lib/PhpParser/Node/Expr/Cast.php', - 65 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 66 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 67 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 68 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 69 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 70 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 71 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 72 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 73 => 'lib/PhpParser/Node/Expr/Clone_.php', - 74 => 'lib/PhpParser/Node/Expr/Closure.php', - 75 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 76 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 77 => 'lib/PhpParser/Node/Expr/Empty_.php', - 78 => 'lib/PhpParser/Node/Expr/Error.php', - 79 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 80 => 'lib/PhpParser/Node/Expr/Eval_.php', - 81 => 'lib/PhpParser/Node/Expr/Exit_.php', - 82 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 83 => 'lib/PhpParser/Node/Expr/Include_.php', - 84 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 85 => 'lib/PhpParser/Node/Expr/Isset_.php', - 86 => 'lib/PhpParser/Node/Expr/List_.php', - 87 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 88 => 'lib/PhpParser/Node/Expr/New_.php', - 89 => 'lib/PhpParser/Node/Expr/PostDec.php', - 90 => 'lib/PhpParser/Node/Expr/PostInc.php', - 91 => 'lib/PhpParser/Node/Expr/PreDec.php', - 92 => 'lib/PhpParser/Node/Expr/PreInc.php', - 93 => 'lib/PhpParser/Node/Expr/Print_.php', - 94 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 95 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 96 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 97 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 98 => 'lib/PhpParser/Node/Expr/Ternary.php', - 99 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 100 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 101 => 'lib/PhpParser/Node/Expr/Variable.php', - 102 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 103 => 'lib/PhpParser/Node/Expr/Yield_.php', - 104 => 'lib/PhpParser/Node/FunctionLike.php', - 105 => 'lib/PhpParser/Node/Name.php', - 106 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 107 => 'lib/PhpParser/Node/Name/Relative.php', - 108 => 'lib/PhpParser/Node/NullableType.php', - 109 => 'lib/PhpParser/Node/Param.php', - 110 => 'lib/PhpParser/Node/Scalar.php', - 111 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 112 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 113 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 114 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 115 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 116 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 117 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 118 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 119 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 120 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 121 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 122 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 123 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 124 => 'lib/PhpParser/Node/Scalar/String_.php', - 125 => 'lib/PhpParser/Node/Stmt.php', - 126 => 'lib/PhpParser/Node/Stmt/Break_.php', - 127 => 'lib/PhpParser/Node/Stmt/Case_.php', - 128 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 129 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 130 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 131 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 132 => 'lib/PhpParser/Node/Stmt/Class_.php', - 133 => 'lib/PhpParser/Node/Stmt/Const_.php', - 134 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 135 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 136 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 137 => 'lib/PhpParser/Node/Stmt/Do_.php', - 138 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 139 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 140 => 'lib/PhpParser/Node/Stmt/Else_.php', - 141 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 142 => 'lib/PhpParser/Node/Stmt/For_.php', - 143 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 144 => 'lib/PhpParser/Node/Stmt/Function_.php', - 145 => 'lib/PhpParser/Node/Stmt/Global_.php', - 146 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 147 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 148 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 149 => 'lib/PhpParser/Node/Stmt/If_.php', - 150 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 151 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 152 => 'lib/PhpParser/Node/Stmt/Label.php', - 153 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 154 => 'lib/PhpParser/Node/Stmt/Nop.php', - 155 => 'lib/PhpParser/Node/Stmt/Property.php', - 156 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 157 => 'lib/PhpParser/Node/Stmt/Return_.php', - 158 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 159 => 'lib/PhpParser/Node/Stmt/Static_.php', - 160 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 161 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 162 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 163 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 164 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 165 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 166 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 167 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 168 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 169 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 170 => 'lib/PhpParser/Node/Stmt/Use_.php', - 171 => 'lib/PhpParser/Node/Stmt/While_.php', - 172 => 'lib/PhpParser/NodeAbstract.php', - 173 => 'lib/PhpParser/NodeDumper.php', - 174 => 'lib/PhpParser/NodeTraverser.php', - 175 => 'lib/PhpParser/NodeTraverserInterface.php', - 176 => 'lib/PhpParser/NodeVisitor.php', - 177 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 178 => 'lib/PhpParser/NodeVisitorAbstract.php', - 179 => 'lib/PhpParser/Parser.php', - 180 => 'lib/PhpParser/Parser/Multiple.php', - 181 => 'lib/PhpParser/Parser/Php5.php', - 182 => 'lib/PhpParser/Parser/Php7.php', - 183 => 'lib/PhpParser/ParserAbstract.php', - 184 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 185 => 'lib/PhpParser/PrettyPrinterAbstract.php', - 186 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Node/Arg.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 1 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 2 => 'lib/PhpParser/Node/Expr/New_.php', - 3 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Const_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 1 => 'lib/PhpParser/Node/Stmt/Const_.php', - 2 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 3 => 'lib/PhpParser/Parser/Php5.php', - 4 => 'lib/PhpParser/Parser/Php7.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr.php' => - array ( - 0 => 'lib/PhpParser/Builder/Param.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Node/Arg.php', - 4 => 'lib/PhpParser/Node/Const_.php', - 5 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 6 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 7 => 'lib/PhpParser/Node/Expr/Array_.php', - 8 => 'lib/PhpParser/Node/Expr/Assign.php', - 9 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 10 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 11 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 12 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 13 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 14 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 15 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 16 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 17 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 18 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 19 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 20 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 22 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 23 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 24 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 25 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 26 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 27 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 28 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 29 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 30 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 31 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 32 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 33 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 34 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 51 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 52 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 53 => 'lib/PhpParser/Node/Expr/Cast.php', - 54 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 55 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 56 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 57 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 58 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 59 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 60 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 61 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 62 => 'lib/PhpParser/Node/Expr/Clone_.php', - 63 => 'lib/PhpParser/Node/Expr/Closure.php', - 64 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 65 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 66 => 'lib/PhpParser/Node/Expr/Empty_.php', - 67 => 'lib/PhpParser/Node/Expr/Error.php', - 68 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 69 => 'lib/PhpParser/Node/Expr/Eval_.php', - 70 => 'lib/PhpParser/Node/Expr/Exit_.php', - 71 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 72 => 'lib/PhpParser/Node/Expr/Include_.php', - 73 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 74 => 'lib/PhpParser/Node/Expr/Isset_.php', - 75 => 'lib/PhpParser/Node/Expr/List_.php', - 76 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 77 => 'lib/PhpParser/Node/Expr/New_.php', - 78 => 'lib/PhpParser/Node/Expr/PostDec.php', - 79 => 'lib/PhpParser/Node/Expr/PostInc.php', - 80 => 'lib/PhpParser/Node/Expr/PreDec.php', - 81 => 'lib/PhpParser/Node/Expr/PreInc.php', - 82 => 'lib/PhpParser/Node/Expr/Print_.php', - 83 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 84 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 85 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 86 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 87 => 'lib/PhpParser/Node/Expr/Ternary.php', - 88 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 89 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 90 => 'lib/PhpParser/Node/Expr/Variable.php', - 91 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 92 => 'lib/PhpParser/Node/Expr/Yield_.php', - 93 => 'lib/PhpParser/Node/Param.php', - 94 => 'lib/PhpParser/Node/Scalar.php', - 95 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 96 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 97 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 98 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 99 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 100 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 101 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 102 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 103 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 104 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 105 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 106 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 107 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 108 => 'lib/PhpParser/Node/Scalar/String_.php', - 109 => 'lib/PhpParser/Node/Stmt/Break_.php', - 110 => 'lib/PhpParser/Node/Stmt/Case_.php', - 111 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 112 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 113 => 'lib/PhpParser/Node/Stmt/Do_.php', - 114 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 115 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 116 => 'lib/PhpParser/Node/Stmt/For_.php', - 117 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 118 => 'lib/PhpParser/Node/Stmt/Global_.php', - 119 => 'lib/PhpParser/Node/Stmt/If_.php', - 120 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 121 => 'lib/PhpParser/Node/Stmt/Return_.php', - 122 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 123 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 124 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 125 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 126 => 'lib/PhpParser/Node/Stmt/While_.php', - 127 => 'lib/PhpParser/NodeDumper.php', - 128 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 129 => 'lib/PhpParser/Parser/Php5.php', - 130 => 'lib/PhpParser/Parser/Php7.php', - 131 => 'lib/PhpParser/ParserAbstract.php', - 132 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 133 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Expr/ArrayDimFetch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ArrayItem.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Node/Expr/Array_.php', - 2 => 'lib/PhpParser/Node/Expr/List_.php', - 3 => 'lib/PhpParser/Parser/Php5.php', - 4 => 'lib/PhpParser/Parser/Php7.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Array_.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Assign.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 1 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 2 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 3 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 4 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 5 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 6 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 7 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 8 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 9 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 10 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 11 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 12 => 'lib/PhpParser/Parser/Php5.php', - 13 => 'lib/PhpParser/Parser/Php7.php', - 14 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Concat.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Div.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Minus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Mod.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Mul.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Plus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Pow.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignRef.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 1 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 2 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 3 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 4 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 5 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 6 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 7 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 8 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 9 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 10 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 11 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 12 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 13 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 14 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 15 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 16 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 17 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 18 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 19 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 20 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 21 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 22 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 23 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 24 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 25 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 26 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 27 => 'lib/PhpParser/Parser/Php5.php', - 28 => 'lib/PhpParser/Parser/Php7.php', - 29 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Div.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BitwiseNot.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BooleanNot.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 1 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 2 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 3 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 4 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 5 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 6 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 7 => 'lib/PhpParser/Parser/Php5.php', - 8 => 'lib/PhpParser/Parser/Php7.php', - 9 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Array_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Bool_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Double.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Int_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Object_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/String_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Unset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ClassConstFetch.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Clone_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Closure.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ClosureUse.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/Closure.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ConstFetch.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Empty_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Error.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ErrorSuppress.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Eval_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Exit_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/FuncCall.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Include_.php' => - array ( - 0 => 'lib/PhpParser/NodeDumper.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Instanceof_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Isset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/List_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/MethodCall.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/New_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PostDec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PostInc.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PreDec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PreInc.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Print_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PropertyFetch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ShellExec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/StaticCall.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Ternary.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/UnaryMinus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/UnaryPlus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Variable.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/YieldFrom.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Yield_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/FunctionLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/Builder/Trait_.php', - 3 => 'lib/PhpParser/Node/Expr/Closure.php', - 4 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 5 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 6 => 'lib/PhpParser/Node/Stmt/Function_.php', - 7 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 8 => 'lib/PhpParser/Parser/Php5.php', - 9 => 'lib/PhpParser/Parser/Php7.php', - 10 => 'lib/PhpParser/ParserAbstract.php', - 11 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Name.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Param.php', - 7 => 'lib/PhpParser/Builder/Use_.php', - 8 => 'lib/PhpParser/BuilderAbstract.php', - 9 => 'lib/PhpParser/BuilderFactory.php', - 10 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 11 => 'lib/PhpParser/Node/Expr/Closure.php', - 12 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 13 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 14 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 15 => 'lib/PhpParser/Node/Expr/New_.php', - 16 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 17 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 18 => 'lib/PhpParser/Node/FunctionLike.php', - 19 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 20 => 'lib/PhpParser/Node/Name/Relative.php', - 21 => 'lib/PhpParser/Node/NullableType.php', - 22 => 'lib/PhpParser/Node/Param.php', - 23 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 24 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 25 => 'lib/PhpParser/Node/Stmt/Class_.php', - 26 => 'lib/PhpParser/Node/Stmt/Function_.php', - 27 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 28 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 29 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 30 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 31 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 32 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 33 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 34 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 35 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 36 => 'lib/PhpParser/Parser/Php5.php', - 37 => 'lib/PhpParser/Parser/Php7.php', - 38 => 'lib/PhpParser/ParserAbstract.php', - 39 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 40 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Name/FullyQualified.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Name/Relative.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/NullableType.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/Builder/Function_.php', - 2 => 'lib/PhpParser/Builder/Method.php', - 3 => 'lib/PhpParser/Builder/Param.php', - 4 => 'lib/PhpParser/BuilderAbstract.php', - 5 => 'lib/PhpParser/Node/Expr/Closure.php', - 6 => 'lib/PhpParser/Node/FunctionLike.php', - 7 => 'lib/PhpParser/Node/Param.php', - 8 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 9 => 'lib/PhpParser/Node/Stmt/Function_.php', - 10 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 11 => 'lib/PhpParser/Parser/Php7.php', - 12 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Param.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/Builder/Param.php', - 2 => 'lib/PhpParser/Node/Expr/Closure.php', - 3 => 'lib/PhpParser/Node/FunctionLike.php', - 4 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 5 => 'lib/PhpParser/Node/Stmt/Function_.php', - 6 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 7 => 'lib/PhpParser/Parser/Php5.php', - 8 => 'lib/PhpParser/Parser/Php7.php', - 9 => 'lib/PhpParser/ParserAbstract.php', - 10 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 2 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 3 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 4 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 5 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 6 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 7 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 8 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 9 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 10 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 11 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 12 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 13 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 14 => 'lib/PhpParser/Node/Scalar/String_.php', - 15 => 'lib/PhpParser/Parser/Php5.php', - 16 => 'lib/PhpParser/Parser/Php7.php', - 17 => 'lib/PhpParser/ParserAbstract.php', - 18 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/DNumber.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/Encapsed.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/LNumber.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/ParserAbstract.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst.php' => - array ( - 0 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 1 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 2 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 3 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 4 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 5 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 6 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 7 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 8 => 'lib/PhpParser/Parser/Php5.php', - 9 => 'lib/PhpParser/Parser/Php7.php', - 10 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/File.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Line.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Method.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/String_.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Function_.php', - 2 => 'lib/PhpParser/Builder/Interface_.php', - 3 => 'lib/PhpParser/Builder/Method.php', - 4 => 'lib/PhpParser/Builder/Namespace_.php', - 5 => 'lib/PhpParser/Builder/Property.php', - 6 => 'lib/PhpParser/Builder/Trait_.php', - 7 => 'lib/PhpParser/Builder/Use_.php', - 8 => 'lib/PhpParser/BuilderAbstract.php', - 9 => 'lib/PhpParser/BuilderFactory.php', - 10 => 'lib/PhpParser/Node/Expr/Closure.php', - 11 => 'lib/PhpParser/Node/Expr/New_.php', - 12 => 'lib/PhpParser/Node/FunctionLike.php', - 13 => 'lib/PhpParser/Node/Stmt/Break_.php', - 14 => 'lib/PhpParser/Node/Stmt/Case_.php', - 15 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 16 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 17 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 18 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 19 => 'lib/PhpParser/Node/Stmt/Class_.php', - 20 => 'lib/PhpParser/Node/Stmt/Const_.php', - 21 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 22 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 23 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 24 => 'lib/PhpParser/Node/Stmt/Do_.php', - 25 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 26 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 27 => 'lib/PhpParser/Node/Stmt/Else_.php', - 28 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 29 => 'lib/PhpParser/Node/Stmt/For_.php', - 30 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 31 => 'lib/PhpParser/Node/Stmt/Function_.php', - 32 => 'lib/PhpParser/Node/Stmt/Global_.php', - 33 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 34 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 35 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 36 => 'lib/PhpParser/Node/Stmt/If_.php', - 37 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 38 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 39 => 'lib/PhpParser/Node/Stmt/Label.php', - 40 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 41 => 'lib/PhpParser/Node/Stmt/Nop.php', - 42 => 'lib/PhpParser/Node/Stmt/Property.php', - 43 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 44 => 'lib/PhpParser/Node/Stmt/Return_.php', - 45 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 46 => 'lib/PhpParser/Node/Stmt/Static_.php', - 47 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 48 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 49 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 50 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 51 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 52 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 53 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 54 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 55 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 56 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 57 => 'lib/PhpParser/Node/Stmt/Use_.php', - 58 => 'lib/PhpParser/Node/Stmt/While_.php', - 59 => 'lib/PhpParser/NodeDumper.php', - 60 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 61 => 'lib/PhpParser/Parser/Php5.php', - 62 => 'lib/PhpParser/Parser/Php7.php', - 63 => 'lib/PhpParser/ParserAbstract.php', - 64 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 65 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Break_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Case_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Catch_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassConst.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Interface_.php', - 2 => 'lib/PhpParser/Builder/Method.php', - 3 => 'lib/PhpParser/Builder/Property.php', - 4 => 'lib/PhpParser/Builder/Trait_.php', - 5 => 'lib/PhpParser/BuilderAbstract.php', - 6 => 'lib/PhpParser/Node/Expr/New_.php', - 7 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 8 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 9 => 'lib/PhpParser/Node/Stmt/Class_.php', - 10 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 11 => 'lib/PhpParser/Node/Stmt/Property.php', - 12 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 13 => 'lib/PhpParser/NodeDumper.php', - 14 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 15 => 'lib/PhpParser/Parser/Php5.php', - 16 => 'lib/PhpParser/Parser/Php7.php', - 17 => 'lib/PhpParser/ParserAbstract.php', - 18 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassMethod.php' => - array ( - 0 => 'lib/PhpParser/Builder/Method.php', - 1 => 'lib/PhpParser/Builder/Trait_.php', - 2 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 3 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/ParserAbstract.php', - 7 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Class_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/Builder/Property.php', - 3 => 'lib/PhpParser/BuilderAbstract.php', - 4 => 'lib/PhpParser/Node/Expr/New_.php', - 5 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 6 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 7 => 'lib/PhpParser/Node/Stmt/Property.php', - 8 => 'lib/PhpParser/NodeDumper.php', - 9 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 10 => 'lib/PhpParser/Parser/Php5.php', - 11 => 'lib/PhpParser/Parser/Php7.php', - 12 => 'lib/PhpParser/ParserAbstract.php', - 13 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Const_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Continue_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/DeclareDeclare.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Declare_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Do_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Echo_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ElseIf_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/If_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Else_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/If_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Finally_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/For_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Foreach_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Function_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Global_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Goto_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/GroupUse.php' => - array ( - 0 => 'lib/PhpParser/NodeDumper.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/HaltCompiler.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/If_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/InlineHTML.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 4 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Interface_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Interface_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Label.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Namespace_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 6 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Nop.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 4 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Property.php' => - array ( - 0 => 'lib/PhpParser/Builder/Property.php', - 1 => 'lib/PhpParser/Builder/Trait_.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/PropertyProperty.php' => - array ( - 0 => 'lib/PhpParser/Builder/Property.php', - 1 => 'lib/PhpParser/Node/Stmt/Property.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Return_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/StaticVar.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Static_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Static_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Switch_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Throw_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUse.php' => - array ( - 0 => 'lib/PhpParser/Builder/Trait_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 1 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 2 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 3 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Trait_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Trait_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TryCatch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Unset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/UseUse.php' => - array ( - 0 => 'lib/PhpParser/Builder/Use_.php', - 1 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 2 => 'lib/PhpParser/Node/Stmt/Use_.php', - 3 => 'lib/PhpParser/NodeDumper.php', - 4 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 5 => 'lib/PhpParser/Parser/Php5.php', - 6 => 'lib/PhpParser/Parser/Php7.php', - 7 => 'lib/PhpParser/ParserAbstract.php', - 8 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Use_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Use_.php', - 1 => 'lib/PhpParser/BuilderFactory.php', - 2 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 3 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 4 => 'lib/PhpParser/NodeDumper.php', - 5 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 6 => 'lib/PhpParser/Parser/Php5.php', - 7 => 'lib/PhpParser/Parser/Php7.php', - 8 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/While_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/NodeAbstract.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Param.php', - 7 => 'lib/PhpParser/Builder/Property.php', - 8 => 'lib/PhpParser/Builder/Trait_.php', - 9 => 'lib/PhpParser/Builder/Use_.php', - 10 => 'lib/PhpParser/BuilderAbstract.php', - 11 => 'lib/PhpParser/BuilderFactory.php', - 12 => 'lib/PhpParser/Node/Arg.php', - 13 => 'lib/PhpParser/Node/Const_.php', - 14 => 'lib/PhpParser/Node/Expr.php', - 15 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 16 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 17 => 'lib/PhpParser/Node/Expr/Array_.php', - 18 => 'lib/PhpParser/Node/Expr/Assign.php', - 19 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 20 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 22 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 23 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 24 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 25 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 26 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 27 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 28 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 29 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 30 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 31 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 32 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 33 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 34 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 51 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 52 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 53 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 54 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 55 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 56 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 57 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 58 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 59 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 60 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 61 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 62 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 63 => 'lib/PhpParser/Node/Expr/Cast.php', - 64 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 65 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 66 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 67 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 68 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 69 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 70 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 71 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 72 => 'lib/PhpParser/Node/Expr/Clone_.php', - 73 => 'lib/PhpParser/Node/Expr/Closure.php', - 74 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 75 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 76 => 'lib/PhpParser/Node/Expr/Empty_.php', - 77 => 'lib/PhpParser/Node/Expr/Error.php', - 78 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 79 => 'lib/PhpParser/Node/Expr/Eval_.php', - 80 => 'lib/PhpParser/Node/Expr/Exit_.php', - 81 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 82 => 'lib/PhpParser/Node/Expr/Include_.php', - 83 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 84 => 'lib/PhpParser/Node/Expr/Isset_.php', - 85 => 'lib/PhpParser/Node/Expr/List_.php', - 86 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 87 => 'lib/PhpParser/Node/Expr/New_.php', - 88 => 'lib/PhpParser/Node/Expr/PostDec.php', - 89 => 'lib/PhpParser/Node/Expr/PostInc.php', - 90 => 'lib/PhpParser/Node/Expr/PreDec.php', - 91 => 'lib/PhpParser/Node/Expr/PreInc.php', - 92 => 'lib/PhpParser/Node/Expr/Print_.php', - 93 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 94 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 95 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 96 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 97 => 'lib/PhpParser/Node/Expr/Ternary.php', - 98 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 99 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 100 => 'lib/PhpParser/Node/Expr/Variable.php', - 101 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 102 => 'lib/PhpParser/Node/Expr/Yield_.php', - 103 => 'lib/PhpParser/Node/FunctionLike.php', - 104 => 'lib/PhpParser/Node/Name.php', - 105 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 106 => 'lib/PhpParser/Node/Name/Relative.php', - 107 => 'lib/PhpParser/Node/NullableType.php', - 108 => 'lib/PhpParser/Node/Param.php', - 109 => 'lib/PhpParser/Node/Scalar.php', - 110 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 111 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 112 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 113 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 114 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 115 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 116 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 117 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 118 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 119 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 120 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 121 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 122 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 123 => 'lib/PhpParser/Node/Scalar/String_.php', - 124 => 'lib/PhpParser/Node/Stmt.php', - 125 => 'lib/PhpParser/Node/Stmt/Break_.php', - 126 => 'lib/PhpParser/Node/Stmt/Case_.php', - 127 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 128 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 129 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 130 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 131 => 'lib/PhpParser/Node/Stmt/Class_.php', - 132 => 'lib/PhpParser/Node/Stmt/Const_.php', - 133 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 134 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 135 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 136 => 'lib/PhpParser/Node/Stmt/Do_.php', - 137 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 138 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 139 => 'lib/PhpParser/Node/Stmt/Else_.php', - 140 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 141 => 'lib/PhpParser/Node/Stmt/For_.php', - 142 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 143 => 'lib/PhpParser/Node/Stmt/Function_.php', - 144 => 'lib/PhpParser/Node/Stmt/Global_.php', - 145 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 146 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 147 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 148 => 'lib/PhpParser/Node/Stmt/If_.php', - 149 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 150 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 151 => 'lib/PhpParser/Node/Stmt/Label.php', - 152 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 153 => 'lib/PhpParser/Node/Stmt/Nop.php', - 154 => 'lib/PhpParser/Node/Stmt/Property.php', - 155 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 156 => 'lib/PhpParser/Node/Stmt/Return_.php', - 157 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 158 => 'lib/PhpParser/Node/Stmt/Static_.php', - 159 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 160 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 161 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 162 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 163 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 164 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 165 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 166 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 167 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 168 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 169 => 'lib/PhpParser/Node/Stmt/Use_.php', - 170 => 'lib/PhpParser/Node/Stmt/While_.php', - 171 => 'lib/PhpParser/NodeDumper.php', - 172 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 173 => 'lib/PhpParser/Parser/Php5.php', - 174 => 'lib/PhpParser/Parser/Php7.php', - 175 => 'lib/PhpParser/ParserAbstract.php', - 176 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 177 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/NodeDumper.php' => - array ( - ), - 'lib/PhpParser/NodeTraverser.php' => - array ( - ), - 'lib/PhpParser/NodeTraverserInterface.php' => - array ( - 0 => 'lib/PhpParser/NodeTraverser.php', - ), - 'lib/PhpParser/NodeVisitor.php' => - array ( - 0 => 'lib/PhpParser/NodeTraverser.php', - 1 => 'lib/PhpParser/NodeTraverserInterface.php', - 2 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 3 => 'lib/PhpParser/NodeVisitorAbstract.php', - ), - 'lib/PhpParser/NodeVisitor/NameResolver.php' => - array ( - ), - 'lib/PhpParser/NodeVisitorAbstract.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - ), - 'lib/PhpParser/Parser.php' => - array ( - 0 => 'lib/PhpParser/Parser/Multiple.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Multiple.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Php5.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Php7.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Tokens.php' => - array ( - 0 => 'lib/PhpParser/Lexer.php', - 1 => 'lib/PhpParser/Lexer/Emulative.php', - ), - 'lib/PhpParser/ParserAbstract.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/ParserFactory.php' => - array ( - ), - 'lib/PhpParser/PrettyPrinter/Standard.php' => - array ( - ), - 'lib/PhpParser/PrettyPrinterAbstract.php' => - array ( - 0 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Serializer.php' => - array ( - 0 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Serializer/XML.php' => - array ( - ), - 'lib/PhpParser/Unserializer.php' => - array ( - 0 => 'lib/PhpParser/Unserializer/XML.php', - ), - 'lib/PhpParser/Unserializer/XML.php' => - array ( - ), - 'lib/bootstrap.php' => - array ( - ), -); diff --git a/tests/e2e/resultCache_2.php b/tests/e2e/resultCache_2.php deleted file mode 100644 index fb4e9bb6d8..0000000000 --- a/tests/e2e/resultCache_2.php +++ /dev/null @@ -1,2023 +0,0 @@ - - array ( - 0 => 'lib/bootstrap.php', - ), - 'lib/PhpParser/Builder.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Declaration.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderAbstract.php', - 12 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Class_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Declaration.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Trait_.php', - 7 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/FunctionLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Function_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Interface_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Method.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Param.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Property.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Trait_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Use_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/BuilderAbstract.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Declaration.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/BuilderFactory.php' => - array ( - ), - 'lib/PhpParser/Comment.php' => - array ( - 0 => 'lib/PhpParser/Builder/Declaration.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Comment/Doc.php', - 4 => 'lib/PhpParser/Lexer.php', - 5 => 'lib/PhpParser/Node.php', - 6 => 'lib/PhpParser/NodeAbstract.php', - 7 => 'lib/PhpParser/NodeDumper.php', - 8 => 'lib/PhpParser/PrettyPrinterAbstract.php', - 9 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Comment/Doc.php' => - array ( - 0 => 'lib/PhpParser/Builder/Declaration.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Comment.php', - 4 => 'lib/PhpParser/Lexer.php', - 5 => 'lib/PhpParser/Node.php', - 6 => 'lib/PhpParser/NodeAbstract.php', - 7 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Error.php' => - array ( - 0 => 'lib/PhpParser/ErrorHandler.php', - 1 => 'lib/PhpParser/ErrorHandler/Collecting.php', - 2 => 'lib/PhpParser/ErrorHandler/Throwing.php', - 3 => 'lib/PhpParser/Lexer.php', - 4 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 5 => 'lib/PhpParser/Node/Scalar/String_.php', - 6 => 'lib/PhpParser/Node/Stmt/Class_.php', - 7 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 8 => 'lib/PhpParser/Parser/Multiple.php', - 9 => 'lib/PhpParser/Parser/Php5.php', - 10 => 'lib/PhpParser/Parser/Php7.php', - 11 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/ErrorHandler.php' => - array ( - 0 => 'lib/PhpParser/ErrorHandler/Collecting.php', - 1 => 'lib/PhpParser/ErrorHandler/Throwing.php', - 2 => 'lib/PhpParser/Lexer.php', - 3 => 'lib/PhpParser/Lexer/Emulative.php', - 4 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 5 => 'lib/PhpParser/Parser.php', - 6 => 'lib/PhpParser/Parser/Multiple.php', - 7 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/ErrorHandler/Collecting.php' => - array ( - ), - 'lib/PhpParser/ErrorHandler/Throwing.php' => - array ( - 0 => 'lib/PhpParser/Lexer.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Multiple.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/Lexer.php' => - array ( - 0 => 'lib/PhpParser/Lexer/Emulative.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Lexer/Emulative.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Node.php' => - array ( - 0 => 'lib/PhpParser/Builder.php', - 1 => 'lib/PhpParser/Builder/Class_.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderAbstract.php', - 12 => 'lib/PhpParser/BuilderFactory.php', - 13 => 'lib/PhpParser/Lexer.php', - 14 => 'lib/PhpParser/Node/Arg.php', - 15 => 'lib/PhpParser/Node/Const_.php', - 16 => 'lib/PhpParser/Node/Expr.php', - 17 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 18 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 19 => 'lib/PhpParser/Node/Expr/Array_.php', - 20 => 'lib/PhpParser/Node/Expr/Assign.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 22 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 23 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 24 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 25 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 26 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 27 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 28 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 29 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 30 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 31 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 32 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 33 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 34 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 51 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 52 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 53 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 54 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 55 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 56 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 57 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 58 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 59 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 60 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 61 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 62 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 63 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 64 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 65 => 'lib/PhpParser/Node/Expr/Cast.php', - 66 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 67 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 68 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 69 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 70 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 71 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 72 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 73 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 74 => 'lib/PhpParser/Node/Expr/Clone_.php', - 75 => 'lib/PhpParser/Node/Expr/Closure.php', - 76 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 77 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 78 => 'lib/PhpParser/Node/Expr/Empty_.php', - 79 => 'lib/PhpParser/Node/Expr/Error.php', - 80 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 81 => 'lib/PhpParser/Node/Expr/Eval_.php', - 82 => 'lib/PhpParser/Node/Expr/Exit_.php', - 83 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 84 => 'lib/PhpParser/Node/Expr/Include_.php', - 85 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 86 => 'lib/PhpParser/Node/Expr/Isset_.php', - 87 => 'lib/PhpParser/Node/Expr/List_.php', - 88 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 89 => 'lib/PhpParser/Node/Expr/New_.php', - 90 => 'lib/PhpParser/Node/Expr/PostDec.php', - 91 => 'lib/PhpParser/Node/Expr/PostInc.php', - 92 => 'lib/PhpParser/Node/Expr/PreDec.php', - 93 => 'lib/PhpParser/Node/Expr/PreInc.php', - 94 => 'lib/PhpParser/Node/Expr/Print_.php', - 95 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 96 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 97 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 98 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 99 => 'lib/PhpParser/Node/Expr/Ternary.php', - 100 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 101 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 102 => 'lib/PhpParser/Node/Expr/Variable.php', - 103 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 104 => 'lib/PhpParser/Node/Expr/Yield_.php', - 105 => 'lib/PhpParser/Node/FunctionLike.php', - 106 => 'lib/PhpParser/Node/Name.php', - 107 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 108 => 'lib/PhpParser/Node/Name/Relative.php', - 109 => 'lib/PhpParser/Node/NullableType.php', - 110 => 'lib/PhpParser/Node/Param.php', - 111 => 'lib/PhpParser/Node/Scalar.php', - 112 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 113 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 114 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 115 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 116 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 117 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 118 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 119 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 120 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 121 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 122 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 123 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 124 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 125 => 'lib/PhpParser/Node/Scalar/String_.php', - 126 => 'lib/PhpParser/Node/Stmt.php', - 127 => 'lib/PhpParser/Node/Stmt/Break_.php', - 128 => 'lib/PhpParser/Node/Stmt/Case_.php', - 129 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 130 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 131 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 132 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 133 => 'lib/PhpParser/Node/Stmt/Class_.php', - 134 => 'lib/PhpParser/Node/Stmt/Const_.php', - 135 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 136 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 137 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 138 => 'lib/PhpParser/Node/Stmt/Do_.php', - 139 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 140 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 141 => 'lib/PhpParser/Node/Stmt/Else_.php', - 142 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 143 => 'lib/PhpParser/Node/Stmt/For_.php', - 144 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 145 => 'lib/PhpParser/Node/Stmt/Function_.php', - 146 => 'lib/PhpParser/Node/Stmt/Global_.php', - 147 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 148 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 149 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 150 => 'lib/PhpParser/Node/Stmt/If_.php', - 151 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 152 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 153 => 'lib/PhpParser/Node/Stmt/Label.php', - 154 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 155 => 'lib/PhpParser/Node/Stmt/Nop.php', - 156 => 'lib/PhpParser/Node/Stmt/Property.php', - 157 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 158 => 'lib/PhpParser/Node/Stmt/Return_.php', - 159 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 160 => 'lib/PhpParser/Node/Stmt/Static_.php', - 161 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 162 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 163 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 164 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 165 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 166 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 167 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 168 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 169 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 170 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 171 => 'lib/PhpParser/Node/Stmt/Use_.php', - 172 => 'lib/PhpParser/Node/Stmt/While_.php', - 173 => 'lib/PhpParser/NodeAbstract.php', - 174 => 'lib/PhpParser/NodeDumper.php', - 175 => 'lib/PhpParser/NodeTraverser.php', - 176 => 'lib/PhpParser/NodeTraverserInterface.php', - 177 => 'lib/PhpParser/NodeVisitor.php', - 178 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 179 => 'lib/PhpParser/NodeVisitorAbstract.php', - 180 => 'lib/PhpParser/Parser.php', - 181 => 'lib/PhpParser/Parser/Multiple.php', - 182 => 'lib/PhpParser/Parser/Php5.php', - 183 => 'lib/PhpParser/Parser/Php7.php', - 184 => 'lib/PhpParser/ParserAbstract.php', - 185 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 186 => 'lib/PhpParser/PrettyPrinterAbstract.php', - 187 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Node/Arg.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 1 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 2 => 'lib/PhpParser/Node/Expr/New_.php', - 3 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Const_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 1 => 'lib/PhpParser/Node/Stmt/Const_.php', - 2 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 3 => 'lib/PhpParser/Parser/Php5.php', - 4 => 'lib/PhpParser/Parser/Php7.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr.php' => - array ( - 0 => 'lib/PhpParser/Builder/Param.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Lexer.php', - 4 => 'lib/PhpParser/Node/Arg.php', - 5 => 'lib/PhpParser/Node/Const_.php', - 6 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 7 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 8 => 'lib/PhpParser/Node/Expr/Array_.php', - 9 => 'lib/PhpParser/Node/Expr/Assign.php', - 10 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 11 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 12 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 13 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 14 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 15 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 16 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 17 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 18 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 19 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 20 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 22 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 23 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 24 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 25 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 26 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 27 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 28 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 29 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 30 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 31 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 32 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 33 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 34 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 51 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 52 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 53 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 54 => 'lib/PhpParser/Node/Expr/Cast.php', - 55 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 56 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 57 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 58 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 59 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 60 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 61 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 62 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 63 => 'lib/PhpParser/Node/Expr/Clone_.php', - 64 => 'lib/PhpParser/Node/Expr/Closure.php', - 65 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 66 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 67 => 'lib/PhpParser/Node/Expr/Empty_.php', - 68 => 'lib/PhpParser/Node/Expr/Error.php', - 69 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 70 => 'lib/PhpParser/Node/Expr/Eval_.php', - 71 => 'lib/PhpParser/Node/Expr/Exit_.php', - 72 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 73 => 'lib/PhpParser/Node/Expr/Include_.php', - 74 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 75 => 'lib/PhpParser/Node/Expr/Isset_.php', - 76 => 'lib/PhpParser/Node/Expr/List_.php', - 77 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 78 => 'lib/PhpParser/Node/Expr/New_.php', - 79 => 'lib/PhpParser/Node/Expr/PostDec.php', - 80 => 'lib/PhpParser/Node/Expr/PostInc.php', - 81 => 'lib/PhpParser/Node/Expr/PreDec.php', - 82 => 'lib/PhpParser/Node/Expr/PreInc.php', - 83 => 'lib/PhpParser/Node/Expr/Print_.php', - 84 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 85 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 86 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 87 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 88 => 'lib/PhpParser/Node/Expr/Ternary.php', - 89 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 90 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 91 => 'lib/PhpParser/Node/Expr/Variable.php', - 92 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 93 => 'lib/PhpParser/Node/Expr/Yield_.php', - 94 => 'lib/PhpParser/Node/Param.php', - 95 => 'lib/PhpParser/Node/Scalar.php', - 96 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 97 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 98 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 99 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 100 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 101 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 102 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 103 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 104 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 105 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 106 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 107 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 108 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 109 => 'lib/PhpParser/Node/Scalar/String_.php', - 110 => 'lib/PhpParser/Node/Stmt/Break_.php', - 111 => 'lib/PhpParser/Node/Stmt/Case_.php', - 112 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 113 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 114 => 'lib/PhpParser/Node/Stmt/Do_.php', - 115 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 116 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 117 => 'lib/PhpParser/Node/Stmt/For_.php', - 118 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 119 => 'lib/PhpParser/Node/Stmt/Global_.php', - 120 => 'lib/PhpParser/Node/Stmt/If_.php', - 121 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 122 => 'lib/PhpParser/Node/Stmt/Return_.php', - 123 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 124 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 125 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 126 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 127 => 'lib/PhpParser/Node/Stmt/While_.php', - 128 => 'lib/PhpParser/NodeDumper.php', - 129 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 130 => 'lib/PhpParser/Parser/Php5.php', - 131 => 'lib/PhpParser/Parser/Php7.php', - 132 => 'lib/PhpParser/ParserAbstract.php', - 133 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 134 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Expr/ArrayDimFetch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ArrayItem.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Node/Expr/Array_.php', - 2 => 'lib/PhpParser/Node/Expr/List_.php', - 3 => 'lib/PhpParser/Parser/Php5.php', - 4 => 'lib/PhpParser/Parser/Php7.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Array_.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Assign.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 1 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 2 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 3 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 4 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 5 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 6 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 7 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 8 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 9 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 10 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 11 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 12 => 'lib/PhpParser/Parser/Php5.php', - 13 => 'lib/PhpParser/Parser/Php7.php', - 14 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Concat.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Div.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Minus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Mod.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Mul.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Plus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Pow.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignRef.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 1 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 2 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 3 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 4 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 5 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 6 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 7 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 8 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 9 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 10 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 11 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 12 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 13 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 14 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 15 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 16 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 17 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 18 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 19 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 20 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 21 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 22 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 23 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 24 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 25 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 26 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 27 => 'lib/PhpParser/Parser/Php5.php', - 28 => 'lib/PhpParser/Parser/Php7.php', - 29 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Div.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BitwiseNot.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BooleanNot.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 1 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 2 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 3 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 4 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 5 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 6 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 7 => 'lib/PhpParser/Parser/Php5.php', - 8 => 'lib/PhpParser/Parser/Php7.php', - 9 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Array_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Bool_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Double.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Int_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Object_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/String_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Unset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ClassConstFetch.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Clone_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Closure.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ClosureUse.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/Closure.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ConstFetch.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Empty_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Error.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ErrorSuppress.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Eval_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Exit_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/FuncCall.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Include_.php' => - array ( - 0 => 'lib/PhpParser/NodeDumper.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Instanceof_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Isset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/List_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/MethodCall.php' => - array ( - 0 => 'lib/PhpParser/Lexer.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/New_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PostDec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PostInc.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PreDec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PreInc.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Print_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PropertyFetch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ShellExec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/StaticCall.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Ternary.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/UnaryMinus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/UnaryPlus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Variable.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/YieldFrom.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Yield_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/FunctionLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/Builder/Trait_.php', - 3 => 'lib/PhpParser/Node/Expr/Closure.php', - 4 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 5 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 6 => 'lib/PhpParser/Node/Stmt/Function_.php', - 7 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 8 => 'lib/PhpParser/Parser/Php5.php', - 9 => 'lib/PhpParser/Parser/Php7.php', - 10 => 'lib/PhpParser/ParserAbstract.php', - 11 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Name.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Param.php', - 7 => 'lib/PhpParser/Builder/Use_.php', - 8 => 'lib/PhpParser/BuilderAbstract.php', - 9 => 'lib/PhpParser/BuilderFactory.php', - 10 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 11 => 'lib/PhpParser/Node/Expr/Closure.php', - 12 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 13 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 14 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 15 => 'lib/PhpParser/Node/Expr/New_.php', - 16 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 17 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 18 => 'lib/PhpParser/Node/FunctionLike.php', - 19 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 20 => 'lib/PhpParser/Node/Name/Relative.php', - 21 => 'lib/PhpParser/Node/NullableType.php', - 22 => 'lib/PhpParser/Node/Param.php', - 23 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 24 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 25 => 'lib/PhpParser/Node/Stmt/Class_.php', - 26 => 'lib/PhpParser/Node/Stmt/Function_.php', - 27 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 28 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 29 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 30 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 31 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 32 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 33 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 34 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 35 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 36 => 'lib/PhpParser/Parser/Php5.php', - 37 => 'lib/PhpParser/Parser/Php7.php', - 38 => 'lib/PhpParser/ParserAbstract.php', - 39 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 40 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Name/FullyQualified.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Name/Relative.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/NullableType.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/Builder/Function_.php', - 2 => 'lib/PhpParser/Builder/Method.php', - 3 => 'lib/PhpParser/Builder/Param.php', - 4 => 'lib/PhpParser/BuilderAbstract.php', - 5 => 'lib/PhpParser/Node/Expr/Closure.php', - 6 => 'lib/PhpParser/Node/FunctionLike.php', - 7 => 'lib/PhpParser/Node/Param.php', - 8 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 9 => 'lib/PhpParser/Node/Stmt/Function_.php', - 10 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 11 => 'lib/PhpParser/Parser/Php7.php', - 12 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Param.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/Builder/Param.php', - 2 => 'lib/PhpParser/Node/Expr/Closure.php', - 3 => 'lib/PhpParser/Node/FunctionLike.php', - 4 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 5 => 'lib/PhpParser/Node/Stmt/Function_.php', - 6 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 7 => 'lib/PhpParser/Parser/Php5.php', - 8 => 'lib/PhpParser/Parser/Php7.php', - 9 => 'lib/PhpParser/ParserAbstract.php', - 10 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 2 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 3 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 4 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 5 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 6 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 7 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 8 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 9 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 10 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 11 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 12 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 13 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 14 => 'lib/PhpParser/Node/Scalar/String_.php', - 15 => 'lib/PhpParser/Parser/Php5.php', - 16 => 'lib/PhpParser/Parser/Php7.php', - 17 => 'lib/PhpParser/ParserAbstract.php', - 18 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/DNumber.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/Encapsed.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/LNumber.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/ParserAbstract.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst.php' => - array ( - 0 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 1 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 2 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 3 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 4 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 5 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 6 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 7 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 8 => 'lib/PhpParser/Parser/Php5.php', - 9 => 'lib/PhpParser/Parser/Php7.php', - 10 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/File.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Line.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Method.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/String_.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Function_.php', - 2 => 'lib/PhpParser/Builder/Interface_.php', - 3 => 'lib/PhpParser/Builder/Method.php', - 4 => 'lib/PhpParser/Builder/Namespace_.php', - 5 => 'lib/PhpParser/Builder/Property.php', - 6 => 'lib/PhpParser/Builder/Trait_.php', - 7 => 'lib/PhpParser/Builder/Use_.php', - 8 => 'lib/PhpParser/BuilderAbstract.php', - 9 => 'lib/PhpParser/BuilderFactory.php', - 10 => 'lib/PhpParser/Node/Expr/Closure.php', - 11 => 'lib/PhpParser/Node/Expr/New_.php', - 12 => 'lib/PhpParser/Node/FunctionLike.php', - 13 => 'lib/PhpParser/Node/Stmt/Break_.php', - 14 => 'lib/PhpParser/Node/Stmt/Case_.php', - 15 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 16 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 17 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 18 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 19 => 'lib/PhpParser/Node/Stmt/Class_.php', - 20 => 'lib/PhpParser/Node/Stmt/Const_.php', - 21 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 22 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 23 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 24 => 'lib/PhpParser/Node/Stmt/Do_.php', - 25 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 26 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 27 => 'lib/PhpParser/Node/Stmt/Else_.php', - 28 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 29 => 'lib/PhpParser/Node/Stmt/For_.php', - 30 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 31 => 'lib/PhpParser/Node/Stmt/Function_.php', - 32 => 'lib/PhpParser/Node/Stmt/Global_.php', - 33 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 34 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 35 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 36 => 'lib/PhpParser/Node/Stmt/If_.php', - 37 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 38 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 39 => 'lib/PhpParser/Node/Stmt/Label.php', - 40 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 41 => 'lib/PhpParser/Node/Stmt/Nop.php', - 42 => 'lib/PhpParser/Node/Stmt/Property.php', - 43 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 44 => 'lib/PhpParser/Node/Stmt/Return_.php', - 45 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 46 => 'lib/PhpParser/Node/Stmt/Static_.php', - 47 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 48 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 49 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 50 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 51 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 52 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 53 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 54 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 55 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 56 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 57 => 'lib/PhpParser/Node/Stmt/Use_.php', - 58 => 'lib/PhpParser/Node/Stmt/While_.php', - 59 => 'lib/PhpParser/NodeDumper.php', - 60 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 61 => 'lib/PhpParser/Parser/Php5.php', - 62 => 'lib/PhpParser/Parser/Php7.php', - 63 => 'lib/PhpParser/ParserAbstract.php', - 64 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 65 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Break_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Case_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Catch_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassConst.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Interface_.php', - 2 => 'lib/PhpParser/Builder/Method.php', - 3 => 'lib/PhpParser/Builder/Property.php', - 4 => 'lib/PhpParser/Builder/Trait_.php', - 5 => 'lib/PhpParser/BuilderAbstract.php', - 6 => 'lib/PhpParser/Node/Expr/New_.php', - 7 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 8 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 9 => 'lib/PhpParser/Node/Stmt/Class_.php', - 10 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 11 => 'lib/PhpParser/Node/Stmt/Property.php', - 12 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 13 => 'lib/PhpParser/NodeDumper.php', - 14 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 15 => 'lib/PhpParser/Parser/Php5.php', - 16 => 'lib/PhpParser/Parser/Php7.php', - 17 => 'lib/PhpParser/ParserAbstract.php', - 18 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassMethod.php' => - array ( - 0 => 'lib/PhpParser/Builder/Method.php', - 1 => 'lib/PhpParser/Builder/Trait_.php', - 2 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 3 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/ParserAbstract.php', - 7 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Class_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/Builder/Property.php', - 3 => 'lib/PhpParser/BuilderAbstract.php', - 4 => 'lib/PhpParser/Node/Expr/New_.php', - 5 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 6 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 7 => 'lib/PhpParser/Node/Stmt/Property.php', - 8 => 'lib/PhpParser/NodeDumper.php', - 9 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 10 => 'lib/PhpParser/Parser/Php5.php', - 11 => 'lib/PhpParser/Parser/Php7.php', - 12 => 'lib/PhpParser/ParserAbstract.php', - 13 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Const_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Continue_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/DeclareDeclare.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Declare_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Do_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Echo_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ElseIf_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/If_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Else_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/If_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Finally_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/For_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Foreach_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Function_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Global_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Goto_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/GroupUse.php' => - array ( - 0 => 'lib/PhpParser/NodeDumper.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/HaltCompiler.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/If_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/InlineHTML.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 4 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Interface_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Interface_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Label.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Namespace_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 6 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Nop.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 4 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Property.php' => - array ( - 0 => 'lib/PhpParser/Builder/Property.php', - 1 => 'lib/PhpParser/Builder/Trait_.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/PropertyProperty.php' => - array ( - 0 => 'lib/PhpParser/Builder/Property.php', - 1 => 'lib/PhpParser/Node/Stmt/Property.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Return_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/StaticVar.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Static_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Static_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Switch_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Throw_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUse.php' => - array ( - 0 => 'lib/PhpParser/Builder/Trait_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 1 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 2 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 3 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Trait_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Trait_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TryCatch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Unset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/UseUse.php' => - array ( - 0 => 'lib/PhpParser/Builder/Use_.php', - 1 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 2 => 'lib/PhpParser/Node/Stmt/Use_.php', - 3 => 'lib/PhpParser/NodeDumper.php', - 4 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 5 => 'lib/PhpParser/Parser/Php5.php', - 6 => 'lib/PhpParser/Parser/Php7.php', - 7 => 'lib/PhpParser/ParserAbstract.php', - 8 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Use_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Use_.php', - 1 => 'lib/PhpParser/BuilderFactory.php', - 2 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 3 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 4 => 'lib/PhpParser/NodeDumper.php', - 5 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 6 => 'lib/PhpParser/Parser/Php5.php', - 7 => 'lib/PhpParser/Parser/Php7.php', - 8 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/While_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/NodeAbstract.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Param.php', - 7 => 'lib/PhpParser/Builder/Property.php', - 8 => 'lib/PhpParser/Builder/Trait_.php', - 9 => 'lib/PhpParser/Builder/Use_.php', - 10 => 'lib/PhpParser/BuilderAbstract.php', - 11 => 'lib/PhpParser/BuilderFactory.php', - 12 => 'lib/PhpParser/Lexer.php', - 13 => 'lib/PhpParser/Node/Arg.php', - 14 => 'lib/PhpParser/Node/Const_.php', - 15 => 'lib/PhpParser/Node/Expr.php', - 16 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 17 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 18 => 'lib/PhpParser/Node/Expr/Array_.php', - 19 => 'lib/PhpParser/Node/Expr/Assign.php', - 20 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 22 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 23 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 24 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 25 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 26 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 27 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 28 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 29 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 30 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 31 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 32 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 33 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 34 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 51 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 52 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 53 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 54 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 55 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 56 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 57 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 58 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 59 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 60 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 61 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 62 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 63 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 64 => 'lib/PhpParser/Node/Expr/Cast.php', - 65 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 66 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 67 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 68 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 69 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 70 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 71 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 72 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 73 => 'lib/PhpParser/Node/Expr/Clone_.php', - 74 => 'lib/PhpParser/Node/Expr/Closure.php', - 75 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 76 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 77 => 'lib/PhpParser/Node/Expr/Empty_.php', - 78 => 'lib/PhpParser/Node/Expr/Error.php', - 79 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 80 => 'lib/PhpParser/Node/Expr/Eval_.php', - 81 => 'lib/PhpParser/Node/Expr/Exit_.php', - 82 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 83 => 'lib/PhpParser/Node/Expr/Include_.php', - 84 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 85 => 'lib/PhpParser/Node/Expr/Isset_.php', - 86 => 'lib/PhpParser/Node/Expr/List_.php', - 87 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 88 => 'lib/PhpParser/Node/Expr/New_.php', - 89 => 'lib/PhpParser/Node/Expr/PostDec.php', - 90 => 'lib/PhpParser/Node/Expr/PostInc.php', - 91 => 'lib/PhpParser/Node/Expr/PreDec.php', - 92 => 'lib/PhpParser/Node/Expr/PreInc.php', - 93 => 'lib/PhpParser/Node/Expr/Print_.php', - 94 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 95 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 96 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 97 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 98 => 'lib/PhpParser/Node/Expr/Ternary.php', - 99 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 100 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 101 => 'lib/PhpParser/Node/Expr/Variable.php', - 102 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 103 => 'lib/PhpParser/Node/Expr/Yield_.php', - 104 => 'lib/PhpParser/Node/FunctionLike.php', - 105 => 'lib/PhpParser/Node/Name.php', - 106 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 107 => 'lib/PhpParser/Node/Name/Relative.php', - 108 => 'lib/PhpParser/Node/NullableType.php', - 109 => 'lib/PhpParser/Node/Param.php', - 110 => 'lib/PhpParser/Node/Scalar.php', - 111 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 112 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 113 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 114 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 115 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 116 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 117 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 118 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 119 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 120 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 121 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 122 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 123 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 124 => 'lib/PhpParser/Node/Scalar/String_.php', - 125 => 'lib/PhpParser/Node/Stmt.php', - 126 => 'lib/PhpParser/Node/Stmt/Break_.php', - 127 => 'lib/PhpParser/Node/Stmt/Case_.php', - 128 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 129 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 130 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 131 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 132 => 'lib/PhpParser/Node/Stmt/Class_.php', - 133 => 'lib/PhpParser/Node/Stmt/Const_.php', - 134 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 135 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 136 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 137 => 'lib/PhpParser/Node/Stmt/Do_.php', - 138 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 139 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 140 => 'lib/PhpParser/Node/Stmt/Else_.php', - 141 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 142 => 'lib/PhpParser/Node/Stmt/For_.php', - 143 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 144 => 'lib/PhpParser/Node/Stmt/Function_.php', - 145 => 'lib/PhpParser/Node/Stmt/Global_.php', - 146 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 147 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 148 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 149 => 'lib/PhpParser/Node/Stmt/If_.php', - 150 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 151 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 152 => 'lib/PhpParser/Node/Stmt/Label.php', - 153 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 154 => 'lib/PhpParser/Node/Stmt/Nop.php', - 155 => 'lib/PhpParser/Node/Stmt/Property.php', - 156 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 157 => 'lib/PhpParser/Node/Stmt/Return_.php', - 158 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 159 => 'lib/PhpParser/Node/Stmt/Static_.php', - 160 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 161 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 162 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 163 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 164 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 165 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 166 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 167 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 168 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 169 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 170 => 'lib/PhpParser/Node/Stmt/Use_.php', - 171 => 'lib/PhpParser/Node/Stmt/While_.php', - 172 => 'lib/PhpParser/NodeDumper.php', - 173 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 174 => 'lib/PhpParser/Parser/Php5.php', - 175 => 'lib/PhpParser/Parser/Php7.php', - 176 => 'lib/PhpParser/ParserAbstract.php', - 177 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 178 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/NodeDumper.php' => - array ( - ), - 'lib/PhpParser/NodeTraverser.php' => - array ( - ), - 'lib/PhpParser/NodeTraverserInterface.php' => - array ( - 0 => 'lib/PhpParser/NodeTraverser.php', - ), - 'lib/PhpParser/NodeVisitor.php' => - array ( - 0 => 'lib/PhpParser/NodeTraverser.php', - 1 => 'lib/PhpParser/NodeTraverserInterface.php', - 2 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 3 => 'lib/PhpParser/NodeVisitorAbstract.php', - ), - 'lib/PhpParser/NodeVisitor/NameResolver.php' => - array ( - ), - 'lib/PhpParser/NodeVisitorAbstract.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - ), - 'lib/PhpParser/Parser.php' => - array ( - 0 => 'lib/PhpParser/Parser/Multiple.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Multiple.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Php5.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Php7.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Tokens.php' => - array ( - 0 => 'lib/PhpParser/Lexer.php', - 1 => 'lib/PhpParser/Lexer/Emulative.php', - ), - 'lib/PhpParser/ParserAbstract.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/ParserFactory.php' => - array ( - ), - 'lib/PhpParser/PrettyPrinter/Standard.php' => - array ( - ), - 'lib/PhpParser/PrettyPrinterAbstract.php' => - array ( - 0 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Serializer.php' => - array ( - 0 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Serializer/XML.php' => - array ( - ), - 'lib/PhpParser/Unserializer.php' => - array ( - 0 => 'lib/PhpParser/Unserializer/XML.php', - ), - 'lib/PhpParser/Unserializer/XML.php' => - array ( - ), - 'lib/bootstrap.php' => - array ( - ), -); diff --git a/tests/e2e/resultCache_3.php b/tests/e2e/resultCache_3.php deleted file mode 100644 index 993f2b65ee..0000000000 --- a/tests/e2e/resultCache_3.php +++ /dev/null @@ -1,2016 +0,0 @@ - - array ( - 0 => 'lib/bootstrap.php', - ), - 'lib/PhpParser/Builder.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Declaration.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderAbstract.php', - 12 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Class_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Declaration.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Trait_.php', - 7 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/FunctionLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Function_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Interface_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Method.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Param.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Property.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Trait_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/Builder/Use_.php' => - array ( - 0 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/BuilderAbstract.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Declaration.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderFactory.php', - ), - 'lib/PhpParser/BuilderFactory.php' => - array ( - ), - 'lib/PhpParser/Comment.php' => - array ( - 0 => 'lib/PhpParser/Builder/Declaration.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Comment/Doc.php', - 4 => 'lib/PhpParser/Lexer.php', - 5 => 'lib/PhpParser/Node.php', - 6 => 'lib/PhpParser/NodeAbstract.php', - 7 => 'lib/PhpParser/NodeDumper.php', - 8 => 'lib/PhpParser/PrettyPrinterAbstract.php', - 9 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Comment/Doc.php' => - array ( - 0 => 'lib/PhpParser/Builder/Declaration.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Comment.php', - 4 => 'lib/PhpParser/Lexer.php', - 5 => 'lib/PhpParser/Node.php', - 6 => 'lib/PhpParser/NodeAbstract.php', - 7 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Error.php' => - array ( - 0 => 'lib/PhpParser/ErrorHandler.php', - 1 => 'lib/PhpParser/ErrorHandler/Collecting.php', - 2 => 'lib/PhpParser/ErrorHandler/Throwing.php', - 3 => 'lib/PhpParser/Lexer.php', - 4 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 5 => 'lib/PhpParser/Node/Scalar/String_.php', - 6 => 'lib/PhpParser/Node/Stmt/Class_.php', - 7 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 8 => 'lib/PhpParser/Parser/Multiple.php', - 9 => 'lib/PhpParser/Parser/Php5.php', - 10 => 'lib/PhpParser/Parser/Php7.php', - 11 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/ErrorHandler.php' => - array ( - 0 => 'lib/PhpParser/ErrorHandler/Collecting.php', - 1 => 'lib/PhpParser/ErrorHandler/Throwing.php', - 2 => 'lib/PhpParser/Lexer.php', - 3 => 'lib/PhpParser/Lexer/Emulative.php', - 4 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 5 => 'lib/PhpParser/Parser.php', - 6 => 'lib/PhpParser/Parser/Multiple.php', - 7 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/ErrorHandler/Collecting.php' => - array ( - ), - 'lib/PhpParser/ErrorHandler/Throwing.php' => - array ( - 0 => 'lib/PhpParser/Lexer.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Multiple.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - ), - 'lib/PhpParser/Lexer.php' => - array ( - 0 => 'lib/PhpParser/Lexer/Emulative.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Lexer/Emulative.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Node.php' => - array ( - 0 => 'lib/PhpParser/Builder.php', - 1 => 'lib/PhpParser/Builder/Class_.php', - 2 => 'lib/PhpParser/Builder/FunctionLike.php', - 3 => 'lib/PhpParser/Builder/Function_.php', - 4 => 'lib/PhpParser/Builder/Interface_.php', - 5 => 'lib/PhpParser/Builder/Method.php', - 6 => 'lib/PhpParser/Builder/Namespace_.php', - 7 => 'lib/PhpParser/Builder/Param.php', - 8 => 'lib/PhpParser/Builder/Property.php', - 9 => 'lib/PhpParser/Builder/Trait_.php', - 10 => 'lib/PhpParser/Builder/Use_.php', - 11 => 'lib/PhpParser/BuilderAbstract.php', - 12 => 'lib/PhpParser/BuilderFactory.php', - 13 => 'lib/PhpParser/Node/Arg.php', - 14 => 'lib/PhpParser/Node/Const_.php', - 15 => 'lib/PhpParser/Node/Expr.php', - 16 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 17 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 18 => 'lib/PhpParser/Node/Expr/Array_.php', - 19 => 'lib/PhpParser/Node/Expr/Assign.php', - 20 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 22 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 23 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 24 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 25 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 26 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 27 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 28 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 29 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 30 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 31 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 32 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 33 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 34 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 51 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 52 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 53 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 54 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 55 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 56 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 57 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 58 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 59 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 60 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 61 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 62 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 63 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 64 => 'lib/PhpParser/Node/Expr/Cast.php', - 65 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 66 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 67 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 68 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 69 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 70 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 71 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 72 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 73 => 'lib/PhpParser/Node/Expr/Clone_.php', - 74 => 'lib/PhpParser/Node/Expr/Closure.php', - 75 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 76 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 77 => 'lib/PhpParser/Node/Expr/Empty_.php', - 78 => 'lib/PhpParser/Node/Expr/Error.php', - 79 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 80 => 'lib/PhpParser/Node/Expr/Eval_.php', - 81 => 'lib/PhpParser/Node/Expr/Exit_.php', - 82 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 83 => 'lib/PhpParser/Node/Expr/Include_.php', - 84 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 85 => 'lib/PhpParser/Node/Expr/Isset_.php', - 86 => 'lib/PhpParser/Node/Expr/List_.php', - 87 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 88 => 'lib/PhpParser/Node/Expr/New_.php', - 89 => 'lib/PhpParser/Node/Expr/PostDec.php', - 90 => 'lib/PhpParser/Node/Expr/PostInc.php', - 91 => 'lib/PhpParser/Node/Expr/PreDec.php', - 92 => 'lib/PhpParser/Node/Expr/PreInc.php', - 93 => 'lib/PhpParser/Node/Expr/Print_.php', - 94 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 95 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 96 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 97 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 98 => 'lib/PhpParser/Node/Expr/Ternary.php', - 99 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 100 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 101 => 'lib/PhpParser/Node/Expr/Variable.php', - 102 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 103 => 'lib/PhpParser/Node/Expr/Yield_.php', - 104 => 'lib/PhpParser/Node/FunctionLike.php', - 105 => 'lib/PhpParser/Node/Name.php', - 106 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 107 => 'lib/PhpParser/Node/Name/Relative.php', - 108 => 'lib/PhpParser/Node/NullableType.php', - 109 => 'lib/PhpParser/Node/Param.php', - 110 => 'lib/PhpParser/Node/Scalar.php', - 111 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 112 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 113 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 114 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 115 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 116 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 117 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 118 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 119 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 120 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 121 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 122 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 123 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 124 => 'lib/PhpParser/Node/Scalar/String_.php', - 125 => 'lib/PhpParser/Node/Stmt.php', - 126 => 'lib/PhpParser/Node/Stmt/Break_.php', - 127 => 'lib/PhpParser/Node/Stmt/Case_.php', - 128 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 129 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 130 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 131 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 132 => 'lib/PhpParser/Node/Stmt/Class_.php', - 133 => 'lib/PhpParser/Node/Stmt/Const_.php', - 134 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 135 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 136 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 137 => 'lib/PhpParser/Node/Stmt/Do_.php', - 138 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 139 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 140 => 'lib/PhpParser/Node/Stmt/Else_.php', - 141 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 142 => 'lib/PhpParser/Node/Stmt/For_.php', - 143 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 144 => 'lib/PhpParser/Node/Stmt/Function_.php', - 145 => 'lib/PhpParser/Node/Stmt/Global_.php', - 146 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 147 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 148 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 149 => 'lib/PhpParser/Node/Stmt/If_.php', - 150 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 151 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 152 => 'lib/PhpParser/Node/Stmt/Label.php', - 153 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 154 => 'lib/PhpParser/Node/Stmt/Nop.php', - 155 => 'lib/PhpParser/Node/Stmt/Property.php', - 156 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 157 => 'lib/PhpParser/Node/Stmt/Return_.php', - 158 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 159 => 'lib/PhpParser/Node/Stmt/Static_.php', - 160 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 161 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 162 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 163 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 164 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 165 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 166 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 167 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 168 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 169 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 170 => 'lib/PhpParser/Node/Stmt/Use_.php', - 171 => 'lib/PhpParser/Node/Stmt/While_.php', - 172 => 'lib/PhpParser/NodeAbstract.php', - 173 => 'lib/PhpParser/NodeDumper.php', - 174 => 'lib/PhpParser/NodeTraverser.php', - 175 => 'lib/PhpParser/NodeTraverserInterface.php', - 176 => 'lib/PhpParser/NodeVisitor.php', - 177 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 178 => 'lib/PhpParser/NodeVisitorAbstract.php', - 179 => 'lib/PhpParser/Parser.php', - 180 => 'lib/PhpParser/Parser/Multiple.php', - 181 => 'lib/PhpParser/Parser/Php5.php', - 182 => 'lib/PhpParser/Parser/Php7.php', - 183 => 'lib/PhpParser/ParserAbstract.php', - 184 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 185 => 'lib/PhpParser/PrettyPrinterAbstract.php', - 186 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Node/Arg.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 1 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 2 => 'lib/PhpParser/Node/Expr/New_.php', - 3 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Const_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 1 => 'lib/PhpParser/Node/Stmt/Const_.php', - 2 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 3 => 'lib/PhpParser/Parser/Php5.php', - 4 => 'lib/PhpParser/Parser/Php7.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr.php' => - array ( - 0 => 'lib/PhpParser/Builder/Param.php', - 1 => 'lib/PhpParser/Builder/Property.php', - 2 => 'lib/PhpParser/BuilderAbstract.php', - 3 => 'lib/PhpParser/Node/Arg.php', - 4 => 'lib/PhpParser/Node/Const_.php', - 5 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 6 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 7 => 'lib/PhpParser/Node/Expr/Array_.php', - 8 => 'lib/PhpParser/Node/Expr/Assign.php', - 9 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 10 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 11 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 12 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 13 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 14 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 15 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 16 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 17 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 18 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 19 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 20 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 22 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 23 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 24 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 25 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 26 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 27 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 28 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 29 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 30 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 31 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 32 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 33 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 34 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 51 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 52 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 53 => 'lib/PhpParser/Node/Expr/Cast.php', - 54 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 55 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 56 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 57 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 58 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 59 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 60 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 61 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 62 => 'lib/PhpParser/Node/Expr/Clone_.php', - 63 => 'lib/PhpParser/Node/Expr/Closure.php', - 64 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 65 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 66 => 'lib/PhpParser/Node/Expr/Empty_.php', - 67 => 'lib/PhpParser/Node/Expr/Error.php', - 68 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 69 => 'lib/PhpParser/Node/Expr/Eval_.php', - 70 => 'lib/PhpParser/Node/Expr/Exit_.php', - 71 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 72 => 'lib/PhpParser/Node/Expr/Include_.php', - 73 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 74 => 'lib/PhpParser/Node/Expr/Isset_.php', - 75 => 'lib/PhpParser/Node/Expr/List_.php', - 76 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 77 => 'lib/PhpParser/Node/Expr/New_.php', - 78 => 'lib/PhpParser/Node/Expr/PostDec.php', - 79 => 'lib/PhpParser/Node/Expr/PostInc.php', - 80 => 'lib/PhpParser/Node/Expr/PreDec.php', - 81 => 'lib/PhpParser/Node/Expr/PreInc.php', - 82 => 'lib/PhpParser/Node/Expr/Print_.php', - 83 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 84 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 85 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 86 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 87 => 'lib/PhpParser/Node/Expr/Ternary.php', - 88 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 89 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 90 => 'lib/PhpParser/Node/Expr/Variable.php', - 91 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 92 => 'lib/PhpParser/Node/Expr/Yield_.php', - 93 => 'lib/PhpParser/Node/Param.php', - 94 => 'lib/PhpParser/Node/Scalar.php', - 95 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 96 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 97 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 98 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 99 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 100 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 101 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 102 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 103 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 104 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 105 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 106 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 107 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 108 => 'lib/PhpParser/Node/Scalar/String_.php', - 109 => 'lib/PhpParser/Node/Stmt/Break_.php', - 110 => 'lib/PhpParser/Node/Stmt/Case_.php', - 111 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 112 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 113 => 'lib/PhpParser/Node/Stmt/Do_.php', - 114 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 115 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 116 => 'lib/PhpParser/Node/Stmt/For_.php', - 117 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 118 => 'lib/PhpParser/Node/Stmt/Global_.php', - 119 => 'lib/PhpParser/Node/Stmt/If_.php', - 120 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 121 => 'lib/PhpParser/Node/Stmt/Return_.php', - 122 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 123 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 124 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 125 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 126 => 'lib/PhpParser/Node/Stmt/While_.php', - 127 => 'lib/PhpParser/NodeDumper.php', - 128 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 129 => 'lib/PhpParser/Parser/Php5.php', - 130 => 'lib/PhpParser/Parser/Php7.php', - 131 => 'lib/PhpParser/ParserAbstract.php', - 132 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 133 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Expr/ArrayDimFetch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ArrayItem.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Node/Expr/Array_.php', - 2 => 'lib/PhpParser/Node/Expr/List_.php', - 3 => 'lib/PhpParser/Parser/Php5.php', - 4 => 'lib/PhpParser/Parser/Php7.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Array_.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Assign.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 1 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 2 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 3 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 4 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 5 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 6 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 7 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 8 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 9 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 10 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 11 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 12 => 'lib/PhpParser/Parser/Php5.php', - 13 => 'lib/PhpParser/Parser/Php7.php', - 14 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Concat.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Div.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Minus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Mod.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Mul.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Plus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/Pow.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/AssignRef.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 1 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 2 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 3 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 4 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 5 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 6 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 7 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 8 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 9 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 10 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 11 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 12 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 13 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 14 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 15 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 16 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 17 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 18 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 19 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 20 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 21 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 22 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 23 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 24 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 25 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 26 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 27 => 'lib/PhpParser/Parser/Php5.php', - 28 => 'lib/PhpParser/Parser/Php7.php', - 29 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Div.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BitwiseNot.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/BooleanNot.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 1 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 2 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 3 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 4 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 5 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 6 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 7 => 'lib/PhpParser/Parser/Php5.php', - 8 => 'lib/PhpParser/Parser/Php7.php', - 9 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Array_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Bool_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Double.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Int_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Object_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/String_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Cast/Unset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ClassConstFetch.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Clone_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Closure.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ClosureUse.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/Closure.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ConstFetch.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Empty_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Error.php' => - array ( - 0 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ErrorSuppress.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Eval_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Exit_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/FuncCall.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Include_.php' => - array ( - 0 => 'lib/PhpParser/NodeDumper.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Instanceof_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Isset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/List_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/MethodCall.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/New_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PostDec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PostInc.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PreDec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PreInc.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Print_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/PropertyFetch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/ShellExec.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/StaticCall.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Ternary.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/UnaryMinus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/UnaryPlus.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Variable.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/YieldFrom.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Expr/Yield_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/FunctionLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/Builder/Trait_.php', - 3 => 'lib/PhpParser/Node/Expr/Closure.php', - 4 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 5 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 6 => 'lib/PhpParser/Node/Stmt/Function_.php', - 7 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 8 => 'lib/PhpParser/Parser/Php5.php', - 9 => 'lib/PhpParser/Parser/Php7.php', - 10 => 'lib/PhpParser/ParserAbstract.php', - 11 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Name.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Param.php', - 7 => 'lib/PhpParser/Builder/Use_.php', - 8 => 'lib/PhpParser/BuilderAbstract.php', - 9 => 'lib/PhpParser/BuilderFactory.php', - 10 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 11 => 'lib/PhpParser/Node/Expr/Closure.php', - 12 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 13 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 14 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 15 => 'lib/PhpParser/Node/Expr/New_.php', - 16 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 17 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 18 => 'lib/PhpParser/Node/FunctionLike.php', - 19 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 20 => 'lib/PhpParser/Node/Name/Relative.php', - 21 => 'lib/PhpParser/Node/NullableType.php', - 22 => 'lib/PhpParser/Node/Param.php', - 23 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 24 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 25 => 'lib/PhpParser/Node/Stmt/Class_.php', - 26 => 'lib/PhpParser/Node/Stmt/Function_.php', - 27 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 28 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 29 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 30 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 31 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 32 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 33 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 34 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 35 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 36 => 'lib/PhpParser/Parser/Php5.php', - 37 => 'lib/PhpParser/Parser/Php7.php', - 38 => 'lib/PhpParser/ParserAbstract.php', - 39 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 40 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Name/FullyQualified.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Name/Relative.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/NullableType.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/Builder/Function_.php', - 2 => 'lib/PhpParser/Builder/Method.php', - 3 => 'lib/PhpParser/Builder/Param.php', - 4 => 'lib/PhpParser/BuilderAbstract.php', - 5 => 'lib/PhpParser/Node/Expr/Closure.php', - 6 => 'lib/PhpParser/Node/FunctionLike.php', - 7 => 'lib/PhpParser/Node/Param.php', - 8 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 9 => 'lib/PhpParser/Node/Stmt/Function_.php', - 10 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 11 => 'lib/PhpParser/Parser/Php7.php', - 12 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Param.php' => - array ( - 0 => 'lib/PhpParser/Builder/FunctionLike.php', - 1 => 'lib/PhpParser/Builder/Param.php', - 2 => 'lib/PhpParser/Node/Expr/Closure.php', - 3 => 'lib/PhpParser/Node/FunctionLike.php', - 4 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 5 => 'lib/PhpParser/Node/Stmt/Function_.php', - 6 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 7 => 'lib/PhpParser/Parser/Php5.php', - 8 => 'lib/PhpParser/Parser/Php7.php', - 9 => 'lib/PhpParser/ParserAbstract.php', - 10 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 2 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 3 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 4 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 5 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 6 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 7 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 8 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 9 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 10 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 11 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 12 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 13 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 14 => 'lib/PhpParser/Node/Scalar/String_.php', - 15 => 'lib/PhpParser/Parser/Php5.php', - 16 => 'lib/PhpParser/Parser/Php7.php', - 17 => 'lib/PhpParser/ParserAbstract.php', - 18 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/DNumber.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/Encapsed.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/LNumber.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/ParserAbstract.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst.php' => - array ( - 0 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 1 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 2 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 3 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 4 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 5 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 6 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 7 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 8 => 'lib/PhpParser/Parser/Php5.php', - 9 => 'lib/PhpParser/Parser/Php7.php', - 10 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/File.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Line.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Method.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Scalar/String_.php' => - array ( - 0 => 'lib/PhpParser/BuilderAbstract.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Function_.php', - 2 => 'lib/PhpParser/Builder/Interface_.php', - 3 => 'lib/PhpParser/Builder/Method.php', - 4 => 'lib/PhpParser/Builder/Namespace_.php', - 5 => 'lib/PhpParser/Builder/Property.php', - 6 => 'lib/PhpParser/Builder/Trait_.php', - 7 => 'lib/PhpParser/Builder/Use_.php', - 8 => 'lib/PhpParser/BuilderAbstract.php', - 9 => 'lib/PhpParser/BuilderFactory.php', - 10 => 'lib/PhpParser/Node/Expr/Closure.php', - 11 => 'lib/PhpParser/Node/Expr/New_.php', - 12 => 'lib/PhpParser/Node/FunctionLike.php', - 13 => 'lib/PhpParser/Node/Stmt/Break_.php', - 14 => 'lib/PhpParser/Node/Stmt/Case_.php', - 15 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 16 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 17 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 18 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 19 => 'lib/PhpParser/Node/Stmt/Class_.php', - 20 => 'lib/PhpParser/Node/Stmt/Const_.php', - 21 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 22 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 23 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 24 => 'lib/PhpParser/Node/Stmt/Do_.php', - 25 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 26 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 27 => 'lib/PhpParser/Node/Stmt/Else_.php', - 28 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 29 => 'lib/PhpParser/Node/Stmt/For_.php', - 30 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 31 => 'lib/PhpParser/Node/Stmt/Function_.php', - 32 => 'lib/PhpParser/Node/Stmt/Global_.php', - 33 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 34 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 35 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 36 => 'lib/PhpParser/Node/Stmt/If_.php', - 37 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 38 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 39 => 'lib/PhpParser/Node/Stmt/Label.php', - 40 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 41 => 'lib/PhpParser/Node/Stmt/Nop.php', - 42 => 'lib/PhpParser/Node/Stmt/Property.php', - 43 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 44 => 'lib/PhpParser/Node/Stmt/Return_.php', - 45 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 46 => 'lib/PhpParser/Node/Stmt/Static_.php', - 47 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 48 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 49 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 50 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 51 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 52 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 53 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 54 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 55 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 56 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 57 => 'lib/PhpParser/Node/Stmt/Use_.php', - 58 => 'lib/PhpParser/Node/Stmt/While_.php', - 59 => 'lib/PhpParser/NodeDumper.php', - 60 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 61 => 'lib/PhpParser/Parser/Php5.php', - 62 => 'lib/PhpParser/Parser/Php7.php', - 63 => 'lib/PhpParser/ParserAbstract.php', - 64 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 65 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Break_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Case_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Catch_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassConst.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassLike.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Interface_.php', - 2 => 'lib/PhpParser/Builder/Method.php', - 3 => 'lib/PhpParser/Builder/Property.php', - 4 => 'lib/PhpParser/Builder/Trait_.php', - 5 => 'lib/PhpParser/BuilderAbstract.php', - 6 => 'lib/PhpParser/Node/Expr/New_.php', - 7 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 8 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 9 => 'lib/PhpParser/Node/Stmt/Class_.php', - 10 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 11 => 'lib/PhpParser/Node/Stmt/Property.php', - 12 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 13 => 'lib/PhpParser/NodeDumper.php', - 14 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 15 => 'lib/PhpParser/Parser/Php5.php', - 16 => 'lib/PhpParser/Parser/Php7.php', - 17 => 'lib/PhpParser/ParserAbstract.php', - 18 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ClassMethod.php' => - array ( - 0 => 'lib/PhpParser/Builder/Method.php', - 1 => 'lib/PhpParser/Builder/Trait_.php', - 2 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 3 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/ParserAbstract.php', - 7 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Class_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/Method.php', - 2 => 'lib/PhpParser/Builder/Property.php', - 3 => 'lib/PhpParser/BuilderAbstract.php', - 4 => 'lib/PhpParser/Node/Expr/New_.php', - 5 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 6 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 7 => 'lib/PhpParser/Node/Stmt/Property.php', - 8 => 'lib/PhpParser/NodeDumper.php', - 9 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 10 => 'lib/PhpParser/Parser/Php5.php', - 11 => 'lib/PhpParser/Parser/Php7.php', - 12 => 'lib/PhpParser/ParserAbstract.php', - 13 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Const_.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Continue_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/DeclareDeclare.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Declare_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Do_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Echo_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/ElseIf_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/If_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Else_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/If_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Finally_.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/For_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Foreach_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Function_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Function_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Global_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Goto_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/GroupUse.php' => - array ( - 0 => 'lib/PhpParser/NodeDumper.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/HaltCompiler.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/If_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/InlineHTML.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 4 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Interface_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Interface_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Label.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Namespace_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Namespace_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 6 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Nop.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 4 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/Node/Stmt/Property.php' => - array ( - 0 => 'lib/PhpParser/Builder/Property.php', - 1 => 'lib/PhpParser/Builder/Trait_.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/ParserAbstract.php', - 5 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/PropertyProperty.php' => - array ( - 0 => 'lib/PhpParser/Builder/Property.php', - 1 => 'lib/PhpParser/Node/Stmt/Property.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Return_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/StaticVar.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/Static_.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Static_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Switch_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Throw_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUse.php' => - array ( - 0 => 'lib/PhpParser/Builder/Trait_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php' => - array ( - 0 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 1 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 2 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 3 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 4 => 'lib/PhpParser/Parser/Php5.php', - 5 => 'lib/PhpParser/Parser/Php7.php', - 6 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Trait_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Trait_.php', - 1 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 2 => 'lib/PhpParser/Parser/Php5.php', - 3 => 'lib/PhpParser/Parser/Php7.php', - 4 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/TryCatch.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserAbstract.php', - 3 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Unset_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/UseUse.php' => - array ( - 0 => 'lib/PhpParser/Builder/Use_.php', - 1 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 2 => 'lib/PhpParser/Node/Stmt/Use_.php', - 3 => 'lib/PhpParser/NodeDumper.php', - 4 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 5 => 'lib/PhpParser/Parser/Php5.php', - 6 => 'lib/PhpParser/Parser/Php7.php', - 7 => 'lib/PhpParser/ParserAbstract.php', - 8 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/Use_.php' => - array ( - 0 => 'lib/PhpParser/Builder/Use_.php', - 1 => 'lib/PhpParser/BuilderFactory.php', - 2 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 3 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 4 => 'lib/PhpParser/NodeDumper.php', - 5 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 6 => 'lib/PhpParser/Parser/Php5.php', - 7 => 'lib/PhpParser/Parser/Php7.php', - 8 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Node/Stmt/While_.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/NodeAbstract.php' => - array ( - 0 => 'lib/PhpParser/Builder/Class_.php', - 1 => 'lib/PhpParser/Builder/FunctionLike.php', - 2 => 'lib/PhpParser/Builder/Function_.php', - 3 => 'lib/PhpParser/Builder/Interface_.php', - 4 => 'lib/PhpParser/Builder/Method.php', - 5 => 'lib/PhpParser/Builder/Namespace_.php', - 6 => 'lib/PhpParser/Builder/Param.php', - 7 => 'lib/PhpParser/Builder/Property.php', - 8 => 'lib/PhpParser/Builder/Trait_.php', - 9 => 'lib/PhpParser/Builder/Use_.php', - 10 => 'lib/PhpParser/BuilderAbstract.php', - 11 => 'lib/PhpParser/BuilderFactory.php', - 12 => 'lib/PhpParser/Node/Arg.php', - 13 => 'lib/PhpParser/Node/Const_.php', - 14 => 'lib/PhpParser/Node/Expr.php', - 15 => 'lib/PhpParser/Node/Expr/ArrayDimFetch.php', - 16 => 'lib/PhpParser/Node/Expr/ArrayItem.php', - 17 => 'lib/PhpParser/Node/Expr/Array_.php', - 18 => 'lib/PhpParser/Node/Expr/Assign.php', - 19 => 'lib/PhpParser/Node/Expr/AssignOp.php', - 20 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php', - 21 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php', - 22 => 'lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php', - 23 => 'lib/PhpParser/Node/Expr/AssignOp/Concat.php', - 24 => 'lib/PhpParser/Node/Expr/AssignOp/Div.php', - 25 => 'lib/PhpParser/Node/Expr/AssignOp/Minus.php', - 26 => 'lib/PhpParser/Node/Expr/AssignOp/Mod.php', - 27 => 'lib/PhpParser/Node/Expr/AssignOp/Mul.php', - 28 => 'lib/PhpParser/Node/Expr/AssignOp/Plus.php', - 29 => 'lib/PhpParser/Node/Expr/AssignOp/Pow.php', - 30 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php', - 31 => 'lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php', - 32 => 'lib/PhpParser/Node/Expr/AssignRef.php', - 33 => 'lib/PhpParser/Node/Expr/BinaryOp.php', - 34 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php', - 35 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php', - 36 => 'lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php', - 37 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php', - 38 => 'lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php', - 39 => 'lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php', - 40 => 'lib/PhpParser/Node/Expr/BinaryOp/Concat.php', - 41 => 'lib/PhpParser/Node/Expr/BinaryOp/Div.php', - 42 => 'lib/PhpParser/Node/Expr/BinaryOp/Equal.php', - 43 => 'lib/PhpParser/Node/Expr/BinaryOp/Greater.php', - 44 => 'lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php', - 45 => 'lib/PhpParser/Node/Expr/BinaryOp/Identical.php', - 46 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php', - 47 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php', - 48 => 'lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php', - 49 => 'lib/PhpParser/Node/Expr/BinaryOp/Minus.php', - 50 => 'lib/PhpParser/Node/Expr/BinaryOp/Mod.php', - 51 => 'lib/PhpParser/Node/Expr/BinaryOp/Mul.php', - 52 => 'lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php', - 53 => 'lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php', - 54 => 'lib/PhpParser/Node/Expr/BinaryOp/Plus.php', - 55 => 'lib/PhpParser/Node/Expr/BinaryOp/Pow.php', - 56 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php', - 57 => 'lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php', - 58 => 'lib/PhpParser/Node/Expr/BinaryOp/Smaller.php', - 59 => 'lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php', - 60 => 'lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php', - 61 => 'lib/PhpParser/Node/Expr/BitwiseNot.php', - 62 => 'lib/PhpParser/Node/Expr/BooleanNot.php', - 63 => 'lib/PhpParser/Node/Expr/Cast.php', - 64 => 'lib/PhpParser/Node/Expr/Cast/Array_.php', - 65 => 'lib/PhpParser/Node/Expr/Cast/Bool_.php', - 66 => 'lib/PhpParser/Node/Expr/Cast/Double.php', - 67 => 'lib/PhpParser/Node/Expr/Cast/Int_.php', - 68 => 'lib/PhpParser/Node/Expr/Cast/Object_.php', - 69 => 'lib/PhpParser/Node/Expr/Cast/String_.php', - 70 => 'lib/PhpParser/Node/Expr/Cast/Unset_.php', - 71 => 'lib/PhpParser/Node/Expr/ClassConstFetch.php', - 72 => 'lib/PhpParser/Node/Expr/Clone_.php', - 73 => 'lib/PhpParser/Node/Expr/Closure.php', - 74 => 'lib/PhpParser/Node/Expr/ClosureUse.php', - 75 => 'lib/PhpParser/Node/Expr/ConstFetch.php', - 76 => 'lib/PhpParser/Node/Expr/Empty_.php', - 77 => 'lib/PhpParser/Node/Expr/Error.php', - 78 => 'lib/PhpParser/Node/Expr/ErrorSuppress.php', - 79 => 'lib/PhpParser/Node/Expr/Eval_.php', - 80 => 'lib/PhpParser/Node/Expr/Exit_.php', - 81 => 'lib/PhpParser/Node/Expr/FuncCall.php', - 82 => 'lib/PhpParser/Node/Expr/Include_.php', - 83 => 'lib/PhpParser/Node/Expr/Instanceof_.php', - 84 => 'lib/PhpParser/Node/Expr/Isset_.php', - 85 => 'lib/PhpParser/Node/Expr/List_.php', - 86 => 'lib/PhpParser/Node/Expr/MethodCall.php', - 87 => 'lib/PhpParser/Node/Expr/New_.php', - 88 => 'lib/PhpParser/Node/Expr/PostDec.php', - 89 => 'lib/PhpParser/Node/Expr/PostInc.php', - 90 => 'lib/PhpParser/Node/Expr/PreDec.php', - 91 => 'lib/PhpParser/Node/Expr/PreInc.php', - 92 => 'lib/PhpParser/Node/Expr/Print_.php', - 93 => 'lib/PhpParser/Node/Expr/PropertyFetch.php', - 94 => 'lib/PhpParser/Node/Expr/ShellExec.php', - 95 => 'lib/PhpParser/Node/Expr/StaticCall.php', - 96 => 'lib/PhpParser/Node/Expr/StaticPropertyFetch.php', - 97 => 'lib/PhpParser/Node/Expr/Ternary.php', - 98 => 'lib/PhpParser/Node/Expr/UnaryMinus.php', - 99 => 'lib/PhpParser/Node/Expr/UnaryPlus.php', - 100 => 'lib/PhpParser/Node/Expr/Variable.php', - 101 => 'lib/PhpParser/Node/Expr/YieldFrom.php', - 102 => 'lib/PhpParser/Node/Expr/Yield_.php', - 103 => 'lib/PhpParser/Node/FunctionLike.php', - 104 => 'lib/PhpParser/Node/Name.php', - 105 => 'lib/PhpParser/Node/Name/FullyQualified.php', - 106 => 'lib/PhpParser/Node/Name/Relative.php', - 107 => 'lib/PhpParser/Node/NullableType.php', - 108 => 'lib/PhpParser/Node/Param.php', - 109 => 'lib/PhpParser/Node/Scalar.php', - 110 => 'lib/PhpParser/Node/Scalar/DNumber.php', - 111 => 'lib/PhpParser/Node/Scalar/Encapsed.php', - 112 => 'lib/PhpParser/Node/Scalar/EncapsedStringPart.php', - 113 => 'lib/PhpParser/Node/Scalar/LNumber.php', - 114 => 'lib/PhpParser/Node/Scalar/MagicConst.php', - 115 => 'lib/PhpParser/Node/Scalar/MagicConst/Class_.php', - 116 => 'lib/PhpParser/Node/Scalar/MagicConst/Dir.php', - 117 => 'lib/PhpParser/Node/Scalar/MagicConst/File.php', - 118 => 'lib/PhpParser/Node/Scalar/MagicConst/Function_.php', - 119 => 'lib/PhpParser/Node/Scalar/MagicConst/Line.php', - 120 => 'lib/PhpParser/Node/Scalar/MagicConst/Method.php', - 121 => 'lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php', - 122 => 'lib/PhpParser/Node/Scalar/MagicConst/Trait_.php', - 123 => 'lib/PhpParser/Node/Scalar/String_.php', - 124 => 'lib/PhpParser/Node/Stmt.php', - 125 => 'lib/PhpParser/Node/Stmt/Break_.php', - 126 => 'lib/PhpParser/Node/Stmt/Case_.php', - 127 => 'lib/PhpParser/Node/Stmt/Catch_.php', - 128 => 'lib/PhpParser/Node/Stmt/ClassConst.php', - 129 => 'lib/PhpParser/Node/Stmt/ClassLike.php', - 130 => 'lib/PhpParser/Node/Stmt/ClassMethod.php', - 131 => 'lib/PhpParser/Node/Stmt/Class_.php', - 132 => 'lib/PhpParser/Node/Stmt/Const_.php', - 133 => 'lib/PhpParser/Node/Stmt/Continue_.php', - 134 => 'lib/PhpParser/Node/Stmt/DeclareDeclare.php', - 135 => 'lib/PhpParser/Node/Stmt/Declare_.php', - 136 => 'lib/PhpParser/Node/Stmt/Do_.php', - 137 => 'lib/PhpParser/Node/Stmt/Echo_.php', - 138 => 'lib/PhpParser/Node/Stmt/ElseIf_.php', - 139 => 'lib/PhpParser/Node/Stmt/Else_.php', - 140 => 'lib/PhpParser/Node/Stmt/Finally_.php', - 141 => 'lib/PhpParser/Node/Stmt/For_.php', - 142 => 'lib/PhpParser/Node/Stmt/Foreach_.php', - 143 => 'lib/PhpParser/Node/Stmt/Function_.php', - 144 => 'lib/PhpParser/Node/Stmt/Global_.php', - 145 => 'lib/PhpParser/Node/Stmt/Goto_.php', - 146 => 'lib/PhpParser/Node/Stmt/GroupUse.php', - 147 => 'lib/PhpParser/Node/Stmt/HaltCompiler.php', - 148 => 'lib/PhpParser/Node/Stmt/If_.php', - 149 => 'lib/PhpParser/Node/Stmt/InlineHTML.php', - 150 => 'lib/PhpParser/Node/Stmt/Interface_.php', - 151 => 'lib/PhpParser/Node/Stmt/Label.php', - 152 => 'lib/PhpParser/Node/Stmt/Namespace_.php', - 153 => 'lib/PhpParser/Node/Stmt/Nop.php', - 154 => 'lib/PhpParser/Node/Stmt/Property.php', - 155 => 'lib/PhpParser/Node/Stmt/PropertyProperty.php', - 156 => 'lib/PhpParser/Node/Stmt/Return_.php', - 157 => 'lib/PhpParser/Node/Stmt/StaticVar.php', - 158 => 'lib/PhpParser/Node/Stmt/Static_.php', - 159 => 'lib/PhpParser/Node/Stmt/Switch_.php', - 160 => 'lib/PhpParser/Node/Stmt/Throw_.php', - 161 => 'lib/PhpParser/Node/Stmt/TraitUse.php', - 162 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation.php', - 163 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php', - 164 => 'lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php', - 165 => 'lib/PhpParser/Node/Stmt/Trait_.php', - 166 => 'lib/PhpParser/Node/Stmt/TryCatch.php', - 167 => 'lib/PhpParser/Node/Stmt/Unset_.php', - 168 => 'lib/PhpParser/Node/Stmt/UseUse.php', - 169 => 'lib/PhpParser/Node/Stmt/Use_.php', - 170 => 'lib/PhpParser/Node/Stmt/While_.php', - 171 => 'lib/PhpParser/NodeDumper.php', - 172 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 173 => 'lib/PhpParser/Parser/Php5.php', - 174 => 'lib/PhpParser/Parser/Php7.php', - 175 => 'lib/PhpParser/ParserAbstract.php', - 176 => 'lib/PhpParser/PrettyPrinter/Standard.php', - 177 => 'lib/PhpParser/PrettyPrinterAbstract.php', - ), - 'lib/PhpParser/NodeDumper.php' => - array ( - ), - 'lib/PhpParser/NodeTraverser.php' => - array ( - ), - 'lib/PhpParser/NodeTraverserInterface.php' => - array ( - 0 => 'lib/PhpParser/NodeTraverser.php', - ), - 'lib/PhpParser/NodeVisitor.php' => - array ( - 0 => 'lib/PhpParser/NodeTraverser.php', - 1 => 'lib/PhpParser/NodeTraverserInterface.php', - 2 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - 3 => 'lib/PhpParser/NodeVisitorAbstract.php', - ), - 'lib/PhpParser/NodeVisitor/NameResolver.php' => - array ( - ), - 'lib/PhpParser/NodeVisitorAbstract.php' => - array ( - 0 => 'lib/PhpParser/NodeVisitor/NameResolver.php', - ), - 'lib/PhpParser/Parser.php' => - array ( - 0 => 'lib/PhpParser/Parser/Multiple.php', - 1 => 'lib/PhpParser/Parser/Php5.php', - 2 => 'lib/PhpParser/Parser/Php7.php', - 3 => 'lib/PhpParser/ParserAbstract.php', - 4 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Multiple.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Php5.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Php7.php' => - array ( - 0 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/Parser/Tokens.php' => - array ( - 0 => 'lib/PhpParser/Lexer.php', - 1 => 'lib/PhpParser/Lexer/Emulative.php', - ), - 'lib/PhpParser/ParserAbstract.php' => - array ( - 0 => 'lib/PhpParser/Parser/Php5.php', - 1 => 'lib/PhpParser/Parser/Php7.php', - 2 => 'lib/PhpParser/ParserFactory.php', - ), - 'lib/PhpParser/ParserFactory.php' => - array ( - ), - 'lib/PhpParser/PrettyPrinter/Standard.php' => - array ( - ), - 'lib/PhpParser/PrettyPrinterAbstract.php' => - array ( - 0 => 'lib/PhpParser/PrettyPrinter/Standard.php', - ), - 'lib/PhpParser/Serializer.php' => - array ( - 0 => 'lib/PhpParser/Serializer/XML.php', - ), - 'lib/PhpParser/Serializer/XML.php' => - array ( - ), - 'lib/PhpParser/Unserializer.php' => - array ( - 0 => 'lib/PhpParser/Unserializer/XML.php', - ), - 'lib/PhpParser/Unserializer/XML.php' => - array ( - ), -); From e812e1e501ee09cf0e3f48bb06062f946cedf2a0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 16:11:41 +0200 Subject: [PATCH 052/508] Issue bot - let all comments about 2.0.x and PHP-Parser 5 through --- issue-bot/src/Console/EvaluateCommand.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index 0f8d05a8d8..f18941039b 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,10 +158,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { - if (count($toPost) > 20) { - $output->writeln('Too many comments to post, something is probably wrong.'); - return 1; - } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From 9369822dd518e8e6df30da6f1edc2c9a31598aaf Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 21:19:53 +0200 Subject: [PATCH 053/508] Revert "Issue bot - let all comments about 2.0.x and PHP-Parser 5 through" This reverts commit e812e1e501ee09cf0e3f48bb06062f946cedf2a0. --- issue-bot/src/Console/EvaluateCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index f18941039b..0f8d05a8d8 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,6 +158,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { + if (count($toPost) > 20) { + $output->writeln('Too many comments to post, something is probably wrong.'); + return 1; + } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From 1dc48d6c858d22839e6a77aadde9590f07194110 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 21:54:22 +0200 Subject: [PATCH 054/508] Update PHPStan Pro branch --- src/Command/FixerApplication.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Command/FixerApplication.php b/src/Command/FixerApplication.php index 6236c3c63f..e3dc297d4c 100644 --- a/src/Command/FixerApplication.php +++ b/src/Command/FixerApplication.php @@ -300,7 +300,7 @@ private function downloadPhar( ): void { $currentVersion = null; - $branch = '1.1.x'; + $branch = '2.0.x'; if (is_file($pharPath) && is_file($infoPath)) { /** @var array{version: string, date: string, branch?: string} $currentInfo */ $currentInfo = Json::decode(FileReader::read($infoPath), Json::FORCE_ARRAY); From f3ccf44a5149d3355223f4ba625224b099f32a40 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 22:07:11 +0200 Subject: [PATCH 055/508] Remove obsolete tests and skipping conditions --- .../Analyser/AnalyserIntegrationTest.php | 6 - .../Analyser/LegacyNodeScopeResolverTest.php | 37 ----- .../Analyser/NodeScopeResolverTest.php | 16 +-- ...rClosureTypeExtensionArrowFunctionTest.php | 9 -- tests/PHPStan/Analyser/data/array-spread.php | 2 +- .../Analyser/data/arrow-functions-inside.php | 2 +- .../PHPStan/Analyser/data/arrow-functions.php | 2 +- tests/PHPStan/Analyser/data/bug-4902.php | 2 +- .../PHPStan/Analyser/data/coalesce-assign.php | 2 +- tests/PHPStan/Analyser/data/die-73.php | 3 - .../PHPStan/Analyser/data/mb-strlen-php72.php | 56 -------- .../Analyser/data/property-native-types.php | 2 +- .../nsrt/array-filter-arrow-functions.php | 2 +- .../Analyser/nsrt/arrow-function-types.php | 2 +- .../PHPStan/Analyser/nsrt/bug-11311-php72.php | 30 ---- tests/PHPStan/Analyser/nsrt/bug-11311.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-3276.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-4188.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-4339.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-6859.php | 2 +- .../Analyser/nsrt/callable-in-union.php | 2 +- .../Analyser/nsrt/filesystem-functions.php | 2 +- .../nsrt/isset-coalesce-empty-type.php | 2 +- tests/PHPStan/Analyser/nsrt/native-types.php | 2 +- .../nsrt/nullable-closure-parameter.php | 2 +- .../Analyser/nsrt/param-closure-this.php | 2 +- .../nsrt/predefined-constants-php74.php | 2 +- .../nsrt/preg_replace_callback_shapes.php | 2 +- .../PHPStan/Analyser/nsrt/reflection-type.php | 2 +- tests/PHPStan/Composer/AutoloadFilesTest.php | 10 +- .../PHPStan/Generics/data/typeProjections.php | 2 +- .../OptimizedDirectorySourceLocatorTest.php | 4 - ...nexistentOffsetInArrayDimFetchRuleTest.php | 4 - .../Rules/Arrays/data/array-unpacking.php | 2 +- tests/PHPStan/Rules/Arrays/data/bug-6243.php | 2 +- tests/PHPStan/Rules/Arrays/data/bug-8292.php | 2 +- .../nonexistent-offset-coalesce-assign.php | 2 +- .../Rules/Arrays/data/unpack-iterable.php | 2 +- .../Rules/Classes/InstantiationRuleTest.php | 4 - .../PHPStan/Rules/Classes/data/bug-3311a.php | 2 +- tests/PHPStan/Rules/Classes/data/bug-9946.php | 2 +- .../Classes/data/phpstan-internal-class.php | 2 +- .../BooleanNotConstantConditionRuleTest.php | 5 - ...rictComparisonOfDifferentTypesRuleTest.php | 4 - .../Rules/Comparison/data/bug-5969.php | 2 +- .../Rules/Comparison/data/bug-6473.php | 2 +- .../Rules/Comparison/data/bug-8474.php | 2 +- .../Rules/Comparison/data/bug-8516.php | 2 +- .../Rules/Comparison/data/bug-8727.php | 2 +- ...-comparison-last-condition-always-true.php | 2 +- ...trict-comparison-property-native-types.php | 2 +- .../Rules/DeadCode/BetterNoopRuleTest.php | 5 - .../UnusedPrivatePropertyRuleTest.php | 8 -- .../PHPStan/Rules/DeadCode/data/bug-11001.php | 2 +- .../PHPStan/Rules/DeadCode/data/bug-3636.php | 2 +- .../PHPStan/Rules/DeadCode/data/bug-5337.php | 2 +- .../PHPStan/Rules/DeadCode/data/bug-5971.php | 2 +- .../PHPStan/Rules/DeadCode/data/bug-6107.php | 2 +- .../DeadCode/data/unused-private-property.php | 2 +- .../CatchWithUnthrownExceptionRuleTest.php | 16 --- .../TooWideMethodThrowTypeRuleTest.php | 4 - .../Rules/Exceptions/data/bug-6256.php | 2 +- .../Rules/Exceptions/data/bug-6786.php | 2 +- .../Rules/Exceptions/data/bug-6791.php | 2 +- .../ArrowFunctionReturnTypeRuleTest.php | 4 - .../CallToFunctionParametersRuleTest.php | 18 +-- .../Functions/ClosureReturnTypeRuleTest.php | 5 - ...owFunctionDefaultParameterTypeRuleTest.php | 4 - ...reFunctionDefaultParameterTypeRuleTest.php | 4 - .../Functions/data/array_reduce_arrow.php | 2 +- .../Rules/Functions/data/array_walk_arrow.php | 2 +- .../data/arrow-function-attributes.php | 2 +- .../Functions/data/arrow-function-never.php | 2 +- .../data/arrow-functions-return-type.php | 2 +- .../PHPStan/Rules/Functions/data/bug-3261.php | 2 +- .../PHPStan/Rules/Functions/data/bug-3660.php | 2 +- .../PHPStan/Rules/Functions/data/bug-5356.php | 2 +- .../PHPStan/Rules/Functions/data/bug-9697.php | 2 +- ...bug-anonymous-function-method-constant.php | 2 +- .../data/function-call-param-closure-this.php | 2 +- ...default-parameter-type-arrow-functions.php | 2 +- ...patible-default-parameter-type-closure.php | 2 +- .../Rules/Functions/data/uasort_arrow.php | 2 +- .../Rules/Functions/data/uksort_arrow.php | 2 +- .../Rules/Functions/data/usort_arrow.php | 2 +- .../Methods/ConsistentConstructorRuleTest.php | 7 +- .../Rules/Methods/MethodSignatureRuleTest.php | 19 --- .../Methods/OverridingMethodRuleTest.php | 22 --- .../Rules/Methods/ReturnTypeRuleTest.php | 4 - .../Methods/data/arrow-function-bind.php | 2 +- tests/PHPStan/Rules/Methods/data/bug-4083.php | 2 +- tests/PHPStan/Rules/Methods/data/bug-4188.php | 2 +- tests/PHPStan/Rules/Methods/data/bug-5372.php | 2 +- tests/PHPStan/Rules/Methods/data/bug-6023.php | 2 +- tests/PHPStan/Rules/Methods/data/bug-6104.php | 2 +- tests/PHPStan/Rules/Methods/data/bug-6249.php | 2 +- tests/PHPStan/Rules/Methods/data/bug-6423.php | 2 +- tests/PHPStan/Rules/Methods/data/bug-7717.php | 2 +- .../Methods/data/final-private-method.php | 2 +- tests/PHPStan/Rules/PhpDoc/data/bug-4227.php | 2 +- tests/PHPStan/Rules/PhpDoc/data/bug-7240.php | 2 +- .../incompatible-property-native-types.php | 2 +- .../data/template-type-native-type-object.php | 2 +- .../AccessPropertiesInAssignRuleTest.php | 5 - .../Properties/AccessPropertiesRuleTest.php | 3 - ...AccessStaticPropertiesInAssignRuleTest.php | 4 - .../AccessStaticPropertiesRuleTest.php | 3 - ...ValueTypesAssignedToPropertiesRuleTest.php | 4 - ...ReadOnlyByPhpDocPropertyAssignRuleTest.php | 4 - .../TypesAssignedToPropertiesRuleTest.php | 22 --- .../data/access-properties-assign-op.php | 2 +- .../access-static-properties-assign-op.php | 2 +- .../Rules/Properties/data/bug-11275.php | 2 +- .../Rules/Properties/data/bug-3311b.php | 2 +- .../Rules/Properties/data/bug-3572.php | 2 +- .../Rules/Properties/data/bug-5382.php | 2 +- .../Rules/Properties/data/bug-6286.php | 2 +- .../Rules/Properties/data/bug-6333.php | 2 +- .../Rules/Properties/data/bug-6356b.php | 2 +- .../Rules/Properties/data/bug-6757.php | 2 +- .../Rules/Properties/data/bug-7190.php | 2 +- .../Rules/Properties/data/bug-7219.php | 2 +- .../Rules/Properties/data/bug-7933.php | 2 +- .../Rules/Properties/data/bug-8190.php | 2 +- .../Rules/Properties/data/bug-8222.php | 2 +- .../Rules/Properties/data/bug-9131.php | 2 +- .../Rules/Properties/data/bug-9619.php | 2 +- .../Properties/data/efabrica-latte-bug.php | 2 +- ...issing-readonly-property-assign-phpdoc.php | 2 +- .../data/php-82-dynamic-properties-allow.php | 2 +- .../data/php-82-dynamic-properties.php | 2 +- .../data/properties-native-types.php | 2 +- .../Rules/Properties/data/require-extends.php | 2 +- .../Properties/data/require-implements.php | 2 +- ...lized-property-additional-constructors.php | 2 +- ...uninitialized-property-readonly-phpdoc.php | 2 +- .../data/uninitialized-property.php | 2 +- .../Rules/Pure/data/impure-assign-ref.php | 2 +- .../RegularExpressionPatternRuleTest.php | 131 +----------------- .../Rules/TooWideTypehints/data/bug-10684.php | 2 +- .../Rules/TooWideTypehints/data/bug-6158.php | 2 +- .../Rules/TooWideTypehints/data/bug-6175.php | 2 +- .../data/tooWideArrowFunctionReturnType.php | 2 +- .../Rules/Variables/NullCoalesceRuleTest.php | 4 - .../Rules/Variables/data/bug-10151.php | 2 +- .../PHPStan/Rules/Variables/data/bug-7292.php | 2 +- .../PHPStan/Rules/Variables/data/bug-7724.php | 2 +- .../defined-variables-arrow-functions.php | 2 +- .../defined-variables-coalesce-assign.php | 2 +- .../data/isset-native-property-types.php | 2 +- .../Variables/data/null-coalesce-assign.php | 2 +- .../data/variable-certainty-null-assign.php | 2 +- .../PHPStan/Rules/WarningEmittingRuleTest.php | 5 - 153 files changed, 126 insertions(+), 601 deletions(-) delete mode 100644 tests/PHPStan/Analyser/data/die-73.php delete mode 100644 tests/PHPStan/Analyser/data/mb-strlen-php72.php delete mode 100644 tests/PHPStan/Analyser/nsrt/bug-11311-php72.php diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index e3a3997bf3..70781bf86c 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -411,9 +411,6 @@ public function testFunctionThatExistsOn72AndLater(): void public function testBug4715(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $errors = $this->runAnalyse(__DIR__ . '/data/bug-4715.php'); $this->assertNoErrors($errors); } @@ -1368,9 +1365,6 @@ public function testBug10979(): void public function testBug11026(): void { - if (PHP_VERSION_ID < 70300) { - $this->markTestSkipped('Test requires PHP 7.3.'); - } $errors = $this->runAnalyse(__DIR__ . '/data/bug-11026.php'); $this->assertNoErrors($errors); } diff --git a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php index f75730744d..98080c2b67 100644 --- a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php @@ -8914,9 +8914,6 @@ public function testPhp73Functions( string $expression, ): void { - if (PHP_VERSION_ID < 70300) { - $this->markTestSkipped('Test requires PHP 7.3'); - } $this->assertTypes( __DIR__ . '/data/php73_functions.php', $description, @@ -9046,9 +9043,6 @@ public function testPhp74Functions( string $expression, ): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4'); - } $this->assertTypes( __DIR__ . '/data/php74_functions.php', $description, @@ -9480,34 +9474,6 @@ public function testArraySpread( ); } - public function dataPhp74FunctionsIn73(): array - { - return [ - [ - 'mixed', - 'password_algos()', - ], - ]; - } - - /** - * @dataProvider dataPhp74FunctionsIn73 - */ - public function testPhp74FunctionsIn73( - string $description, - string $expression, - ): void - { - if (PHP_VERSION_ID >= 70400) { - $this->markTestSkipped('Test does not run on PHP >= 7.4.'); - } - $this->assertTypes( - __DIR__ . '/data/die-73.php', - $description, - $expression, - ); - } - public function dataPhp74FunctionsIn74(): array { return [ @@ -9526,9 +9492,6 @@ public function testPhp74FunctionsIn74( string $expression, ): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->assertTypes( __DIR__ . '/data/die-74.php', $description, diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 56017066d1..dce99191c0 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -20,7 +20,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/enum-reflection-php81.php'); } - if (PHP_VERSION_ID < 80000 && PHP_VERSION_ID >= 70400) { + if (PHP_VERSION_ID < 80000) { yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4902.php'); } @@ -29,8 +29,6 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/mb-strlen-php82.php'); } elseif (PHP_VERSION_ID >= 80000) { yield from $this->gatherAssertTypes(__DIR__ . '/data/mb-strlen-php8.php'); - } elseif (PHP_VERSION_ID < 70300) { - yield from $this->gatherAssertTypes(__DIR__ . '/data/mb-strlen-php72.php'); } else { yield from $this->gatherAssertTypes(__DIR__ . '/data/mb-strlen-php73.php'); } @@ -69,9 +67,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Functions/data/varying-acceptor.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/bug-4415.php'); - if (PHP_VERSION_ID >= 70400) { - yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/bug-5372.php'); - } + yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/bug-5372.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Arrays/data/bug-5372_2.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/bug-5562.php'); @@ -85,9 +81,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/new-in-initializers-runtime.php'); } - if (PHP_VERSION_ID >= 70400) { - yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-6473.php'); - } + yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-6473.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/filter-iterator-child-class.php'); @@ -125,9 +119,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Arrays/data/bug-7469.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Variables/data/bug-3391.php'); - if (PHP_VERSION_ID >= 70400) { - yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Functions/data/bug-anonymous-function-method-constant.php'); - } + yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Functions/data/bug-anonymous-function-method-constant.php'); if (PHP_VERSION_ID >= 80200) { yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/true-typehint.php'); diff --git a/tests/PHPStan/Analyser/ParameterClosureTypeExtensionArrowFunctionTest.php b/tests/PHPStan/Analyser/ParameterClosureTypeExtensionArrowFunctionTest.php index 025513c4bf..c3476c32fa 100644 --- a/tests/PHPStan/Analyser/ParameterClosureTypeExtensionArrowFunctionTest.php +++ b/tests/PHPStan/Analyser/ParameterClosureTypeExtensionArrowFunctionTest.php @@ -3,17 +3,12 @@ namespace PHPStan\Analyser; use PHPStan\Testing\TypeInferenceTestCase; -use const PHP_VERSION_ID; class ParameterClosureTypeExtensionArrowFunctionTest extends TypeInferenceTestCase { public function dataFileAsserts(): iterable { - if (PHP_VERSION_ID < 70400) { - return []; - } - yield from $this->gatherAssertTypes(__DIR__ . '/data/parameter-closure-type-extension-arrow-function.php'); } @@ -27,10 +22,6 @@ public function testFileAsserts( ...$args, ): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->assertFileAsserts($assertType, $file, ...$args); } diff --git a/tests/PHPStan/Analyser/data/array-spread.php b/tests/PHPStan/Analyser/data/array-spread.php index 5bd12fdc38..f752a03270 100644 --- a/tests/PHPStan/Analyser/data/array-spread.php +++ b/tests/PHPStan/Analyser/data/array-spread.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.2 - -namespace MbStrlenPhp72; - -use function PHPStan\Testing\assertType; - -class MbStrlenPhp72 -{ - - /** - * @param non-empty-string $nonEmpty - * @param 'utf-8'|'8bit' $utf8And8bit - * @param 'utf-8'|'foo' $utf8AndInvalidEncoding - * @param '1'|'2'|'5'|'10' $constUnion - * @param 1|2|5|10|123|'1234'|false $constUnionMixed - * @param int|float $intFloat - * @param non-empty-string|int|float $nonEmptyStringIntFloat - * @param ""|false|null $emptyStringFalseNull - * @param ""|bool|null $emptyStringBoolNull - * @param "pass"|"none" $encodingsValidOnlyUntilPhp72 - */ - public function doFoo(int $i, string $s, bool $bool, float $float, $intFloat, $nonEmpty, $nonEmptyStringIntFloat, $emptyStringFalseNull, $emptyStringBoolNull, $constUnion, $constUnionMixed, $utf8And8bit, $utf8AndInvalidEncoding, string $unknownEncoding, $encodingsValidOnlyUntilPhp72) - { - assertType('0', mb_strlen('')); - assertType('5', mb_strlen('hallo')); - assertType('int<0, 1>', mb_strlen($bool)); - assertType('int<1, max>', mb_strlen($i)); - assertType('int<0, max>', mb_strlen($s)); - assertType('int<1, max>', mb_strlen($nonEmpty)); - assertType('int<1, 2>', mb_strlen($constUnion)); - assertType('int<0, 4>', mb_strlen($constUnionMixed)); - assertType('3', mb_strlen(123)); - assertType('1', mb_strlen(true)); - assertType('0', mb_strlen(false)); - assertType('0', mb_strlen(null)); - assertType('1', mb_strlen(1.0)); - assertType('4', mb_strlen(1.23)); - assertType('int<1, max>', mb_strlen($float)); - assertType('int<1, max>', mb_strlen($intFloat)); - assertType('int<1, max>', mb_strlen($nonEmptyStringIntFloat)); - assertType('0', mb_strlen($emptyStringFalseNull)); - assertType('int<0, 1>', mb_strlen($emptyStringBoolNull)); - assertType('8', mb_strlen('паляниця', 'utf-8')); - assertType('11', mb_strlen('alias test🤔', 'utf8')); - assertType('false', mb_strlen('', 'invalid encoding')); - assertType('int<5, 6>', mb_strlen('école', $utf8And8bit)); - assertType('5|false', mb_strlen('école', $utf8AndInvalidEncoding)); - assertType('1|3|5|6|false', mb_strlen('école', $unknownEncoding)); - assertType('2|4|5|6|8|false', mb_strlen('מזגן', $unknownEncoding)); - assertType('6|8|12|13|15|18|24|false', mb_strlen('いい天気ですね〜', $unknownEncoding)); - assertType('3|false', mb_strlen(123, $utf8AndInvalidEncoding)); - assertType('3', mb_strlen('foo', $encodingsValidOnlyUntilPhp72)); - } - -} - diff --git a/tests/PHPStan/Analyser/data/property-native-types.php b/tests/PHPStan/Analyser/data/property-native-types.php index 2892179613..87d990b96f 100644 --- a/tests/PHPStan/Analyser/data/property-native-types.php +++ b/tests/PHPStan/Analyser/data/property-native-types.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 +\d+)\.(?\d+)(?:\.(?\d+))?/', $s, $matches, PREG_UNMATCHED_AS_NULL)) { - assertType('array{0: string, major: numeric-string, 1: numeric-string, minor: numeric-string, 2: numeric-string, patch?: numeric-string, 3?: numeric-string}', $matches); - } -} - -function doUnmatchedAsNull(string $s): void { - if (preg_match('/(foo)?(bar)?(baz)?/', $s, $matches, PREG_UNMATCHED_AS_NULL)) { - assertType("array{0: string, 1?: ''|'foo', 2?: ''|'bar', 3?: 'baz'}", $matches); - } - assertType("array{}|array{0: string, 1?: ''|'foo', 2?: ''|'bar', 3?: 'baz'}", $matches); -} - -// see https://3v4l.org/VeDob#veol -function unmatchedAsNullWithOptionalGroup(string $s): void { - if (preg_match('/Price: (£|€)?\d+/', $s, $matches, PREG_UNMATCHED_AS_NULL)) { - assertType("array{0: string, 1?: '£'|'€'}", $matches); - } else { - assertType('array{}', $matches); - } - assertType("array{}|array{0: string, 1?: '£'|'€'}", $matches); -} diff --git a/tests/PHPStan/Analyser/nsrt/bug-11311.php b/tests/PHPStan/Analyser/nsrt/bug-11311.php index 0d2eaec66d..a30f261fae 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-11311.php +++ b/tests/PHPStan/Analyser/nsrt/bug-11311.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 70300) { - array_splice($expectedFiles, 6, 0, [ - $phpunitFunctions, - ]); - } - $expectedFiles = array_map(static fn (string $path): string => $fileHelper->normalizePath($path), $expectedFiles); sort($expectedFiles); diff --git a/tests/PHPStan/Generics/data/typeProjections.php b/tests/PHPStan/Generics/data/typeProjections.php index 8cfe1f92db..555c1a50ae 100644 --- a/tests/PHPStan/Generics/data/typeProjections.php +++ b/tests/PHPStan/Generics/data/typeProjections.php @@ -1,4 +1,4 @@ -= 7.4 +getByType(OptimizedDirectorySourceLocatorFactory::class); $locator = $factory->createByFiles([__DIR__ . '/data/bug-5525.php']); $reflector = new DefaultReflector($locator); diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index bde2d1100e..a31fe488e2 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -687,10 +687,6 @@ public function testBug8068(): void public function testBug6243(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/bug-6243.php'], []); } diff --git a/tests/PHPStan/Rules/Arrays/data/array-unpacking.php b/tests/PHPStan/Rules/Arrays/data/array-unpacking.php index d7d1e64de5..ff2f652cac 100644 --- a/tests/PHPStan/Rules/Arrays/data/array-unpacking.php +++ b/tests/PHPStan/Rules/Arrays/data/array-unpacking.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 +markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/bug-3311a.php'], [ [ 'Parameter #1 $bar of class Bug3311a\Foo constructor expects list, array{1: \'baz\'} given.', diff --git a/tests/PHPStan/Rules/Classes/data/bug-3311a.php b/tests/PHPStan/Rules/Classes/data/bug-3311a.php index d4f646deb5..bb28ed1eb1 100644 --- a/tests/PHPStan/Rules/Classes/data/bug-3311a.php +++ b/tests/PHPStan/Rules/Classes/data/bug-3311a.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 + @@ -126,10 +125,6 @@ public function testTreatPhpDocTypesAsCertainRegression(bool $treatPhpDocTypesAs public function testBug6473(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-6473.php'], []); } diff --git a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php index e1c99901de..ff6e8c9aca 100644 --- a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php @@ -678,10 +678,6 @@ public function testBug8485(): void public function testBug8516(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8516.php'], []); } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-5969.php b/tests/PHPStan/Rules/Comparison/data/bug-5969.php index 87693235ad..b01b9b2412 100644 --- a/tests/PHPStan/Rules/Comparison/data/bug-5969.php +++ b/tests/PHPStan/Rules/Comparison/data/bug-5969.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 + @@ -146,10 +145,6 @@ public function testRuleImpurePoints(): void public function testBug11001(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/bug-11001.php'], []); } diff --git a/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php b/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php index e17c06a69d..3f60827491 100644 --- a/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php +++ b/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php @@ -241,10 +241,6 @@ public function testBug5337(): void public function testBug5971(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->alwaysWrittenTags = []; $this->alwaysReadTags = []; $this->analyse([__DIR__ . '/data/bug-5971.php'], []); @@ -252,10 +248,6 @@ public function testBug5971(): void public function testBug6107(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->alwaysWrittenTags = []; $this->alwaysReadTags = []; $this->analyse([__DIR__ . '/data/bug-6107.php'], []); diff --git a/tests/PHPStan/Rules/DeadCode/data/bug-11001.php b/tests/PHPStan/Rules/DeadCode/data/bug-11001.php index 5351fc8302..4b39b689c1 100644 --- a/tests/PHPStan/Rules/DeadCode/data/bug-11001.php +++ b/tests/PHPStan/Rules/DeadCode/data/bug-11001.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 +markTestSkipped('Test requires PHP 7.3.'); - } - $this->analyse([__DIR__ . '/data/bug-4814.php'], [ [ 'Dead catch - JsonException is never thrown in the try block.', @@ -415,10 +411,6 @@ public function testBug6262(): void public function testBug6256(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/bug-6256.php'], [ [ 'Dead catch - TypeError is never thrown in the try block.', @@ -449,10 +441,6 @@ public function testBug6256(): void public function testBug6791(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/bug-6791.php'], [ [ 'Dead catch - TypeError is never thrown in the try block.', @@ -471,10 +459,6 @@ public function testBug6791(): void public function testBug6786(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/bug-6786.php'], []); } diff --git a/tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php b/tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php index 98c3737887..5a32351986 100644 --- a/tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php @@ -55,10 +55,6 @@ public function testBug6233(): void public function testImmediatelyCalledArrowFunction(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/immediately-called-arrow-function.php'], [ [ 'Method ImmediatelyCalledArrowFunction\ImmediatelyCalledCallback::doFoo2() has InvalidArgumentException in PHPDoc @throws tag but it\'s not thrown.', diff --git a/tests/PHPStan/Rules/Exceptions/data/bug-6256.php b/tests/PHPStan/Rules/Exceptions/data/bug-6256.php index c7cb4766ad..ed14c55755 100644 --- a/tests/PHPStan/Rules/Exceptions/data/bug-6256.php +++ b/tests/PHPStan/Rules/Exceptions/data/bug-6256.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 +markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/bug-anonymous-function-method-constant.php'], []); } diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index 174f8ece4a..7dc89a5f58 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -316,9 +316,6 @@ public function testImplodeOnPhp74(): void 8, ], ]; - if (PHP_VERSION_ID < 70400) { - $errors = []; - } if (PHP_VERSION_ID >= 80000) { $errors = [ [ @@ -333,7 +330,6 @@ public function testImplodeOnPhp74(): void public function testImplodeOnLessThanPhp74(): void { - $errors = []; if (PHP_VERSION_ID >= 80000) { $errors = [ [ @@ -341,7 +337,7 @@ public function testImplodeOnLessThanPhp74(): void 8, ], ]; - } elseif (PHP_VERSION_ID >= 70400) { + } else { $errors = [ [ 'Parameter #1 $glue of function implode expects string, array given.', @@ -815,10 +811,6 @@ public function testExplode(): void public function testProcOpen(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/proc_open.php'], [ [ "Parameter #1 \$command of function proc_open expects list|string, array{something: 'bogus', in: 'here'} given.", @@ -1632,10 +1624,6 @@ public function testDiscussion10454(): void public function testBug10527(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4'); - } - $this->analyse([__DIR__ . '/data/bug-10527.php'], []); } @@ -1660,10 +1648,6 @@ public function testArgon2PasswordHash(): void public function testParamClosureThis(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/function-call-param-closure-this.php'], [ [ 'Parameter #1 $cb of function FunctionCallParamClosureThis\acceptClosure expects bindable closure, static closure given.', diff --git a/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php index 020000b38a..2a7a309e1a 100644 --- a/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php @@ -6,7 +6,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; -use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -131,10 +130,6 @@ public function testBug7220(): void public function testBugFunctionMethodConstants(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/bug-anonymous-function-method-constant.php'], []); } diff --git a/tests/PHPStan/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRuleTest.php b/tests/PHPStan/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRuleTest.php index 9ec40a74a9..b6a79b6817 100644 --- a/tests/PHPStan/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRuleTest.php @@ -4,7 +4,6 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -19,9 +18,6 @@ protected function getRule(): Rule public function testRule(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->analyse([__DIR__ . '/data/incompatible-default-parameter-type-arrow-functions.php'], [ [ 'Default value of the parameter #1 $i (string) of anonymous function is incompatible with type int.', diff --git a/tests/PHPStan/Rules/Functions/IncompatibleClosureFunctionDefaultParameterTypeRuleTest.php b/tests/PHPStan/Rules/Functions/IncompatibleClosureFunctionDefaultParameterTypeRuleTest.php index 8d0506f9fc..88ce97861e 100644 --- a/tests/PHPStan/Rules/Functions/IncompatibleClosureFunctionDefaultParameterTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/IncompatibleClosureFunctionDefaultParameterTypeRuleTest.php @@ -4,7 +4,6 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; -use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -19,9 +18,6 @@ protected function getRule(): Rule public function testRule(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->analyse([__DIR__ . '/data/incompatible-default-parameter-type-closure.php'], [ [ 'Default value of the parameter #1 $i (string) of anonymous function is incompatible with type int.', diff --git a/tests/PHPStan/Rules/Functions/data/array_reduce_arrow.php b/tests/PHPStan/Rules/Functions/data/array_reduce_arrow.php index 0606d7a275..d93d7b6ffc 100644 --- a/tests/PHPStan/Rules/Functions/data/array_reduce_arrow.php +++ b/tests/PHPStan/Rules/Functions/data/array_reduce_arrow.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 + 1, 'bar' => 2]; array_walk( diff --git a/tests/PHPStan/Rules/Functions/data/arrow-function-attributes.php b/tests/PHPStan/Rules/Functions/data/arrow-function-attributes.php index fa1ec0f17a..30f1a93884 100644 --- a/tests/PHPStan/Rules/Functions/data/arrow-function-attributes.php +++ b/tests/PHPStan/Rules/Functions/data/arrow-function-attributes.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 +analyse([__DIR__ . '/data/consistent-constructor.php'], [ [ - sprintf('Parameter #1 $b (int) of method ConsistentConstructor\Bar2::__construct() is not %s with parameter #1 $b (string) of method ConsistentConstructor\Bar::__construct().', PHP_VERSION_ID >= 70400 ? 'contravariant' : 'compatible'), + sprintf('Parameter #1 $b (int) of method ConsistentConstructor\Bar2::__construct() is not %s with parameter #1 $b (string) of method ConsistentConstructor\Bar::__construct().', 'contravariant'), 13, ], [ @@ -40,10 +40,7 @@ public function testRule(): void public function testRuleNoErrors(): void { - $this->analyse( - [__DIR__ . '/data/consistent-constructor-no-errors.php'], - PHP_VERSION_ID < 70400 ? [['Parameter #1 $b (ConsistentConstructorNoErrors\A) of method ConsistentConstructorNoErrors\Baz::__construct() is not compatible with parameter #1 $b (ConsistentConstructorNoErrors\B) of method ConsistentConstructorNoErrors\Foo::__construct().', 49]] : [], - ); + $this->analyse([__DIR__ . '/data/consistent-constructor-no-errors.php'], []); } } diff --git a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php index 93c6a67b9d..cbdac548bc 100644 --- a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php @@ -252,9 +252,6 @@ public function testBug4003(): void public function testBug4017(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->reportMaybes = true; $this->reportStatic = true; $this->analyse([__DIR__ . '/data/bug-4017.php'], []); @@ -504,10 +501,6 @@ public function testBug10184(): void public function testBug10208(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->reportMaybes = true; $this->reportStatic = true; @@ -516,10 +509,6 @@ public function testBug10208(): void public function testBug6462(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->reportMaybes = true; $this->reportStatic = true; @@ -528,10 +517,6 @@ public function testBug6462(): void public function testBug4396(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->reportMaybes = true; $this->reportStatic = true; @@ -540,10 +525,6 @@ public function testBug4396(): void public function testBug3580(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->reportMaybes = true; $this->reportStatic = true; diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index 75f9465e74..916532a7b9 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -559,18 +559,12 @@ public function testBug6264(): void public function testBug7717(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->phpVersionId = PHP_VERSION_ID; $this->analyse([__DIR__ . '/data/bug-7717.php'], []); } public function testBug6104(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->phpVersionId = PHP_VERSION_ID; $this->analyse([__DIR__ . '/data/bug-6104.php'], []); } @@ -624,10 +618,6 @@ public function testBug7859(): void public function testBug8081(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->phpVersionId = PHP_VERSION_ID; $this->analyse([__DIR__ . '/data/bug-8081.php'], [ [ @@ -639,10 +629,6 @@ public function testBug8081(): void public function testBug8500(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->phpVersionId = PHP_VERSION_ID; $this->analyse([__DIR__ . '/data/bug-8500.php'], [ [ @@ -654,10 +640,6 @@ public function testBug8500(): void public function testBug9014(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->phpVersionId = PHP_VERSION_ID; $this->analyse([__DIR__ . '/data/bug-9014.php'], [ [ @@ -684,10 +666,6 @@ public function testBug9135(): void public function testBug10101(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->phpVersionId = PHP_VERSION_ID; $this->analyse([__DIR__ . '/data/bug-10101.php'], [ [ diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index f080bd4be8..d3b5a5a237 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -1033,10 +1033,6 @@ public function testWrongListTip(): void public function testArrowFunctionReturningVoidClosure(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/arrow-function-returning-void-closure.php'], []); } diff --git a/tests/PHPStan/Rules/Methods/data/arrow-function-bind.php b/tests/PHPStan/Rules/Methods/data/arrow-function-bind.php index 449d409b2c..a71fa7d809 100644 --- a/tests/PHPStan/Rules/Methods/data/arrow-function-bind.php +++ b/tests/PHPStan/Rules/Methods/data/arrow-function-bind.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 + @@ -40,10 +39,6 @@ public function testRule(): void public function testRuleAssignOp(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } - $tipText = 'Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property'; $this->analyse([__DIR__ . '/data/access-properties-assign-op.php'], [ [ diff --git a/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php index a07611980b..2809d62a9a 100644 --- a/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php @@ -301,9 +301,6 @@ public function testAccessPropertiesWithoutUnionTypes(): void public function testRuleAssignOp(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } $this->checkThisOnly = false; $this->checkUnionTypes = true; $this->checkDynamicProperties = false; diff --git a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesInAssignRuleTest.php b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesInAssignRuleTest.php index e8cd8306de..593aa13f97 100644 --- a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesInAssignRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesInAssignRuleTest.php @@ -8,7 +8,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; -use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -47,9 +46,6 @@ public function testRule(): void public function testRuleAssignOp(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } $this->analyse([__DIR__ . '/data/access-static-properties-assign-op.php'], [ [ 'Access to an undefined static property AccessStaticProperties\AssignOpNonexistentProperty::$flags.', diff --git a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php index 14e4779f22..0ae3edbc3c 100644 --- a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php @@ -416,9 +416,6 @@ public function testAccessStaticPropertiesPhp82(): void public function testRuleAssignOp(): void { - if (PHP_VERSION_ID < 70400) { - self::markTestSkipped('Test requires PHP 7.4.'); - } $this->analyse([__DIR__ . '/data/access-static-properties-assign-op.php'], [ [ 'Access to an undefined static property AccessStaticProperties\AssignOpNonexistentProperty::$flags.', diff --git a/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php index 5c92162410..7f99a5ae72 100644 --- a/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php @@ -5,7 +5,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; -use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -58,9 +57,6 @@ public function testBug5607(): void public function testBug7933(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->analyse([__DIR__ . '/data/bug-7933.php'], []); } diff --git a/tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php b/tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php index c7a90b03ab..a72e7d23f2 100644 --- a/tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php +++ b/tests/PHPStan/Rules/Properties/MissingReadOnlyByPhpDocPropertyAssignRuleTest.php @@ -59,10 +59,6 @@ private function isEntityId(PropertyReflection $property, string $propertyName): public function testRule(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->analyse([__DIR__ . '/data/missing-readonly-property-assign-phpdoc.php'], [ [ 'Class MissingReadOnlyPropertyAssignPhpDoc\Foo has an uninitialized @readonly property $unassigned. Assign it in the constructor.', diff --git a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php index 09f34d1d40..fea9ffb9e1 100644 --- a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php @@ -315,9 +315,6 @@ public function testBug5804(): void public function testBug6286(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->analyse([__DIR__ . '/data/bug-6286.php'], [ [ 'Property Bug6286\HelloWorld::$details (array{name: string, age: int}) does not accept array{name: string, age: \'Forty-two\'}.', @@ -408,19 +405,12 @@ public function testGenericObjectWithUnspecifiedTemplateTypesLevel8(): void public function testBug5382(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } $this->checkExplicitMixed = false; $this->analyse([__DIR__ . '/data/bug-5382.php'], []); } public function testBug6757(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->checkExplicitMixed = true; $this->analyse([__DIR__ . '/data/bug-6757.php'], []); } @@ -506,10 +496,6 @@ public function testIntegerRangesAndConstants(): void public function testBug3311b(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->checkExplicitMixed = true; $this->analyse([__DIR__ . '/data/bug-3311b.php'], [ [ @@ -528,20 +514,12 @@ public function testBug7789(): void public function testBug9131(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->checkExplicitMixed = true; $this->analyse([__DIR__ . '/data/bug-9131.php'], []); } public function testBug8222(): void { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Test requires PHP 7.4.'); - } - $this->checkExplicitMixed = true; $this->analyse([__DIR__ . '/data/bug-8222.php'], []); } diff --git a/tests/PHPStan/Rules/Properties/data/access-properties-assign-op.php b/tests/PHPStan/Rules/Properties/data/access-properties-assign-op.php index 7af71ae1b8..ddac393d08 100644 --- a/tests/PHPStan/Rules/Properties/data/access-properties-assign-op.php +++ b/tests/PHPStan/Rules/Properties/data/access-properties-assign-op.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 70300) { - $this->markTestSkipped('This test requires PHP < 7.3.0'); - } - - $this->analyse( - [__DIR__ . '/data/valid-regex-pattern.php'], - [ - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 6, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 7, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 11, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 12, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 16, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 17, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 21, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 22, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 26, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 27, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 29, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 29, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 32, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 33, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 35, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 35, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 38, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 39, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 41, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 41, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok', - 43, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 1 in pattern: ~(~', - 43, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok(?:.*)', - 57, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok(?:.*)', - 58, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 7 in pattern: ~((?:.*)~', - 59, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok(?:.*)nono', - 61, - ], - [ - 'Regex pattern is invalid: Delimiter must not be alphanumeric or backslash in pattern: nok(?:.*)nope', - 62, - ], - [ - 'Regex pattern is invalid: Compilation failed: missing ) at offset 7 in pattern: ~((?:.*)~', - 63, - ], - ], - ); - } - - public function testValidRegexPatternAfter73(): void - { - if (PHP_VERSION_ID < 70300) { - $this->markTestSkipped('This test requires PHP >= 7.3.0'); - } - $messagePart = 'alphanumeric or backslash'; if (PHP_VERSION_ID >= 80200) { $messagePart = 'alphanumeric, backslash, or NUL'; diff --git a/tests/PHPStan/Rules/TooWideTypehints/data/bug-10684.php b/tests/PHPStan/Rules/TooWideTypehints/data/bug-10684.php index 1949d4d8b6..4335dabd72 100644 --- a/tests/PHPStan/Rules/TooWideTypehints/data/bug-10684.php +++ b/tests/PHPStan/Rules/TooWideTypehints/data/bug-10684.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 +markTestSkipped('Test requires PHP 7.4.'); - } - $this->treatPhpDocTypesAsCertain = true; $this->strictUnnecessaryNullsafePropertyFetch = false; diff --git a/tests/PHPStan/Rules/Variables/data/bug-10151.php b/tests/PHPStan/Rules/Variables/data/bug-10151.php index f93e860eb8..78d5c4219d 100644 --- a/tests/PHPStan/Rules/Variables/data/bug-10151.php +++ b/tests/PHPStan/Rules/Variables/data/bug-10151.php @@ -1,4 +1,4 @@ -= 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 += 7.4 + @@ -37,10 +36,6 @@ public function processNode(Node $node, Scope $scope): array public function testRule(): void { - if (PHP_VERSION_ID < 70300) { - self::markTestSkipped('For some reason this test does not work on PHP 7.2 with old PHPUnit'); - } - try { $this->analyse([__DIR__ . '/data/empty-file.php'], []); self::fail('Should throw an exception'); From 7fdf5b5d106a996f30ae36f6e27f9e79e892ac2a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 23:10:33 +0200 Subject: [PATCH 056/508] Update PHPStan dependencies --- composer.json | 8 ++--- composer.lock | 91 +++++++++++++++++++++++++-------------------------- 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/composer.json b/composer.json index e4e61cd532..84ed1845a0 100644 --- a/composer.json +++ b/composer.json @@ -57,10 +57,10 @@ "cweagans/composer-patches": "^1.7.3", "ondrejmirtes/simple-downgrader": "^2.0", "php-parallel-lint/php-parallel-lint": "^1.2.0", - "phpstan/phpstan-deprecation-rules": "^1.2", - "phpstan/phpstan-nette": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.6", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-nette": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^9.6", "shipmonk/composer-dependency-analyser": "^1.5", "shipmonk/name-collision-detector": "^2.0" diff --git a/composer.lock b/composer.lock index 0aba247c22..33f2c2e5d0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bba4725ca58df1d370b5aa291335076d", + "content-hash": "3413a4b61ab62bc50a603a5313fda2e9", "packages": [ { "name": "clue/ndjson-react", @@ -4817,26 +4817,26 @@ }, { "name": "phpstan/phpstan-deprecation-rules", - "version": "1.2.0", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "fa8cce7720fa782899a0aa97b6a41225d1bb7b26" + "reference": "4590cf64974274acb3cf683bddfbe59031272949" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/fa8cce7720fa782899a0aa97b6a41225d1bb7b26", - "reference": "fa8cce7720fa782899a0aa97b6a41225d1bb7b26", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/4590cf64974274acb3cf683bddfbe59031272949", + "reference": "4590cf64974274acb3cf683bddfbe59031272949", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.5" + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" }, "type": "phpstan-extension", "extra": { @@ -4858,27 +4858,27 @@ "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", "support": { "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.2.0" + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.x" }, - "time": "2024-04-20T06:39:48+00:00" + "time": "2024-09-04T20:43:23+00:00" }, { "name": "phpstan/phpstan-nette", - "version": "1.3.8", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-nette.git", - "reference": "bc74b8b208b47f163fe55708fcf1a0333247fa79" + "reference": "93a4f025a4d11ffcf9523617cb3c620c5373fe56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-nette/zipball/bc74b8b208b47f163fe55708fcf1a0333247fa79", - "reference": "bc74b8b208b47f163fe55708fcf1a0333247fa79", + "url": "https://api.github.com/repos/phpstan/phpstan-nette/zipball/93a4f025a4d11ffcf9523617cb3c620c5373fe56", + "reference": "93a4f025a4d11ffcf9523617cb3c620c5373fe56", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11.11" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0" }, "conflict": { "nette/application": "<2.3.0", @@ -4892,12 +4892,12 @@ "nette/application": "^3.0", "nette/forms": "^3.0", "nette/utils": "^2.3.0 || ^3.0.0", - "nikic/php-parser": "^4.13.2", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "~9.5.28" + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6" }, + "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { @@ -4919,36 +4919,35 @@ "description": "Nette Framework class reflection extension for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-nette/issues", - "source": "https://github.com/phpstan/phpstan-nette/tree/1.3.8" + "source": "https://github.com/phpstan/phpstan-nette/tree/2.0.x" }, - "time": "2024-08-25T12:11:12+00:00" + "time": "2024-09-04T21:08:28+00:00" }, { "name": "phpstan/phpstan-phpunit", - "version": "1.4.0", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11" + "reference": "3faa60573a32522772e7cda004003b15466e2b5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/f3ea021866f4263f07ca3636bf22c64be9610c11", - "reference": "f3ea021866f4263f07ca3636bf22c64be9610c11", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/3faa60573a32522772e7cda004003b15466e2b5b", + "reference": "3faa60573a32522772e7cda004003b15466e2b5b", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0" }, "conflict": { "phpunit/phpunit": "<7.0" }, "require-dev": { - "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^9.5" + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6" }, "type": "phpstan-extension", "extra": { @@ -4971,35 +4970,35 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.0" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.x" }, - "time": "2024-04-20T06:39:00+00:00" + "time": "2024-09-04T20:57:24+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.6.0", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "363f921dd8441777d4fc137deb99beb486c77df1" + "reference": "8e2c8b0abb83ec35ba2fca475898880f7e700783" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/363f921dd8441777d4fc137deb99beb486c77df1", - "reference": "363f921dd8441777d4fc137deb99beb486c77df1", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/8e2c8b0abb83ec35ba2fca475898880f7e700783", + "reference": "8e2c8b0abb83ec35ba2fca475898880f7e700783", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0" }, "require-dev": { - "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.5" + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" }, + "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { @@ -5020,9 +5019,9 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.0" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-04-20T06:37:51+00:00" + "time": "2024-09-04T21:09:40+00:00" }, { "name": "phpunit/php-code-coverage", From b701c07ec88365dc34440a0c3891f355cf2c67a9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 23:11:06 +0200 Subject: [PATCH 057/508] Update COMPOSER_ROOT_VERSION in workflows --- .github/workflows/apiref.yml | 2 +- .github/workflows/backward-compatibility.yml | 2 +- .github/workflows/build-issue-bot.yml | 2 +- .github/workflows/changelog-generator.yml | 2 +- .github/workflows/checksum-phar.yml | 6 +++--- .github/workflows/e2e-tests.yml | 2 +- .github/workflows/issue-bot.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/phar.yml | 2 +- .github/workflows/reflection-golden-test.yml | 2 +- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/apiref.yml b/.github/workflows/apiref.yml index 32c7417841..7700ceb911 100644 --- a/.github/workflows/apiref.yml +++ b/.github/workflows/apiref.yml @@ -14,7 +14,7 @@ on: - '.github/workflows/apiref.yml' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: apigen-${{ github.ref }} # will be canceled on subsequent pushes in branch diff --git a/.github/workflows/backward-compatibility.yml b/.github/workflows/backward-compatibility.yml index d7651c9202..9078243232 100644 --- a/.github/workflows/backward-compatibility.yml +++ b/.github/workflows/backward-compatibility.yml @@ -12,7 +12,7 @@ on: - '.github/workflows/backward-compatibility.yml' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: bc-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches diff --git a/.github/workflows/build-issue-bot.yml b/.github/workflows/build-issue-bot.yml index 0e541ca5b1..882a0eb6ae 100644 --- a/.github/workflows/build-issue-bot.yml +++ b/.github/workflows/build-issue-bot.yml @@ -15,7 +15,7 @@ on: - '.github/workflows/build-issue-bot.yml' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: build-issue-bot-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches diff --git a/.github/workflows/changelog-generator.yml b/.github/workflows/changelog-generator.yml index bda67d4725..5989cfb021 100644 --- a/.github/workflows/changelog-generator.yml +++ b/.github/workflows/changelog-generator.yml @@ -15,7 +15,7 @@ on: - '.github/workflows/changelog-generator.yml' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: changelog-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches diff --git a/.github/workflows/checksum-phar.yml b/.github/workflows/checksum-phar.yml index b5dc04f6dc..3f2e1b80f9 100644 --- a/.github/workflows/checksum-phar.yml +++ b/.github/workflows/checksum-phar.yml @@ -18,7 +18,7 @@ on: - '.github/workflows/checksum-phar.yml' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: checksum-phar-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches @@ -101,14 +101,14 @@ jobs: - name: "Composer dump" run: "composer install --no-interaction --no-progress" env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" - name: "Compile PHAR for checksum" working-directory: "compiler/build" run: "php box.phar compile --no-parallel" env: PHAR_CHECKSUM: "1" - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" - name: "Re-sign PHAR" run: "php compiler/build/resign.php tmp/phpstan.phar" diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index dd8a44e406..1b32f42e3d 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -19,7 +19,7 @@ on: - 'issue-bot/**' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: e2e-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches diff --git a/.github/workflows/issue-bot.yml b/.github/workflows/issue-bot.yml index 5ef4bd6275..fa9cc1f845 100644 --- a/.github/workflows/issue-bot.yml +++ b/.github/workflows/issue-bot.yml @@ -18,7 +18,7 @@ on: - 'changelog-generator/**' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: run-issue-bot-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bdc15d968a..a262c8e2a2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,7 +9,7 @@ on: - "2.0.x" env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: lint-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index c6534ecd7b..03926a683d 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -11,7 +11,7 @@ on: - '2.0.*' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: phar-${{ github.ref }} # will be canceled on subsequent pushes in both branches and pull requests diff --git a/.github/workflows/reflection-golden-test.yml b/.github/workflows/reflection-golden-test.yml index 2bf67cb14f..39fc0583d5 100644 --- a/.github/workflows/reflection-golden-test.yml +++ b/.github/workflows/reflection-golden-test.yml @@ -19,7 +19,7 @@ on: - 'issue-bot/**' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" REFLECTION_GOLDEN_TEST_FILE: "/tmp/reflection-golden.test" REFLECTION_GOLDEN_SYMBOLS_FILE: "/tmp/reflection-golden-symbols.txt" diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index a0c08f6171..6dc9e9e0da 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -15,7 +15,7 @@ on: - 'apigen/**' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: sa-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5533bd7e6a..25a7bebfd2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ on: - 'issue-bot/**' env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" + COMPOSER_ROOT_VERSION: "2.0.x-dev" concurrency: group: tests-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches From fa25a041d4997eb1fcc857328233793326474b9d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 23:25:17 +0200 Subject: [PATCH 058/508] Fix build --- tests/PHPStan/Rules/Methods/ConsistentConstructorRuleTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/PHPStan/Rules/Methods/ConsistentConstructorRuleTest.php b/tests/PHPStan/Rules/Methods/ConsistentConstructorRuleTest.php index bcec59c628..28b0091af9 100644 --- a/tests/PHPStan/Rules/Methods/ConsistentConstructorRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ConsistentConstructorRuleTest.php @@ -5,7 +5,6 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; use function sprintf; -use const PHP_VERSION_ID; /** @extends RuleTestCase */ class ConsistentConstructorRuleTest extends RuleTestCase From bfa057c19566b82a425ba4fd52de3bfa07d7e21a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 5 Sep 2024 10:16:34 +0200 Subject: [PATCH 059/508] Remove polyfills for unsupported PHP versions --- bin/phpstan | 8 - compiler/build/scoper.inc.php | 4 - composer.json | 5 +- composer.lock | 155 +------------------ tests/PHPStan/Composer/AutoloadFilesTest.php | 2 - 5 files changed, 3 insertions(+), 171 deletions(-) diff --git a/bin/phpstan b/bin/phpstan index bb97758ff6..d4c45e5934 100755 --- a/bin/phpstan +++ b/bin/phpstan @@ -45,8 +45,6 @@ use Symfony\Component\Console\Helper\ProgressBar; || !array_key_exists('a4a119a56e50fbb293281d9a48007e0e', $composerAutoloadFiles) || !array_key_exists('0e6d7bf4a5811bfa5cf40c5ccd6fae6a', $composerAutoloadFiles) || !array_key_exists('e69f7f6ee287b969198c3c9d6777bd38', $composerAutoloadFiles) - || !array_key_exists('0d59ee240a4cd96ddbb4ff164fccea4d', $composerAutoloadFiles) - || !array_key_exists('b686b8e46447868025a15ce5d0cb2634', $composerAutoloadFiles) || !array_key_exists('8825ede83f2f289127722d4e842cf7e8', $composerAutoloadFiles) || !array_key_exists('23c18046f52bef3eea034657bafda50f', $composerAutoloadFiles) ) { @@ -69,12 +67,6 @@ use Symfony\Component\Console\Helper\ProgressBar; // vendor/symfony/polyfill-intl-normalizer/bootstrap.php 'e69f7f6ee287b969198c3c9d6777bd38' => true, - // vendor/symfony/polyfill-php73/bootstrap.php - '0d59ee240a4cd96ddbb4ff164fccea4d' => true, - - // vendor/symfony/polyfill-php74/bootstrap.php - 'b686b8e46447868025a15ce5d0cb2634' => true, - // vendor/symfony/polyfill-intl-grapheme/bootstrap.php '8825ede83f2f289127722d4e842cf7e8' => true, diff --git a/compiler/build/scoper.inc.php b/compiler/build/scoper.inc.php index 5b4a21c5b2..fd867cbb48 100644 --- a/compiler/build/scoper.inc.php +++ b/compiler/build/scoper.inc.php @@ -20,8 +20,6 @@ '../../vendor/symfony/polyfill-php81', '../../vendor/symfony/polyfill-mbstring', '../../vendor/symfony/polyfill-intl-normalizer', - '../../vendor/symfony/polyfill-php73', - '../../vendor/symfony/polyfill-php74', '../../vendor/symfony/polyfill-intl-grapheme', ]) as $file) { if ($file->getPathName() === '../../vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php') { @@ -238,8 +236,6 @@ function (string $filePath, string $prefix, string $content): string { 'Symfony\Polyfill\Php81', 'Symfony\Polyfill\Mbstring', 'Symfony\Polyfill\Intl\Normalizer', - 'Symfony\Polyfill\Php73', - 'Symfony\Polyfill\Php74', 'Symfony\Polyfill\Intl\Grapheme', ], 'expose-global-functions' => false, diff --git a/composer.json b/composer.json index b2feaaa21e..52c510ff2d 100644 --- a/composer.json +++ b/composer.json @@ -41,8 +41,6 @@ "symfony/polyfill-intl-grapheme": "^1.23", "symfony/polyfill-intl-normalizer": "^1.23", "symfony/polyfill-mbstring": "^1.23", - "symfony/polyfill-php73": "^1.23", - "symfony/polyfill-php74": "^1.23", "symfony/polyfill-php80": "^1.23", "symfony/polyfill-php81": "^1.27", "symfony/process": "^5.4.3", @@ -50,7 +48,8 @@ "symfony/string": "^5.4.3" }, "replace": { - "phpstan/phpstan": "self.version" + "phpstan/phpstan": "self.version", + "symfony/polyfill-php73": "*" }, "require-dev": { "brianium/paratest": "^6.5", diff --git a/composer.lock b/composer.lock index eae3007e67..9318843ada 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a7d5c10ae8b0587d4147084f8a0455e8", + "content-hash": "4dde3e8ef5a5e7291597a6d5f2ca13fb", "packages": [ { "name": "clue/ndjson-react", @@ -3715,159 +3715,6 @@ ], "time": "2024-06-19T12:30:46+00:00" }, - { - "name": "symfony/polyfill-php73", - "version": "v1.30.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/ec444d3f3f6505bb28d11afa41e75faadebc10a1", - "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "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": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.30.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-05-31T15:07:36+00:00" - }, - { - "name": "symfony/polyfill-php74", - "version": "v1.30.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php74.git", - "reference": "37f1d1a2fb3ebc494f9f9b0f7e92064b43332321" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php74/zipball/37f1d1a2fb3ebc494f9f9b0f7e92064b43332321", - "reference": "37f1d1a2fb3ebc494f9f9b0f7e92064b43332321", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php74\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.4+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php74/tree/v1.30.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-05-31T15:07:36+00:00" - }, { "name": "symfony/polyfill-php80", "version": "v1.30.0", diff --git a/tests/PHPStan/Composer/AutoloadFilesTest.php b/tests/PHPStan/Composer/AutoloadFilesTest.php index e86af17617..3d735839e3 100644 --- a/tests/PHPStan/Composer/AutoloadFilesTest.php +++ b/tests/PHPStan/Composer/AutoloadFilesTest.php @@ -66,8 +66,6 @@ public function testExpectedFiles(): void 'symfony/polyfill-intl-grapheme/bootstrap.php', // afaik polyfills aren't necessary 'symfony/polyfill-intl-normalizer/bootstrap.php', // afaik polyfills aren't necessary 'symfony/polyfill-mbstring/bootstrap.php', // afaik polyfills aren't necessary - 'symfony/polyfill-php73/bootstrap.php', // afaik polyfills aren't necessary - 'symfony/polyfill-php74/bootstrap.php', // afaik polyfills aren't necessary 'symfony/polyfill-php80/bootstrap.php', // afaik polyfills aren't necessary 'symfony/polyfill-php81/bootstrap.php', // afaik polyfills aren't necessary 'symfony/string/Resources/functions.php', // afaik polyfills aren't necessary From 8acca821f1acbcfbd9499b378eb92a3de5d57f80 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 5 Sep 2024 10:23:10 +0200 Subject: [PATCH 060/508] Fix PHAR compilation --- compiler/src/Console/PrepareCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/Console/PrepareCommand.php b/compiler/src/Console/PrepareCommand.php index 6d23dde7a6..9dbc3e3192 100644 --- a/compiler/src/Console/PrepareCommand.php +++ b/compiler/src/Console/PrepareCommand.php @@ -63,7 +63,7 @@ private function fixComposerJson(string $buildDir): void { $json = json_decode($this->filesystem->read($buildDir . '/composer.json'), true); - unset($json['replace']); + unset($json['replace']['phpstan/phpstan']); $json['name'] = 'phpstan/phpstan'; $json['require']['php'] = '^7.4|^8.0'; From 2edfdb221acec87bf2afc506ff8678509c3daa13 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 5 Sep 2024 10:23:54 +0200 Subject: [PATCH 061/508] Fix build --- build/composer-dependency-analyser.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/composer-dependency-analyser.php b/build/composer-dependency-analyser.php index 7502680e13..79dc694253 100644 --- a/build/composer-dependency-analyser.php +++ b/build/composer-dependency-analyser.php @@ -9,8 +9,6 @@ 'symfony/polyfill-intl-grapheme', 'symfony/polyfill-intl-normalizer', 'symfony/polyfill-mbstring', - 'symfony/polyfill-php73', - 'symfony/polyfill-php74', 'symfony/polyfill-php80', 'symfony/polyfill-php81', ]; From 033eb78ff6e4a06da89e2ed92dc5a955220e2594 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 5 Sep 2024 11:24:38 +0200 Subject: [PATCH 062/508] Simplify code --- src/Rules/FunctionDefinitionCheck.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Rules/FunctionDefinitionCheck.php b/src/Rules/FunctionDefinitionCheck.php index c8e839e478..3942cc1b40 100644 --- a/src/Rules/FunctionDefinitionCheck.php +++ b/src/Rules/FunctionDefinitionCheck.php @@ -712,18 +712,12 @@ private function checkImplicitlyNullableType( if ($type instanceof Identifier && strtolower($type->name) === 'mixed') { return null; } - if ($type instanceof Name && $type->toLowerString() === 'mixed') { - return null; - } if ($type instanceof UnionType) { foreach ($type->types as $innerType) { if ($innerType instanceof Identifier && strtolower($innerType->name) === 'null') { return null; } - if ($innerType instanceof Name && $innerType->toLowerString() === 'null') { - return null; - } } } From 263d5e42e2e734733a718eac427623ad607b5656 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 5 Sep 2024 17:42:04 +0200 Subject: [PATCH 063/508] Fix phar.yml --- .github/workflows/phar.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index 131592080a..03926a683d 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -13,9 +13,6 @@ on: env: COMPOSER_ROOT_VERSION: "2.0.x-dev" -env: - COMPOSER_ROOT_VERSION: "1.12.x-dev" - concurrency: group: phar-${{ github.ref }} # will be canceled on subsequent pushes in both branches and pull requests cancel-in-progress: true From ff910cec6a377c25bc99a79c63dabd761ec26dc4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 6 Sep 2024 13:55:11 +0200 Subject: [PATCH 064/508] Fix Adapter ReflectionEnum tests on PHP 7.4 --- conf/config.neon | 19 ++++ ...tionEnumCaseDynamicReturnTypeExtension.php | 66 +++++++++++ ...flectionEnumDynamicReturnTypeExtension.php | 105 ++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php create mode 100644 src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php diff --git a/conf/config.neon b/conf/config.neon index 4efef75454..02d1fd848e 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -794,6 +794,25 @@ services: - class: PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedSingleFileSourceLocatorRepository + - + class: PHPStan\Reflection\BetterReflection\Type\AdapterReflectionEnumCaseDynamicReturnTypeExtension + arguments: + class: PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Reflection\BetterReflection\Type\AdapterReflectionEnumCaseDynamicReturnTypeExtension + arguments: + class: PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Reflection\BetterReflection\Type\AdapterReflectionEnumDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + - class: PHPStan\Reflection\RequireExtension\RequireExtendsMethodsClassReflectionExtension diff --git a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php new file mode 100644 index 0000000000..8c2f4ca526 --- /dev/null +++ b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php @@ -0,0 +1,66 @@ +class; + } + + public function isMethodSupported(MethodReflection $methodReflection): bool + { + return in_array($methodReflection->getName(), [ + 'getDocComment', + 'getType', + ], true); + } + + public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type + { + if ($this->phpVersion->getVersionId() >= 80000) { + return null; + } + + if ($methodReflection->getName() === 'getDocComment') { + return new UnionType([ + new StringType(), + new ConstantBooleanType(false), + ]); + } + + if ($methodReflection->getName() === 'getType') { + return new UnionType([ + new ObjectType(ReflectionIntersectionType::class), + new ObjectType(ReflectionNamedType::class), + new ObjectType(ReflectionUnionType::class), + new NullType(), + ]); + } + + return null; + } + +} diff --git a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php new file mode 100644 index 0000000000..40c8f05b92 --- /dev/null +++ b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php @@ -0,0 +1,105 @@ +getName(), [ + 'getFileName', + 'getStartLine', + 'getEndLine', + 'getDocComment', + 'getReflectionConstant', + 'getParentClass', + 'getExtensionName', + 'getBackingType', + ], true); + } + + public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type + { + if ($this->phpVersion->getVersionId() >= 80000) { + return null; + } + + if (in_array($methodReflection->getName(), ['getFileName', 'getExtensionName'], true)) { + return new UnionType([ + new IntersectionType([ + new StringType(), + new AccessoryNonEmptyStringType(), + ]), + new ConstantBooleanType(false), + ]); + } + + if ($methodReflection->getName() === 'getDocComment') { + return new UnionType([ + new StringType(), + new ConstantBooleanType(false), + ]); + } + + if (in_array($methodReflection->getName(), ['getStartLine', 'getEndLine'], true)) { + return new UnionType([ + new IntegerType(), + new ConstantBooleanType(false), + ]); + } + + if ($methodReflection->getName() === 'getReflectionConstant') { + return new UnionType([ + new ObjectType(ReflectionClassConstant::class), + new ConstantBooleanType(false), + ]); + } + + if ($methodReflection->getName() === 'getParentClass') { + return new UnionType([ + new ObjectType(ReflectionClass::class), + new ConstantBooleanType(false), + ]); + } + + if ($methodReflection->getName() === 'getBackingType') { + return new UnionType([ + new ObjectType(ReflectionNamedType::class), + new NullType(), + ]); + } + + return null; + } + +} From 3c0c82508701d7711b5975feb28f3bb72c0993ea Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 6 Sep 2024 14:07:42 +0200 Subject: [PATCH 065/508] Final --- .../AdapterReflectionEnumCaseDynamicReturnTypeExtension.php | 2 +- .../Type/AdapterReflectionEnumDynamicReturnTypeExtension.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php index 8c2f4ca526..5ab5e725b9 100644 --- a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php +++ b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php @@ -18,7 +18,7 @@ use PHPStan\Type\UnionType; use function in_array; -class AdapterReflectionEnumCaseDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension +final class AdapterReflectionEnumCaseDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension { public function __construct(private PhpVersion $phpVersion, private string $class) diff --git a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php index 40c8f05b92..f0e25e9296 100644 --- a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php +++ b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php @@ -22,7 +22,7 @@ use PHPStan\Type\UnionType; use function in_array; -class AdapterReflectionEnumDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension +final class AdapterReflectionEnumDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension { public function __construct(private PhpVersion $phpVersion) From 111e47469011551bd39a815724a4c8254df3bb5c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 6 Sep 2024 14:11:27 +0200 Subject: [PATCH 066/508] Fix tests that use `mixed` type --- tests/PHPStan/Analyser/nsrt/array-reverse.php | 4 +++- tests/PHPStan/Analyser/nsrt/bug-11188.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Analyser/nsrt/array-reverse.php b/tests/PHPStan/Analyser/nsrt/array-reverse.php index 413e1d5f2a..f416539531 100644 --- a/tests/PHPStan/Analyser/nsrt/array-reverse.php +++ b/tests/PHPStan/Analyser/nsrt/array-reverse.php @@ -1,4 +1,6 @@ -= 8.0 + +declare(strict_types = 1); namespace ArrayReverse; diff --git a/tests/PHPStan/Analyser/nsrt/bug-11188.php b/tests/PHPStan/Analyser/nsrt/bug-11188.php index 4c96faacb6..1280620263 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-11188.php +++ b/tests/PHPStan/Analyser/nsrt/bug-11188.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug11188; From 1c2e2090f92395623179bd46313393d9a12cc247 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 6 Sep 2024 20:28:14 +0200 Subject: [PATCH 067/508] Regression test Closes https://github.com/phpstan/phpstan/issues/6861 Closes https://github.com/phpstan/phpstan/issues/5629 --- .../UnknownMixedTypeOnOlderPhpTest.php | 42 +++++++++++++++++++ .../Analyser/data/unknown-mixed-type.php | 13 ++++++ .../PHPStan/Analyser/unknown-mixed-type.neon | 2 + 3 files changed, 57 insertions(+) create mode 100644 tests/PHPStan/Analyser/UnknownMixedTypeOnOlderPhpTest.php create mode 100644 tests/PHPStan/Analyser/data/unknown-mixed-type.php create mode 100644 tests/PHPStan/Analyser/unknown-mixed-type.neon diff --git a/tests/PHPStan/Analyser/UnknownMixedTypeOnOlderPhpTest.php b/tests/PHPStan/Analyser/UnknownMixedTypeOnOlderPhpTest.php new file mode 100644 index 0000000000..3c83a57e57 --- /dev/null +++ b/tests/PHPStan/Analyser/UnknownMixedTypeOnOlderPhpTest.php @@ -0,0 +1,42 @@ + + */ +class UnknownMixedTypeOnOlderPhpTest extends RuleTestCase +{ + + protected function getRule(): TRule + { + return self::getContainer()->getByType(ExistingClassesInTypehintsRule::class); + } + + public function testMixedUnknownType(): void + { + $this->analyse([__DIR__ . '/data/unknown-mixed-type.php'], [ + [ + 'Parameter $m of method UnknownMixedType\Foo::doFoo() has invalid type UnknownMixedType\mixed.', + 8, + ], + [ + 'Method UnknownMixedType\Foo::doFoo() has invalid return type UnknownMixedType\mixed.', + 8, + ], + ]); + } + + public static function getAdditionalConfigFiles(): array + { + return array_merge(parent::getAdditionalConfigFiles(), [ + __DIR__ . '/unknown-mixed-type.neon', + ]); + } + +} diff --git a/tests/PHPStan/Analyser/data/unknown-mixed-type.php b/tests/PHPStan/Analyser/data/unknown-mixed-type.php new file mode 100644 index 0000000000..d603b6d3ef --- /dev/null +++ b/tests/PHPStan/Analyser/data/unknown-mixed-type.php @@ -0,0 +1,13 @@ + Date: Fri, 6 Sep 2024 20:34:13 +0200 Subject: [PATCH 068/508] Test block statement --- .../PHPStan/Analyser/nsrt/block-statement.php | 22 +++++++++++++++++++ tests/PHPStan/Rules/Cast/EchoRuleTest.php | 4 ++++ tests/PHPStan/Rules/Cast/data/echo.php | 6 +++++ 3 files changed, 32 insertions(+) create mode 100644 tests/PHPStan/Analyser/nsrt/block-statement.php diff --git a/tests/PHPStan/Analyser/nsrt/block-statement.php b/tests/PHPStan/Analyser/nsrt/block-statement.php new file mode 100644 index 0000000000..fc752007d8 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/block-statement.php @@ -0,0 +1,22 @@ + Date: Fri, 6 Sep 2024 20:39:08 +0200 Subject: [PATCH 069/508] New option: `polluteScopeWithBlock` --- conf/config.neon | 2 ++ conf/parametersSchema.neon | 1 + src/Analyser/NodeScopeResolver.php | 16 ++++++++- src/Testing/RuleTestCase.php | 1 + src/Testing/TypeInferenceTestCase.php | 1 + tests/PHPStan/Analyser/AnalyserTest.php | 1 + .../DoNotPolluteScopeWithBlockTest.php | 36 +++++++++++++++++++ .../data/do-not-pollute-scope-with-block.php | 26 ++++++++++++++ .../do-not-pollute-scope-with-block.neon | 2 ++ 9 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 tests/PHPStan/Analyser/DoNotPolluteScopeWithBlockTest.php create mode 100644 tests/PHPStan/Analyser/data/do-not-pollute-scope-with-block.php create mode 100644 tests/PHPStan/Analyser/do-not-pollute-scope-with-block.neon diff --git a/conf/config.neon b/conf/config.neon index 02d1fd848e..eda169fc20 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -154,6 +154,7 @@ parameters: phpVersion: null polluteScopeWithLoopInitialAssignments: true polluteScopeWithAlwaysIterableForeach: true + polluteScopeWithBlock: true propertyAlwaysWrittenTags: [] propertyAlwaysReadTags: [] fixerTmpDir: %pro.tmpDir% #unused @@ -544,6 +545,7 @@ services: reflector: @nodeScopeResolverReflector polluteScopeWithLoopInitialAssignments: %polluteScopeWithLoopInitialAssignments% polluteScopeWithAlwaysIterableForeach: %polluteScopeWithAlwaysIterableForeach% + polluteScopeWithBlock: %polluteScopeWithBlock% earlyTerminatingMethodCalls: %earlyTerminatingMethodCalls% earlyTerminatingFunctionCalls: %earlyTerminatingFunctionCalls% implicitThrows: %exceptions.implicitThrows% diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 8b986b0442..d26f5d2092 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -148,6 +148,7 @@ parametersSchema: phpVersion: schema(anyOf(schema(int(), min(70100), max(80499))), nullable()) polluteScopeWithLoopInitialAssignments: bool() polluteScopeWithAlwaysIterableForeach: bool() + polluteScopeWithBlock: bool() propertyAlwaysWrittenTags: listOf(string()) propertyAlwaysReadTags: listOf(string()) additionalConstructors: listOf(string()) diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 8a992f5c13..360f5ef6eb 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -253,6 +253,7 @@ public function __construct( private readonly ScopeFactory $scopeFactory, private readonly bool $polluteScopeWithLoopInitialAssignments, private readonly bool $polluteScopeWithAlwaysIterableForeach, + private readonly bool $polluteScopeWithBlock, private readonly array $earlyTerminatingMethodCalls, private readonly array $earlyTerminatingFunctionCalls, private readonly array $universalObjectCratesClasses, @@ -1895,7 +1896,20 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void { new ImpurePoint($scope, $stmt, 'betweenPhpTags', 'output between PHP opening and closing tags', true), ]; } elseif ($stmt instanceof Node\Stmt\Block) { - return $this->processStmtNodes($stmt, $stmt->stmts, $scope, $nodeCallback, $context); + $result = $this->processStmtNodes($stmt, $stmt->stmts, $scope, $nodeCallback, $context); + if ($this->polluteScopeWithBlock) { + return $result; + } + + return new StatementResult( + $scope->mergeWith($result->getScope()), + $result->hasYield(), + $result->isAlwaysTerminating(), + $result->getExitPoints(), + $result->getThrowPoints(), + $result->getImpurePoints(), + $result->getEndStatements(), + ); } elseif ($stmt instanceof Node\Stmt\Nop) { $hasYield = false; $throwPoints = $overridingThrowPoints ?? []; diff --git a/src/Testing/RuleTestCase.php b/src/Testing/RuleTestCase.php index b507b05ae6..6e88b1ab68 100644 --- a/src/Testing/RuleTestCase.php +++ b/src/Testing/RuleTestCase.php @@ -99,6 +99,7 @@ private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser self::createScopeFactory($reflectionProvider, $typeSpecifier), $this->shouldPolluteScopeWithLoopInitialAssignments(), $this->shouldPolluteScopeWithAlwaysIterableForeach(), + self::getContainer()->getParameter('polluteScopeWithBlock'), [], [], self::getContainer()->getParameter('universalObjectCratesClasses'), diff --git a/src/Testing/TypeInferenceTestCase.php b/src/Testing/TypeInferenceTestCase.php index 874b601156..df47758569 100644 --- a/src/Testing/TypeInferenceTestCase.php +++ b/src/Testing/TypeInferenceTestCase.php @@ -79,6 +79,7 @@ public static function processFile( self::createScopeFactory($reflectionProvider, $typeSpecifier), self::getContainer()->getParameter('polluteScopeWithLoopInitialAssignments'), self::getContainer()->getParameter('polluteScopeWithAlwaysIterableForeach'), + self::getContainer()->getParameter('polluteScopeWithBlock'), static::getEarlyTerminatingMethodCalls(), static::getEarlyTerminatingFunctionCalls(), self::getContainer()->getParameter('universalObjectCratesClasses'), diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index d59549b9da..a27d75468f 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -735,6 +735,7 @@ private function createAnalyser(bool $enableIgnoreErrorsWithinPhpDocs): Analyser self::createScopeFactory($reflectionProvider, $typeSpecifier), false, true, + true, [], [], [stdClass::class], diff --git a/tests/PHPStan/Analyser/DoNotPolluteScopeWithBlockTest.php b/tests/PHPStan/Analyser/DoNotPolluteScopeWithBlockTest.php new file mode 100644 index 0000000000..cd4ceb5d85 --- /dev/null +++ b/tests/PHPStan/Analyser/DoNotPolluteScopeWithBlockTest.php @@ -0,0 +1,36 @@ +gatherAssertTypes(__DIR__ . '/data/do-not-pollute-scope-with-block.php'); + } + + /** + * @dataProvider dataFileAsserts + * @param mixed ...$args + */ + public function testFileAsserts( + string $assertType, + string $file, + ...$args, + ): void + { + $this->assertFileAsserts($assertType, $file, ...$args); + } + + public static function getAdditionalConfigFiles(): array + { + return [ + __DIR__ . '/../../../conf/bleedingEdge.neon', + __DIR__ . '/do-not-pollute-scope-with-block.neon', + ]; + } + +} diff --git a/tests/PHPStan/Analyser/data/do-not-pollute-scope-with-block.php b/tests/PHPStan/Analyser/data/do-not-pollute-scope-with-block.php new file mode 100644 index 0000000000..d1569b1d5b --- /dev/null +++ b/tests/PHPStan/Analyser/data/do-not-pollute-scope-with-block.php @@ -0,0 +1,26 @@ + Date: Fri, 6 Sep 2024 20:52:41 +0200 Subject: [PATCH 070/508] Update phpstan-strict-rules in issue-bot --- issue-bot/composer.json | 2 +- issue-bot/composer.lock | 41 +++++++++++++++++++---------------------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/issue-bot/composer.json b/issue-bot/composer.json index 92ec4ec6e8..1d35a96375 100644 --- a/issue-bot/composer.json +++ b/issue-bot/composer.json @@ -7,7 +7,7 @@ "league/commonmark": "^2.3", "nette/neon": "^3.3", "nette/utils": "^3.2", - "phpstan/phpstan-strict-rules": "1.6.x-dev", + "phpstan/phpstan-strict-rules": "^2.0", "symfony/console": "^6.1", "symfony/finder": "^6.1" }, diff --git a/issue-bot/composer.lock b/issue-bot/composer.lock index af4a00fca8..9653a2cef4 100644 --- a/issue-bot/composer.lock +++ b/issue-bot/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fa15712157441e401f9e8107ea219d0e", + "content-hash": "6a526cc8f4e310c4a649c65001b30782", "packages": [ { "name": "clue/stream-filter", @@ -1403,20 +1403,20 @@ }, { "name": "phpstan/phpstan", - "version": "1.11.x-dev", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "7a2e524c7bdc18295d62b0ed598cec1166da80ab" + "reference": "946cf18b3e9f64c41d2f62903f8148b3f0b3be41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/7a2e524c7bdc18295d62b0ed598cec1166da80ab", - "reference": "7a2e524c7bdc18295d62b0ed598cec1166da80ab", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/946cf18b3e9f64c41d2f62903f8148b3f0b3be41", + "reference": "946cf18b3e9f64c41d2f62903f8148b3f0b3be41", "shasum": "" }, "require": { - "php": "^7.2|^8.0" + "php": "^7.4|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" @@ -1458,32 +1458,31 @@ "type": "github" } ], - "time": "2024-04-19T14:55:18+00:00" + "time": "2024-09-06T18:47:21+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.6.x-dev", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "c7b4d283fbffd23b9405c01d1f68124739d698f6" + "reference": "5eec39fc6ef36015e6de08949c8e9ae9d64560a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/c7b4d283fbffd23b9405c01d1f68124739d698f6", - "reference": "c7b4d283fbffd23b9405c01d1f68124739d698f6", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/5eec39fc6ef36015e6de08949c8e9ae9d64560a3", + "reference": "5eec39fc6ef36015e6de08949c8e9ae9d64560a3", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.11" + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0" }, "require-dev": { - "nikic/php-parser": "^4.13.0", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.5" + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" }, "default-branch": true, "type": "phpstan-extension", @@ -1506,9 +1505,9 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.x" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-04-19T14:52:46+00:00" + "time": "2024-09-06T18:44:39+00:00" }, { "name": "psr/cache", @@ -4472,9 +4471,7 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": { - "phpstan/phpstan-strict-rules": 20 - }, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { From e738d636e1ac8f0de7f5b7dd945854c8af20b057 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 6 Sep 2024 20:53:15 +0200 Subject: [PATCH 071/508] Update phpstan-strict-rules --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 4af6cdedaf..383b1bf73d 100644 --- a/composer.lock +++ b/composer.lock @@ -4827,12 +4827,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "8e2c8b0abb83ec35ba2fca475898880f7e700783" + "reference": "5eec39fc6ef36015e6de08949c8e9ae9d64560a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/8e2c8b0abb83ec35ba2fca475898880f7e700783", - "reference": "8e2c8b0abb83ec35ba2fca475898880f7e700783", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/5eec39fc6ef36015e6de08949c8e9ae9d64560a3", + "reference": "5eec39fc6ef36015e6de08949c8e9ae9d64560a3", "shasum": "" }, "require": { @@ -4868,7 +4868,7 @@ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-09-04T21:09:40+00:00" + "time": "2024-09-06T18:44:39+00:00" }, { "name": "phpunit/php-code-coverage", From e4f5b2be3148b7dea77082c3a56a1980f0c8236c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 6 Sep 2024 20:53:26 +0200 Subject: [PATCH 072/508] Update phpstan-deprecation-rules --- composer.lock | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index 383b1bf73d..87b3132246 100644 --- a/composer.lock +++ b/composer.lock @@ -4668,12 +4668,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "4590cf64974274acb3cf683bddfbe59031272949" + "reference": "398e2e2d7b71cbdd943c87bd7c7731ad1eeaf1cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/4590cf64974274acb3cf683bddfbe59031272949", - "reference": "4590cf64974274acb3cf683bddfbe59031272949", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/398e2e2d7b71cbdd943c87bd7c7731ad1eeaf1cd", + "reference": "398e2e2d7b71cbdd943c87bd7c7731ad1eeaf1cd", "shasum": "" }, "require": { @@ -4685,6 +4685,7 @@ "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^9.6" }, + "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { @@ -4707,7 +4708,7 @@ "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.x" }, - "time": "2024-09-04T20:43:23+00:00" + "time": "2024-09-06T13:40:51+00:00" }, { "name": "phpstan/phpstan-nette", @@ -4796,6 +4797,7 @@ "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^9.6" }, + "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { From 7928a2a1ea77c017e379ec1bdc90b90cd130a734 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 7 Sep 2024 23:34:08 +0200 Subject: [PATCH 073/508] Update phpdoc-parser to 2.0.x --- composer.json | 2 +- composer.lock | 37 ++++++++++--------- conf/bleedingEdge.neon | 2 - conf/config.neon | 21 +++-------- conf/parametersSchema.neon | 2 - phpstan-baseline.neon | 20 ---------- .../ValidateIgnoredErrorsExtension.php | 7 +++- src/PhpDoc/ConstExprParserFactory.php | 19 ---------- src/PhpDoc/PhpDocNodeResolver.php | 6 +-- src/PhpDoc/TypeNodeResolver.php | 2 +- src/Type/Constant/ConstantStringType.php | 4 +- src/Type/Helper/GetTemplateTypeType.php | 4 +- 12 files changed, 39 insertions(+), 87 deletions(-) delete mode 100644 src/PhpDoc/ConstExprParserFactory.php diff --git a/composer.json b/composer.json index 2cd14e4298..46ba2c3cd6 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.7", "phpstan/php-8-stubs": "0.3.102", - "phpstan/phpdoc-parser": "1.30.0", + "phpstan/phpdoc-parser": "^2.0", "psr/http-message": "^1.1", "react/async": "^3", "react/child-process": "^0.7", diff --git a/composer.lock b/composer.lock index 87b3132246..eb3567da21 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6ddd2ca1209453c124e93e7c5aaae4c0", + "content-hash": "35946ee5494c73903dd91c4abfa4c290", "packages": [ { "name": "clue/ndjson-react", @@ -2282,32 +2282,33 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.30.0", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f" + "reference": "9d57f3db5bba9b0d8d11726389eb8af3126780b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/5ceb0e384997db59f38774bf79c2a6134252c08f", - "reference": "5ceb0e384997db59f38774bf79c2a6134252c08f", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9d57f3db5bba9b0d8d11726389eb8af3126780b4", + "reference": "9d57f3db5bba9b0d8d11726389eb8af3126780b4", "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.1", "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" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2323,9 +2324,9 @@ "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.30.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.x" }, - "time": "2024-08-29T09:54:52+00:00" + "time": "2024-09-07T21:23:59+00:00" }, { "name": "psr/container", @@ -4440,19 +4441,19 @@ "source": { "type": "git", "url": "https://github.com/ondrejmirtes/simple-downgrader.git", - "reference": "dbbf56fab0bc71310ff3766ea204d84f019e99b7" + "reference": "1630e1672948a2b59955d7fa634992dc4331ac00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/simple-downgrader/zipball/dbbf56fab0bc71310ff3766ea204d84f019e99b7", - "reference": "dbbf56fab0bc71310ff3766ea204d84f019e99b7", + "url": "https://api.github.com/repos/ondrejmirtes/simple-downgrader/zipball/1630e1672948a2b59955d7fa634992dc4331ac00", + "reference": "1630e1672948a2b59955d7fa634992dc4331ac00", "shasum": "" }, "require": { "nette/utils": "^3.2.5", "nikic/php-parser": "^5.0", "php": "^7.4|^8.0", - "phpstan/phpdoc-parser": "^1.24.5", + "phpstan/phpdoc-parser": "^2.0", "symfony/console": "^5.4", "symfony/finder": "^5.4" }, @@ -4481,7 +4482,7 @@ "issues": "https://github.com/ondrejmirtes/simple-downgrader/issues", "source": "https://github.com/ondrejmirtes/simple-downgrader/tree/2.x" }, - "time": "2024-02-12T19:24:54+00:00" + "time": "2024-09-07T21:32:41+00:00" }, { "name": "phar-io/manifest", diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 12694539ae..b07884cc2a 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -16,8 +16,6 @@ parameters: consistentConstructor: true checkUnresolvableParameterTypes: true readOnlyByPhpDoc: true - phpDocParserRequireWhitespaceBeforeDescription: true - phpDocParserIncludeLines: true enableIgnoreErrorsWithinPhpDocs: true runtimeReflectionRules: true notAnalysedTrait: true diff --git a/conf/config.neon b/conf/config.neon index ebb430c312..3c6e1d4072 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -51,8 +51,6 @@ parameters: consistentConstructor: false checkUnresolvableParameterTypes: false readOnlyByPhpDoc: false - phpDocParserRequireWhitespaceBeforeDescription: false - phpDocParserIncludeLines: false enableIgnoreErrorsWithinPhpDocs: false runtimeReflectionRules: false notAnalysedTrait: false @@ -416,30 +414,23 @@ services: versionId: %phpVersion% composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% + - + class: PHPStan\PhpDocParser\ParserConfig + arguments: + usedAttributes: + lines: true + - class: PHPStan\PhpDocParser\Lexer\Lexer - class: PHPStan\PhpDocParser\Parser\TypeParser - arguments: - quoteAwareConstExprString: %featureToggles.unescapeStrings% - class: PHPStan\PhpDocParser\Parser\ConstExprParser - factory: @PHPStan\PhpDoc\ConstExprParserFactory::create() - class: PHPStan\PhpDocParser\Parser\PhpDocParser - arguments: - requireWhitespaceBeforeDescription: %featureToggles.phpDocParserRequireWhitespaceBeforeDescription% - preserveTypeAliasesWithInvalidTypes: true - usedAttributes: - lines: %featureToggles.phpDocParserIncludeLines% - - - - class: PHPStan\PhpDoc\ConstExprParserFactory - arguments: - unescapeStrings: %featureToggles.unescapeStrings% - class: PHPStan\PhpDoc\PhpDocInheritanceResolver diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index d26f5d2092..528e437a21 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -46,8 +46,6 @@ parametersSchema: consistentConstructor: bool() checkUnresolvableParameterTypes: bool() readOnlyByPhpDoc: bool() - phpDocParserRequireWhitespaceBeforeDescription: bool() - phpDocParserIncludeLines: bool() enableIgnoreErrorsWithinPhpDocs: bool() runtimeReflectionRules: bool() notAnalysedTrait: bool() diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index cbc07aa2be..b487902192 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -194,21 +194,6 @@ parameters: count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - - - message: "#^Property PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\AssertTagMethodValueNode\\:\\:\\$isEquality \\(bool\\) on left side of \\?\\? is not nullable\\.$#" - count: 1 - path: src/PhpDoc/PhpDocNodeResolver.php - - - - message: "#^Property PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\AssertTagPropertyValueNode\\:\\:\\$isEquality \\(bool\\) on left side of \\?\\? is not nullable\\.$#" - count: 1 - path: src/PhpDoc/PhpDocNodeResolver.php - - - - message: "#^Property PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\AssertTagValueNode\\:\\:\\$isEquality \\(bool\\) on left side of \\?\\? is not nullable\\.$#" - count: 1 - path: src/PhpDoc/PhpDocNodeResolver.php - - message: "#^Method PHPStan\\\\PhpDoc\\\\ResolvedPhpDocBlock\\:\\:getNameScope\\(\\) should return PHPStan\\\\Analyser\\\\NameScope but returns PHPStan\\\\Analyser\\\\NameScope\\|null\\.$#" count: 1 @@ -242,11 +227,6 @@ parameters: count: 2 path: src/PhpDoc/TypeNodeResolver.php - - - message: "#^Property PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\CallableTypeNode\\:\\:\\$templateTypes \\(array\\\\) on left side of \\?\\? is not nullable\\.$#" - count: 1 - path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\Identifier\\\\Exception\\\\InvalidIdentifierName is never thrown in the try block\\.$#" count: 3 diff --git a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php index 71a1e04c07..1973f7e303 100644 --- a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php +++ b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php @@ -20,6 +20,7 @@ use PHPStan\PhpDocParser\Lexer\Lexer; use PHPStan\PhpDocParser\Parser\ConstExprParser; use PHPStan\PhpDocParser\Parser\TypeParser; +use PHPStan\PhpDocParser\ParserConfig; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\PhpVersionStaticAccessor; use PHPStan\Reflection\ReflectionProvider\DirectReflectionProviderProvider; @@ -67,11 +68,13 @@ public function loadConfiguration(): void ReflectionProviderStaticAccessor::registerInstance($reflectionProvider); PhpVersionStaticAccessor::registerInstance(new PhpVersion(PHP_VERSION_ID)); $constantResolver = new ConstantResolver($reflectionProviderProvider, []); + + $phpDocParserConfig = new ParserConfig([]); $ignoredRegexValidator = new IgnoredRegexValidator( $parser, new TypeStringResolver( - new Lexer(), - new TypeParser(new ConstExprParser($builder->parameters['featureToggles']['unescapeStrings'])), + new Lexer($phpDocParserConfig), + new TypeParser($phpDocParserConfig, new ConstExprParser($phpDocParserConfig)), new TypeNodeResolver( new DirectTypeNodeResolverExtensionRegistryProvider( new class implements TypeNodeResolverExtensionRegistry { diff --git a/src/PhpDoc/ConstExprParserFactory.php b/src/PhpDoc/ConstExprParserFactory.php deleted file mode 100644 index 4af1282a78..0000000000 --- a/src/PhpDoc/ConstExprParserFactory.php +++ /dev/null @@ -1,19 +0,0 @@ -unescapeStrings, $this->unescapeStrings); - } - -} diff --git a/src/PhpDoc/PhpDocNodeResolver.php b/src/PhpDoc/PhpDocNodeResolver.php index 402f8c7dd1..75857e5eed 100644 --- a/src/PhpDoc/PhpDocNodeResolver.php +++ b/src/PhpDoc/PhpDocNodeResolver.php @@ -587,19 +587,19 @@ private function resolveAssertTagsFor(PhpDocNode $phpDocNode, NameScope $nameSco foreach ($phpDocNode->getAssertTagValues($tagName) as $assertTagValue) { $type = $this->typeNodeResolver->resolve($assertTagValue->type, $nameScope); $parameter = new AssertTagParameter($assertTagValue->parameter, null, null); - $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality ?? false, true); + $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality, true); } foreach ($phpDocNode->getAssertPropertyTagValues($tagName) as $assertTagValue) { $type = $this->typeNodeResolver->resolve($assertTagValue->type, $nameScope); $parameter = new AssertTagParameter($assertTagValue->parameter, $assertTagValue->property, null); - $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality ?? false, true); + $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality, true); } foreach ($phpDocNode->getAssertMethodTagValues($tagName) as $assertTagValue) { $type = $this->typeNodeResolver->resolve($assertTagValue->type, $nameScope); $parameter = new AssertTagParameter($assertTagValue->parameter, null, $assertTagValue->method); - $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality ?? false, true); + $resolved[] = new AssertTag($if, $type, $parameter, $assertTagValue->isNegated, $assertTagValue->isEquality, true); } return $resolved; diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php index c0fa6c5585..ccfd16f32a 100644 --- a/src/PhpDoc/TypeNodeResolver.php +++ b/src/PhpDoc/TypeNodeResolver.php @@ -894,7 +894,7 @@ private function resolveCallableTypeNode(CallableTypeNode $typeNode, NameScope $ { $templateTags = []; - if (count($typeNode->templateTypes ?? []) > 0) { + if (count($typeNode->templateTypes) > 0) { foreach ($typeNode->templateTypes as $templateType) { $templateTags[$templateType->name] = new TemplateTag( $templateType->name, diff --git a/src/Type/Constant/ConstantStringType.php b/src/Type/Constant/ConstantStringType.php index fbdbaf2f97..3aa75ee5fb 100644 --- a/src/Type/Constant/ConstantStringType.php +++ b/src/Type/Constant/ConstantStringType.php @@ -7,7 +7,7 @@ use PhpParser\Node\Name; use PHPStan\Analyser\OutOfClassScope; use PHPStan\DependencyInjection\BleedingEdgeToggle; -use PHPStan\PhpDocParser\Ast\ConstExpr\QuoteAwareConstExprStringNode; +use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode; use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\Callables\FunctionCallableVariant; @@ -528,7 +528,7 @@ public function toPhpDocNode(): TypeNode return $this->generalize(GeneralizePrecision::moreSpecific())->toPhpDocNode(); } - return new ConstTypeNode(new QuoteAwareConstExprStringNode($this->value, QuoteAwareConstExprStringNode::SINGLE_QUOTED)); + return new ConstTypeNode(new ConstExprStringNode($this->value, ConstExprStringNode::SINGLE_QUOTED)); } /** diff --git a/src/Type/Helper/GetTemplateTypeType.php b/src/Type/Helper/GetTemplateTypeType.php index 12e03fe1b0..e8af52e322 100644 --- a/src/Type/Helper/GetTemplateTypeType.php +++ b/src/Type/Helper/GetTemplateTypeType.php @@ -2,7 +2,7 @@ namespace PHPStan\Type\Helper; -use PHPStan\PhpDocParser\Ast\ConstExpr\QuoteAwareConstExprStringNode; +use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode; use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; @@ -98,7 +98,7 @@ public function toPhpDocNode(): TypeNode [ $this->type->toPhpDocNode(), new IdentifierTypeNode($this->ancestorClassName), - new ConstTypeNode(new QuoteAwareConstExprStringNode($this->templateTypeName, QuoteAwareConstExprStringNode::SINGLE_QUOTED)), + new ConstTypeNode(new ConstExprStringNode($this->templateTypeName, ConstExprStringNode::SINGLE_QUOTED)), ], ); } From b8299b7d0284aa196fcf2b078147afe68bf30609 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 8 Sep 2024 12:33:58 +0200 Subject: [PATCH 074/508] Work-in-progress 2.0 changelog --- changelog-2.0.md | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 changelog-2.0.md diff --git a/changelog-2.0.md b/changelog-2.0.md new file mode 100644 index 0000000000..82382370fd --- /dev/null +++ b/changelog-2.0.md @@ -0,0 +1,150 @@ +This document is a work in progress. + +When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](https://github.com/phpstan/phpstan/releases) + a separate UPGRADING document. + +Major new features 🚀 +===================== + +Bleeding edge (TODO move to other sections) +===================== + +* Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 +* Countable stub with `0|positive-int` ([#1027](https://github.com/phpstan/phpstan-src/pull/1027)), thanks @staabm! +* Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! +* Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! +* Lower memory consumption thanks to breaking up of reference cycles + * This is a BC break for rules that use `'parent'`, `'next'`, and `'previous'` node attributes. [Learn more »](https://phpstan.org/blog/preprocessing-ast-for-custom-rules) + * In testing the memory consumption was reduced by 50–70 %. +* ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! +* Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! +* `checkMissingIterableValueType: false` no longer does anything (https://github.com/phpstan/phpstan-src/commit/50d0c8e23ea85da508ab8481f1ff2c89148cc80b) +* ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) +* Unresolvable parameters ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! +* Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! +* Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) +* Check that each trait is used and analysed at least once - level 4 (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) +* Check that PHPStan class in class constant fetch is covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) +* Check code in custom PHPStan extensions for runtime reflection concepts like `is_a()` or `class_parents()` (https://github.com/phpstan/phpstan-src/commit/c4a662ac6c3ec63f063238880b243b5399c34fcc) +* Check code in custom PHPStan extensions for runtime reflection concepts like `new ReflectionMethod()` (https://github.com/phpstan/phpstan-src/commit/536306611cbb5877b6565755cd07b87f9ccfdf08) +* ApiInstanceofRule + * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) + * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) +* Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! +* PHPDoc parser: Require whitespace before description with limited start tokens (https://github.com/phpstan/phpdoc-parser/pull/128), https://github.com/phpstan/phpdoc-parser/issues/125, thanks @rvanvelzen! +* Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! +* **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! + * Lists are arrays with sequential integer keys starting at 0 +* Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! +* MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! +* Unescape strings in phpdoc-parser (https://github.com/phpstan/phpstan-src/commit/97786ed8376b478ec541ea9df1c450c1fbfe7461) +* Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) +* Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! +* Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) +* Fix invariance composition ([#2054](https://github.com/phpstan/phpstan-src/pull/2054)), thanks @jiripudil! +* Validate inline PHPDoc `@var` tag type against native type (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) + * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones +* Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! +* Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule + * Because "always true" is always reported, these are no longer needed +* IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) +* New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23) +* Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 +* Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) +* Stricter function signature map (https://github.com/phpstan/phpstan-src/commit/06b746d8e72cc0843707896ec161559bb6a81137, [#2163](https://github.com/phpstan/phpstan-src/pull/2163)), #7239, thanks @staabm! +* Specify `Imagick` parameter types ([#2334](https://github.com/phpstan/phpstan-src/pull/2334)), thanks @zonuexe! +* Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! +* Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! +* OverridingMethodRule - include template types in prototype declaring class description (https://github.com/phpstan/phpstan-src/commit/ca2c66cc4dff59ba44d52b82cb9e0aa3256240f3) +* Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 +* Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) +* InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) +* More precise `file()` flags args ([#2476](https://github.com/phpstan/phpstan-src/pull/2476), [#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! +* Non-static methods cannot be used as static callables in PHP 8+ ([#2420](https://github.com/phpstan/phpstan-src/pull/2420)), thanks @staabm! +* More precise `flock()` operation flags ([#2477](https://github.com/phpstan/phpstan-src/pull/2477)), thanks @staabm! +* Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! +* Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 +* Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! +* `error_log` errors with `message_type=2` ([#2428](https://github.com/phpstan/phpstan-src/pull/2428)), #9380, thanks @staabm! +* InvalidPhpDocTagValueRule: include PHPDoc line number in the error message (https://github.com/phpstan/phpstan-src/commit/a04e0be832900749b5b4ba22e2de21db8bfa09a0) +* Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! +* More precise `stream_socket_client()` signature ([#2519](https://github.com/phpstan/phpstan-src/pull/2519)), thanks @staabm! +* More precise `scandir()` signature ([#2518](https://github.com/phpstan/phpstan-src/pull/2518)), thanks @staabm! +* More precise `extract()` signature ([#2517](https://github.com/phpstan/phpstan-src/pull/2517)), thanks @staabm! +* Detect overriding `@final` method in OverridingMethodRule, #9135 +* MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) +* MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! +* More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! +* PhpDocParser: add config for lines in its AST & enable ignoring errors within PHPDocs ([#2807](https://github.com/phpstan/phpstan-src/pull/2807)), thanks @janedbal! +* Do not generalize template types, except when in `GenericObjectType` ([#2818](https://github.com/phpstan/phpstan-src/pull/2818), [#2821](https://github.com/phpstan/phpstan-src/pull/2821)) + * This fixes following **17 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092 +* TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) +* LogicalXorConstantConditionRule (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 +* NoopRule - report top-level `xor` because that's probably not what the user intended to do (https://github.com/phpstan/phpstan-src/commit/a1fffb3346e09f1e8e8d987d4282263295a55142), #10267 +* Report unused results of `and` and `or` (https://github.com/phpstan/phpstan-src/commit/1d8fff637d70a9e9ed3f11dee5d61b9f796cbf1a) +* Report unused result of ternary (https://github.com/phpstan/phpstan-src/commit/9664f7a9d2223c07e750f0dfc949c3accfa6b65e) +* Report unused results of `&&` and `||` (https://github.com/phpstan/phpstan-src/commit/cf2c8bbd9ebd2ebe300dbd310e136ad603d7def3) +* **Enhancements in Handling Parameters Passed by Reference** + * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) + * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! +* Add option `reportAnyTypeWideningInVarTag` ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! +* `array_values` rule (report when a `list` type is always passed in) ([#2917](https://github.com/phpstan/phpstan-src/pull/2917)), thanks @kamil-zacek! +* Fix checking generic `mixed` type based on config ([#2885](https://github.com/phpstan/phpstan-src/pull/2885)), thanks @schlndh! +* Checking truthiness of `@phpstan-pure` above functions and methods +* Check `new`/function call/method call/static method call on a separate line without any side effects even without `@phpstan-pure` PHPDoc tag on the declaration side + * https://github.com/phpstan/phpstan-src/commit/281a87d1ab61809076ecfa6dfc2cc86e3babe235 + * [#3020](https://github.com/phpstan/phpstan-src/pull/3020), thanks @staabm! + * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! + * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! +* BetterNoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 +* Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) +* CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) +* Deprecated: returning plain strings as errors, use RuleErrorBuilder + * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) +* Deprecated: returning RuleError without identifier (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) +* Fail build when project config uses custom extensions outside of analysed paths + * This will only occur after a run that uses already present and valid result cache +* Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! +* Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) +* Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) +* More precise types for bcmath function parameters ([#2217](https://github.com/phpstan/phpstan-src/pull/2217)), thanks @Warxcell! +* Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 +* Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) +* Consider implicit throw points when the only explicit one is Throw_ (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4) +* Check existing classes in `@param-out` (https://github.com/phpstan/phpstan-src/commit/30c4b9e80f51af8b5f166ba3aae93d8409c9c0ea), #10260 +* Check existing classes in `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/2fa539a39e06bcc3155b109fd8d246703ceb176d), #10933 +* Check invalid `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/95c0a5806c65c975201b9d3a464873f75a04c8b8), #10932 +* Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 +* Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) +* Check missing types in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/892b319f25f04bc1b55c3d0063b607909612fe6d) +* Check missing types in local type aliases (https://github.com/phpstan/phpstan-src/commit/ce7ffaf02d624a7fb9d38f8e5dffc9739f1233fc) +* Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) +* Check unresolvable types in local type aliases (https://github.com/phpstan/phpstan-src/commit/5f7d12b2fb2809525ab0e96eeae95093204ea4d3) +* Check generics in local type aliases (https://github.com/phpstan/phpstan-src/commit/5a2d4416d94ab77a2a2e7e1bfaba4c5ed2a13c25) +* Check missing types in `@mixin` (https://github.com/phpstan/phpstan-src/commit/3175c81f26fd5bcb4a161b24e774921870ed2533) +* Check types in `@property` tags (https://github.com/phpstan/phpstan-src/commit/55ea2ae516df22a071ab873fdd6f748a3af0520e), #10752, #9356 +* Check types in `@method` tags (https://github.com/phpstan/phpstan-src/commit/5b7e474680eaf33874b7ed6a227677adcbed9ca5) +* Check `@extends`, `@implements`, `@use` for unresolvable types (https://github.com/phpstan/phpstan-src/commit/2bb528233edb75312614166e282776f279cf2018), #11552 +* Report invalid exclude paths in PHP config (https://github.com/phpstan/phpstan-src/commit/9718c14f1ffac81ba3d2bf331b4e8b4041a4d004) +* RegularExpressionPatternRule: validate preg_quote'd patterns ([#3270](https://github.com/phpstan/phpstan-src/pull/3270)), thanks @staabm! +* No implicit wildcard in FileExcluder (https://github.com/phpstan/phpstan-src/commit/e19e6e5f8cfa706cc30e44a17276a6bc269f995c), #10299 +* Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! +* Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! +* Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! +* Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! +* Report "missing return" error closer to where the return is missing (https://github.com/phpstan/phpstan-src/commit/04f8636e6577cbcaefc944725eed74c0d7865ead) +* Stricter ++/-- operator check ([#3255](https://github.com/phpstan/phpstan-src/pull/3255)), thanks @schlndh! +* Check preg_quote delimiter sanity ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! +* Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3! +* Check array functions which require stringish values ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! + +Improvements 🔧 +===================== + +Bugfixes 🐛 +===================== + +Function signature fixes 🤖 +======================= + +Internals 🔍 +===================== From 694467a829c21b6b49b49bc805e31e53f81e68fe Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 8 Sep 2024 12:42:19 +0200 Subject: [PATCH 075/508] phodoc-parser has already been updated --- changelog-2.0.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 82382370fd..5525195f4b 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -30,13 +30,11 @@ Bleeding edge (TODO move to other sections) * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) * Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! -* PHPDoc parser: Require whitespace before description with limited start tokens (https://github.com/phpstan/phpdoc-parser/pull/128), https://github.com/phpstan/phpdoc-parser/issues/125, thanks @rvanvelzen! * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! * Lists are arrays with sequential integer keys starting at 0 * Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! -* Unescape strings in phpdoc-parser (https://github.com/phpstan/phpstan-src/commit/97786ed8376b478ec541ea9df1c450c1fbfe7461) * Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) * Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! * Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) @@ -65,7 +63,6 @@ Bleeding edge (TODO move to other sections) * Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 * Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! * `error_log` errors with `message_type=2` ([#2428](https://github.com/phpstan/phpstan-src/pull/2428)), #9380, thanks @staabm! -* InvalidPhpDocTagValueRule: include PHPDoc line number in the error message (https://github.com/phpstan/phpstan-src/commit/a04e0be832900749b5b4ba22e2de21db8bfa09a0) * Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! * More precise `stream_socket_client()` signature ([#2519](https://github.com/phpstan/phpstan-src/pull/2519)), thanks @staabm! * More precise `scandir()` signature ([#2518](https://github.com/phpstan/phpstan-src/pull/2518)), thanks @staabm! @@ -74,7 +71,6 @@ Bleeding edge (TODO move to other sections) * MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! -* PhpDocParser: add config for lines in its AST & enable ignoring errors within PHPDocs ([#2807](https://github.com/phpstan/phpstan-src/pull/2807)), thanks @janedbal! * Do not generalize template types, except when in `GenericObjectType` ([#2818](https://github.com/phpstan/phpstan-src/pull/2818), [#2821](https://github.com/phpstan/phpstan-src/pull/2821)) * This fixes following **17 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092 * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) @@ -140,6 +136,11 @@ Bleeding edge (TODO move to other sections) Improvements 🔧 ===================== +* PHPDoc parser: Require whitespace before description with limited start tokens (https://github.com/phpstan/phpdoc-parser/pull/128), https://github.com/phpstan/phpdoc-parser/issues/125, thanks @rvanvelzen! +* Unescape strings in PHPDoc parser (https://github.com/phpstan/phpstan-src/commit/97786ed8376b478ec541ea9df1c450c1fbfe7461) +* PHPDoc parser: add config for lines in its AST & enable ignoring errors within PHPDocs ([#2807](https://github.com/phpstan/phpstan-src/pull/2807)), thanks @janedbal! +* InvalidPhpDocTagValueRule: include PHPDoc line number in the error message (https://github.com/phpstan/phpstan-src/commit/a04e0be832900749b5b4ba22e2de21db8bfa09a0) + Bugfixes 🐛 ===================== From 2c8ab048d91378718116bd42a5e84bf68ed20dac Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 8 Sep 2024 12:43:50 +0200 Subject: [PATCH 076/508] Remove more bleeding edge toggles about phpdoc-parser --- conf/bleedingEdge.neon | 2 - conf/config.level2.neon | 2 - conf/config.neon | 3 -- conf/parametersSchema.neon | 2 - src/Parser/RichParser.php | 3 +- src/PhpDoc/StubValidator.php | 1 - .../PhpDoc/InvalidPhpDocTagValueRule.php | 15 +------ tests/PHPStan/Analyser/AnalyserTest.php | 18 +-------- .../Analyser/data/ignore-next-line-legacy.php | 40 ------------------- .../PhpDoc/InvalidPhpDocTagValueRuleTest.php | 1 - 10 files changed, 5 insertions(+), 82 deletions(-) delete mode 100644 tests/PHPStan/Analyser/data/ignore-next-line-legacy.php diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index b07884cc2a..dae0bbb2ab 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -16,7 +16,6 @@ parameters: consistentConstructor: true checkUnresolvableParameterTypes: true readOnlyByPhpDoc: true - enableIgnoreErrorsWithinPhpDocs: true runtimeReflectionRules: true notAnalysedTrait: true curlSetOptTypes: true @@ -41,7 +40,6 @@ parameters: propertyVariance: true genericPrototypeMessage: true stricterFunctionMap: true - invalidPhpDocTagLine: true detectDeadTypeInMultiCatch: true zeroFiles: true projectServicesNotInAnalysedPaths: true diff --git a/conf/config.level2.neon b/conf/config.level2.neon index d7a7cc943b..29234ebe71 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -145,8 +145,6 @@ services: class: PHPStan\Rules\Methods\IllegalConstructorStaticCallRule - class: PHPStan\Rules\PhpDoc\InvalidPhpDocTagValueRule - arguments: - invalidPhpDocTagLine: %featureToggles.invalidPhpDocTagLine% tags: - phpstan.rules.rule - diff --git a/conf/config.neon b/conf/config.neon index 3c6e1d4072..94074a853a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -51,7 +51,6 @@ parameters: consistentConstructor: false checkUnresolvableParameterTypes: false readOnlyByPhpDoc: false - enableIgnoreErrorsWithinPhpDocs: false runtimeReflectionRules: false notAnalysedTrait: false curlSetOptTypes: false @@ -77,7 +76,6 @@ parameters: propertyVariance: false genericPrototypeMessage: false stricterFunctionMap: false - invalidPhpDocTagLine: false detectDeadTypeInMultiCatch: false zeroFiles: false projectServicesNotInAnalysedPaths: false @@ -2018,7 +2016,6 @@ services: class: PHPStan\Parser\RichParser arguments: parser: @currentPhpVersionPhpParser - enableIgnoreErrorsWithinPhpDocs: %featureToggles.enableIgnoreErrorsWithinPhpDocs% autowired: no currentPhpVersionSimpleParser: diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 528e437a21..0d8cfd70a7 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -46,7 +46,6 @@ parametersSchema: consistentConstructor: bool() checkUnresolvableParameterTypes: bool() readOnlyByPhpDoc: bool() - enableIgnoreErrorsWithinPhpDocs: bool() runtimeReflectionRules: bool() notAnalysedTrait: bool() curlSetOptTypes: bool() @@ -71,7 +70,6 @@ parametersSchema: propertyVariance: bool() genericPrototypeMessage: bool() stricterFunctionMap: bool() - invalidPhpDocTagLine: bool() detectDeadTypeInMultiCatch: bool() zeroFiles: bool() projectServicesNotInAnalysedPaths: bool() diff --git a/src/Parser/RichParser.php b/src/Parser/RichParser.php index 14ade510c3..0bf45b07a3 100644 --- a/src/Parser/RichParser.php +++ b/src/Parser/RichParser.php @@ -44,7 +44,6 @@ public function __construct( private NameResolver $nameResolver, private Container $container, private IgnoreLexer $ignoreLexer, - private bool $enableIgnoreErrorsWithinPhpDocs = false, ) { } @@ -152,7 +151,7 @@ private function getLinesToIgnore(array $tokens): array $isNextLine = str_contains($text, '@phpstan-ignore-next-line'); $isCurrentLine = str_contains($text, '@phpstan-ignore-line'); - if ($this->enableIgnoreErrorsWithinPhpDocs && $type === T_DOC_COMMENT) { + if ($type === T_DOC_COMMENT) { $lines += $this->getLinesToIgnoreForTokenByIgnoreComment($text, $line, '@phpstan-ignore-line'); if ($isNextLine) { $pattern = sprintf('~%s~si', implode('|', [self::PHPDOC_TAG_REGEX, self::PHPDOC_DOCTRINE_TAG_REGEX])); diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index 7260542411..5bc8934959 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -217,7 +217,6 @@ private function getRuleRegistry(Container $container): RuleRegistry new InvalidPhpDocTagValueRule( $container->getByType(Lexer::class), $container->getByType(PhpDocParser::class), - $container->getParameter('featureToggles')['invalidPhpDocTagLine'], ), new IncompatibleParamImmediatelyInvokedCallableRule($fileTypeMapper), new IncompatibleSelfOutTypeRule($unresolvableTypeHelper, $genericObjectTypeCheck), diff --git a/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php b/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php index 569c776df3..2caa53394e 100644 --- a/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php +++ b/src/Rules/PhpDoc/InvalidPhpDocTagValueRule.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\PhpDoc; -use Nette\Utils\Strings; use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\VirtualNode; @@ -26,7 +25,6 @@ final class InvalidPhpDocTagValueRule implements Rule public function __construct( private Lexer $phpDocLexer, private PhpDocParser $phpDocParser, - private bool $invalidPhpDocTagLine, ) { } @@ -72,7 +70,7 @@ public function processNode(Node $node, Scope $scope): array 'PHPDoc tag %s %s has invalid value: %s', $phpDocTag->name, $phpDocTag->value->alias, - $this->trimExceptionMessage($phpDocTag->value->type->getException()->getMessage()), + $phpDocTag->value->type->getException()->getMessage(), )) ->line(PhpDocLineHelper::detectLine($node, $phpDocTag)) ->identifier('phpDoc.parseError')->build(); @@ -86,7 +84,7 @@ public function processNode(Node $node, Scope $scope): array 'PHPDoc tag %s has invalid value (%s): %s', $phpDocTag->name, $phpDocTag->value->value, - $this->trimExceptionMessage($phpDocTag->value->exception->getMessage()), + $phpDocTag->value->exception->getMessage(), )) ->line(PhpDocLineHelper::detectLine($node, $phpDocTag)) ->identifier('phpDoc.parseError')->build(); @@ -95,13 +93,4 @@ public function processNode(Node $node, Scope $scope): array return $errors; } - private function trimExceptionMessage(string $message): string - { - if ($this->invalidPhpDocTagLine) { - return $message; - } - - return Strings::replace($message, '~( on line \d+)$~', ''); - } - } diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index a27d75468f..39155bdb6f 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -555,18 +555,6 @@ public function testIgnoreNextLineUnmatched(): void } } - public function testIgnoreNextLineLegacyBehaviour(): void - { - $result = $this->runAnalyser([], false, [__DIR__ . '/data/ignore-next-line-legacy.php'], true, false); - - foreach ([10, 32, 36] as $i => $line) { - $this->assertArrayHasKey($i, $result); - $this->assertInstanceOf(Error::class, $result[$i]); - $this->assertSame('Fail.', $result[$i]->getMessage()); - $this->assertSame($line, $result[$i]->getLine()); - } - } - /** * @dataProvider dataTrueAndFalse */ @@ -653,10 +641,9 @@ private function runAnalyser( bool $reportUnmatchedIgnoredErrors, $filePaths, bool $onlyFiles, - bool $enableIgnoreErrorsWithinPhpDocs = true, ): array { - $analyser = $this->createAnalyser($enableIgnoreErrorsWithinPhpDocs); + $analyser = $this->createAnalyser(); if (is_string($filePaths)) { $filePaths = [$filePaths]; @@ -701,7 +688,7 @@ private function runAnalyser( ); } - private function createAnalyser(bool $enableIgnoreErrorsWithinPhpDocs): Analyser + private function createAnalyser(): Analyser { $ruleRegistry = new DirectRuleRegistry([ new AlwaysFailRule(), @@ -755,7 +742,6 @@ private function createAnalyser(bool $enableIgnoreErrorsWithinPhpDocs): Analyser new NameResolver(), self::getContainer(), new IgnoreLexer(), - $enableIgnoreErrorsWithinPhpDocs, ), new DependencyResolver($fileHelper, $reflectionProvider, new ExportedNodeResolver($fileTypeMapper, new ExprPrinter(new Printer())), $fileTypeMapper), new RuleErrorTransformer(), diff --git a/tests/PHPStan/Analyser/data/ignore-next-line-legacy.php b/tests/PHPStan/Analyser/data/ignore-next-line-legacy.php deleted file mode 100644 index fa8f2a50fd..0000000000 --- a/tests/PHPStan/Analyser/data/ignore-next-line-legacy.php +++ /dev/null @@ -1,40 +0,0 @@ -getByType(Lexer::class), self::getContainer()->getByType(PhpDocParser::class), - true, ); } From 44b8b73382bd9de5c99ee50ea430420acd15178a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 9 Sep 2024 13:04:49 +0200 Subject: [PATCH 077/508] Regression tests Closes https://github.com/phpstan/phpstan/issues/6299 --- .../PhpDoc/InvalidPhpDocTagValueRuleTest.php | 20 ++++++++++++++ tests/PHPStan/Rules/PhpDoc/data/bug-6299.php | 21 +++++++++++++++ tests/PHPStan/Rules/PhpDoc/data/bug-6692.php | 27 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 tests/PHPStan/Rules/PhpDoc/data/bug-6299.php create mode 100644 tests/PHPStan/Rules/PhpDoc/data/bug-6692.php diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php index a96c45d795..0047c107ed 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocTagValueRuleTest.php @@ -124,4 +124,24 @@ public function testIgnoreWithinPhpDoc(): void $this->analyse([__DIR__ . '/data/ignore-line-within-phpdoc.php'], []); } + public function testBug6299(): void + { + $this->analyse([__DIR__ . '/data/bug-6299.php'], [ + [ + "PHPDoc tag @phpstan-return has invalid value (array{'numeric': stdClass[], 'branches': array{'names': string[], 'exclude': bool}}}|int): Unexpected token \"}\", expected TOKEN_HORIZONTAL_WS at offset 107 on line 2", + 10, + ], + ]); + } + + public function testBug6692(): void + { + $this->analyse([__DIR__ . '/data/bug-6692.php'], [ + [ + 'PHPDoc tag @return has invalid value ($this): Unexpected token "<", expected TOKEN_HORIZONTAL_WS at offset 21 on line 2', + 11, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/PhpDoc/data/bug-6299.php b/tests/PHPStan/Rules/PhpDoc/data/bug-6299.php new file mode 100644 index 0000000000..025eaefe2e --- /dev/null +++ b/tests/PHPStan/Rules/PhpDoc/data/bug-6299.php @@ -0,0 +1,21 @@ + [], 'branches' => ['names' => [], 'exclude' => false]]; + } + else { + return 0; + } + } +} diff --git a/tests/PHPStan/Rules/PhpDoc/data/bug-6692.php b/tests/PHPStan/Rules/PhpDoc/data/bug-6692.php new file mode 100644 index 0000000000..c2312fc0ed --- /dev/null +++ b/tests/PHPStan/Rules/PhpDoc/data/bug-6692.php @@ -0,0 +1,27 @@ + + */ + public function change(): static + { + return $this; + } +} + +/** + * @template T + * @extends Wrapper + * + * @method self change() + */ +class SubWrapper extends Wrapper +{ +} From 64d4a3b61c81aced05fa690bb7a418d34bfb4213 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 9 Sep 2024 13:12:46 +0200 Subject: [PATCH 078/508] Fix build --- tests/PHPStan/Command/ErrorFormatter/data/unixBaseline.neon | 5 ++++- .../PHPStan/Command/ErrorFormatter/data/windowsBaseline.neon | 5 ++++- tests/PHPStan/Rules/PhpDoc/data/bug-6692.php | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/PHPStan/Command/ErrorFormatter/data/unixBaseline.neon b/tests/PHPStan/Command/ErrorFormatter/data/unixBaseline.neon index ca7c8f9c2c..ff39bfc9d7 100644 --- a/tests/PHPStan/Command/ErrorFormatter/data/unixBaseline.neon +++ b/tests/PHPStan/Command/ErrorFormatter/data/unixBaseline.neon @@ -11,7 +11,10 @@ parameters: path: WindowsNewlines.php - - message: "#^PHPDoc tag @param has invalid value \\(\\)\\: Unexpected token \"\\\\n\\\\t \\* \", expected type at offset 113$#" + message: """ + #^PHPDoc tag @param has invalid value \\(\r + \\$object\\)\\: Unexpected token "\\\\r\\\\n\\\\t \\* ", expected type at offset 113 on line 4$# + """ count: 1 path: WindowsNewlines.php diff --git a/tests/PHPStan/Command/ErrorFormatter/data/windowsBaseline.neon b/tests/PHPStan/Command/ErrorFormatter/data/windowsBaseline.neon index 3bfe998b6e..398e241bd7 100644 --- a/tests/PHPStan/Command/ErrorFormatter/data/windowsBaseline.neon +++ b/tests/PHPStan/Command/ErrorFormatter/data/windowsBaseline.neon @@ -11,7 +11,10 @@ parameters: path: UnixNewlines.php - - message: "#^PHPDoc tag @param has invalid value \\(\\)\\: Unexpected token \"\\\\r\\\\n\\\\t \\* \", expected type at offset 110$#" + message: """ + #^PHPDoc tag @param has invalid value \\( + \\$object\\)\\: Unexpected token "\\\\n\\\\t \\* ", expected type at offset 110 on line 4$# + """ count: 1 path: UnixNewlines.php diff --git a/tests/PHPStan/Rules/PhpDoc/data/bug-6692.php b/tests/PHPStan/Rules/PhpDoc/data/bug-6692.php index c2312fc0ed..41bd197ed9 100644 --- a/tests/PHPStan/Rules/PhpDoc/data/bug-6692.php +++ b/tests/PHPStan/Rules/PhpDoc/data/bug-6692.php @@ -1,4 +1,4 @@ -= 8.0 namespace Bug6692; From c447d32aceaa85c98f03ce235d19c4c74f784785 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 9 Sep 2024 16:25:59 +0200 Subject: [PATCH 079/508] UPGRADING guide WIP --- .github/workflows/phar.yml | 3 +++ UPGRADING.md | 29 +++++++++++++++++++++++++++++ changelog-2.0.md | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 UPGRADING.md diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index adea89e232..04cda78057 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -211,6 +211,9 @@ jobs: env: GPG_ID: ${{ steps.import-gpg.outputs.fingerprint }} + - name: "cp UPGRADING.md" + run: cp phpstan-src/UPGRADING.md phpstan-dist/UPGRADING.md + - name: "Verify PHAR" working-directory: phpstan-dist run: "gpg --verify phpstan.phar.asc" diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 0000000000..c209e8ffb0 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,29 @@ +This document is a work in progress. + +Upgrading from PHPStan 1.x to 2.0 +================================= + +## PHP version requirements + +PHPStan now requires PHP 7.4 or newer to run. + +## Upgrading guide for end users + +TODO + +## Upgrading guide for extension developers + +### PHPStan now uses nikic/php-parser v5 + +See [UPGRADING](https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md) guide for PHP-Parser. + +The most notable change is how `throw` statement is represented. Previously, `throw` statements like `throw $e;` were represented using the `Stmt\Throw_` class, while uses inside other expressions (such as `$x ?? throw $e`) used the `Expr\Throw_` class. + +Now, `throw $e;` is represented as a `Stmt\Expression` that contains an `Expr\Throw_`. The +`Stmt\Throw_` class has been removed. + +### PHPStan now uses phpstan/phpdoc-parser v2 + +See [UPGRADING](https://github.com/phpstan/phpdoc-parser/blob/2.0.x/UPGRADING.md) guide for phpstan/phpdoc-parser. + +TODO diff --git a/changelog-2.0.md b/changelog-2.0.md index 5525195f4b..4f9a5843f1 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -1,6 +1,6 @@ This document is a work in progress. -When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](https://github.com/phpstan/phpstan/releases) + a separate UPGRADING document. +When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](https://github.com/phpstan/phpstan/releases) + a separate [UPGRADING](./UPGRADING.md) document. Major new features 🚀 ===================== From e3cebb9ff44c76d65a6aedeb45ffe0f24531337d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 10 Sep 2024 12:36:56 +0200 Subject: [PATCH 080/508] Regression test --- tests/PHPStan/Analyser/nsrt/bug-5168-php7.php | 12 ++++++++++++ tests/PHPStan/Analyser/nsrt/bug-5168-php8.php | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-5168-php7.php create mode 100644 tests/PHPStan/Analyser/nsrt/bug-5168-php8.php diff --git a/tests/PHPStan/Analyser/nsrt/bug-5168-php7.php b/tests/PHPStan/Analyser/nsrt/bug-5168-php7.php new file mode 100644 index 0000000000..a0049b55fc --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-5168-php7.php @@ -0,0 +1,12 @@ += 8.0 + +namespace Bug5168Php8; + +use function PHPStan\Testing\assertType; + +function (float $f): void { + define('LARAVEL_START', microtime(true)); + + $comment = 'Calculated in ' . microtime(true) - $f; + assertType('non-falsy-string', $comment); +}; From c11e98aca2682d26ebb8c5b7bfb5ed803ac37e96 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 10 Sep 2024 15:34:49 +0200 Subject: [PATCH 081/508] Fix test --- tests/PHPStan/Analyser/nsrt/bug-5168-php7.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Analyser/nsrt/bug-5168-php7.php b/tests/PHPStan/Analyser/nsrt/bug-5168-php7.php index a0049b55fc..9e981de789 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-5168-php7.php +++ b/tests/PHPStan/Analyser/nsrt/bug-5168-php7.php @@ -8,5 +8,5 @@ function (float $f): void { define('LARAVEL_START', microtime(true)); $comment = 'Calculated in ' . microtime(true) - $f; - assertType('float', $comment); + assertType('*ERROR*', $comment); }; From 7e366e08f96e2e4095b3f02b5487e8f9531f37bf Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 12 Sep 2024 08:54:04 +0200 Subject: [PATCH 082/508] Tool to make optional parameters required across the codebase --- bin/make-optional-parameters-required.php | 51 +++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 bin/make-optional-parameters-required.php diff --git a/bin/make-optional-parameters-required.php b/bin/make-optional-parameters-required.php new file mode 100755 index 0000000000..5d2dd308c0 --- /dev/null +++ b/bin/make-optional-parameters-required.php @@ -0,0 +1,51 @@ +#!/usr/bin/env php +createForHostVersion(); + $traverser = new NodeTraverser(new CloningVisitor()); + $printer = new Standard(); + $finder = new Finder(); + $finder->followLinks(); + + $removeParamDefaultTraverser = new NodeTraverser(new class () extends NodeVisitorAbstract { + + public function enterNode(Node $node) + { + if (!$node instanceof Node\Param) { + return null; + } + + $node->default = null; + + return $node; + } + + }); + foreach ($finder->files()->name('*.php')->in($dir) as $fileInfo) { + $oldStmts = $parser->parse(file_get_contents($fileInfo->getPathname())); + $oldTokens = $parser->getTokens(); + + $newStmts = $traverser->traverse($oldStmts); + $newStmts = $removeParamDefaultTraverser->traverse($newStmts); + + $newCode = $printer->printFormatPreserving($newStmts, $oldStmts, $oldTokens); + file_put_contents($fileInfo->getPathname(), $newCode); + } +})(); From c2c30d733c801a7a2142abf0060f39f1afe63b15 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 13 Sep 2024 10:21:49 +0200 Subject: [PATCH 083/508] [BCB] Refactor TypeSpecifier::create() method and SpecifiedTypes constructor parameters --- UPGRADING.md | 22 +- src/Analyser/SpecifiedTypes.php | 85 +++- src/Analyser/TypeSpecifier.php | 434 ++++++++---------- ...yExistsFunctionTypeSpecifyingExtension.php | 6 +- ...ySearchFunctionTypeSpecifyingExtension.php | 1 - ...sExistsFunctionTypeSpecifyingExtension.php | 2 - .../CountFunctionTypeSpecifyingExtension.php | 2 +- ...peDigitFunctionTypeSpecifyingExtension.php | 4 +- .../DefineConstantTypeSpecifyingExtension.php | 3 +- ...DefinedConstantTypeSpecifyingExtension.php | 1 - ...nExistsFunctionTypeSpecifyingExtension.php | 2 - ...InArrayFunctionTypeSpecifyingExtension.php | 9 +- .../IsAFunctionTypeSpecifyingExtension.php | 1 - ...IsArrayFunctionTypeSpecifyingExtension.php | 2 +- ...allableFunctionTypeSpecifyingExtension.php | 2 +- ...terableFunctionTypeSpecifyingExtension.php | 2 +- ...classOfFunctionTypeSpecifyingExtension.php | 1 - .../MethodExistsTypeSpecifyingExtension.php | 2 - .../Php/PregMatchTypeSpecifyingExtension.php | 11 +- .../PropertyExistsTypeSpecifyingExtension.php | 1 - ...assIsSubclassOfTypeSpecifyingExtension.php | 1 - ...SetTypeFunctionTypeSpecifyingExtension.php | 3 +- .../StrContainingTypeSpecifyingExtension.php | 18 +- ...sibleCheckTypeMethodCallRuleEqualsTest.php | 2 + .../ImpossibleCheckTypeMethodCallRuleTest.php | 2 + .../TestTypeOverwriteSpecifyingExtensions.php | 4 +- 26 files changed, 310 insertions(+), 313 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index c209e8ffb0..6baecd8e10 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -26,4 +26,24 @@ Now, `throw $e;` is represented as a `Stmt\Expression` that contains an `Expr\Th See [UPGRADING](https://github.com/phpstan/phpdoc-parser/blob/2.0.x/UPGRADING.md) guide for phpstan/phpdoc-parser. -TODO +### Changed `TypeSpecifier::create()` and `SpecifiedTypes` constructor parameters + +[`PHPStan\Analyser\TypeSpecifier::create()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.TypeSpecifier.html#_create) now accepts (all parameters are required): + +* `Expr $expr` +* `Type $type` +* `TypeSpecifierContext $context` +* `Scope $scope` + +If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by this method), call `setAlwaysOverwriteTypes()` and `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::create()`). These methods return a new object (SpecifiedTypes is immutable). + +[`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) constructor now accepts: + +* `array $sureTypes` +* `array $sureNotTypes` + +If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by the constructor), call `setAlwaysOverwriteTypes()` and `setRootExpr()`. These methods return a new object (SpecifiedTypes is immutable). + +### Changed `TypeSpecifier::specifyTypesInCondition()` + +This method now longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable). diff --git a/src/Analyser/SpecifiedTypes.php b/src/Analyser/SpecifiedTypes.php index ca290a17c4..fd9ddda81d 100644 --- a/src/Analyser/SpecifiedTypes.php +++ b/src/Analyser/SpecifiedTypes.php @@ -9,22 +9,78 @@ final class SpecifiedTypes { + private bool $overwrite = false; + + /** @var array */ + private array $newConditionalExpressionHolders = []; + + private ?Expr $rootExpr = null; + /** * @api * @param array $sureTypes * @param array $sureNotTypes - * @param array $newConditionalExpressionHolders */ public function __construct( private array $sureTypes = [], private array $sureNotTypes = [], - private bool $overwrite = false, - private array $newConditionalExpressionHolders = [], - private ?Expr $rootExpr = null, ) { } + /** + * Normally, $sureTypes in truthy context are used to intersect with the pre-existing type. + * And $sureNotTypes are used to remove type from the pre-existing type. + * + * Example: By default, non-empty-string intersected with '' (ConstantStringType) will lead to NeverType. + * Because it's not possible to narrow non-empty-string to an empty string. + * + * In rare cases, a type-specifying extension might want to overwrite the pre-existing types + * without taking the pre-existing types into consideration. + * + * In that case it should also call setAlwaysOverwriteTypes() on + * the returned object. + * + * ! Only do this if you're certain. Otherwise, this is a source of common bugs. ! + * + * @api + */ + public function setAlwaysOverwriteTypes(): self + { + $self = new self($this->sureTypes, $this->sureNotTypes); + $self->overwrite = true; + $self->newConditionalExpressionHolders = $this->newConditionalExpressionHolders; + $self->rootExpr = $this->rootExpr; + + return $self; + } + + /** + * @api + */ + public function setRootExpr(?Expr $rootExpr): self + { + $self = new self($this->sureTypes, $this->sureNotTypes); + $self->overwrite = $this->overwrite; + $self->newConditionalExpressionHolders = $this->newConditionalExpressionHolders; + $self->rootExpr = $rootExpr; + + return $self; + } + + /** + * @param array $newConditionalExpressionHolders + */ + public function setNewConditionalExpressionHolders(array $newConditionalExpressionHolders): self + { + $self = new self($this->sureTypes, $this->sureNotTypes); + $self->overwrite = $this->overwrite; + $self->newConditionalExpressionHolders = $newConditionalExpressionHolders; + $self->rootExpr = $this->rootExpr; + + return $self; + } + /** * @api * @return array @@ -90,7 +146,12 @@ public function intersectWith(SpecifiedTypes $other): self ]; } - return new self($sureTypeUnion, $sureNotTypeUnion, $this->overwrite && $other->overwrite, [], $rootExpr); + $result = new self($sureTypeUnion, $sureNotTypeUnion); + if ($this->overwrite && $other->overwrite) { + $result = $result->setAlwaysOverwriteTypes(); + } + + return $result->setRootExpr($rootExpr); } /** @api */ @@ -122,7 +183,12 @@ public function unionWith(SpecifiedTypes $other): self ]; } - return new self($sureTypeUnion, $sureNotTypeUnion, $this->overwrite || $other->overwrite, [], $rootExpr); + $result = new self($sureTypeUnion, $sureNotTypeUnion); + if ($this->overwrite || $other->overwrite) { + $result = $result->setAlwaysOverwriteTypes(); + } + + return $result->setRootExpr($rootExpr); } public function normalize(Scope $scope): self @@ -138,7 +204,12 @@ public function normalize(Scope $scope): self $sureTypes[$exprString][1] = TypeCombinator::remove($sureTypes[$exprString][1], $sureNotType); } - return new self($sureTypes, [], $this->overwrite, $this->newConditionalExpressionHolders, $this->rootExpr); + $result = new self($sureTypes, []); + if ($this->overwrite) { + $result = $result->setAlwaysOverwriteTypes(); + } + + return $result->setRootExpr($this->rootExpr); } private function mergeRootExpr(?Expr $rootExprA, ?Expr $rootExprB): ?Expr diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index f02e5f51d2..5c349ce624 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -120,13 +120,10 @@ public function specifyTypesInCondition( Scope $scope, Expr $expr, TypeSpecifierContext $context, - ?Expr $rootExpr = null, ): SpecifiedTypes { - $rootExpr ??= $expr; - if ($expr instanceof Expr\CallLike && $expr->isFirstClassCallable()) { - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } if ($expr instanceof Instanceof_) { @@ -150,7 +147,7 @@ public function specifyTypesInCondition( } else { $type = new ObjectType($className); } - return $this->create($exprNode, $type, $context, false, $scope, $rootExpr); + return $this->create($exprNode, $type, $context, $scope)->setRootExpr($expr); } $classType = $scope->getType($expr->class); @@ -176,64 +173,58 @@ public function specifyTypesInCondition( $type, new ObjectWithoutClassType(), ); - return $this->create($exprNode, $type, $context, false, $scope, $rootExpr); + return $this->create($exprNode, $type, $context, $scope)->setRootExpr($expr); } elseif ($context->false()) { $exprType = $scope->getType($expr->expr); if (!$type->isSuperTypeOf($exprType)->yes()) { - return $this->create($exprNode, $type, $context, false, $scope, $rootExpr); + return $this->create($exprNode, $type, $context, $scope)->setRootExpr($expr); } } } if ($context->true()) { - return $this->create($exprNode, new ObjectWithoutClassType(), $context, false, $scope, $rootExpr); + return $this->create($exprNode, new ObjectWithoutClassType(), $context, $scope)->setRootExpr($exprNode); } } elseif ($expr instanceof Node\Expr\BinaryOp\Identical) { - return $this->resolveIdentical($expr, $scope, $context, $rootExpr); + return $this->resolveIdentical($expr, $scope, $context); } elseif ($expr instanceof Node\Expr\BinaryOp\NotIdentical) { return $this->specifyTypesInCondition( $scope, new Node\Expr\BooleanNot(new Node\Expr\BinaryOp\Identical($expr->left, $expr->right)), $context, - $rootExpr, - ); + )->setRootExpr($expr); } elseif ($expr instanceof Expr\Cast\Bool_) { return $this->specifyTypesInCondition( $scope, new Node\Expr\BinaryOp\Equal($expr->expr, new ConstFetch(new Name\FullyQualified('true'))), $context, - $rootExpr, - ); + )->setRootExpr($expr); } elseif ($expr instanceof Expr\Cast\String_) { return $this->specifyTypesInCondition( $scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\String_('')), $context, - $rootExpr, - ); + )->setRootExpr($expr); } elseif ($expr instanceof Expr\Cast\Int_) { return $this->specifyTypesInCondition( $scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\LNumber(0)), $context, - $rootExpr, - ); + )->setRootExpr($expr); } elseif ($expr instanceof Expr\Cast\Double) { return $this->specifyTypesInCondition( $scope, new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\DNumber(0.0)), $context, - $rootExpr, - ); + )->setRootExpr($expr); } elseif ($expr instanceof Node\Expr\BinaryOp\Equal) { - return $this->resolveEqual($expr, $scope, $context, $rootExpr); + return $this->resolveEqual($expr, $scope, $context); } elseif ($expr instanceof Node\Expr\BinaryOp\NotEqual) { return $this->specifyTypesInCondition( $scope, new Node\Expr\BooleanNot(new Node\Expr\BinaryOp\Equal($expr->left, $expr->right)), $context, - $rootExpr, - ); + )->setRootExpr($expr); } elseif ($expr instanceof Node\Expr\BinaryOp\Smaller || $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual) { @@ -256,14 +247,13 @@ public function specifyTypesInCondition( $scope, new Node\Expr\BooleanNot($inverseOperator), $context, - $rootExpr, - ); + )->setRootExpr($expr); } $orEqual = $expr instanceof Node\Expr\BinaryOp\SmallerOrEqual; $offset = $orEqual ? 0 : 1; $leftType = $scope->getType($expr->left); - $result = new SpecifiedTypes([], [], false, [], $rootExpr); + $result = (new SpecifiedTypes([], []))->setRootExpr($expr); if ( !$context->null() @@ -287,7 +277,7 @@ public function specifyTypesInCondition( $sizeType = $leftType; } - $narrowed = $this->narrowUnionByArraySize($expr->right, $argType, $sizeType, $context, $scope, $rootExpr); + $narrowed = $this->narrowUnionByArraySize($expr->right, $argType, $sizeType, $context, $scope, $expr); if ($narrowed !== null) { return $narrowed; } @@ -318,7 +308,7 @@ public function specifyTypesInCondition( if (count($countables) > 0) { $countableType = TypeCombinator::union(...$countables); - return $this->create($expr->right->getArgs()[0]->value, $countableType, $context, false, $scope, $rootExpr); + return $this->create($expr->right->getArgs()[0]->value, $countableType, $context, $scope)->setRootExpr($expr); } } @@ -329,7 +319,7 @@ public function specifyTypesInCondition( } $result = $result->unionWith( - $this->create($expr->right->getArgs()[0]->value, $newType, $context, false, $scope, $rootExpr), + $this->create($expr->right->getArgs()[0]->value, $newType, $context, $scope)->setRootExpr($expr), ); } } @@ -355,7 +345,7 @@ public function specifyTypesInCondition( $accessory = new AccessoryNonFalsyStringType(); } - $result = $result->unionWith($this->create($expr->right->getArgs()[0]->value, $accessory, $context, false, $scope, $rootExpr)); + $result = $result->unionWith($this->create($expr->right->getArgs()[0]->value, $accessory, $context, $scope)->setRootExpr($expr)); } } } @@ -363,21 +353,21 @@ public function specifyTypesInCondition( if ($leftType instanceof ConstantIntegerType) { if ($expr->right instanceof Expr\PostInc) { $result = $result->unionWith($this->createRangeTypes( - $rootExpr, + $expr, $expr->right->var, IntegerRangeType::fromInterval($leftType->getValue(), null, $offset + 1), $context, )); } elseif ($expr->right instanceof Expr\PostDec) { $result = $result->unionWith($this->createRangeTypes( - $rootExpr, + $expr, $expr->right->var, IntegerRangeType::fromInterval($leftType->getValue(), null, $offset - 1), $context, )); } elseif ($expr->right instanceof Expr\PreInc || $expr->right instanceof Expr\PreDec) { $result = $result->unionWith($this->createRangeTypes( - $rootExpr, + $expr, $expr->right->var, IntegerRangeType::fromInterval($leftType->getValue(), null, $offset), $context, @@ -389,21 +379,21 @@ public function specifyTypesInCondition( if ($rightType instanceof ConstantIntegerType) { if ($expr->left instanceof Expr\PostInc) { $result = $result->unionWith($this->createRangeTypes( - $rootExpr, + $expr, $expr->left->var, IntegerRangeType::fromInterval(null, $rightType->getValue(), -$offset + 1), $context, )); } elseif ($expr->left instanceof Expr\PostDec) { $result = $result->unionWith($this->createRangeTypes( - $rootExpr, + $expr, $expr->left->var, IntegerRangeType::fromInterval(null, $rightType->getValue(), -$offset - 1), $context, )); } elseif ($expr->left instanceof Expr\PreInc || $expr->left instanceof Expr\PreDec) { $result = $result->unionWith($this->createRangeTypes( - $rootExpr, + $expr, $expr->left->var, IntegerRangeType::fromInterval(null, $rightType->getValue(), -$offset), $context, @@ -418,10 +408,8 @@ public function specifyTypesInCondition( $expr->left, $orEqual ? $rightType->getSmallerOrEqualType() : $rightType->getSmallerType(), TypeSpecifierContext::createTruthy(), - false, $scope, - $rootExpr, - ), + )->setRootExpr($expr), ); } if (!$expr->right instanceof Node\Scalar) { @@ -430,10 +418,8 @@ public function specifyTypesInCondition( $expr->right, $orEqual ? $leftType->getGreaterOrEqualType() : $leftType->getGreaterType(), TypeSpecifierContext::createTruthy(), - false, $scope, - $rootExpr, - ), + )->setRootExpr($expr), ); } } elseif ($context->false()) { @@ -443,10 +429,8 @@ public function specifyTypesInCondition( $expr->left, $orEqual ? $rightType->getGreaterType() : $rightType->getGreaterOrEqualType(), TypeSpecifierContext::createTruthy(), - false, $scope, - $rootExpr, - ), + )->setRootExpr($expr), ); } if (!$expr->right instanceof Node\Scalar) { @@ -455,10 +439,8 @@ public function specifyTypesInCondition( $expr->right, $orEqual ? $leftType->getSmallerType() : $leftType->getSmallerOrEqualType(), TypeSpecifierContext::createTruthy(), - false, $scope, - $rootExpr, - ), + )->setRootExpr($expr), ); } } @@ -466,10 +448,10 @@ public function specifyTypesInCondition( return $result; } elseif ($expr instanceof Node\Expr\BinaryOp\Greater) { - return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Smaller($expr->right, $expr->left), $context, $rootExpr); + return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Smaller($expr->right, $expr->left), $context)->setRootExpr($expr); } elseif ($expr instanceof Node\Expr\BinaryOp\GreaterOrEqual) { - return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\SmallerOrEqual($expr->right, $expr->left), $context, $rootExpr); + return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\SmallerOrEqual($expr->right, $expr->left), $context)->setRootExpr($expr); } elseif ($expr instanceof FuncCall && $expr->name instanceof Name) { if ($this->reflectionProvider->hasFunction($expr->name, $scope)) { @@ -510,7 +492,7 @@ public function specifyTypesInCondition( } } - return $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); + return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); } elseif ($expr instanceof MethodCall && $expr->name instanceof Node\Identifier) { $methodCalledOnType = $scope->getType($expr->var); $methodReflection = $scope->getMethodReflection($methodCalledOnType, $expr->name->name); @@ -558,7 +540,7 @@ public function specifyTypesInCondition( } } - return $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); + return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); } elseif ($expr instanceof StaticCall && $expr->name instanceof Node\Identifier) { if ($expr->class instanceof Name) { $calleeType = $scope->resolveTypeByName($expr->class); @@ -611,28 +593,25 @@ public function specifyTypesInCondition( } } - return $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); + return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); } elseif ($expr instanceof BooleanAnd || $expr instanceof LogicalAnd) { if (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); } - $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr); + $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context)->setRootExpr($expr); $rightScope = $scope->filterByTruthyValue($expr->left); - $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr); + $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context)->setRootExpr($expr); $types = $context->true() ? $leftTypes->unionWith($rightTypes) : $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope)); if ($context->false()) { - return new SpecifiedTypes( + return (new SpecifiedTypes( $types->getSureTypes(), $types->getSureNotTypes(), - false, - array_merge( - $this->processBooleanNotSureConditionalTypes($scope, $leftTypes, $rightTypes), - $this->processBooleanNotSureConditionalTypes($scope, $rightTypes, $leftTypes), - $this->processBooleanSureConditionalTypes($scope, $leftTypes, $rightTypes), - $this->processBooleanSureConditionalTypes($scope, $rightTypes, $leftTypes), - ), - $rootExpr, - ); + ))->setNewConditionalExpressionHolders(array_merge( + $this->processBooleanNotSureConditionalTypes($scope, $leftTypes, $rightTypes), + $this->processBooleanNotSureConditionalTypes($scope, $rightTypes, $leftTypes), + $this->processBooleanSureConditionalTypes($scope, $leftTypes, $rightTypes), + $this->processBooleanSureConditionalTypes($scope, $rightTypes, $leftTypes), + ))->setRootExpr($expr); } return $types; @@ -640,37 +619,34 @@ public function specifyTypesInCondition( if (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); } - $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr); + $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context)->setRootExpr($expr); $rightScope = $scope->filterByFalseyValue($expr->left); - $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr); + $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context)->setRootExpr($expr); $types = $context->true() ? $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope)) : $leftTypes->unionWith($rightTypes); if ($context->true()) { - return new SpecifiedTypes( + return (new SpecifiedTypes( $types->getSureTypes(), $types->getSureNotTypes(), - false, - array_merge( - $this->processBooleanNotSureConditionalTypes($scope, $leftTypes, $rightTypes), - $this->processBooleanNotSureConditionalTypes($scope, $rightTypes, $leftTypes), - $this->processBooleanSureConditionalTypes($scope, $leftTypes, $rightTypes), - $this->processBooleanSureConditionalTypes($scope, $rightTypes, $leftTypes), - ), - $rootExpr, - ); + ))->setNewConditionalExpressionHolders(array_merge( + $this->processBooleanNotSureConditionalTypes($scope, $leftTypes, $rightTypes), + $this->processBooleanNotSureConditionalTypes($scope, $rightTypes, $leftTypes), + $this->processBooleanSureConditionalTypes($scope, $leftTypes, $rightTypes), + $this->processBooleanSureConditionalTypes($scope, $rightTypes, $leftTypes), + ))->setRootExpr($expr); } return $types; } elseif ($expr instanceof Node\Expr\BooleanNot && !$context->null()) { - return $this->specifyTypesInCondition($scope, $expr->expr, $context->negate(), $rootExpr); + return $this->specifyTypesInCondition($scope, $expr->expr, $context->negate())->setRootExpr($expr); } elseif ($expr instanceof Node\Expr\Assign) { if (!$scope instanceof MutatingScope) { throw new ShouldNotHappenException(); } if ($context->null()) { - return $this->specifyTypesInCondition($scope->exitFirstLevelStatements(), $expr->expr, $context, $rootExpr); + return $this->specifyTypesInCondition($scope->exitFirstLevelStatements(), $expr->expr, $context)->setRootExpr($expr); } - return $this->specifyTypesInCondition($scope->exitFirstLevelStatements(), $expr->var, $context, $rootExpr); + return $this->specifyTypesInCondition($scope->exitFirstLevelStatements(), $expr->var, $context)->setRootExpr($expr); } elseif ( $expr instanceof Expr\Isset_ && count($expr->vars) > 0 @@ -698,7 +674,7 @@ public function specifyTypesInCondition( throw new ShouldNotHappenException(); } - return $this->specifyTypesInCondition($scope, $andChain, $context, $rootExpr); + return $this->specifyTypesInCondition($scope, $andChain, $context)->setRootExpr($expr); } $issetExpr = $expr->vars[0]; @@ -720,10 +696,8 @@ public function specifyTypesInCondition( $issetExpr, new NullType(), $context->negate(), - false, $scope, - $rootExpr, - ); + )->setRootExpr($expr); if ($issetExpr instanceof Expr\Variable && is_string($issetExpr->name)) { if ($isset === true) { @@ -736,10 +710,8 @@ public function specifyTypesInCondition( new IssetExpr($issetExpr), new NullType(), $context, - false, $scope, - $rootExpr, - )); + ))->setRootExpr($expr); } if ($isNullable) { @@ -748,10 +720,8 @@ public function specifyTypesInCondition( new IssetExpr($issetExpr), new NullType(), $context->negate(), - false, $scope, - $rootExpr, - )); + ))->setRootExpr($expr); } // variable cannot exist in !isset() @@ -759,10 +729,8 @@ public function specifyTypesInCondition( new IssetExpr($issetExpr), new NullType(), $context, - false, $scope, - $rootExpr, - ); + )->setRootExpr($expr); } if ($isNullable && $isset === true) { @@ -796,7 +764,7 @@ public function specifyTypesInCondition( if ($var instanceof Expr\Variable && is_string($var->name)) { if ($scope->hasVariableType($var->name)->no()) { - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } } @@ -813,10 +781,8 @@ public function specifyTypesInCondition( $var->var, new HasOffsetType($dimType), $context, - false, $scope, - $rootExpr, - ), + )->setRootExpr($expr), ); } } @@ -829,7 +795,7 @@ public function specifyTypesInCondition( $this->create($var->var, new IntersectionType([ new ObjectWithoutClassType(), new HasPropertyType($var->name->toString()), - ]), TypeSpecifierContext::createTruthy(), false, $scope, $rootExpr), + ]), TypeSpecifierContext::createTruthy(), $scope)->setRootExpr($expr), ); } elseif ( $var instanceof StaticPropertyFetch @@ -840,12 +806,12 @@ public function specifyTypesInCondition( $this->create($var->class, new IntersectionType([ new ObjectWithoutClassType(), new HasPropertyType($var->name->toString()), - ]), TypeSpecifierContext::createTruthy(), false, $scope, $rootExpr), + ]), TypeSpecifierContext::createTruthy(), $scope)->setRootExpr($expr), ); } $types = $types->unionWith( - $this->create($var, new NullType(), TypeSpecifierContext::createFalse(), false, $scope, $rootExpr), + $this->create($var, new NullType(), TypeSpecifierContext::createFalse(), $scope)->setRootExpr($expr), ); } @@ -869,10 +835,8 @@ public function specifyTypesInCondition( $expr->left, new NullType(), $context->negate(), - false, $scope, - $rootExpr, - ); + )->setRootExpr($expr); } if ((new ConstantBooleanType(false))->isSuperTypeOf($scope->getType($expr->right)->toBoolean())->yes()) { @@ -880,10 +844,8 @@ public function specifyTypesInCondition( $expr->left, new NullType(), TypeSpecifierContext::createFalse(), - false, $scope, - $rootExpr, - ); + )->setRootExpr($expr); } } elseif ( @@ -901,9 +863,9 @@ public function specifyTypesInCondition( return $this->specifyTypesInCondition($scope, new BooleanOr( new Expr\BooleanNot(new Expr\Isset_([$expr->expr])), new Expr\BooleanNot($expr->expr), - ), $context, $rootExpr); + ), $context)->setRootExpr($expr); } elseif ($expr instanceof Expr\ErrorSuppress) { - return $this->specifyTypesInCondition($scope, $expr->expr, $context, $rootExpr); + return $this->specifyTypesInCondition($scope, $expr->expr, $context)->setRootExpr($expr); } elseif ( $expr instanceof Expr\Ternary && !$context->null() @@ -914,7 +876,7 @@ public function specifyTypesInCondition( $conditionExpr = new BooleanAnd($conditionExpr, $expr->if); } - return $this->specifyTypesInCondition($scope, $conditionExpr, $context, $rootExpr); + return $this->specifyTypesInCondition($scope, $conditionExpr, $context)->setRootExpr($expr); } elseif ($expr instanceof Expr\NullsafePropertyFetch && !$context->null()) { $types = $this->specifyTypesInCondition( @@ -924,10 +886,9 @@ public function specifyTypesInCondition( new PropertyFetch($expr->var, $expr->name), ), $context, - $rootExpr, - ); + )->setRootExpr($expr); - $nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); + $nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); return $context->true() ? $types->unionWith($nullSafeTypes) : $types->normalize($scope)->intersectWith($nullSafeTypes->normalize($scope)); } elseif ($expr instanceof Expr\NullsafeMethodCall && !$context->null()) { $types = $this->specifyTypesInCondition( @@ -937,10 +898,9 @@ public function specifyTypesInCondition( new MethodCall($expr->var, $expr->name, $expr->args), ), $context, - $rootExpr, - ); + )->setRootExpr($expr); - $nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); + $nullSafeTypes = $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); return $context->true() ? $types->unionWith($nullSafeTypes) : $types->normalize($scope)->intersectWith($nullSafeTypes->normalize($scope)); } elseif ( $expr instanceof Expr\New_ @@ -971,10 +931,10 @@ public function specifyTypesInCondition( } } } elseif (!$context->null()) { - return $this->handleDefaultTruthyOrFalseyContext($context, $rootExpr, $expr, $scope); + return $this->handleDefaultTruthyOrFalseyContext($context, $expr, $scope); } - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } private function narrowUnionByArraySize(FuncCall $countFuncCall, UnionType $argType, ?Type $sizeType, TypeSpecifierContext $context, Scope $scope, ?Expr $rootExpr): ?SpecifiedTypes @@ -1017,7 +977,7 @@ private function narrowUnionByArraySize(FuncCall $countFuncCall, UnionType $argT $result[] = $innerType; } - return $this->create($countFuncCall->getArgs()[0]->value, TypeCombinator::union(...$result), $context, false, $scope, $rootExpr); + return $this->create($countFuncCall->getArgs()[0]->value, TypeCombinator::union(...$result), $context, $scope)->setRootExpr($rootExpr); } return null; @@ -1093,11 +1053,11 @@ private function specifyTypesForConstantBinaryExpression( Type $constantType, TypeSpecifierContext $context, Scope $scope, - ?Expr $rootExpr, + Expr $rootExpr, ): ?SpecifiedTypes { if (!$context->null() && $constantType->isFalse()->yes()) { - $types = $this->create($exprNode, $constantType, $context, false, $scope, $rootExpr); + $types = $this->create($exprNode, $constantType, $context, $scope)->setRootExpr($rootExpr); if ($exprNode instanceof Expr\NullsafeMethodCall || $exprNode instanceof Expr\NullsafePropertyFetch) { return $types; } @@ -1106,12 +1066,11 @@ private function specifyTypesForConstantBinaryExpression( $scope, $exprNode, $context->true() ? TypeSpecifierContext::createFalse() : TypeSpecifierContext::createFalse()->negate(), - $rootExpr, - )); + )->setRootExpr($rootExpr)); } if (!$context->null() && $constantType->isTrue()->yes()) { - $types = $this->create($exprNode, $constantType, $context, false, $scope, $rootExpr); + $types = $this->create($exprNode, $constantType, $context, $scope)->setRootExpr($rootExpr); if ($exprNode instanceof Expr\NullsafeMethodCall || $exprNode instanceof Expr\NullsafePropertyFetch) { return $types; } @@ -1120,8 +1079,7 @@ private function specifyTypesForConstantBinaryExpression( $scope, $exprNode, $context->true() ? TypeSpecifierContext::createTrue() : TypeSpecifierContext::createTrue()->negate(), - $rootExpr, - )); + )->setRootExpr($rootExpr)); } if ( @@ -1133,7 +1091,7 @@ private function specifyTypesForConstantBinaryExpression( && $constantType instanceof ConstantIntegerType ) { if ($constantType->getValue() < 0) { - return $this->create($exprNode->getArgs()[0]->value, new NeverType(), $context, false, $scope, $rootExpr); + return $this->create($exprNode->getArgs()[0]->value, new NeverType(), $context, $scope)->setRootExpr($rootExpr); } if ($context->truthy() || $constantType->getValue() === 0) { @@ -1143,13 +1101,13 @@ private function specifyTypesForConstantBinaryExpression( } $argType = $scope->getType($exprNode->getArgs()[0]->value); if ($argType->isString()->yes()) { - $funcTypes = $this->create($exprNode, $constantType, $context, false, $scope, $rootExpr); + $funcTypes = $this->create($exprNode, $constantType, $context, $scope)->setRootExpr($rootExpr); $accessory = new AccessoryNonEmptyStringType(); if ($constantType->getValue() >= 2) { $accessory = new AccessoryNonFalsyStringType(); } - $valueTypes = $this->create($exprNode->getArgs()[0]->value, $accessory, $newContext, false, $scope, $rootExpr); + $valueTypes = $this->create($exprNode->getArgs()[0]->value, $accessory, $newContext, $scope)->setRootExpr($rootExpr); return $funcTypes->unionWith($valueTypes); } @@ -1165,7 +1123,7 @@ private function specifyTypesForConstantStringBinaryExpression( Type $constantType, TypeSpecifierContext $context, Scope $scope, - ?Expr $rootExpr, + Expr $rootExpr, ): ?SpecifiedTypes { $scalarValues = $constantType->getConstantScalarValues(); @@ -1207,8 +1165,8 @@ private function specifyTypesForConstantStringBinaryExpression( } if ($type !== null) { - $callType = $this->create($exprNode, $constantType, $context, false, $scope, $rootExpr); - $argType = $this->create($exprNode->getArgs()[0]->value, $type, $context, false, $scope, $rootExpr); + $callType = $this->create($exprNode, $constantType, $context, $scope)->setRootExpr($rootExpr); + $argType = $this->create($exprNode->getArgs()[0]->value, $type, $context, $scope)->setRootExpr($rootExpr); return $callType->unionWith($argType); } } @@ -1229,9 +1187,8 @@ private function specifyTypesForConstantStringBinaryExpression( $exprNode->getArgs()[0]->value, $classStringType, $context, - false, $scope, - ); + )->setRootExpr($rootExpr); } if ($argType->isObject()->yes()) { @@ -1239,37 +1196,35 @@ private function specifyTypesForConstantStringBinaryExpression( $exprNode->getArgs()[0]->value, $objectType, $context, - false, $scope, - ); + )->setRootExpr($rootExpr); } return $this->create( $exprNode->getArgs()[0]->value, TypeCombinator::union($objectType, $classStringType), $context, - false, $scope, - ); + )->setRootExpr($rootExpr); } return null; } - private function handleDefaultTruthyOrFalseyContext(TypeSpecifierContext $context, ?Expr $rootExpr, Expr $expr, Scope $scope): SpecifiedTypes + private function handleDefaultTruthyOrFalseyContext(TypeSpecifierContext $context, Expr $expr, Scope $scope): SpecifiedTypes { if ($context->null()) { - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } if (!$context->truthy()) { $type = StaticTypeFactory::truthy(); - return $this->create($expr, $type, TypeSpecifierContext::createFalse(), false, $scope, $rootExpr); + return $this->create($expr, $type, TypeSpecifierContext::createFalse(), $scope)->setRootExpr($expr); } elseif (!$context->falsey()) { $type = StaticTypeFactory::falsey(); - return $this->create($expr, $type, TypeSpecifierContext::createFalse(), false, $scope, $rootExpr); + return $this->create($expr, $type, TypeSpecifierContext::createFalse(), $scope)->setRootExpr($expr); } - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } private function specifyTypesFromConditionalReturnType( @@ -1354,7 +1309,6 @@ public function getConditionalSpecifiedTypes( $argsMap[$parameterName], $targetType, $context, - false, $scope, ); @@ -1450,10 +1404,8 @@ static function (Type $type, callable $traverse) use ($templateTypeMap, &$contai $assertExpr, $assertedType, $assert->isNegated() ? TypeSpecifierContext::createFalse() : TypeSpecifierContext::createTrue(), - false, $scope, - $containsUnresolvedTemplate || $assert->isEquality() ? $call : null, - ); + )->setRootExpr($containsUnresolvedTemplate || $assert->isEquality() ? $call : null); $types = $types !== null ? $types->unionWith($newTypes) : $newTypes; if (!$context->null() || !$assertedType instanceof ConstantBooleanType) { @@ -1650,13 +1602,11 @@ public function create( Expr $expr, Type $type, TypeSpecifierContext $context, - bool $overwrite = false, - ?Scope $scope = null, - ?Expr $rootExpr = null, + Scope $scope, ): SpecifiedTypes { if ($expr instanceof Instanceof_ || $expr instanceof Expr\List_) { - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } $specifiedExprs = []; @@ -1682,7 +1632,7 @@ public function create( $types = null; foreach ($specifiedExprs as $specifiedExpr) { - $newTypes = $this->createForExpr($specifiedExpr, $type, $context, $overwrite, $scope, $rootExpr); + $newTypes = $this->createForExpr($specifiedExpr, $type, $context, $scope); if ($types === null) { $types = $newTypes; @@ -1698,17 +1648,13 @@ private function createForExpr( Expr $expr, Type $type, TypeSpecifierContext $context, - bool $overwrite = false, - ?Scope $scope = null, - ?Expr $rootExpr = null, + Scope $scope, ): SpecifiedTypes { - if ($scope !== null) { - if ($context->true()) { - $containsNull = !$type->isNull()->no() && !$scope->getType($expr)->isNull()->no(); - } elseif ($context->false()) { - $containsNull = !TypeCombinator::containsNull($type) && !$scope->getType($expr)->isNull()->no(); - } + if ($context->true()) { + $containsNull = !$type->isNull()->no() && !$scope->getType($expr)->isNull()->no(); + } elseif ($context->false()) { + $containsNull = !TypeCombinator::containsNull($type) && !$scope->getType($expr)->isNull()->no(); } $originalExpr = $expr; @@ -1717,8 +1663,7 @@ private function createForExpr( } if ( - $scope !== null - && !$context->null() + !$context->null() && $expr instanceof Expr\BinaryOp\Coalesce ) { $rightIsSuperType = $type->isSuperTypeOf($scope->getType($expr->right)); @@ -1734,24 +1679,23 @@ private function createForExpr( $has = $this->reflectionProvider->hasFunction($expr->name, $scope); if (!$has) { // backwards compatibility with previous behaviour - return new SpecifiedTypes([], [], false, [], $rootExpr); + return new SpecifiedTypes([], []); } $functionReflection = $this->reflectionProvider->getFunction($expr->name, $scope); $hasSideEffects = $functionReflection->hasSideEffects(); if ($hasSideEffects->yes()) { - return new SpecifiedTypes([], [], false, [], $rootExpr); + return new SpecifiedTypes([], []); } if (!$this->rememberPossiblyImpureFunctionValues && !$hasSideEffects->no()) { - return new SpecifiedTypes([], [], false, [], $rootExpr); + return new SpecifiedTypes([], []); } } if ( $expr instanceof MethodCall && $expr->name instanceof Node\Identifier - && $scope !== null ) { $methodName = $expr->name->toString(); $calledOnType = $scope->getType($expr->var); @@ -1762,17 +1706,16 @@ private function createForExpr( || (!$this->rememberPossiblyImpureFunctionValues && !$methodReflection->hasSideEffects()->no()) ) { if (isset($containsNull) && !$containsNull) { - return $this->createNullsafeTypes($rootExpr, $originalExpr, $scope, $context, $overwrite, $type); + return $this->createNullsafeTypes($originalExpr, $scope, $context, $type); } - return new SpecifiedTypes([], [], false, [], $rootExpr); + return new SpecifiedTypes([], []); } } if ( $expr instanceof StaticCall && $expr->name instanceof Node\Identifier - && $scope !== null ) { $methodName = $expr->name->toString(); if ($expr->class instanceof Name) { @@ -1788,10 +1731,10 @@ private function createForExpr( || (!$this->rememberPossiblyImpureFunctionValues && !$methodReflection->hasSideEffects()->no()) ) { if (isset($containsNull) && !$containsNull) { - return $this->createNullsafeTypes($rootExpr, $originalExpr, $scope, $context, $overwrite, $type); + return $this->createNullsafeTypes($originalExpr, $scope, $context, $type); } - return new SpecifiedTypes([], [], false, [], $rootExpr); + return new SpecifiedTypes([], []); } } @@ -1811,61 +1754,61 @@ private function createForExpr( } } - $types = new SpecifiedTypes($sureTypes, $sureNotTypes, $overwrite, [], $rootExpr); - if ($scope !== null && isset($containsNull) && !$containsNull) { - return $this->createNullsafeTypes($rootExpr, $originalExpr, $scope, $context, $overwrite, $type)->unionWith($types); + $types = new SpecifiedTypes($sureTypes, $sureNotTypes); + if (isset($containsNull) && !$containsNull) { + return $this->createNullsafeTypes($originalExpr, $scope, $context, $type)->unionWith($types); } return $types; } - private function createNullsafeTypes(?Expr $rootExpr, Expr $expr, Scope $scope, TypeSpecifierContext $context, bool $overwrite, ?Type $type): SpecifiedTypes + private function createNullsafeTypes(Expr $expr, Scope $scope, TypeSpecifierContext $context, ?Type $type): SpecifiedTypes { if ($expr instanceof Expr\NullsafePropertyFetch) { if ($type !== null) { - $propertyFetchTypes = $this->create(new PropertyFetch($expr->var, $expr->name), $type, $context, false, $scope, $rootExpr); + $propertyFetchTypes = $this->create(new PropertyFetch($expr->var, $expr->name), $type, $context, $scope); } else { - $propertyFetchTypes = $this->create(new PropertyFetch($expr->var, $expr->name), new NullType(), TypeSpecifierContext::createFalse(), false, $scope, $rootExpr); + $propertyFetchTypes = $this->create(new PropertyFetch($expr->var, $expr->name), new NullType(), TypeSpecifierContext::createFalse(), $scope); } return $propertyFetchTypes->unionWith( - $this->create($expr->var, new NullType(), TypeSpecifierContext::createFalse(), $overwrite, $scope, $rootExpr), + $this->create($expr->var, new NullType(), TypeSpecifierContext::createFalse(), $scope), ); } if ($expr instanceof Expr\NullsafeMethodCall) { if ($type !== null) { - $methodCallTypes = $this->create(new MethodCall($expr->var, $expr->name, $expr->args), $type, $context, $overwrite, $scope, $rootExpr); + $methodCallTypes = $this->create(new MethodCall($expr->var, $expr->name, $expr->args), $type, $context, $scope); } else { - $methodCallTypes = $this->create(new MethodCall($expr->var, $expr->name, $expr->args), new NullType(), TypeSpecifierContext::createFalse(), $overwrite, $scope, $rootExpr); + $methodCallTypes = $this->create(new MethodCall($expr->var, $expr->name, $expr->args), new NullType(), TypeSpecifierContext::createFalse(), $scope); } return $methodCallTypes->unionWith( - $this->create($expr->var, new NullType(), TypeSpecifierContext::createFalse(), $overwrite, $scope, $rootExpr), + $this->create($expr->var, new NullType(), TypeSpecifierContext::createFalse(), $scope), ); } if ($expr instanceof Expr\PropertyFetch) { - return $this->createNullsafeTypes($rootExpr, $expr->var, $scope, $context, $overwrite, null); + return $this->createNullsafeTypes($expr->var, $scope, $context, null); } if ($expr instanceof Expr\MethodCall) { - return $this->createNullsafeTypes($rootExpr, $expr->var, $scope, $context, $overwrite, null); + return $this->createNullsafeTypes($expr->var, $scope, $context, null); } if ($expr instanceof Expr\ArrayDimFetch) { - return $this->createNullsafeTypes($rootExpr, $expr->var, $scope, $context, $overwrite, null); + return $this->createNullsafeTypes($expr->var, $scope, $context, null); } if ($expr instanceof Expr\StaticPropertyFetch && $expr->class instanceof Expr) { - return $this->createNullsafeTypes($rootExpr, $expr->class, $scope, $context, $overwrite, null); + return $this->createNullsafeTypes($expr->class, $scope, $context, null); } if ($expr instanceof Expr\StaticCall && $expr->class instanceof Expr) { - return $this->createNullsafeTypes($rootExpr, $expr->class, $scope, $context, $overwrite, null); + return $this->createNullsafeTypes($expr->class, $scope, $context, null); } - return new SpecifiedTypes([], [], $overwrite, [], $rootExpr); + return new SpecifiedTypes([], []); } private function createRangeTypes(?Expr $rootExpr, Expr $expr, Type $type, TypeSpecifierContext $context): SpecifiedTypes @@ -1882,7 +1825,7 @@ private function createRangeTypes(?Expr $rootExpr, Expr $expr, Type $type, TypeS } } - return new SpecifiedTypes([], $sureNotTypes, false, [], $rootExpr); + return (new SpecifiedTypes([], $sureNotTypes))->setRootExpr($rootExpr); } /** @@ -1944,7 +1887,7 @@ private function getTypeSpecifyingExtensionsForType(array $extensions, string $c return array_merge(...$extensionsForClass); } - public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecifierContext $context, ?Expr $rootExpr): SpecifiedTypes + public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes { $expressions = $this->findTypeExpressionsFromBinaryOperation($scope, $expr); if ($expressions !== null) { @@ -1955,8 +1898,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif $scope, $exprNode, $context->true() ? TypeSpecifierContext::createFalsey() : TypeSpecifierContext::createFalsey()->negate(), - $rootExpr, - ); + )->setRootExpr($expr); } if (!$context->null() && $constantType->getValue() === true) { @@ -1964,8 +1906,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif $scope, $exprNode, $context->true() ? TypeSpecifierContext::createTruthy() : TypeSpecifierContext::createTruthy()->negate(), - $rootExpr, - ); + )->setRootExpr($expr); } if ( @@ -1975,7 +1916,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif && isset($exprNode->getArgs()[0]) && $constantType->isString()->yes() ) { - return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); + return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context)->setRootExpr($expr); } if ( @@ -1985,7 +1926,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif && $exprNode->name->toLowerString() === 'preg_match' && (new ConstantIntegerType(1))->isSuperTypeOf($constantType)->yes() ) { - return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); + return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context)->setRootExpr($expr); } } @@ -2001,8 +1942,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif $expr->right, ), $context, - $rootExpr, - ); + )->setRootExpr($expr); } $rightBooleanType = $rightType->toBoolean(); @@ -2014,8 +1954,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif new ConstFetch(new Name($rightBooleanType->getValue() ? 'true' : 'false')), ), $context, - $rootExpr, - ); + )->setRootExpr($expr); } if ( @@ -2023,7 +1962,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif && $rightType->isArray()->yes() && $leftType->isConstantArray()->yes() && $leftType->isIterableAtLeastOnce()->no() ) { - return $this->create($expr->right, new NonEmptyArrayType(), $context->negate(), false, $scope, $rootExpr); + return $this->create($expr->right, new NonEmptyArrayType(), $context->negate(), $scope)->setRootExpr($expr); } if ( @@ -2031,7 +1970,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif && $leftType->isArray()->yes() && $rightType->isConstantArray()->yes() && $rightType->isIterableAtLeastOnce()->no() ) { - return $this->create($expr->left, new NonEmptyArrayType(), $context->negate(), false, $scope, $rootExpr); + return $this->create($expr->left, new NonEmptyArrayType(), $context->negate(), $scope)->setRootExpr($expr); } if ( @@ -2040,26 +1979,26 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif || ($leftType->isFloat()->yes() && $rightType->isFloat()->yes()) || ($leftType->isEnum()->yes() && $rightType->isEnum()->yes()) ) { - return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context, $rootExpr); + return $this->specifyTypesInCondition($scope, new Expr\BinaryOp\Identical($expr->left, $expr->right), $context)->setRootExpr($expr); } $leftExprString = $this->exprPrinter->printExpr($expr->left); $rightExprString = $this->exprPrinter->printExpr($expr->right); if ($leftExprString === $rightExprString) { if (!$expr->left instanceof Expr\Variable || !$expr->right instanceof Expr\Variable) { - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } } - $leftTypes = $this->create($expr->left, $leftType, $context, false, $scope, $rootExpr); - $rightTypes = $this->create($expr->right, $rightType, $context, false, $scope, $rootExpr); + $leftTypes = $this->create($expr->left, $leftType, $context, $scope)->setRootExpr($expr); + $rightTypes = $this->create($expr->right, $rightType, $context, $scope)->setRootExpr($expr); return $context->true() ? $leftTypes->unionWith($rightTypes) : $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($scope)); } - public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, TypeSpecifierContext $context, ?Expr $rootExpr): SpecifiedTypes + public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes { $leftExpr = $expr->left; $rightExpr = $expr->right; @@ -2085,13 +2024,13 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty && $rightType->isInteger()->yes() ) { if (IntegerRangeType::fromInterval(null, -1)->isSuperTypeOf($rightType)->yes()) { - return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, false, $scope, $rootExpr); + return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, $scope)->setRootExpr($expr); } $argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($rightType); if ($isZero->yes()) { - $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, false, $scope, $rootExpr); + $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, $scope)->setRootExpr($expr); if ($context->truthy() && !$argType->isArray()->yes()) { $newArgType = new UnionType([ @@ -2103,12 +2042,12 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty } return $funcTypes->unionWith( - $this->create($unwrappedLeftExpr->getArgs()[0]->value, $newArgType, $context, false, $scope, $rootExpr), + $this->create($unwrappedLeftExpr->getArgs()[0]->value, $newArgType, $context, $scope)->setRootExpr($expr), ); } if ($argType instanceof UnionType) { - $narrowed = $this->narrowUnionByArraySize($unwrappedLeftExpr, $argType, $rightType, $context, $scope, $rootExpr); + $narrowed = $this->narrowUnionByArraySize($unwrappedLeftExpr, $argType, $rightType, $context, $scope, $expr); if ($narrowed !== null) { return $narrowed; } @@ -2120,18 +2059,18 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $argType->isConstantArray()->yes() && $rightType->isSuperTypeOf($argType->getArraySize())->no() ) { - return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, false, $scope, $rootExpr); + return $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NeverType(), $context, $scope)->setRootExpr($expr); } - $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, false, $scope, $rootExpr); + $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, $scope)->setRootExpr($expr); $constArray = $this->turnListIntoConstantArray($unwrappedLeftExpr, $argType, $rightType, $scope); if ($constArray !== null) { return $funcTypes->unionWith( - $this->create($unwrappedLeftExpr->getArgs()[0]->value, $constArray, $context, false, $scope, $rootExpr), + $this->create($unwrappedLeftExpr->getArgs()[0]->value, $constArray, $context, $scope)->setRootExpr($expr), ); } elseif (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($rightType)->yes()) { return $funcTypes->unionWith( - $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, false, $scope, $rootExpr), + $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, $scope)->setRootExpr($expr), ); } @@ -2151,8 +2090,7 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $scope, $leftExpr, $context, - $rootExpr, - ); + )->setRootExpr($expr); } if ( @@ -2167,10 +2105,8 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $unwrappedLeftExpr->getArgs()[0]->value, $rightType->getClassStringObjectType(), $context, - false, $scope, - $rootExpr, - )->unionWith($this->create($leftExpr, $rightType, $context, false, $scope, $rootExpr)); + )->unionWith($this->create($leftExpr, $rightType, $context, $scope))->setRootExpr($expr); } } @@ -2194,18 +2130,16 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $unwrappedLeftExpr->getArgs()[0]->value, TypeCombinator::intersect($argType, new AccessoryNonFalsyStringType()), $context, - false, $scope, - ); + )->setRootExpr($expr); } return $this->create( $unwrappedLeftExpr->getArgs()[0]->value, TypeCombinator::intersect($argType, new AccessoryNonEmptyStringType()), $context, - false, $scope, - ); + )->setRootExpr($expr); } } @@ -2213,9 +2147,9 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $types = null; foreach ($rightType->getFiniteTypes() as $finiteType) { if ($finiteType->isString()->yes()) { - $specifiedType = $this->specifyTypesForConstantStringBinaryExpression($unwrappedLeftExpr, $finiteType, $context, $scope, $rootExpr); + $specifiedType = $this->specifyTypesForConstantStringBinaryExpression($unwrappedLeftExpr, $finiteType, $context, $scope, $expr); } else { - $specifiedType = $this->specifyTypesForConstantBinaryExpression($unwrappedLeftExpr, $finiteType, $context, $scope, $rootExpr); + $specifiedType = $this->specifyTypesForConstantBinaryExpression($unwrappedLeftExpr, $finiteType, $context, $scope, $expr); } if ($specifiedType === null) { continue; @@ -2230,7 +2164,7 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty if ($types !== null) { if ($leftExpr !== $unwrappedLeftExpr) { - $types = $types->unionWith($this->create($leftExpr, $rightType, $context, false, $scope, $rootExpr)); + $types = $types->unionWith($this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr)); } return $types; } @@ -2246,11 +2180,11 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $unwrappedExprNode = $exprNode->getExpr(); } - $specifiedType = $this->specifyTypesForConstantBinaryExpression($unwrappedExprNode, $constantType, $context, $scope, $rootExpr); + $specifiedType = $this->specifyTypesForConstantBinaryExpression($unwrappedExprNode, $constantType, $context, $scope, $expr); if ($specifiedType !== null) { if ($exprNode !== $unwrappedExprNode) { $specifiedType = $specifiedType->unionWith( - $this->create($exprNode, $constantType, $context, false, $scope, $rootExpr), + $this->create($exprNode, $constantType, $context, $scope)->setRootExpr($expr), ); } return $specifiedType; @@ -2274,8 +2208,7 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty new Name($rightType->getValue()), ), $context, - $rootExpr, - )->unionWith($this->create($leftExpr, $rightType, $context, false, $scope, $rootExpr)); + )->unionWith($this->create($leftExpr, $rightType, $context, $scope))->setRootExpr($expr); } $leftType = $scope->getType($leftExpr); @@ -2296,8 +2229,7 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty new Name($leftType->getValue()), ), $context, - $rootExpr, - )->unionWith($this->create($rightExpr, $leftType, $context, false, $scope, $rootExpr)); + )->unionWith($this->create($rightExpr, $leftType, $context, $scope)->setRootExpr($expr)); } if ($context->false()) { @@ -2305,16 +2237,16 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty if ($identicalType instanceof ConstantBooleanType) { $never = new NeverType(); $contextForTypes = $identicalType->getValue() ? $context->negate() : $context; - $leftTypes = $this->create($leftExpr, $never, $contextForTypes, false, $scope, $rootExpr); - $rightTypes = $this->create($rightExpr, $never, $contextForTypes, false, $scope, $rootExpr); + $leftTypes = $this->create($leftExpr, $never, $contextForTypes, $scope)->setRootExpr($expr); + $rightTypes = $this->create($rightExpr, $never, $contextForTypes, $scope)->setRootExpr($expr); if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $leftTypes->unionWith( - $this->create($unwrappedLeftExpr, $never, $contextForTypes, false, $scope, $rootExpr), + $this->create($unwrappedLeftExpr, $never, $contextForTypes, $scope)->setRootExpr($expr), ); } if ($rightExpr instanceof AlwaysRememberedExpr) { $rightTypes = $rightTypes->unionWith( - $this->create($unwrappedRightExpr, $never, $contextForTypes, false, $scope, $rootExpr), + $this->create($unwrappedRightExpr, $never, $contextForTypes, $scope)->setRootExpr($expr), ); } return $leftTypes->unionWith($rightTypes); @@ -2330,19 +2262,15 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $rightExpr, $leftType, $context, - false, $scope, - $rootExpr, - ); + )->setRootExpr($expr); if ($rightExpr instanceof AlwaysRememberedExpr) { $types = $types->unionWith($this->create( $unwrappedRightExpr, $leftType, $context, - false, $scope, - $rootExpr, - )); + ))->setRootExpr($expr); } } if ( @@ -2353,19 +2281,15 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $leftExpr, $rightType, $context, - false, $scope, - $rootExpr, - ); + )->setRootExpr($expr); if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $leftTypes->unionWith($this->create( $unwrappedLeftExpr, $rightType, $context, - false, $scope, - $rootExpr, - )); + ))->setRootExpr($expr); } if ($types !== null) { $types = $types->unionWith($leftTypes); @@ -2382,30 +2306,30 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty $rightExprString = $this->exprPrinter->printExpr($unwrappedRightExpr); if ($leftExprString === $rightExprString) { if (!$unwrappedLeftExpr instanceof Expr\Variable || !$unwrappedRightExpr instanceof Expr\Variable) { - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } } if ($context->true()) { - $leftTypes = $this->create($leftExpr, $rightType, $context, false, $scope, $rootExpr); - $rightTypes = $this->create($rightExpr, $leftType, $context, false, $scope, $rootExpr); + $leftTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); + $rightTypes = $this->create($rightExpr, $leftType, $context, $scope)->setRootExpr($expr); if ($leftExpr instanceof AlwaysRememberedExpr) { $leftTypes = $leftTypes->unionWith( - $this->create($unwrappedLeftExpr, $rightType, $context, false, $scope, $rootExpr), + $this->create($unwrappedLeftExpr, $rightType, $context, $scope)->setRootExpr($expr), ); } if ($rightExpr instanceof AlwaysRememberedExpr) { $rightTypes = $rightTypes->unionWith( - $this->create($unwrappedRightExpr, $leftType, $context, false, $scope, $rootExpr), + $this->create($unwrappedRightExpr, $leftType, $context, $scope)->setRootExpr($expr), ); } return $leftTypes->unionWith($rightTypes); } elseif ($context->false()) { - return $this->create($leftExpr, $leftType, $context, false, $scope, $rootExpr)->normalize($scope) - ->intersectWith($this->create($rightExpr, $rightType, $context, false, $scope, $rootExpr)->normalize($scope)); + return $this->create($leftExpr, $leftType, $context, $scope)->setRootExpr($expr)->normalize($scope) + ->intersectWith($this->create($rightExpr, $rightType, $context, $scope)->setRootExpr($expr)->normalize($scope)); } - return new SpecifiedTypes([], [], false, [], $rootExpr); + return (new SpecifiedTypes([], []))->setRootExpr($expr); } } diff --git a/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php b/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php index d255aa8c15..35a3ecb8ea 100644 --- a/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php @@ -73,7 +73,6 @@ public function specifyTypes( $key, $arrayKeyType, $context, - false, $scope, ); @@ -86,10 +85,8 @@ public function specifyTypes( $arrayDimFetch, $arrayType->getIterableValueType(), $context, - false, $scope, - new Identical($arrayDimFetch, new ConstFetch(new Name('__PHPSTAN_FAUX_CONSTANT'))), - )); + ))->setRootExpr(new Identical($arrayDimFetch, new ConstFetch(new Name('__PHPSTAN_FAUX_CONSTANT')))); } return new SpecifiedTypes(); @@ -108,7 +105,6 @@ public function specifyTypes( $array, $type, $context, - false, $scope, ); } diff --git a/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php b/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php index 4b974bbe1d..b382891275 100644 --- a/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php @@ -47,7 +47,6 @@ public function specifyTypes( $arrayArg, TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new NonEmptyArrayType()), $context, - false, $scope, ); } diff --git a/src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php b/src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php index 8cf3d88c19..e10e74a53e 100644 --- a/src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php @@ -50,7 +50,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n ]), new ConstantBooleanType(true), $context, - false, $scope, ); } @@ -64,7 +63,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $node->getArgs()[0]->value, $narrowedType, $context, - false, $scope, ); } diff --git a/src/Type/Php/CountFunctionTypeSpecifyingExtension.php b/src/Type/Php/CountFunctionTypeSpecifyingExtension.php index 03d938a7e4..b109b13f91 100644 --- a/src/Type/Php/CountFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/CountFunctionTypeSpecifyingExtension.php @@ -41,7 +41,7 @@ public function specifyTypes( return new SpecifiedTypes([], []); } - return $this->typeSpecifier->create($node->getArgs()[0]->value, new NonEmptyArrayType(), $context, false, $scope); + return $this->typeSpecifier->create($node->getArgs()[0]->value, new NonEmptyArrayType(), $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void diff --git a/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php b/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php index 7e70566044..837c3fb890 100644 --- a/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/CtypeDigitFunctionTypeSpecifyingExtension.php @@ -59,7 +59,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n } $unionType = TypeCombinator::union(...$types); - $specifiedTypes = $this->typeSpecifier->create($exprArg, $unionType, $context, false, $scope); + $specifiedTypes = $this->typeSpecifier->create($exprArg, $unionType, $context, $scope); if ($exprArg instanceof Cast\String_) { $castedType = new UnionType([ @@ -71,7 +71,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n new ConstantBooleanType(true), ]); $specifiedTypes = $specifiedTypes->unionWith( - $this->typeSpecifier->create($exprArg->expr, $castedType, $context, false, $scope), + $this->typeSpecifier->create($exprArg->expr, $castedType, $context, $scope), ); } diff --git a/src/Type/Php/DefineConstantTypeSpecifyingExtension.php b/src/Type/Php/DefineConstantTypeSpecifyingExtension.php index 81a836f620..9d4ac3d682 100644 --- a/src/Type/Php/DefineConstantTypeSpecifyingExtension.php +++ b/src/Type/Php/DefineConstantTypeSpecifyingExtension.php @@ -56,9 +56,8 @@ public function specifyTypes( ), $scope->getType($node->getArgs()[1]->value), TypeSpecifierContext::createTruthy(), - true, $scope, - ); + )->setAlwaysOverwriteTypes(); } } diff --git a/src/Type/Php/DefinedConstantTypeSpecifyingExtension.php b/src/Type/Php/DefinedConstantTypeSpecifyingExtension.php index 880a3c8c21..01c310459b 100644 --- a/src/Type/Php/DefinedConstantTypeSpecifyingExtension.php +++ b/src/Type/Php/DefinedConstantTypeSpecifyingExtension.php @@ -63,7 +63,6 @@ public function specifyTypes( $expr, new MixedType(), $context, - false, $scope, ); } diff --git a/src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php b/src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php index 51bc6c4b2d..5d320104a7 100644 --- a/src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php @@ -42,7 +42,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n ]), new ConstantBooleanType(true), $context, - false, $scope, ); } @@ -51,7 +50,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $node->getArgs()[0]->value, new CallableType(), $context, - false, $scope, ); } diff --git a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php index 1c4436ca46..a91974e466 100644 --- a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php @@ -71,9 +71,9 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n } if ($isStrictComparison) { - $itemTypes = $this->typeSpecifier->resolveIdentical(new Identical($needleExpr, $item->value), $scope, $context, null); + $itemTypes = $this->typeSpecifier->resolveIdentical(new Identical($needleExpr, $item->value), $scope, $context); } else { - $itemTypes = $this->typeSpecifier->resolveEqual(new Equal($needleExpr, $item->value), $scope, $context, null); + $itemTypes = $this->typeSpecifier->resolveEqual(new Equal($needleExpr, $item->value), $scope, $context); } if ($types === null) { @@ -99,7 +99,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $node->getArgs()[1]->value, TypeCombinator::intersect($arrayType, new NonEmptyArrayType()), $context, - false, $scope, ); } @@ -122,7 +121,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $needleExpr, $arrayValueType, $context, - false, $scope, ); if ($needleExpr instanceof AlwaysRememberedExpr) { @@ -130,7 +128,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $needleExpr->getExpr(), $arrayValueType, $context, - false, $scope, )); } @@ -156,7 +153,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $node->getArgs()[1]->value, new ArrayType(new MixedType(), $arrayValueType), TypeSpecifierContext::createTrue(), - false, $scope, )); } @@ -166,7 +162,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $node->getArgs()[1]->value, TypeCombinator::intersect($arrayType, new NonEmptyArrayType()), $context, - false, $scope, )); } diff --git a/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php index c4000b9aff..fe6048dbb9 100644 --- a/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsAFunctionTypeSpecifyingExtension.php @@ -51,7 +51,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $node->getArgs()[0]->value, $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, true), $context, - false, $scope, ); } diff --git a/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php index 20ca925c1c..5f6c0d710e 100644 --- a/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php @@ -39,7 +39,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n throw new ShouldNotHappenException(); } - return $this->typeSpecifier->create($node->getArgs()[0]->value, new ArrayType(new MixedType($this->explicitMixed), new MixedType($this->explicitMixed)), $context, false, $scope); + return $this->typeSpecifier->create($node->getArgs()[0]->value, new ArrayType(new MixedType($this->explicitMixed), new MixedType($this->explicitMixed)), $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void diff --git a/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php index a571338e18..42c5fe8505 100644 --- a/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsCallableFunctionTypeSpecifyingExtension.php @@ -58,7 +58,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n return $this->methodExistsExtension->specifyTypes($functionReflection, $functionCall, $scope, $context); } - return $this->typeSpecifier->create($value, new CallableType(), $context, false, $scope); + return $this->typeSpecifier->create($value, new CallableType(), $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void diff --git a/src/Type/Php/IsIterableFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsIterableFunctionTypeSpecifyingExtension.php index c523fde243..a8404ef99f 100644 --- a/src/Type/Php/IsIterableFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsIterableFunctionTypeSpecifyingExtension.php @@ -36,7 +36,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n return new SpecifiedTypes(); } - return $this->typeSpecifier->create($node->getArgs()[0]->value, new IterableType(new MixedType(), new MixedType()), $context, false, $scope); + return $this->typeSpecifier->create($node->getArgs()[0]->value, new IterableType(new MixedType(), new MixedType()), $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void diff --git a/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php index 2d52ee99e1..5bf3d9df9b 100644 --- a/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php @@ -52,7 +52,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $node->getArgs()[0]->value, $this->isAFunctionTypeSpecifyingHelper->determineType($objectOrClassType, $classType, $allowString, false), $context, - false, $scope, ); } diff --git a/src/Type/Php/MethodExistsTypeSpecifyingExtension.php b/src/Type/Php/MethodExistsTypeSpecifyingExtension.php index bdff31b842..bc00486cbf 100644 --- a/src/Type/Php/MethodExistsTypeSpecifyingExtension.php +++ b/src/Type/Php/MethodExistsTypeSpecifyingExtension.php @@ -61,7 +61,6 @@ public function specifyTypes( new HasMethodType($methodNameType->getValue()), ]), $context, - false, $scope, ); } @@ -79,7 +78,6 @@ public function specifyTypes( new ClassStringType(), ]), $context, - false, $scope, ); } diff --git a/src/Type/Php/PregMatchTypeSpecifyingExtension.php b/src/Type/Php/PregMatchTypeSpecifyingExtension.php index 2c7cad49be..09606087f1 100644 --- a/src/Type/Php/PregMatchTypeSpecifyingExtension.php +++ b/src/Type/Php/PregMatchTypeSpecifyingExtension.php @@ -68,14 +68,17 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $context = $context->negate(); } - return $this->typeSpecifier->create( + $types = $this->typeSpecifier->create( $matchesArg->value, $matchedType, $context, - $overwrite, $scope, - $node, - ); + )->setRootExpr($node); + if ($overwrite) { + $types = $types->setAlwaysOverwriteTypes(); + } + + return $types; } } diff --git a/src/Type/Php/PropertyExistsTypeSpecifyingExtension.php b/src/Type/Php/PropertyExistsTypeSpecifyingExtension.php index 70d08b9098..38592e632e 100644 --- a/src/Type/Php/PropertyExistsTypeSpecifyingExtension.php +++ b/src/Type/Php/PropertyExistsTypeSpecifyingExtension.php @@ -82,7 +82,6 @@ public function specifyTypes( new HasPropertyType($propertyNameType->getValue()), ]), $context, - false, $scope, ); } diff --git a/src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php b/src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php index fb3e577d38..df49f7cb16 100644 --- a/src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php +++ b/src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php @@ -50,7 +50,6 @@ public function specifyTypes(MethodReflection $methodReflection, MethodCall $nod new ObjectType($valueType->getValue()), ]), $context, - false, $scope, ); } diff --git a/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php b/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php index 934aece46e..a9134026ea 100644 --- a/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php @@ -78,9 +78,8 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $value, TypeCombinator::union(...$types), TypeSpecifierContext::createTruthy(), - true, $scope, - ); + )->setAlwaysOverwriteTypes(); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void diff --git a/src/Type/Php/StrContainingTypeSpecifyingExtension.php b/src/Type/Php/StrContainingTypeSpecifyingExtension.php index 8cf678ae56..af5f0e55b7 100644 --- a/src/Type/Php/StrContainingTypeSpecifyingExtension.php +++ b/src/Type/Php/StrContainingTypeSpecifyingExtension.php @@ -90,18 +90,16 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $args[$hackstackArg]->value, new IntersectionType($accessories), $context, - false, $scope, - new BooleanAnd( - new NotIdentical( - $args[$needleArg]->value, - new String_(''), - ), - new FuncCall(new Name('FAUX_FUNCTION'), [ - new Arg($args[$needleArg]->value), - ]), + )->setRootExpr(new BooleanAnd( + new NotIdentical( + $args[$needleArg]->value, + new String_(''), ), - ); + new FuncCall(new Name('FAUX_FUNCTION'), [ + new Arg($args[$needleArg]->value), + ]), + )); } } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php index 3aa4bf0810..fe386028a3 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php @@ -41,10 +41,12 @@ public function testRule(): void [ 'Call to method PHPStan\Tests\AssertionClass::assertNotInt() with int will always evaluate to false.', 30, + 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', ], [ 'Call to method PHPStan\Tests\AssertionClass::assertNotInt() with string will always evaluate to true.', 36, + 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', ], [ 'Call to method ImpossibleMethodCall\Foo::isSame() with 1 and 1 will always evaluate to true.', diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php index 29f63a6bf2..206e7acc45 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php @@ -52,10 +52,12 @@ public function testRule(): void [ 'Call to method PHPStan\Tests\AssertionClass::assertNotInt() with int will always evaluate to false.', 30, + 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', ], [ 'Call to method PHPStan\Tests\AssertionClass::assertNotInt() with string will always evaluate to true.', 36, + 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', ], [ 'Call to method ImpossibleMethodCall\Foo::isSame() with 1 and 1 will always evaluate to true.', diff --git a/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php b/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php index 4e2acbd198..1ba7c4855f 100644 --- a/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php +++ b/tests/PHPStan/Rules/Comparison/data/TestTypeOverwriteSpecifyingExtensions.php @@ -51,8 +51,8 @@ public function specifyTypes( $node->var, $newType, TypeSpecifierContext::createTruthy(), - true - ); + $scope, + )->setAlwaysOverwriteTypes(); } } From 51ce513308fb5d50459f0896dd7e6421f4d3be85 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 13 Sep 2024 14:46:46 +0200 Subject: [PATCH 084/508] Fix --- src/Analyser/TypeSpecifier.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 5c349ce624..f05f7e4358 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -1405,7 +1405,7 @@ static function (Type $type, callable $traverse) use ($templateTypeMap, &$contai $assertedType, $assert->isNegated() ? TypeSpecifierContext::createFalse() : TypeSpecifierContext::createTrue(), $scope, - )->setRootExpr($containsUnresolvedTemplate || $assert->isEquality() ? $call : null); + )->setRootExpr($containsUnresolvedTemplate || $assert->isEquality() ? $call : $assertExpr); $types = $types !== null ? $types->unionWith($newTypes) : $newTypes; if (!$context->null() || !$assertedType instanceof ConstantBooleanType) { From 5962aa1cb9d16ae86362a8aca8a5f8eecf81ee40 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 13 Sep 2024 22:21:12 +0200 Subject: [PATCH 085/508] Revert "Fix" This reverts commit 51ce513308fb5d50459f0896dd7e6421f4d3be85. --- src/Analyser/TypeSpecifier.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index f05f7e4358..5c349ce624 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -1405,7 +1405,7 @@ static function (Type $type, callable $traverse) use ($templateTypeMap, &$contai $assertedType, $assert->isNegated() ? TypeSpecifierContext::createFalse() : TypeSpecifierContext::createTrue(), $scope, - )->setRootExpr($containsUnresolvedTemplate || $assert->isEquality() ? $call : $assertExpr); + )->setRootExpr($containsUnresolvedTemplate || $assert->isEquality() ? $call : null); $types = $types !== null ? $types->unionWith($newTypes) : $newTypes; if (!$context->null() || !$assertedType instanceof ConstantBooleanType) { From a2854d1c276ada4fd3a5c7348585ebfa2fac9289 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 14:19:57 +0200 Subject: [PATCH 086/508] [BCB] Parameter `$callableParameters` of MutatingScope::enterAnonymousFunction() and enterArrowFunction() made required --- UPGRADING.md | 4 ++++ src/Analyser/MutatingScope.php | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 6baecd8e10..3516ec8d6b 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -47,3 +47,7 @@ If you want to change `$overwrite` or `$rootExpr` (previous parameters also used ### Changed `TypeSpecifier::specifyTypesInCondition()` This method now longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable). + +### Minor backward compatibility breaks + +* Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 6d0bccf719..06974beea7 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3376,7 +3376,7 @@ public function isInClosureBind(): bool */ public function enterAnonymousFunction( Expr\Closure $closure, - ?array $callableParameters = null, + ?array $callableParameters, ): self { $anonymousFunctionReflection = $this->getType($closure); @@ -3411,7 +3411,7 @@ public function enterAnonymousFunction( */ private function enterAnonymousFunctionWithoutReflection( Expr\Closure $closure, - ?array $callableParameters = null, + ?array $callableParameters, ): self { $expressionTypes = []; @@ -3553,7 +3553,7 @@ private function invalidateStaticExpressions(array $expressionTypes): array * @api * @param ParameterReflection[]|null $callableParameters */ - public function enterArrowFunction(Expr\ArrowFunction $arrowFunction, ?array $callableParameters = null): self + public function enterArrowFunction(Expr\ArrowFunction $arrowFunction, ?array $callableParameters): self { $anonymousFunctionReflection = $this->getType($arrowFunction); if (!$anonymousFunctionReflection instanceof ClosureType) { From 2c4c0cde75e637ac323e81def57d4a2ace952429 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 14:39:53 +0200 Subject: [PATCH 087/508] A few more MutatingScope method parameters made required --- src/Analyser/MutatingScope.php | 38 +++++++++---------- src/Analyser/NodeScopeResolver.php | 23 +++++------ .../Operators/InvalidBinaryOperationRule.php | 5 ++- .../Operators/InvalidUnaryOperationRule.php | 3 +- ...ArrayFilterFunctionReturnTypeExtension.php | 5 ++- tests/PHPStan/Analyser/ScopeTest.php | 5 ++- .../PHPStan/Analyser/StatementResultTest.php | 9 +++-- tests/PHPStan/Analyser/TypeSpecifierTest.php | 29 +++++++------- tests/PHPStan/Type/BitwiseFlagHelperTest.php | 14 +++---- 9 files changed, 68 insertions(+), 63 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 06974beea7..6de895a04b 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3614,7 +3614,7 @@ private function enterArrowFunctionWithoutReflection(Expr\ArrowFunction $arrowFu if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } - $arrowFunctionScope = $arrowFunctionScope->assignVariable($parameter->var->name, $parameterType, $parameterType); + $arrowFunctionScope = $arrowFunctionScope->assignVariable($parameter->var->name, $parameterType, $parameterType, TrinaryLogic::createYes()); } if ($arrowFunction->static) { @@ -3733,6 +3733,7 @@ public function enterForeach(self $originalScope, Expr $iteratee, string $valueN $valueName, $originalScope->getIterableValueType($iterateeType), $originalScope->getIterableValueType($nativeIterateeType), + TrinaryLogic::createYes(), ); if ($keyName !== null) { $scope = $scope->enterForeachKey($originalScope, $iteratee, $keyName); @@ -3749,6 +3750,7 @@ public function enterForeachKey(self $originalScope, Expr $iteratee, string $key $keyName, $originalScope->getIterableKeyType($iterateeType), $originalScope->getIterableKeyType($nativeIterateeType), + TrinaryLogic::createYes(), ); if ($iterateeType->isArray()->yes()) { @@ -3783,6 +3785,7 @@ public function enterCatchType(Type $catchType, ?string $variableName): self $variableName, TypeCombinator::intersect($catchType, new ObjectType(Throwable::class)), TypeCombinator::intersect($catchType, new ObjectType(Throwable::class)), + TrinaryLogic::createYes(), ); } @@ -3928,18 +3931,16 @@ public function isUndefinedExpressionAllowed(Expr $expr): bool return array_key_exists($exprString, $this->currentlyAllowedUndefinedExpressions); } - public function assignVariable(string $variableName, Type $type, Type $nativeType, ?TrinaryLogic $certainty = null): self + public function assignVariable(string $variableName, Type $type, Type $nativeType, TrinaryLogic $certainty): self { $node = new Variable($variableName); $scope = $this->assignExpression($node, $type, $nativeType); - if ($certainty !== null) { - if ($certainty->no()) { - throw new ShouldNotHappenException(); - } elseif (!$certainty->yes()) { - $exprString = '$' . $variableName; - $scope->expressionTypes[$exprString] = new ExpressionTypeHolder($node, $type, $certainty); - $scope->nativeExpressionTypes[$exprString] = new ExpressionTypeHolder($node, $nativeType, $certainty); - } + if ($certainty->no()) { + throw new ShouldNotHappenException(); + } elseif (!$certainty->yes()) { + $exprString = '$' . $variableName; + $scope->expressionTypes[$exprString] = new ExpressionTypeHolder($node, $type, $certainty); + $scope->nativeExpressionTypes[$exprString] = new ExpressionTypeHolder($node, $nativeType, $certainty); } $parameterOriginalValueExprString = $this->getNodeKey(new ParameterVariableOriginalValueExpr($variableName)); @@ -3987,7 +3988,7 @@ public function unsetExpression(Expr $expr): self return $scope->invalidateExpression($expr); } - public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, ?TrinaryLogic $certainty = null): self + public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, TrinaryLogic $certainty): self { if ($expr instanceof ConstFetch) { $loweredConstName = strtolower($expr->name->toString()); @@ -4035,9 +4036,7 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, } } - if ($certainty === null) { - $certainty = TrinaryLogic::createYes(); - } elseif ($certainty->no()) { + if ($certainty->no()) { throw new ShouldNotHappenException(); } @@ -4073,11 +4072,8 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType, return $scope; } - public function assignExpression(Expr $expr, Type $type, ?Type $nativeType = null): self + public function assignExpression(Expr $expr, Type $type, Type $nativeType): self { - if ($nativeType === null) { - $nativeType = new MixedType(); - } $scope = $this; if ($expr instanceof PropertyFetch) { $scope = $this->invalidateExpression($expr) @@ -4088,7 +4084,7 @@ public function assignExpression(Expr $expr, Type $type, ?Type $nativeType = nul $scope = $this->invalidateExpression($expr); } - return $scope->specifyExpressionType($expr, $type, $nativeType); + return $scope->specifyExpressionType($expr, $type, $nativeType, TrinaryLogic::createYes()); } public function assignInitializedProperty(Type $fetchedOnType, string $propertyName): self @@ -4292,13 +4288,14 @@ public function addTypeToExpression(Expr $expr, Type $type): self if ($originalExprType->equals($nativeType)) { $newType = TypeCombinator::intersect($type, $originalExprType); - return $this->specifyExpressionType($expr, $newType, $newType); + return $this->specifyExpressionType($expr, $newType, $newType, TrinaryLogic::createYes()); } return $this->specifyExpressionType( $expr, TypeCombinator::intersect($type, $originalExprType), TypeCombinator::intersect($type, $nativeType), + TrinaryLogic::createYes(), ); } @@ -4315,6 +4312,7 @@ public function removeTypeFromExpression(Expr $expr, Type $typeToRemove): self $expr, TypeCombinator::remove($exprType, $typeToRemove), TypeCombinator::remove($this->getNativeType($expr), $typeToRemove), + TrinaryLogic::createYes(), ); } diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index ca8d1e7458..09f53137c9 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1809,7 +1809,7 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void { continue; } - $scope = $scope->assignVariable($var->name, new MixedType(), new MixedType()); + $scope = $scope->assignVariable($var->name, new MixedType(), new MixedType(), TrinaryLogic::createYes()); $vars[] = $var->name; } $scope = $this->processVarAnnotation($scope, $vars, $stmt); @@ -1842,7 +1842,7 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void { $impurePoints = array_merge($impurePoints, $varResult->getImpurePoints()); $scope = $scope->exitExpressionAssign($var->var); - $scope = $scope->assignVariable($var->var->name, new MixedType(), new MixedType()); + $scope = $scope->assignVariable($var->var->name, new MixedType(), new MixedType(), TrinaryLogic::createYes()); $vars[] = $var->var->name; } @@ -2091,6 +2091,7 @@ private function ensureShallowNonNullability(MutatingScope $scope, Scope $origin $exprToSpecify, $exprTypeWithoutNull, TypeCombinator::removeNull($nativeType), + TrinaryLogic::createYes(), ); return new EnsuredNonNullabilityResult( @@ -2457,7 +2458,7 @@ static function (): void { $functionReflection !== null && in_array($functionReflection->getName(), ['fopen', 'file_get_contents'], true) ) { - $scope = $scope->assignVariable('http_response_header', AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())), new ArrayType(new IntegerType(), new StringType())); + $scope = $scope->assignVariable('http_response_header', AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())), new ArrayType(new IntegerType(), new StringType()), TrinaryLogic::createYes()); } if ( @@ -4217,7 +4218,7 @@ private function processClosureNode( $variableNativeType = TypeCombinator::union($scope->getVariableType($inAssignRightSideVariableName), $inAssignRightSideNativeType); } } - $scope = $scope->assignVariable($inAssignRightSideVariableName, $variableType, $variableNativeType); + $scope = $scope->assignVariable($inAssignRightSideVariableName, $variableType, $variableNativeType, TrinaryLogic::createYes()); } } $this->processExprNode($stmt, $use->var, $useScope, $nodeCallback, $context); @@ -4625,7 +4626,7 @@ private function processArgs( && !$arg->value->static ) { $restoreThisScope = $scopeToPass; - $scopeToPass = $scopeToPass->assignVariable('this', $parameter->getClosureThisType(), new ObjectWithoutClassType()); + $scopeToPass = $scopeToPass->assignVariable('this', $parameter->getClosureThisType(), new ObjectWithoutClassType(), TrinaryLogic::createYes()); } if ($parameter !== null) { @@ -4677,7 +4678,7 @@ private function processArgs( && $parameter->getClosureThisType() !== null && !$arg->value->static ) { - $scopeToPass = $scopeToPass->assignVariable('this', $parameter->getClosureThisType(), new ObjectWithoutClassType()); + $scopeToPass = $scopeToPass->assignVariable('this', $parameter->getClosureThisType(), new ObjectWithoutClassType(), TrinaryLogic::createYes()); } if ($parameter !== null) { @@ -4983,7 +4984,7 @@ private function processAssignVar( $conditionalExpressions = $this->processSureNotTypesForConditionalExpressionsAfterAssign($scope, $var->name, $conditionalExpressions, $falseySpecifiedTypes, $falseyType); $nodeCallback(new VariableAssignNode($var, $assignedExpr, $isAssignOp), $result->getScope()); - $scope = $scope->assignVariable($var->name, $type, $scope->getNativeType($assignedExpr)); + $scope = $scope->assignVariable($var->name, $type, $scope->getNativeType($assignedExpr), TrinaryLogic::createYes()); foreach ($conditionalExpressions as $exprString => $holders) { $scope = $scope->addConditionalExpressions($exprString, $holders); } @@ -5142,7 +5143,7 @@ private function processAssignVar( if ($varType->isArray()->yes() || !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->yes()) { if ($var instanceof Variable && is_string($var->name)) { $nodeCallback(new VariableAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); - $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite); + $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite, TrinaryLogic::createYes()); } else { if ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { $nodeCallback(new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); @@ -5394,7 +5395,7 @@ static function (): void { if ($var instanceof Variable && is_string($var->name)) { $nodeCallback(new VariableAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); - $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite); + $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite, TrinaryLogic::createYes()); } else { if ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { $nodeCallback(new PropertyAssignNode($var, $assignedPropertyExpr, $isAssignOp), $scope); @@ -5603,13 +5604,13 @@ private function processVarAnnotation(MutatingScope $scope, array $variableNames $variableType = $varTags[$variableName]->getType(); $changed = true; - $scope = $scope->assignVariable($variableName, $variableType, new MixedType()); + $scope = $scope->assignVariable($variableName, $variableType, new MixedType(), TrinaryLogic::createYes()); } if (count($variableNames) === 1 && count($varTags) === 1 && isset($varTags[0])) { $variableType = $varTags[0]->getType(); $changed = true; - $scope = $scope->assignVariable($variableNames[0], $variableType, new MixedType()); + $scope = $scope->assignVariable($variableNames[0], $variableType, new MixedType(), TrinaryLogic::createYes()); } return $scope; diff --git a/src/Rules/Operators/InvalidBinaryOperationRule.php b/src/Rules/Operators/InvalidBinaryOperationRule.php index 517c41b909..77653e1f1a 100644 --- a/src/Rules/Operators/InvalidBinaryOperationRule.php +++ b/src/Rules/Operators/InvalidBinaryOperationRule.php @@ -10,6 +10,7 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\ShouldNotHappenException; +use PHPStan\TrinaryLogic; use PHPStan\Type\ErrorType; use PHPStan\Type\Type; use PHPStan\Type\VerbosityLevel; @@ -104,8 +105,8 @@ public function processNode(Node $node, Scope $scope): array } $scope = $scope - ->assignVariable($leftName, $leftType, $leftType) - ->assignVariable($rightName, $rightType, $rightType); + ->assignVariable($leftName, $leftType, $leftType, TrinaryLogic::createYes()) + ->assignVariable($rightName, $rightType, $rightType, TrinaryLogic::createYes()); if (!$scope->getType($newNode) instanceof ErrorType) { return []; diff --git a/src/Rules/Operators/InvalidUnaryOperationRule.php b/src/Rules/Operators/InvalidUnaryOperationRule.php index 9ea9c07342..cf823a82bf 100644 --- a/src/Rules/Operators/InvalidUnaryOperationRule.php +++ b/src/Rules/Operators/InvalidUnaryOperationRule.php @@ -9,6 +9,7 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\ShouldNotHappenException; +use PHPStan\TrinaryLogic; use PHPStan\Type\ErrorType; use PHPStan\Type\Type; use PHPStan\Type\VerbosityLevel; @@ -69,7 +70,7 @@ public function processNode(Node $node, Scope $scope): array throw new ShouldNotHappenException(); } - $scope = $scope->assignVariable($varName, $exprType, $exprType); + $scope = $scope->assignVariable($varName, $exprType, $exprType, TrinaryLogic::createYes()); if (!$scope->getType($newNode) instanceof ErrorType) { return []; } diff --git a/src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php b/src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php index 4672fd1a96..8f2e5d096c 100644 --- a/src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php @@ -18,6 +18,7 @@ use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\ShouldNotHappenException; +use PHPStan\TrinaryLogic; use PHPStan\Type\ArrayType; use PHPStan\Type\BenevolentUnionType; use PHPStan\Type\Constant\ConstantArrayType; @@ -244,7 +245,7 @@ private function processKeyAndItemType(MutatingScope $scope, Type $keyType, Type throw new ShouldNotHappenException(); } $itemVarName = $itemVar->name; - $scope = $scope->assignVariable($itemVarName, $itemType, new MixedType()); + $scope = $scope->assignVariable($itemVarName, $itemType, new MixedType(), TrinaryLogic::createYes()); } $keyVarName = null; @@ -253,7 +254,7 @@ private function processKeyAndItemType(MutatingScope $scope, Type $keyType, Type throw new ShouldNotHappenException(); } $keyVarName = $keyVar->name; - $scope = $scope->assignVariable($keyVarName, $keyType, new MixedType()); + $scope = $scope->assignVariable($keyVarName, $keyType, new MixedType(), TrinaryLogic::createYes()); } $booleanResult = $scope->getType($expr)->toBoolean(); diff --git a/tests/PHPStan/Analyser/ScopeTest.php b/tests/PHPStan/Analyser/ScopeTest.php index 99bba5ea9b..88d5ee4122 100644 --- a/tests/PHPStan/Analyser/ScopeTest.php +++ b/tests/PHPStan/Analyser/ScopeTest.php @@ -5,6 +5,7 @@ use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Name\FullyQualified; use PHPStan\Testing\PHPStanTestCase; +use PHPStan\TrinaryLogic; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantIntegerType; @@ -232,8 +233,8 @@ public function testGeneralize(Type $a, Type $b, string $expectedTypeDescription { /** @var ScopeFactory $scopeFactory */ $scopeFactory = self::getContainer()->getByType(ScopeFactory::class); - $scopeA = $scopeFactory->create(ScopeContext::create('file.php'))->assignVariable('a', $a, $a); - $scopeB = $scopeFactory->create(ScopeContext::create('file.php'))->assignVariable('a', $b, $b); + $scopeA = $scopeFactory->create(ScopeContext::create('file.php'))->assignVariable('a', $a, $a, TrinaryLogic::createYes()); + $scopeB = $scopeFactory->create(ScopeContext::create('file.php'))->assignVariable('a', $b, $b, TrinaryLogic::createYes()); $resultScope = $scopeA->generalizeWith($scopeB); $this->assertSame($expectedTypeDescription, $resultScope->getVariableType('a')->describe(VerbosityLevel::precise())); } diff --git a/tests/PHPStan/Analyser/StatementResultTest.php b/tests/PHPStan/Analyser/StatementResultTest.php index fb3a9dd5b1..afc4e3f9ca 100644 --- a/tests/PHPStan/Analyser/StatementResultTest.php +++ b/tests/PHPStan/Analyser/StatementResultTest.php @@ -5,6 +5,7 @@ use PhpParser\Node\Stmt; use PHPStan\Parser\Parser; use PHPStan\Testing\PHPStanTestCase; +use PHPStan\TrinaryLogic; use PHPStan\Type\ArrayType; use PHPStan\Type\IntegerType; use PHPStan\Type\MixedType; @@ -395,10 +396,10 @@ public function testIsAlwaysTerminating( /** @var ScopeFactory $scopeFactory */ $scopeFactory = self::getContainer()->getByType(ScopeFactory::class); $scope = $scopeFactory->create(ScopeContext::create('test.php')) - ->assignVariable('string', new StringType(), new StringType()) - ->assignVariable('x', new IntegerType(), new IntegerType()) - ->assignVariable('cond', new MixedType(), new MixedType()) - ->assignVariable('arr', new ArrayType(new MixedType(), new MixedType()), new ArrayType(new MixedType(), new MixedType())); + ->assignVariable('string', new StringType(), new StringType(), TrinaryLogic::createYes()) + ->assignVariable('x', new IntegerType(), new IntegerType(), TrinaryLogic::createYes()) + ->assignVariable('cond', new MixedType(), new MixedType(), TrinaryLogic::createYes()) + ->assignVariable('arr', new ArrayType(new MixedType(), new MixedType()), new ArrayType(new MixedType(), new MixedType()), TrinaryLogic::createYes()); $result = $nodeScopeResolver->processStmtNodes( new Stmt\Namespace_(null, $stmts), $stmts, diff --git a/tests/PHPStan/Analyser/TypeSpecifierTest.php b/tests/PHPStan/Analyser/TypeSpecifierTest.php index c2b21e92c4..122160c7fa 100644 --- a/tests/PHPStan/Analyser/TypeSpecifierTest.php +++ b/tests/PHPStan/Analyser/TypeSpecifierTest.php @@ -21,6 +21,7 @@ use PHPStan\Node\Expr\AlwaysRememberedExpr; use PHPStan\Node\Printer\Printer; use PHPStan\Testing\PHPStanTestCase; +use PHPStan\TrinaryLogic; use PHPStan\Type\ArrayType; use PHPStan\Type\ClassStringType; use PHPStan\Type\Constant\ConstantBooleanType; @@ -62,20 +63,20 @@ protected function setUp(): void $this->typeSpecifier = self::getContainer()->getService('typeSpecifier'); $this->scope = $this->createScopeFactory($reflectionProvider, $this->typeSpecifier)->create(ScopeContext::create('')); $this->scope = $this->scope->enterClass($reflectionProvider->getClass('DateTime')); - $this->scope = $this->scope->assignVariable('bar', new ObjectType('Bar'), new ObjectType('Bar')); - $this->scope = $this->scope->assignVariable('stringOrNull', new UnionType([new StringType(), new NullType()]), new UnionType([new StringType(), new NullType()])); - $this->scope = $this->scope->assignVariable('string', new StringType(), new StringType()); - $this->scope = $this->scope->assignVariable('fooOrNull', new UnionType([new ObjectType('Foo'), new NullType()]), new UnionType([new ObjectType('Foo'), new NullType()])); - $this->scope = $this->scope->assignVariable('barOrNull', new UnionType([new ObjectType('Bar'), new NullType()]), new UnionType([new ObjectType('Bar'), new NullType()])); - $this->scope = $this->scope->assignVariable('barOrFalse', new UnionType([new ObjectType('Bar'), new ConstantBooleanType(false)]), new UnionType([new ObjectType('Bar'), new ConstantBooleanType(false)])); - $this->scope = $this->scope->assignVariable('stringOrFalse', new UnionType([new StringType(), new ConstantBooleanType(false)]), new UnionType([new StringType(), new ConstantBooleanType(false)])); - $this->scope = $this->scope->assignVariable('array', new ArrayType(new MixedType(), new MixedType()), new ArrayType(new MixedType(), new MixedType())); - $this->scope = $this->scope->assignVariable('foo', new MixedType(), new MixedType()); - $this->scope = $this->scope->assignVariable('classString', new ClassStringType(), new ClassStringType()); - $this->scope = $this->scope->assignVariable('genericClassString', new GenericClassStringType(new ObjectType('Bar')), new GenericClassStringType(new ObjectType('Bar'))); - $this->scope = $this->scope->assignVariable('object', new ObjectWithoutClassType(), new ObjectWithoutClassType()); - $this->scope = $this->scope->assignVariable('int', new IntegerType(), new IntegerType()); - $this->scope = $this->scope->assignVariable('float', new FloatType(), new FloatType()); + $this->scope = $this->scope->assignVariable('bar', new ObjectType('Bar'), new ObjectType('Bar'), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('stringOrNull', new UnionType([new StringType(), new NullType()]), new UnionType([new StringType(), new NullType()]), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('string', new StringType(), new StringType(), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('fooOrNull', new UnionType([new ObjectType('Foo'), new NullType()]), new UnionType([new ObjectType('Foo'), new NullType()]), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('barOrNull', new UnionType([new ObjectType('Bar'), new NullType()]), new UnionType([new ObjectType('Bar'), new NullType()]), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('barOrFalse', new UnionType([new ObjectType('Bar'), new ConstantBooleanType(false)]), new UnionType([new ObjectType('Bar'), new ConstantBooleanType(false)]), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('stringOrFalse', new UnionType([new StringType(), new ConstantBooleanType(false)]), new UnionType([new StringType(), new ConstantBooleanType(false)]), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('array', new ArrayType(new MixedType(), new MixedType()), new ArrayType(new MixedType(), new MixedType()), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('foo', new MixedType(), new MixedType(), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('classString', new ClassStringType(), new ClassStringType(), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('genericClassString', new GenericClassStringType(new ObjectType('Bar')), new GenericClassStringType(new ObjectType('Bar')), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('object', new ObjectWithoutClassType(), new ObjectWithoutClassType(), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('int', new IntegerType(), new IntegerType(), TrinaryLogic::createYes()); + $this->scope = $this->scope->assignVariable('float', new FloatType(), new FloatType(), TrinaryLogic::createYes()); } /** diff --git a/tests/PHPStan/Type/BitwiseFlagHelperTest.php b/tests/PHPStan/Type/BitwiseFlagHelperTest.php index f2136604c3..7703524f47 100644 --- a/tests/PHPStan/Type/BitwiseFlagHelperTest.php +++ b/tests/PHPStan/Type/BitwiseFlagHelperTest.php @@ -127,13 +127,13 @@ public function testExprContainsConst(Expr $expr, string $constName, TrinaryLogi /** @var ScopeFactory $scopeFactory */ $scopeFactory = self::getContainer()->getByType(ScopeFactory::class); $scope = $scopeFactory->create(ScopeContext::create('file.php')) - ->assignVariable('mixedVar', new MixedType(), new MixedType()) - ->assignVariable('stringVar', new StringType(), new StringType()) - ->assignVariable('integerVar', new IntegerType(), new IntegerType()) - ->assignVariable('booleanVar', new BooleanType(), new BooleanType()) - ->assignVariable('floatVar', new FloatType(), new FloatType()) - ->assignVariable('unionIntFloatVar', new UnionType([new IntegerType(), new FloatType()]), new UnionType([new IntegerType(), new FloatType()])) - ->assignVariable('unionStringFloatVar', new UnionType([new StringType(), new FloatType()]), new UnionType([new StringType(), new FloatType()])); + ->assignVariable('mixedVar', new MixedType(), new MixedType(), TrinaryLogic::createYes()) + ->assignVariable('stringVar', new StringType(), new StringType(), TrinaryLogic::createYes()) + ->assignVariable('integerVar', new IntegerType(), new IntegerType(), TrinaryLogic::createYes()) + ->assignVariable('booleanVar', new BooleanType(), new BooleanType(), TrinaryLogic::createYes()) + ->assignVariable('floatVar', new FloatType(), new FloatType(), TrinaryLogic::createYes()) + ->assignVariable('unionIntFloatVar', new UnionType([new IntegerType(), new FloatType()]), new UnionType([new IntegerType(), new FloatType()]), TrinaryLogic::createYes()) + ->assignVariable('unionStringFloatVar', new UnionType([new StringType(), new FloatType()]), new UnionType([new StringType(), new FloatType()]), TrinaryLogic::createYes()); $analyser = new BitwiseFlagHelper($this->createReflectionProvider()); $actual = $analyser->bitwiseOrContainsConstant($expr, $scope, $constName); From 1648f008c60796631c7c585d31eac2c8ed956172 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 14:57:33 +0200 Subject: [PATCH 088/508] Document StatementContext --- src/Analyser/StatementContext.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Analyser/StatementContext.php b/src/Analyser/StatementContext.php index e9308cfb77..5fd5381601 100644 --- a/src/Analyser/StatementContext.php +++ b/src/Analyser/StatementContext.php @@ -2,6 +2,14 @@ namespace PHPStan\Analyser; +/** + * Object of this class is one of the parameters of `NodeScopeResolver::processStmtNodes()`. + * + * It determines whether loops will be analysed once or multiple times + * until the types "stabilize". + * + * When in doubt, use `StatementContext::createTopLevel()`. + */ final class StatementContext { @@ -11,11 +19,17 @@ private function __construct( { } + /** + * @api + */ public static function createTopLevel(): self { return new self(true); } + /** + * @api + */ public static function createDeep(): self { return new self(false); From 4b6ac9c8f7654d8f751fbb21f5d2473a621b8739 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 14:58:24 +0200 Subject: [PATCH 089/508] [BCB] Parameter `$context` of `NodeScopeResolver::processStmtNodes()` made required --- UPGRADING.md | 1 + src/Analyser/NodeScopeResolver.php | 5 +---- tests/PHPStan/Analyser/StatementResultTest.php | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 3516ec8d6b..99bd896620 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -51,3 +51,4 @@ This method now longer accepts `Expr $rootExpr`. If you want to change it, call ### Minor backward compatibility breaks * Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required +* Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 09f53137c9..3bd5080928 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -329,12 +329,9 @@ public function processStmtNodes( array $stmts, MutatingScope $scope, callable $nodeCallback, - ?StatementContext $context = null, + StatementContext $context, ): StatementResult { - if ($context === null) { - $context = StatementContext::createTopLevel(); - } $exitPoints = []; $throwPoints = []; $impurePoints = []; diff --git a/tests/PHPStan/Analyser/StatementResultTest.php b/tests/PHPStan/Analyser/StatementResultTest.php index afc4e3f9ca..2a44edc546 100644 --- a/tests/PHPStan/Analyser/StatementResultTest.php +++ b/tests/PHPStan/Analyser/StatementResultTest.php @@ -406,6 +406,7 @@ public function testIsAlwaysTerminating( $scope, static function (): void { }, + StatementContext::createTopLevel(), ); $this->assertSame($expectedIsAlwaysTerminating, $result->isAlwaysTerminating()); } From f17cf9ec43111cb29dd50d620fb6259c0ab0d373 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:06:54 +0200 Subject: [PATCH 090/508] CommandHelper::begin() parameters made required --- src/Command/AnalyseCommand.php | 1 + src/Command/ClearResultCacheCommand.php | 1 + src/Command/CommandHelper.php | 4 ++-- src/Command/DiagnoseCommand.php | 2 ++ src/Command/DumpParametersCommand.php | 2 ++ tests/PHPStan/Command/CommandHelperTest.php | 4 ++++ 6 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index a112f22235..f4281c48e4 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -171,6 +171,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $level, $allowXdebug, $debugEnabled, + true, ); } catch (InceptionNotSuccessfulException $e) { return 1; diff --git a/src/Command/ClearResultCacheCommand.php b/src/Command/ClearResultCacheCommand.php index 89e3c45ee7..ac41019e2b 100644 --- a/src/Command/ClearResultCacheCommand.php +++ b/src/Command/ClearResultCacheCommand.php @@ -81,6 +81,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int '0', $allowXdebug, $debugEnabled, + true, ); } catch (InceptionNotSuccessfulException) { return 1; diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index 55926064a2..8b1db512f1 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -89,8 +89,8 @@ public static function begin( ?string $generateBaselineFile, ?string $level, bool $allowXdebug, - bool $debugEnabled = false, - bool $cleanupContainerCache = true, + bool $debugEnabled, + bool $cleanupContainerCache, ): InceptionResult { $stdOutput = new SymfonyOutput($output, new SymfonyStyle(new ErrorsConsoleStyle($input, $output))); diff --git a/src/Command/DiagnoseCommand.php b/src/Command/DiagnoseCommand.php index 2f8a5a47b0..5a9f17e0ab 100644 --- a/src/Command/DiagnoseCommand.php +++ b/src/Command/DiagnoseCommand.php @@ -79,6 +79,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int null, $level, false, + false, + false, ); } catch (InceptionNotSuccessfulException) { return 1; diff --git a/src/Command/DumpParametersCommand.php b/src/Command/DumpParametersCommand.php index b3085db0c6..ccb8188933 100644 --- a/src/Command/DumpParametersCommand.php +++ b/src/Command/DumpParametersCommand.php @@ -81,6 +81,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int null, $level, false, + false, + false, ); } catch (InceptionNotSuccessfulException) { return 1; diff --git a/tests/PHPStan/Command/CommandHelperTest.php b/tests/PHPStan/Command/CommandHelperTest.php index bbb00f122c..d5a1480199 100644 --- a/tests/PHPStan/Command/CommandHelperTest.php +++ b/tests/PHPStan/Command/CommandHelperTest.php @@ -124,6 +124,8 @@ public function testBegin( null, $level, false, + false, + false, ); if ($expectException) { $this->fail(); @@ -307,6 +309,8 @@ public function testResolveParameters( null, '0', false, + false, + false, ); $parameters = $result->getContainer()->getParameters(); foreach ($expectedParameters as $name => $expectedValue) { From 939a715a0636ed05752659dbe7646c1f1a574765 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:08:17 +0200 Subject: [PATCH 091/508] ContainerFactory - always check duplicate files --- src/Command/CommandHelper.php | 2 +- src/DependencyInjection/ContainerFactory.php | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index 8b1db512f1..4ea6fb9cd3 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -212,7 +212,7 @@ public static function begin( $paths = array_map(static fn (string $path): string => $currentWorkingDirectoryFileHelper->normalizePath($currentWorkingDirectoryFileHelper->absolutizePath($path)), $paths); $analysedPathsFromConfig = []; - $containerFactory = new ContainerFactory($currentWorkingDirectory, true); + $containerFactory = new ContainerFactory($currentWorkingDirectory); $projectConfig = null; if ($projectConfigFile !== null) { if (!is_file($projectConfigFile)) { diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index 5c8dad2f23..4cd4dfc0db 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -71,7 +71,7 @@ class ContainerFactory private static ?int $lastInitializedContainerId = null; /** @api */ - public function __construct(private string $currentWorkingDirectory, private bool $checkDuplicateFiles = false) + public function __construct(private string $currentWorkingDirectory) { $this->fileHelper = new FileHelper($currentWorkingDirectory); @@ -277,10 +277,6 @@ private function detectDuplicateIncludedFiles( return [$normalized, $configArray]; } - if (!$this->checkDuplicateFiles) { - return [$normalized, $configArray]; - } - $duplicateFiles = array_unique(array_diff_key($normalized, $deduplicated)); throw new DuplicateIncludedFilesException($duplicateFiles); From aefd71ceb3d9cdf6823111c46a76fda29806d80a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:10:06 +0200 Subject: [PATCH 092/508] [BCB] ClassPropertiesNode - remove `$extensions` parameter from `getUninitializedProperties()` --- UPGRADING.md | 1 + src/Node/ClassPropertiesNode.php | 7 +------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 99bd896620..d8172940a0 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -52,3 +52,4 @@ This method now longer accepts `Expr $rootExpr`. If you want to change it, call * Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required * Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required +* ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) diff --git a/src/Node/ClassPropertiesNode.php b/src/Node/ClassPropertiesNode.php index 0707a5bc6d..df8f0f993a 100644 --- a/src/Node/ClassPropertiesNode.php +++ b/src/Node/ClassPropertiesNode.php @@ -18,7 +18,6 @@ use PHPStan\Node\Property\PropertyWrite; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodReflection; -use PHPStan\Rules\Properties\ReadWritePropertiesExtension; use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider; use PHPStan\TrinaryLogic; use PHPStan\Type\NeverType; @@ -98,13 +97,11 @@ public function getClassReflection(): ClassReflection /** * @param string[] $constructors - * @param ReadWritePropertiesExtension[]|null $extensions * @return array{array, array, array} */ public function getUninitializedProperties( Scope $scope, array $constructors, - ?array $extensions = null, ): array { if (!$this->getClass() instanceof Class_) { @@ -116,9 +113,7 @@ public function getUninitializedProperties( $originalProperties = []; $initialInitializedProperties = []; $initializedProperties = []; - if ($extensions === null) { - $extensions = $this->readWritePropertiesExtensionProvider->getExtensions(); - } + $extensions = $this->readWritePropertiesExtensionProvider->getExtensions(); $initializedViaExtension = []; foreach ($this->getProperties() as $property) { if ($property->isStatic()) { From 61bb049ad2ab31c69b93d86f1bab3b247155d87d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:11:28 +0200 Subject: [PATCH 093/508] RichParser - required parameter in private method --- src/Parser/RichParser.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Parser/RichParser.php b/src/Parser/RichParser.php index 0bf45b07a3..73fd744fae 100644 --- a/src/Parser/RichParser.php +++ b/src/Parser/RichParser.php @@ -152,7 +152,7 @@ private function getLinesToIgnore(array $tokens): array $isCurrentLine = str_contains($text, '@phpstan-ignore-line'); if ($type === T_DOC_COMMENT) { - $lines += $this->getLinesToIgnoreForTokenByIgnoreComment($text, $line, '@phpstan-ignore-line'); + $lines += $this->getLinesToIgnoreForTokenByIgnoreComment($text, $line, '@phpstan-ignore-line', false); if ($isNextLine) { $pattern = sprintf('~%s~si', implode('|', [self::PHPDOC_TAG_REGEX, self::PHPDOC_DOCTRINE_TAG_REGEX])); $r = preg_match_all($pattern, $text, $pregMatches, PREG_OFFSET_CAPTURE); @@ -242,7 +242,7 @@ private function getLinesToIgnoreForTokenByIgnoreComment( string $tokenText, int $tokenLine, string $ignoreComment, - bool $ignoreNextLine = false, + bool $ignoreNextLine, ): array { $lines = []; From 5b58f83e6d8b5044d742caed9729d00178c4a9de Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:11:53 +0200 Subject: [PATCH 094/508] MethodTag - constructor parameter `$templateTags` is required --- src/PhpDoc/Tag/MethodTag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpDoc/Tag/MethodTag.php b/src/PhpDoc/Tag/MethodTag.php index 793fd3d6d2..85018267b1 100644 --- a/src/PhpDoc/Tag/MethodTag.php +++ b/src/PhpDoc/Tag/MethodTag.php @@ -19,7 +19,7 @@ public function __construct( private Type $returnType, private bool $isStatic, private array $parameters, - private array $templateTags = [], + private array $templateTags, ) { } From f88d9ba7f56ef6c3b783aee1c909a3422c0ef3c3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:13:24 +0200 Subject: [PATCH 095/508] InitializerExprTypeResolver - constructor parameter `$usePathConstantsAsConstantString` made required --- src/DependencyInjection/ValidateIgnoredErrorsExtension.php | 2 +- src/Reflection/InitializerExprTypeResolver.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php index 1973f7e303..5384f86d2d 100644 --- a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php +++ b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php @@ -108,7 +108,7 @@ public function getRegistry(): OperatorTypeSpecifyingExtensionRegistry return new OperatorTypeSpecifyingExtensionRegistry(null, []); } - }, new OversizedArrayBuilder()), + }, new OversizedArrayBuilder(), true), ), ), ); diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 3faf85d131..6d4734b397 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -102,7 +102,7 @@ public function __construct( private PhpVersion $phpVersion, private OperatorTypeSpecifyingExtensionRegistryProvider $operatorTypeSpecifyingExtensionRegistryProvider, private OversizedArrayBuilder $oversizedArrayBuilder, - private bool $usePathConstantsAsConstantString = false, + private bool $usePathConstantsAsConstantString, ) { } From 8bfbf8f254a68e4f1b15419eb950ea677fc2916e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:13:51 +0200 Subject: [PATCH 096/508] `PhpMethodReflectionFactory::create()` - all parameters are required --- src/Reflection/Php/PhpMethodReflectionFactory.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Reflection/Php/PhpMethodReflectionFactory.php b/src/Reflection/Php/PhpMethodReflectionFactory.php index 2aa2aca526..77de1aa1b7 100644 --- a/src/Reflection/Php/PhpMethodReflectionFactory.php +++ b/src/Reflection/Php/PhpMethodReflectionFactory.php @@ -34,9 +34,9 @@ public function create( ?Type $selfOutType, ?string $phpDocComment, array $phpDocParameterOutTypes, - array $immediatelyInvokedCallableParameters = [], - array $phpDocClosureThisTypeParameters = [], - bool $acceptsNamedArguments = true, + array $immediatelyInvokedCallableParameters, + array $phpDocClosureThisTypeParameters, + bool $acceptsNamedArguments, ): PhpMethodReflection; } From 493752737c32eb878de4dfb91817761b952348e4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:14:45 +0200 Subject: [PATCH 097/508] FunctionCallParametersCheck - parameters `$nodeType` and `$acceptsNamedArguments` made required --- src/Rules/FunctionCallParametersCheck.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 4f0d2ae447..76b9eff371 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -63,8 +63,8 @@ public function check( bool $isBuiltin, $funcCall, array $messages, - string $nodeType = 'function', - bool $acceptsNamedArguments = true, + string $nodeType, + bool $acceptsNamedArguments, ): array { $functionParametersMinCount = 0; From f85a500288b0b8ef9a19d405c0e3d99ab57ce797 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:15:41 +0200 Subject: [PATCH 098/508] MethodParameterComparisonHelper - parameter `$ignorable` of `compare()` method made required --- src/Rules/Methods/MethodParameterComparisonHelper.php | 2 +- src/Rules/Methods/OverridingMethodRule.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Rules/Methods/MethodParameterComparisonHelper.php b/src/Rules/Methods/MethodParameterComparisonHelper.php index 2f21d52123..284152b9c9 100644 --- a/src/Rules/Methods/MethodParameterComparisonHelper.php +++ b/src/Rules/Methods/MethodParameterComparisonHelper.php @@ -31,7 +31,7 @@ public function __construct(private PhpVersion $phpVersion, private bool $generi /** * @return list */ - public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method, bool $ignorable = false): array + public function compare(ExtendedMethodReflection $prototype, ClassReflection $prototypeDeclaringClass, PhpMethodFromParserNodeReflection $method, bool $ignorable): array { /** @var list $messages */ $messages = []; diff --git a/src/Rules/Methods/OverridingMethodRule.php b/src/Rules/Methods/OverridingMethodRule.php index 9d414f6f2b..99f3b1866e 100644 --- a/src/Rules/Methods/OverridingMethodRule.php +++ b/src/Rules/Methods/OverridingMethodRule.php @@ -233,7 +233,7 @@ public function processNode(Node $node, Scope $scope): array } } - $messages = array_merge($messages, $this->methodParameterComparisonHelper->compare($prototype, $prototypeDeclaringClass, $method)); + $messages = array_merge($messages, $this->methodParameterComparisonHelper->compare($prototype, $prototypeDeclaringClass, $method, false)); if (!$prototypeVariant instanceof FunctionVariantWithPhpDocs) { return $this->addErrors($messages, $node, $scope); From a8cd423e842deaa7d924580665207a4b1a373115 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:16:11 +0200 Subject: [PATCH 099/508] Parameter `$dateTimeClass` of DateTimeModifyReturnTypeExtension constructor made required --- src/Type/Php/DateTimeModifyReturnTypeExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Type/Php/DateTimeModifyReturnTypeExtension.php b/src/Type/Php/DateTimeModifyReturnTypeExtension.php index 6ab34811e5..0ed2933856 100644 --- a/src/Type/Php/DateTimeModifyReturnTypeExtension.php +++ b/src/Type/Php/DateTimeModifyReturnTypeExtension.php @@ -22,7 +22,7 @@ final class DateTimeModifyReturnTypeExtension implements DynamicMethodReturnType /** @param class-string $dateTimeClass */ public function __construct( private PhpVersion $phpVersion, - private string $dateTimeClass = DateTime::class, + private string $dateTimeClass, ) { } From bcbb5036d38e03092ac4a1294b1289ddc44174eb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:24:12 +0200 Subject: [PATCH 100/508] Upgrading note --- UPGRADING.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index d8172940a0..8e61c27788 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -9,7 +9,28 @@ PHPStan now requires PHP 7.4 or newer to run. ## Upgrading guide for end users -TODO +The best way do get ready for upgrade to PHPStan 2.0 is to update to the **latest PHPStan 1.12 release** +and enable [**Bleeding Edge**](https://phpstan.org/blog/what-is-bleeding-edge). This will enable the new rules and behaviours that 2.0 turns on for all users. + +Once you get to a green build with no deprecations showed on latest PHPStan 1.12.x with Bleeding Edge enabled, you can update all your related PHPStan dependencies to 2.0 in `composer.json`: + +```json +"require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-doctrine": "^2.0", + "phpstan/phpstan-nette": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/phpstan-symfony": "^2.0", + "phpstan/phpstan-webmozart-assert": "^2.0", + ... +} +``` + +Don't forget to update [3rd party PHPStan extensions](https://phpstan.org/user-guide/extension-library) as well. + +After changing your `composer.json`, run `composer update 'phpstan/*' -W`. ## Upgrading guide for extension developers From 64ff598cd42268d2178d02efd208afe637060978 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 14 Sep 2024 15:27:14 +0200 Subject: [PATCH 101/508] NativeFunctionReflection construct parameters made required --- src/Reflection/Native/NativeFunctionReflection.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Reflection/Native/NativeFunctionReflection.php b/src/Reflection/Native/NativeFunctionReflection.php index 2dd98f2951..6ba0c0b7c5 100644 --- a/src/Reflection/Native/NativeFunctionReflection.php +++ b/src/Reflection/Native/NativeFunctionReflection.php @@ -26,10 +26,10 @@ public function __construct( private ?Type $throwType, private TrinaryLogic $hasSideEffects, private bool $isDeprecated, - ?Assertions $assertions = null, - private ?string $phpDocComment = null, - ?TrinaryLogic $returnsByReference = null, - private bool $acceptsNamedArguments = true, + ?Assertions $assertions, + private ?string $phpDocComment, + ?TrinaryLogic $returnsByReference, + private bool $acceptsNamedArguments, ) { $this->assertions = $assertions ?? Assertions::createEmpty(); From cdf7d673c53b2a4f6e1d58f794b221a976c28d1e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 15 Sep 2024 13:30:19 +0200 Subject: [PATCH 102/508] Update PHPStan extensions --- composer.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/composer.lock b/composer.lock index e11ebd0c9b..37d6db47ae 100644 --- a/composer.lock +++ b/composer.lock @@ -2286,12 +2286,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "9d57f3db5bba9b0d8d11726389eb8af3126780b4" + "reference": "f9635550d59587171fc60dc0840ee015e8a76453" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9d57f3db5bba9b0d8d11726389eb8af3126780b4", - "reference": "9d57f3db5bba9b0d8d11726389eb8af3126780b4", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/f9635550d59587171fc60dc0840ee015e8a76453", + "reference": "f9635550d59587171fc60dc0840ee015e8a76453", "shasum": "" }, "require": { @@ -2326,7 +2326,7 @@ "issues": "https://github.com/phpstan/phpdoc-parser/issues", "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.x" }, - "time": "2024-09-07T21:23:59+00:00" + "time": "2024-09-09T14:20:27+00:00" }, { "name": "psr/container", @@ -4669,12 +4669,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "398e2e2d7b71cbdd943c87bd7c7731ad1eeaf1cd" + "reference": "89572d5481ec1e121ac1567f689fe49a25d6cef6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/398e2e2d7b71cbdd943c87bd7c7731ad1eeaf1cd", - "reference": "398e2e2d7b71cbdd943c87bd7c7731ad1eeaf1cd", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/89572d5481ec1e121ac1567f689fe49a25d6cef6", + "reference": "89572d5481ec1e121ac1567f689fe49a25d6cef6", "shasum": "" }, "require": { @@ -4709,7 +4709,7 @@ "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.x" }, - "time": "2024-09-06T13:40:51+00:00" + "time": "2024-09-11T15:52:56+00:00" }, { "name": "phpstan/phpstan-nette", @@ -4778,12 +4778,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "3faa60573a32522772e7cda004003b15466e2b5b" + "reference": "4d861e0843cd1f8eccacfac14e24a8629280a887" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/3faa60573a32522772e7cda004003b15466e2b5b", - "reference": "3faa60573a32522772e7cda004003b15466e2b5b", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/4d861e0843cd1f8eccacfac14e24a8629280a887", + "reference": "4d861e0843cd1f8eccacfac14e24a8629280a887", "shasum": "" }, "require": { @@ -4822,7 +4822,7 @@ "issues": "https://github.com/phpstan/phpstan-phpunit/issues", "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.x" }, - "time": "2024-09-04T20:57:24+00:00" + "time": "2024-09-13T12:47:01+00:00" }, { "name": "phpstan/phpstan-strict-rules", @@ -4830,12 +4830,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "5eec39fc6ef36015e6de08949c8e9ae9d64560a3" + "reference": "1062d489f1d10e79df42d73fa5352a27741d65f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/5eec39fc6ef36015e6de08949c8e9ae9d64560a3", - "reference": "5eec39fc6ef36015e6de08949c8e9ae9d64560a3", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/1062d489f1d10e79df42d73fa5352a27741d65f1", + "reference": "1062d489f1d10e79df42d73fa5352a27741d65f1", "shasum": "" }, "require": { @@ -4871,7 +4871,7 @@ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-09-06T18:44:39+00:00" + "time": "2024-09-13T12:49:46+00:00" }, { "name": "phpunit/php-code-coverage", From 4bb7e72d3baac0dfbd5a33905ed04f8797903da8 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 15 Sep 2024 14:54:06 +0200 Subject: [PATCH 103/508] Update phpdoc-parser --- composer.lock | 8 ++++---- src/Type/Constant/ConstantArrayType.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.lock b/composer.lock index 37d6db47ae..6b92d5bffb 100644 --- a/composer.lock +++ b/composer.lock @@ -2286,12 +2286,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "f9635550d59587171fc60dc0840ee015e8a76453" + "reference": "0fe292d7fa9deb3a869a4a74363497e1ae527a54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/f9635550d59587171fc60dc0840ee015e8a76453", - "reference": "f9635550d59587171fc60dc0840ee015e8a76453", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/0fe292d7fa9deb3a869a4a74363497e1ae527a54", + "reference": "0fe292d7fa9deb3a869a4a74363497e1ae527a54", "shasum": "" }, "require": { @@ -2326,7 +2326,7 @@ "issues": "https://github.com/phpstan/phpdoc-parser/issues", "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.x" }, - "time": "2024-09-09T14:20:27+00:00" + "time": "2024-09-15T12:53:31+00:00" }, { "name": "psr/container", diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 7d2d0c9bc1..2161d3f4a2 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -1685,7 +1685,7 @@ public function toPhpDocNode(): TypeNode ); } - return new ArrayShapeNode($exportValuesOnly ? $values : $items); + return ArrayShapeNode::createSealed($exportValuesOnly ? $values : $items); } public static function isValidIdentifier(string $value): bool From 202c2e1c84e01c011338ca01ce095ec1d03433fb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 15 Sep 2024 16:04:20 +0200 Subject: [PATCH 104/508] Update simple-downgrader --- composer.lock | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 6b92d5bffb..4162573cd2 100644 --- a/composer.lock +++ b/composer.lock @@ -4441,12 +4441,12 @@ "source": { "type": "git", "url": "https://github.com/ondrejmirtes/simple-downgrader.git", - "reference": "1630e1672948a2b59955d7fa634992dc4331ac00" + "reference": "760b4c5c0b5ae631e6604bdcf074387e40e35ed1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/simple-downgrader/zipball/1630e1672948a2b59955d7fa634992dc4331ac00", - "reference": "1630e1672948a2b59955d7fa634992dc4331ac00", + "url": "https://api.github.com/repos/ondrejmirtes/simple-downgrader/zipball/760b4c5c0b5ae631e6604bdcf074387e40e35ed1", + "reference": "760b4c5c0b5ae631e6604bdcf074387e40e35ed1", "shasum": "" }, "require": { @@ -4459,9 +4459,10 @@ }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.5.36" + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^9.6" }, + "default-branch": true, "bin": [ "bin/simple-downgrade" ], @@ -4482,7 +4483,7 @@ "issues": "https://github.com/ondrejmirtes/simple-downgrader/issues", "source": "https://github.com/ondrejmirtes/simple-downgrader/tree/2.x" }, - "time": "2024-09-07T21:32:41+00:00" + "time": "2024-09-15T14:01:11+00:00" }, { "name": "phar-io/manifest", From 104b6b8ba3d20133bac61d15064cd035610bb439 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 15 Sep 2024 20:34:48 +0200 Subject: [PATCH 105/508] Update nikic/php-parser --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 30da24daf1..33b8daac2f 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "nette/php-generator": "3.6.9", "nette/schema": "^1.2.2", "nette/utils": "^3.2.5", - "nikic/php-parser": "^5.1.0", + "nikic/php-parser": "^5.2.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.8", "phpstan/php-8-stubs": "0.3.104", diff --git a/composer.lock b/composer.lock index 4162573cd2..90d9df7f41 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a6eb11a29766ed815fc1ad8931ef7f48", + "content-hash": "2992836f30621996bc1a9f11f903c7f2", "packages": [ { "name": "clue/ndjson-react", @@ -2049,16 +2049,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.1.0", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", + "reference": "23c79fbbfb725fb92af9bcf41065c8e9a0d49ddb", "shasum": "" }, "require": { @@ -2101,9 +2101,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.2.0" }, - "time": "2024-07-01T20:03:41+00:00" + "time": "2024-09-15T16:40:33+00:00" }, { "name": "ondram/ci-detector", From 10de8332f63a79a9510914a083e27b12c31182a5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 16:11:41 +0200 Subject: [PATCH 106/508] Issue bot - let all comments about PHP-Parser 5.2 through --- issue-bot/src/Console/EvaluateCommand.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index 0f8d05a8d8..f18941039b 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,10 +158,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { - if (count($toPost) > 20) { - $output->writeln('Too many comments to post, something is probably wrong.'); - return 1; - } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From 3d7ed3ffaeca23a52986128edc6caa9baa3402d4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 15 Sep 2024 20:54:47 +0200 Subject: [PATCH 107/508] Revert "Issue bot - let all comments about PHP-Parser 5.2 through" This reverts commit 10de8332f63a79a9510914a083e27b12c31182a5. --- issue-bot/src/Console/EvaluateCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index f18941039b..0f8d05a8d8 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,6 +158,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { + if (count($toPost) > 20) { + $output->writeln('Too many comments to post, something is probably wrong.'); + return 1; + } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From f2bb4ca9fb645246482db193f2a4138f2b422a93 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 09:20:51 +0200 Subject: [PATCH 108/508] Fix prefixing in PHP-Parser --- compiler/build/scoper.inc.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/build/scoper.inc.php b/compiler/build/scoper.inc.php index fd867cbb48..b6659a93b0 100644 --- a/compiler/build/scoper.inc.php +++ b/compiler/build/scoper.inc.php @@ -216,6 +216,16 @@ function (string $filePath, string $prefix, string $content): string { return str_replace(sprintf('use %s\\PhpParser;', $prefix), 'use PhpParser;', $content); }, + function (string $filePath, string $prefix, string $content): string { + if (!str_starts_with($filePath, 'vendor/nikic/php-parser/lib')) { + return $content; + } + + return str_replace([ + sprintf('\\%s', $prefix), + sprintf('\\\\%s', $prefix), + ], '', $content); + }, function (string $filePath, string $prefix, string $content): string { if ( $filePath !== 'vendor/nette/utils/src/Utils/Strings.php' From 041922bf7320165bface60b047980c790238f276 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 10:31:55 +0200 Subject: [PATCH 109/508] [BE] No implicit wildcard in FileExcluder --- UPGRADING.md | 21 +++++++++++ changelog-2.0.md | 4 +-- conf/bleedingEdge.neon | 1 - conf/config.neon | 3 -- conf/parametersSchema.neon | 1 - src/Analyser/Ignore/IgnoredError.php | 3 +- src/Command/CommandHelper.php | 2 +- .../ValidateExcludePathsExtension.php | 3 +- .../ValidateIgnoredErrorsExtension.php | 4 +-- src/File/FileExcluder.php | 35 ++++++++----------- tests/PHPStan/File/FileExcluderTest.php | 34 ++++++------------ 11 files changed, 51 insertions(+), 60 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 8e61c27788..2e9830c098 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -32,6 +32,27 @@ Don't forget to update [3rd party PHPStan extensions](https://phpstan.org/user-g After changing your `composer.json`, run `composer update 'phpstan/*' -W`. +### Paths in `excludePaths` and `ignoreErrors` have to be a valid file path or a fnmatch pattern + +If you are excluding a file path that might not exist but you still want to have it in `excludePaths`, append `(?)`: + +```neon +parameters: + excludePaths: + - tests/*/data/* + - src/broken + - node_modules (?) # optional path, might not exist +``` + +If you have the same situation in `ignoreErrors` (ignoring an error in a path that might not exist), use `reportUnmatchedIgnoredErrors: false`. + +```neon +parameters: + reportUnmatchedIgnoredErrors: false +``` + +Appending `(?)` in `ignoreErrors` is not supported. + ## Upgrading guide for extension developers ### PHPStan now uses nikic/php-parser v5 diff --git a/changelog-2.0.md b/changelog-2.0.md index 4f9a5843f1..090eea5e3a 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -120,9 +120,7 @@ Bleeding edge (TODO move to other sections) * Check types in `@property` tags (https://github.com/phpstan/phpstan-src/commit/55ea2ae516df22a071ab873fdd6f748a3af0520e), #10752, #9356 * Check types in `@method` tags (https://github.com/phpstan/phpstan-src/commit/5b7e474680eaf33874b7ed6a227677adcbed9ca5) * Check `@extends`, `@implements`, `@use` for unresolvable types (https://github.com/phpstan/phpstan-src/commit/2bb528233edb75312614166e282776f279cf2018), #11552 -* Report invalid exclude paths in PHP config (https://github.com/phpstan/phpstan-src/commit/9718c14f1ffac81ba3d2bf331b4e8b4041a4d004) * RegularExpressionPatternRule: validate preg_quote'd patterns ([#3270](https://github.com/phpstan/phpstan-src/pull/3270)), thanks @staabm! -* No implicit wildcard in FileExcluder (https://github.com/phpstan/phpstan-src/commit/e19e6e5f8cfa706cc30e44a17276a6bc269f995c), #10299 * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! @@ -140,6 +138,8 @@ Improvements 🔧 * Unescape strings in PHPDoc parser (https://github.com/phpstan/phpstan-src/commit/97786ed8376b478ec541ea9df1c450c1fbfe7461) * PHPDoc parser: add config for lines in its AST & enable ignoring errors within PHPDocs ([#2807](https://github.com/phpstan/phpstan-src/pull/2807)), thanks @janedbal! * InvalidPhpDocTagValueRule: include PHPDoc line number in the error message (https://github.com/phpstan/phpstan-src/commit/a04e0be832900749b5b4ba22e2de21db8bfa09a0) +* No implicit wildcard in FileExcluder (https://github.com/phpstan/phpstan-src/commit/e19e6e5f8cfa706cc30e44a17276a6bc269f995c), #10299 +* Report invalid exclude paths in PHP config (https://github.com/phpstan/phpstan-src/commit/9718c14f1ffac81ba3d2bf331b4e8b4041a4d004) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index dae0bbb2ab..c5f05f8208 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -53,7 +53,6 @@ parameters: printfArrayParameters: true preciseMissingReturn: true validatePregQuote: true - noImplicitWildcard: true tooWidePropertyType: true explicitThrow: true absentTypeChecks: true diff --git a/conf/config.neon b/conf/config.neon index b004e06bbd..552b99403a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -89,7 +89,6 @@ parameters: printfArrayParameters: false preciseMissingReturn: false validatePregQuote: false - noImplicitWildcard: false requireFileExists: false narrowPregMatches: true tooWidePropertyType: false @@ -682,8 +681,6 @@ services: - implement: PHPStan\File\FileExcluderRawFactory - arguments: - noImplicitWildcard: %featureToggles.noImplicitWildcard% fileExcluderAnalyse: class: PHPStan\File\FileExcluder diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 0d8cfd70a7..6b8a6c44b7 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -83,7 +83,6 @@ parametersSchema: printfArrayParameters: bool() preciseMissingReturn: bool() validatePregQuote: bool() - noImplicitWildcard: bool() narrowPregMatches: bool() tooWidePropertyType: bool() explicitThrow: bool() diff --git a/src/Analyser/Ignore/IgnoredError.php b/src/Analyser/Ignore/IgnoredError.php index e714c93f79..b420ae29ce 100644 --- a/src/Analyser/Ignore/IgnoredError.php +++ b/src/Analyser/Ignore/IgnoredError.php @@ -4,7 +4,6 @@ use Nette\Utils\Strings; use PHPStan\Analyser\Error; -use PHPStan\DependencyInjection\BleedingEdgeToggle; use PHPStan\File\FileExcluder; use PHPStan\File\FileHelper; use PHPStan\ShouldNotHappenException; @@ -86,7 +85,7 @@ public static function shouldIgnore( } if ($path !== null) { - $fileExcluder = new FileExcluder($fileHelper, [$path], BleedingEdgeToggle::isBleedingEdge()); + $fileExcluder = new FileExcluder($fileHelper, [$path]); $isExcluded = $fileExcluder->isExcludedFromAnalysing($error->getFilePath()); if (!$isExcluded && $error->getTraitFilePath() !== null) { return $fileExcluder->isExcludedFromAnalysing($error->getTraitFilePath()); diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index 4ea6fb9cd3..c899ccc8cc 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -609,7 +609,7 @@ public static function begin( $pathRoutingParser->setAnalysedFiles($files); - $stubFilesExcluder = new FileExcluder($currentWorkingDirectoryFileHelper, $stubFilesProvider->getProjectStubFiles(), true); + $stubFilesExcluder = new FileExcluder($currentWorkingDirectoryFileHelper, $stubFilesProvider->getProjectStubFiles()); $files = array_values(array_filter($files, static fn (string $file) => !$stubFilesExcluder->isExcludedFromAnalysing($file))); diff --git a/src/DependencyInjection/ValidateExcludePathsExtension.php b/src/DependencyInjection/ValidateExcludePathsExtension.php index b322c4b18c..6d099d1c10 100644 --- a/src/DependencyInjection/ValidateExcludePathsExtension.php +++ b/src/DependencyInjection/ValidateExcludePathsExtension.php @@ -28,8 +28,7 @@ public function loadConfiguration(): void } $errors = []; - $noImplicitWildcard = $builder->parameters['featureToggles']['noImplicitWildcard']; - if ($builder->parameters['__validate'] && $noImplicitWildcard) { + if ($builder->parameters['__validate']) { $paths = []; if (array_key_exists('analyse', $excludePaths)) { $paths = $excludePaths['analyse']; diff --git a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php index 5384f86d2d..0f5dc0d9e2 100644 --- a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php +++ b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php @@ -59,8 +59,6 @@ public function loadConfiguration(): void return; } - $noImplicitWildcard = $builder->parameters['featureToggles']['noImplicitWildcard']; - /** @throws void */ $parser = Llk::load(new Read(__DIR__ . '/../../resources/RegexGrammar.pp')); $reflectionProvider = new DummyReflectionProvider(); @@ -141,7 +139,7 @@ public function getRegistry(): OperatorTypeSpecifyingExtensionRegistry $reportUnmatched = (bool) $builder->parameters['reportUnmatchedIgnoredErrors']; - if ($noImplicitWildcard && $reportUnmatched) { + if ($reportUnmatched) { foreach ($ignoreErrors as $ignoreError) { if (!is_array($ignoreError)) { continue; diff --git a/src/File/FileExcluder.php b/src/File/FileExcluder.php index 7e6fefdaca..7ebb938302 100644 --- a/src/File/FileExcluder.php +++ b/src/File/FileExcluder.php @@ -52,7 +52,6 @@ final class FileExcluder public function __construct( FileHelper $fileHelper, array $analyseExcludes, - private bool $noImplicitWildcard, ) { foreach ($analyseExcludes as $exclude) { @@ -68,18 +67,14 @@ public function __construct( if (self::isFnmatchPattern($normalized)) { $this->fnmatchAnalyseExcludes[] = $normalized; } else { - if ($this->noImplicitWildcard) { - if (is_file($normalized)) { - $this->literalAnalyseFilesExcludes[] = $normalized; - } elseif (is_dir($normalized)) { - if (!$trailingDirSeparator) { - $normalized .= DIRECTORY_SEPARATOR; - } - - $this->literalAnalyseDirectoryExcludes[] = $normalized; + if (is_file($normalized)) { + $this->literalAnalyseFilesExcludes[] = $normalized; + } elseif (is_dir($normalized)) { + if (!$trailingDirSeparator) { + $normalized .= DIRECTORY_SEPARATOR; } - } else { - $this->literalAnalyseExcludes[] = $fileHelper->absolutizePath($normalized); + + $this->literalAnalyseDirectoryExcludes[] = $normalized; } } } @@ -99,16 +94,14 @@ public function isExcludedFromAnalysing(string $file): bool return true; } } - if ($this->noImplicitWildcard) { - foreach ($this->literalAnalyseDirectoryExcludes as $exclude) { - if (str_starts_with($file, $exclude)) { - return true; - } + foreach ($this->literalAnalyseDirectoryExcludes as $exclude) { + if (str_starts_with($file, $exclude)) { + return true; } - foreach ($this->literalAnalyseFilesExcludes as $exclude) { - if ($file === $exclude) { - return true; - } + } + foreach ($this->literalAnalyseFilesExcludes as $exclude) { + if ($file === $exclude) { + return true; } } foreach ($this->fnmatchAnalyseExcludes as $exclude) { diff --git a/tests/PHPStan/File/FileExcluderTest.php b/tests/PHPStan/File/FileExcluderTest.php index 7477416b6c..f5c746a3ad 100644 --- a/tests/PHPStan/File/FileExcluderTest.php +++ b/tests/PHPStan/File/FileExcluderTest.php @@ -19,7 +19,7 @@ public function testFilesAreExcludedFromAnalysingOnWindows( { $this->skipIfNotOnWindows(); - $fileExcluder = new FileExcluder($this->getFileHelper(), $analyseExcludes, false); + $fileExcluder = new FileExcluder($this->getFileHelper(), $analyseExcludes); $this->assertSame($isExcluded, $fileExcluder->isExcludedFromAnalysing($filePath)); } @@ -34,7 +34,7 @@ public function dataExcludeOnWindows(): array ], [ __DIR__ . '/data/excluded-file.php', - [__DIR__], + [__DIR__ . '/*'], true, ], [ @@ -64,7 +64,7 @@ public function dataExcludeOnWindows(): array ], [ __DIR__ . '\data\parse-error.php', - ['tests/PHPStan/File/data'], + ['tests/PHPStan/File/data/*'], true, ], [ @@ -99,7 +99,7 @@ public function dataExcludeOnWindows(): array ], [ 'c:\etc\phpstan\dummy-1.php', - ['c:\etc\phpstan\\'], + ['c:\etc\phpstan\\*'], true, ], [ @@ -109,7 +109,7 @@ public function dataExcludeOnWindows(): array ], [ 'c:\etc\phpstan-test\dummy-2.php', - ['c:\etc\phpstan'], + ['c:\etc\phpstan*'], true, ], ]; @@ -127,7 +127,7 @@ public function testFilesAreExcludedFromAnalysingOnUnix( { $this->skipIfNotOnUnix(); - $fileExcluder = new FileExcluder($this->getFileHelper(), $analyseExcludes, false); + $fileExcluder = new FileExcluder($this->getFileHelper(), $analyseExcludes); $this->assertSame($isExcluded, $fileExcluder->isExcludedFromAnalysing($filePath)); } @@ -172,7 +172,7 @@ public function dataExcludeOnUnix(): array ], [ __DIR__ . '/data/parse-error.php', - ['tests/PHPStan/File/data'], + ['*/tests/PHPStan/File/data/*'], true, ], [ @@ -192,7 +192,7 @@ public function dataExcludeOnUnix(): array ], [ '/etc/phpstan/dummy-1.php', - ['/etc/phpstan/'], + ['/etc/phpstan/*'], true, ], [ @@ -202,7 +202,7 @@ public function dataExcludeOnUnix(): array ], [ '/etc/phpstan-test/dummy-2.php', - ['/etc/phpstan'], + ['/etc/phpstan*'], true, ], ]; @@ -216,16 +216,6 @@ public function dataNoImplicitWildcard(): iterable __DIR__ . '/test', ], false, - true, - ]; - - yield [ - __DIR__ . '/tests/foo.php', - [ - __DIR__ . '/test', - ], - true, - false, ]; yield [ @@ -234,7 +224,6 @@ public function dataNoImplicitWildcard(): iterable __DIR__ . '/test', ], true, - true, ]; yield [ @@ -243,7 +232,6 @@ public function dataNoImplicitWildcard(): iterable __DIR__ . '/FileExcluderTest.php', ], true, - true, ]; yield [ @@ -252,7 +240,6 @@ public function dataNoImplicitWildcard(): iterable __DIR__ . '/test*', ], true, - true, ]; } @@ -263,13 +250,12 @@ public function dataNoImplicitWildcard(): iterable public function testNoImplicitWildcard( string $filePath, array $analyseExcludes, - bool $noImplicitWildcard, bool $isExcluded, ): void { $this->skipIfNotOnUnix(); - $fileExcluder = new FileExcluder($this->getFileHelper(), $analyseExcludes, $noImplicitWildcard); + $fileExcluder = new FileExcluder($this->getFileHelper(), $analyseExcludes); $this->assertSame($isExcluded, $fileExcluder->isExcludedFromAnalysing($filePath)); } From 2e027658e061f647b0de5fbf5b68588ee668eae5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 10:46:30 +0200 Subject: [PATCH 110/508] [BE] Do not generalize template types, except when in `GenericObjectType` --- changelog-2.0.md | 4 ++-- src/Reflection/ResolvedFunctionVariantWithOriginal.php | 3 +-- src/Type/Generic/TemplateTypeTrait.php | 9 --------- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 090eea5e3a..628c9412d8 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -71,8 +71,6 @@ Bleeding edge (TODO move to other sections) * MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! -* Do not generalize template types, except when in `GenericObjectType` ([#2818](https://github.com/phpstan/phpstan-src/pull/2818), [#2821](https://github.com/phpstan/phpstan-src/pull/2821)) - * This fixes following **17 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092 * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) * LogicalXorConstantConditionRule (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * NoopRule - report top-level `xor` because that's probably not what the user intended to do (https://github.com/phpstan/phpstan-src/commit/a1fffb3346e09f1e8e8d987d4282263295a55142), #10267 @@ -140,6 +138,8 @@ Improvements 🔧 * InvalidPhpDocTagValueRule: include PHPDoc line number in the error message (https://github.com/phpstan/phpstan-src/commit/a04e0be832900749b5b4ba22e2de21db8bfa09a0) * No implicit wildcard in FileExcluder (https://github.com/phpstan/phpstan-src/commit/e19e6e5f8cfa706cc30e44a17276a6bc269f995c), #10299 * Report invalid exclude paths in PHP config (https://github.com/phpstan/phpstan-src/commit/9718c14f1ffac81ba3d2bf331b4e8b4041a4d004) +* Do not generalize template types, except when in `GenericObjectType` ([#2818](https://github.com/phpstan/phpstan-src/pull/2818), [#2821](https://github.com/phpstan/phpstan-src/pull/2821)) + * This fixes following **17 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092 Bugfixes 🐛 ===================== diff --git a/src/Reflection/ResolvedFunctionVariantWithOriginal.php b/src/Reflection/ResolvedFunctionVariantWithOriginal.php index c9f0d94ac6..ab5b182105 100644 --- a/src/Reflection/ResolvedFunctionVariantWithOriginal.php +++ b/src/Reflection/ResolvedFunctionVariantWithOriginal.php @@ -2,7 +2,6 @@ namespace PHPStan\Reflection; -use PHPStan\DependencyInjection\BleedingEdgeToggle; use PHPStan\Reflection\Php\DummyParameterWithPhpDocs; use PHPStan\Type\ConditionalTypeForParameter; use PHPStan\Type\ErrorType; @@ -245,7 +244,7 @@ private function resolveResolvableTemplateTypes(Type $type, TemplateTypeVariance }; return TypeTraverser::map($type, function (Type $type, callable $traverse) use ($references, $objectCb): Type { - if (BleedingEdgeToggle::isBleedingEdge() && $type instanceof GenericObjectType) { + if ($type instanceof GenericObjectType) { return TypeTraverser::map($type, $objectCb); } diff --git a/src/Type/Generic/TemplateTypeTrait.php b/src/Type/Generic/TemplateTypeTrait.php index 66fd32a2fd..13440a54a7 100644 --- a/src/Type/Generic/TemplateTypeTrait.php +++ b/src/Type/Generic/TemplateTypeTrait.php @@ -2,12 +2,10 @@ namespace PHPStan\Type\Generic; -use PHPStan\DependencyInjection\BleedingEdgeToggle; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\TrinaryLogic; use PHPStan\Type\AcceptsResult; -use PHPStan\Type\GeneralizePrecision; use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; @@ -268,13 +266,6 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap TemplateTypeVariance::createStatic(), )); if ($resolvedBound->isSuperTypeOf($receivedType)->yes()) { - if (!BleedingEdgeToggle::isBleedingEdge() && $this->shouldGeneralizeInferredType()) { - $generalizedType = $receivedType->generalize(GeneralizePrecision::templateArgument()); - if ($resolvedBound->isSuperTypeOf($generalizedType)->yes()) { - $receivedType = $generalizedType; - } - } - return (new TemplateTypeMap([ $this->name => $receivedType, ]))->union($map); From 0253a68fcbb04253c0e64efd5002c15ca80c2f5d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 10:51:23 +0200 Subject: [PATCH 111/508] [BE] Non-static methods cannot be used as static callables in PHP 8+ --- changelog-2.0.md | 2 +- src/Type/Constant/ConstantArrayType.php | 4 +--- src/Type/Constant/ConstantStringType.php | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 628c9412d8..e49e16733e 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -57,7 +57,6 @@ Bleeding edge (TODO move to other sections) * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) * More precise `file()` flags args ([#2476](https://github.com/phpstan/phpstan-src/pull/2476), [#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! -* Non-static methods cannot be used as static callables in PHP 8+ ([#2420](https://github.com/phpstan/phpstan-src/pull/2420)), thanks @staabm! * More precise `flock()` operation flags ([#2477](https://github.com/phpstan/phpstan-src/pull/2477)), thanks @staabm! * Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 @@ -140,6 +139,7 @@ Improvements 🔧 * Report invalid exclude paths in PHP config (https://github.com/phpstan/phpstan-src/commit/9718c14f1ffac81ba3d2bf331b4e8b4041a4d004) * Do not generalize template types, except when in `GenericObjectType` ([#2818](https://github.com/phpstan/phpstan-src/pull/2818), [#2821](https://github.com/phpstan/phpstan-src/pull/2821)) * This fixes following **17 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092 +* Non-static methods cannot be used as static callables in PHP 8+ ([#2420](https://github.com/phpstan/phpstan-src/pull/2420)), thanks @staabm! Bugfixes 🐛 ===================== diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 2161d3f4a2..7d16286e4f 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -4,7 +4,6 @@ use Nette\Utils\Strings; use PHPStan\Analyser\OutOfClassScope; -use PHPStan\DependencyInjection\BleedingEdgeToggle; use PHPStan\Internal\CombinationsHelper; use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode; @@ -579,8 +578,7 @@ public function findTypeAndMethodNames(): array } if ( - BleedingEdgeToggle::isBleedingEdge() - && $has->yes() + $has->yes() && !$phpVersion->supportsCallableInstanceMethods() ) { $methodReflection = $type->getMethod($method->getValue(), new OutOfClassScope()); diff --git a/src/Type/Constant/ConstantStringType.php b/src/Type/Constant/ConstantStringType.php index 3aa75ee5fb..48da3f2c48 100644 --- a/src/Type/Constant/ConstantStringType.php +++ b/src/Type/Constant/ConstantStringType.php @@ -6,7 +6,6 @@ use Nette\Utils\Strings; use PhpParser\Node\Name; use PHPStan\Analyser\OutOfClassScope; -use PHPStan\DependencyInjection\BleedingEdgeToggle; use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode; use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; @@ -217,8 +216,7 @@ public function isCallable(): TrinaryLogic if ($classRef->hasMethod($matches[2])) { $method = $classRef->getMethod($matches[2], new OutOfClassScope()); if ( - BleedingEdgeToggle::isBleedingEdge() - && !$phpVersion->supportsCallableInstanceMethods() + !$phpVersion->supportsCallableInstanceMethods() && !$method->isStatic() ) { return TrinaryLogic::createNo(); From 39b82cdd415faf7f4f62149a860e6a073770af5c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 10:53:53 +0200 Subject: [PATCH 112/508] [BE] Analysis with zero files results in non-zero exit code --- changelog-2.0.md | 2 +- src/Command/AnalyseCommand.php | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index e49e16733e..ec3add18a1 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -59,7 +59,6 @@ Bleeding edge (TODO move to other sections) * More precise `file()` flags args ([#2476](https://github.com/phpstan/phpstan-src/pull/2476), [#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! * More precise `flock()` operation flags ([#2477](https://github.com/phpstan/phpstan-src/pull/2477)), thanks @staabm! * Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! -* Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 * Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! * `error_log` errors with `message_type=2` ([#2428](https://github.com/phpstan/phpstan-src/pull/2428)), #9380, thanks @staabm! * Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! @@ -140,6 +139,7 @@ Improvements 🔧 * Do not generalize template types, except when in `GenericObjectType` ([#2818](https://github.com/phpstan/phpstan-src/pull/2818), [#2821](https://github.com/phpstan/phpstan-src/pull/2821)) * This fixes following **17 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092 * Non-static methods cannot be used as static callables in PHP 8+ ([#2420](https://github.com/phpstan/phpstan-src/pull/2420)), thanks @staabm! +* Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 Bugfixes 🐛 ===================== diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index f4281c48e4..d7ff2a6132 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -244,17 +244,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if (count($files) === 0) { - $bleedingEdge = (bool) $container->getParameter('featureToggles')['zeroFiles']; - $this->runDiagnoseExtensions($container, $inceptionResult->getErrorOutput()); - if (!$bleedingEdge) { - $inceptionResult->getErrorOutput()->getStyle()->note('No files found to analyse.'); - $inceptionResult->getErrorOutput()->getStyle()->warning('This will cause a non-zero exit code in PHPStan 2.0.'); - - return $inceptionResult->handleReturn(0, null, $this->analysisStartTime); - } - $inceptionResult->getErrorOutput()->getStyle()->error('No files found to analyse.'); return $inceptionResult->handleReturn(1, null, $this->analysisStartTime); From 741c4011cf42e02cb1ca2da01739bf44b455891b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 10:54:21 +0200 Subject: [PATCH 113/508] [BE] Fail build when project config uses custom extensions outside of analysed paths --- changelog-2.0.md | 4 ++-- src/Command/AnalyseCommand.php | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index ec3add18a1..d1343fa30c 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -93,8 +93,6 @@ Bleeding edge (TODO move to other sections) * Deprecated: returning plain strings as errors, use RuleErrorBuilder * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) * Deprecated: returning RuleError without identifier (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) -* Fail build when project config uses custom extensions outside of analysed paths - * This will only occur after a run that uses already present and valid result cache * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) * Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) @@ -140,6 +138,8 @@ Improvements 🔧 * This fixes following **17 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092 * Non-static methods cannot be used as static callables in PHP 8+ ([#2420](https://github.com/phpstan/phpstan-src/pull/2420)), thanks @staabm! * Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 +* Fail build when project config uses custom extensions outside of analysed paths + * This will only occur after a run that uses already present and valid result cache Bugfixes 🐛 ===================== diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index d7ff2a6132..5e4aa61443 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -503,12 +503,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $errorOutput->writeLineFormatted(''); - $bleedingEdge = (bool) $container->getParameter('featureToggles')['projectServicesNotInAnalysedPaths']; - if ($bleedingEdge) { - return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); - } - - $errorOutput->getStyle()->warning('This will cause a non-zero exit code in PHPStan 2.0.'); + return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes(), $this->analysisStartTime); } } From e4a3488fca79b8cd4aa04ea0883ed674d8d6772c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 10:57:07 +0200 Subject: [PATCH 114/508] [BE] Countable stub with `0|positive-int` --- changelog-2.0.md | 3 ++- conf/config.neon | 8 +------- src/PhpDoc/CountableStubFilesExtension.php | 21 --------------------- stubs/Countable.stub | 2 +- stubs/bleedingEdge/Countable.stub | 9 --------- 5 files changed, 4 insertions(+), 39 deletions(-) delete mode 100644 src/PhpDoc/CountableStubFilesExtension.php delete mode 100644 stubs/bleedingEdge/Countable.stub diff --git a/changelog-2.0.md b/changelog-2.0.md index d1343fa30c..6e690a7ca4 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -9,7 +9,6 @@ Bleeding edge (TODO move to other sections) ===================== * Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 -* Countable stub with `0|positive-int` ([#1027](https://github.com/phpstan/phpstan-src/pull/1027)), thanks @staabm! * Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! * Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! * Lower memory consumption thanks to breaking up of reference cycles @@ -147,5 +146,7 @@ Bugfixes 🐛 Function signature fixes 🤖 ======================= +* Countable stub with `0|positive-int` ([#1027](https://github.com/phpstan/phpstan-src/pull/1027)), thanks @staabm! + Internals 🔍 ===================== diff --git a/conf/config.neon b/conf/config.neon index 552b99403a..38c6cb6206 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -195,6 +195,7 @@ parameters: - ../stubs/arrayFunctions.stub - ../stubs/core.stub - ../stubs/typeCheckingFunctions.stub + - ../stubs/Countable.stub earlyTerminatingMethodCalls: [] earlyTerminatingFunctionCalls: [] memoryLimitFile: %tmpDir%/.memory_limit @@ -456,13 +457,6 @@ services: arguments: duplicateStubs: %featureToggles.duplicateStubs% - - - class: PHPStan\PhpDoc\CountableStubFilesExtension - arguments: - bleedingEdge: %featureToggles.bleedingEdge% - tags: - - phpstan.stubFilesExtension - - class: PHPStan\PhpDoc\SocketSelectStubFilesExtension tags: diff --git a/src/PhpDoc/CountableStubFilesExtension.php b/src/PhpDoc/CountableStubFilesExtension.php deleted file mode 100644 index 3fc3a15666..0000000000 --- a/src/PhpDoc/CountableStubFilesExtension.php +++ /dev/null @@ -1,21 +0,0 @@ -bleedingEdge) { - return [__DIR__ . '/../../stubs/bleedingEdge/Countable.stub']; - } - - return [__DIR__ . '/../../stubs/Countable.stub']; - } - -} diff --git a/stubs/Countable.stub b/stubs/Countable.stub index c69c9dba43..2491db1ce5 100644 --- a/stubs/Countable.stub +++ b/stubs/Countable.stub @@ -3,7 +3,7 @@ interface Countable { /** - * @return int + * @return 0|positive-int */ public function count(): int; } diff --git a/stubs/bleedingEdge/Countable.stub b/stubs/bleedingEdge/Countable.stub deleted file mode 100644 index 2491db1ce5..0000000000 --- a/stubs/bleedingEdge/Countable.stub +++ /dev/null @@ -1,9 +0,0 @@ - Date: Mon, 16 Sep 2024 10:57:46 +0200 Subject: [PATCH 115/508] [BE] Require identifier in custom rules --- changelog-2.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 6e690a7ca4..f920c123b1 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -91,7 +91,6 @@ Bleeding edge (TODO move to other sections) * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Deprecated: returning plain strings as errors, use RuleErrorBuilder * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) -* Deprecated: returning RuleError without identifier (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) * Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) @@ -139,6 +138,7 @@ Improvements 🔧 * Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 * Fail build when project config uses custom extensions outside of analysed paths * This will only occur after a run that uses already present and valid result cache +* Require identifier in custom rules (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) Bugfixes 🐛 ===================== From 6a62c4e7f0a362d9169263e5d103e7cc04f78dcb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 10:59:32 +0200 Subject: [PATCH 116/508] [BE] Require RuleErrorBuilder and identifiers in custom rules --- UPGRADING.md | 22 ++++++++++++++++++++++ changelog-2.0.md | 4 ++-- conf/bleedingEdge.neon | 2 -- src/Rules/Rule.php | 2 +- stubs/bleedingEdge/Rule.stub | 26 -------------------------- 5 files changed, 25 insertions(+), 31 deletions(-) delete mode 100644 stubs/bleedingEdge/Rule.stub diff --git a/UPGRADING.md b/UPGRADING.md index 2e9830c098..f31af1f3d3 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -68,6 +68,28 @@ Now, `throw $e;` is represented as a `Stmt\Expression` that contains an `Expr\Th See [UPGRADING](https://github.com/phpstan/phpdoc-parser/blob/2.0.x/UPGRADING.md) guide for phpstan/phpdoc-parser. +### Returning plain strings as errors no longer supported, use RuleErrorBuilder + * +Identifiers are also required in custom rules. + +Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) + +Before: + +```php +return ['My error']; +``` + +After: + +```php +return [ + RuleErrorBuilder::mesage('My error') + ->identifier('my.error') + ->build(), +]; +``` + ### Changed `TypeSpecifier::create()` and `SpecifiedTypes` constructor parameters [`PHPStan\Analyser\TypeSpecifier::create()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.TypeSpecifier.html#_create) now accepts (all parameters are required): diff --git a/changelog-2.0.md b/changelog-2.0.md index f920c123b1..b4d4ac25c0 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -89,8 +89,6 @@ Bleeding edge (TODO move to other sections) * BetterNoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 * Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) -* Deprecated: returning plain strings as errors, use RuleErrorBuilder - * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) * Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) @@ -138,6 +136,8 @@ Improvements 🔧 * Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 * Fail build when project config uses custom extensions outside of analysed paths * This will only occur after a run that uses already present and valid result cache +* Returning plain strings as errors no longer supported, use RuleErrorBuilder + * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) * Require identifier in custom rules (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) Bugfixes 🐛 diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index c5f05f8208..1742fadfaf 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -57,5 +57,3 @@ parameters: explicitThrow: true absentTypeChecks: true requireFileExists: true - stubFiles: - - ../stubs/bleedingEdge/Rule.stub diff --git a/src/Rules/Rule.php b/src/Rules/Rule.php index e145e4b530..293c06e622 100644 --- a/src/Rules/Rule.php +++ b/src/Rules/Rule.php @@ -32,7 +32,7 @@ public function getNodeType(): string; /** * @phpstan-param TNodeType $node - * @return (string|RuleError)[] errors + * @return list */ public function processNode(Node $node, Scope $scope): array; diff --git a/stubs/bleedingEdge/Rule.stub b/stubs/bleedingEdge/Rule.stub deleted file mode 100644 index 0a86ea9d2c..0000000000 --- a/stubs/bleedingEdge/Rule.stub +++ /dev/null @@ -1,26 +0,0 @@ - - */ - public function getNodeType(): string; - - /** - * @phpstan-param TNodeType $node - * @return list - */ - public function processNode(Node $node, Scope $scope): array; - -} From b3be0259df63540a71ffbdf85b3afadf017a4d25 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 12:46:37 +0200 Subject: [PATCH 117/508] Fix tests --- tests/PHPStan/Command/CommandHelperTest.php | 1 + tests/PHPStan/Command/exclude-paths/full.neon | 2 +- tests/PHPStan/Command/exclude-paths/including-mixed.neon | 2 +- tests/PHPStan/Command/exclude-paths/including.neon | 4 ++-- tests/PHPStan/Command/exclude-paths/straightforward.neon | 2 +- tests/PHPStan/Command/exclude-paths/test/.gitkeep | 0 tests/PHPStan/Command/relative-paths/nested/nested.neon | 1 + tests/PHPStan/File/FileExcluderTest.php | 7 +------ 8 files changed, 8 insertions(+), 11 deletions(-) create mode 100644 tests/PHPStan/Command/exclude-paths/test/.gitkeep diff --git a/tests/PHPStan/Command/CommandHelperTest.php b/tests/PHPStan/Command/CommandHelperTest.php index d5a1480199..817dea23f8 100644 --- a/tests/PHPStan/Command/CommandHelperTest.php +++ b/tests/PHPStan/Command/CommandHelperTest.php @@ -205,6 +205,7 @@ public function dataParameters(): array __DIR__ . DIRECTORY_SEPARATOR . 'relative-paths' . DIRECTORY_SEPARATOR . 'nested' . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'there.php', __DIR__ . DIRECTORY_SEPARATOR . 'relative-paths' . DIRECTORY_SEPARATOR . 'up.php', ], + 'reportUnmatchedIgnoredErrors' => false, 'ignoreErrors' => [ [ 'message' => '#aaa#', diff --git a/tests/PHPStan/Command/exclude-paths/full.neon b/tests/PHPStan/Command/exclude-paths/full.neon index bb813f036e..275024f3a0 100644 --- a/tests/PHPStan/Command/exclude-paths/full.neon +++ b/tests/PHPStan/Command/exclude-paths/full.neon @@ -3,4 +3,4 @@ parameters: analyse: - test analyseAndScan: - - test2 + - test2 (?) diff --git a/tests/PHPStan/Command/exclude-paths/including-mixed.neon b/tests/PHPStan/Command/exclude-paths/including-mixed.neon index d7b9f3ae38..5cb7be683d 100644 --- a/tests/PHPStan/Command/exclude-paths/including-mixed.neon +++ b/tests/PHPStan/Command/exclude-paths/including-mixed.neon @@ -6,4 +6,4 @@ parameters: analyse: - test analyseAndScan: - - test2 + - test2 (?) diff --git a/tests/PHPStan/Command/exclude-paths/including.neon b/tests/PHPStan/Command/exclude-paths/including.neon index 199397750d..058059038b 100644 --- a/tests/PHPStan/Command/exclude-paths/including.neon +++ b/tests/PHPStan/Command/exclude-paths/including.neon @@ -4,6 +4,6 @@ includes: parameters: excludePaths: analyse: - - test2 + - test2 (?) analyseAndScan: - - test3 + - test3 (?) diff --git a/tests/PHPStan/Command/exclude-paths/straightforward.neon b/tests/PHPStan/Command/exclude-paths/straightforward.neon index 2b5facc315..6a4a1bd0ab 100644 --- a/tests/PHPStan/Command/exclude-paths/straightforward.neon +++ b/tests/PHPStan/Command/exclude-paths/straightforward.neon @@ -1,4 +1,4 @@ parameters: excludePaths: - test - - test2 + - test2 (?) diff --git a/tests/PHPStan/Command/exclude-paths/test/.gitkeep b/tests/PHPStan/Command/exclude-paths/test/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/PHPStan/Command/relative-paths/nested/nested.neon b/tests/PHPStan/Command/relative-paths/nested/nested.neon index 6e097edf21..c004fd54b6 100644 --- a/tests/PHPStan/Command/relative-paths/nested/nested.neon +++ b/tests/PHPStan/Command/relative-paths/nested/nested.neon @@ -3,6 +3,7 @@ parameters: - here.php - test/there.php - ../up.php + reportUnmatchedIgnoredErrors: false ignoreErrors: - message: '#aaa#' diff --git a/tests/PHPStan/File/FileExcluderTest.php b/tests/PHPStan/File/FileExcluderTest.php index f5c746a3ad..860b779e75 100644 --- a/tests/PHPStan/File/FileExcluderTest.php +++ b/tests/PHPStan/File/FileExcluderTest.php @@ -142,7 +142,7 @@ public function dataExcludeOnUnix(): array ], [ __DIR__ . '/data/excluded-file.php', - [__DIR__], + [__DIR__ . '/*'], true, ], [ @@ -170,11 +170,6 @@ public function dataExcludeOnUnix(): array [__DIR__ . '/data/[pP]arse-[eE]rror.ph[pP]'], true, ], - [ - __DIR__ . '/data/parse-error.php', - ['*/tests/PHPStan/File/data/*'], - true, - ], [ __DIR__ . '/data/parse-error.php', [__DIR__ . '/aaa'], From f7a73266acb96059da8a2885e3d41a8d6a4528bf Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 13:02:20 +0200 Subject: [PATCH 118/508] Regression tests Closes https://github.com/phpstan/phpstan/issues/11126 Closes https://github.com/phpstan/phpstan/issues/11032 Closes https://github.com/phpstan/phpstan/issues/10653 --- changelog-2.0.md | 2 +- tests/PHPStan/Analyser/nsrt/bug-10653.php | 13 ++++++ .../Rules/Functions/ReturnTypeRuleTest.php | 14 +++++++ .../Rules/Functions/data/bug-11032.php | 42 +++++++++++++++++++ .../Rules/Functions/data/bug-11126.php | 41 ++++++++++++++++++ .../Rules/Methods/ReturnTypeRuleTest.php | 5 +++ .../PHPStan/Rules/Methods/data/bug-10653.php | 42 +++++++++++++++++++ 7 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-10653.php create mode 100644 tests/PHPStan/Rules/Functions/data/bug-11032.php create mode 100644 tests/PHPStan/Rules/Functions/data/bug-11126.php create mode 100644 tests/PHPStan/Rules/Methods/data/bug-10653.php diff --git a/changelog-2.0.md b/changelog-2.0.md index b4d4ac25c0..8407fcacd1 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -131,7 +131,7 @@ Improvements 🔧 * No implicit wildcard in FileExcluder (https://github.com/phpstan/phpstan-src/commit/e19e6e5f8cfa706cc30e44a17276a6bc269f995c), #10299 * Report invalid exclude paths in PHP config (https://github.com/phpstan/phpstan-src/commit/9718c14f1ffac81ba3d2bf331b4e8b4041a4d004) * Do not generalize template types, except when in `GenericObjectType` ([#2818](https://github.com/phpstan/phpstan-src/pull/2818), [#2821](https://github.com/phpstan/phpstan-src/pull/2821)) - * This fixes following **17 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092 + * This fixes following **20 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092, #11126, #11032, #10653 * Non-static methods cannot be used as static callables in PHP 8+ ([#2420](https://github.com/phpstan/phpstan-src/pull/2420)), thanks @staabm! * Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 * Fail build when project config uses custom extensions outside of analysed paths diff --git a/tests/PHPStan/Analyser/nsrt/bug-10653.php b/tests/PHPStan/Analyser/nsrt/bug-10653.php new file mode 100644 index 0000000000..fc6642a229 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-10653.php @@ -0,0 +1,13 @@ +mayFail(); + assertType('stdClass|false', $value); + $value = $a->throwOnFailure($value); + assertType(stdClass::class, $value); +}; diff --git a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php index 53476ec81b..5ba98544fb 100644 --- a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php @@ -301,4 +301,18 @@ public function testBug8881(): void $this->analyse([__DIR__ . '/data/bug-8881.php'], []); } + public function testBug11126(): void + { + $this->checkExplicitMixed = true; + $this->checkNullables = true; + $this->analyse([__DIR__ . '/data/bug-11126.php'], []); + } + + public function testBug11032(): void + { + $this->checkExplicitMixed = true; + $this->checkNullables = true; + $this->analyse([__DIR__ . '/data/bug-11032.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Functions/data/bug-11032.php b/tests/PHPStan/Rules/Functions/data/bug-11032.php new file mode 100644 index 0000000000..ea967f31ee --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-11032.php @@ -0,0 +1,42 @@ + + */ + private $promise = null; + + /** + * @return PromiseInterface + */ + public function promise(): PromiseInterface + { + return $this->promise; + } +} + +/** + * @template T + * @param iterable $tasks + * @return PromiseInterface> + */ +function parallel(iterable $tasks): PromiseInterface +{ + /** @var Deferred> $deferred*/ + $deferred = new Deferred(); + + return $deferred->promise(); +} diff --git a/tests/PHPStan/Rules/Functions/data/bug-11126.php b/tests/PHPStan/Rules/Functions/data/bug-11126.php new file mode 100644 index 0000000000..8569f55ac0 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-11126.php @@ -0,0 +1,41 @@ + + */ + public function map(callable $callback): Collection { + return $this; + } +} + +/** + * @param Collection> $in + * @return Collection> + */ +function foo(Collection $in): Collection { + return $in->map(static fn ($v) => $v); +} + +/** + * @param Collection> $in + * @return Collection> + */ +function bar(Collection $in): Collection { + return $in->map(value(...)); +} + +/** + * @param int<0, max> $in + * @return int<0, max> + */ +function value(int $in): int { + return $in; +} diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index 2730a29791..5446ab66db 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -1081,4 +1081,9 @@ public function testBug10715(): void $this->analyse([__DIR__ . '/data/bug-10715.php'], []); } + public function testBug10653(): void + { + $this->analyse([__DIR__ . '/data/bug-10653.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-10653.php b/tests/PHPStan/Rules/Methods/data/bug-10653.php new file mode 100644 index 0000000000..3aaa3c735b --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-10653.php @@ -0,0 +1,42 @@ +throwOnFailure($this->mayFail()); + } + + /** + * @template T + * + * @param T $result + * @return (T is false ? never : T) + */ + public function throwOnFailure($result) + { + if ($result === false) { + throw new Exception('Operation failed'); + } + return $result; + } + + /** + * @return stdClass|false + */ + public function mayFail() + { + $this->Counter++; + return $this->Counter % 2 ? new stdClass() : false; + } +} From 5d17773d65ce7f528d076ff61d4c240e560b034e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 17:21:18 +0200 Subject: [PATCH 119/508] RuleErrorTransformer - accept only IdentifierRuleError --- src/Analyser/RuleErrorTransformer.php | 62 +++++++++++---------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/src/Analyser/RuleErrorTransformer.php b/src/Analyser/RuleErrorTransformer.php index 0cb9f9ef98..916f284505 100644 --- a/src/Analyser/RuleErrorTransformer.php +++ b/src/Analyser/RuleErrorTransformer.php @@ -8,9 +8,7 @@ use PHPStan\Rules\LineRuleError; use PHPStan\Rules\MetadataRuleError; use PHPStan\Rules\NonIgnorableRuleError; -use PHPStan\Rules\RuleError; use PHPStan\Rules\TipRuleError; -use function is_string; final class RuleErrorTransformer { @@ -19,7 +17,7 @@ final class RuleErrorTransformer * @param class-string $nodeType */ public function transform( - string|RuleError $ruleError, + IdentifierRuleError $ruleError, Scope $scope, string $nodeType, int $nodeLine, @@ -31,7 +29,6 @@ public function transform( $filePath = $scope->getFile(); $traitFilePath = null; $tip = null; - $identifier = null; $metadata = []; if ($scope->isInTrait()) { $traitReflection = $scope->getTraitReflection(); @@ -39,43 +36,36 @@ public function transform( $traitFilePath = $traitReflection->getFileName(); } } - if (is_string($ruleError)) { - $message = $ruleError; - } else { - $message = $ruleError->getMessage(); - if ( - $ruleError instanceof LineRuleError - && $ruleError->getLine() !== -1 - ) { - $line = $ruleError->getLine(); - } - if ( - $ruleError instanceof FileRuleError - && $ruleError->getFile() !== '' - ) { - $fileName = $ruleError->getFileDescription(); - $filePath = $ruleError->getFile(); - $traitFilePath = null; - } - if ($ruleError instanceof TipRuleError) { - $tip = $ruleError->getTip(); - } + if ( + $ruleError instanceof LineRuleError + && $ruleError->getLine() !== -1 + ) { + $line = $ruleError->getLine(); + } + if ( + $ruleError instanceof FileRuleError + && $ruleError->getFile() !== '' + ) { + $fileName = $ruleError->getFileDescription(); + $filePath = $ruleError->getFile(); + $traitFilePath = null; + } - if ($ruleError instanceof IdentifierRuleError) { - $identifier = $ruleError->getIdentifier(); - } + if ($ruleError instanceof TipRuleError) { + $tip = $ruleError->getTip(); + } - if ($ruleError instanceof MetadataRuleError) { - $metadata = $ruleError->getMetadata(); - } + if ($ruleError instanceof MetadataRuleError) { + $metadata = $ruleError->getMetadata(); + } - if ($ruleError instanceof NonIgnorableRuleError) { - $canBeIgnored = false; - } + if ($ruleError instanceof NonIgnorableRuleError) { + $canBeIgnored = false; } + return new Error( - $message, + $ruleError->getMessage(), $fileName, $line, $canBeIgnored, @@ -84,7 +74,7 @@ public function transform( $tip, $nodeLine, $nodeType, - $identifier, + $ruleError->getIdentifier(), $metadata, ); } From 9b91afb90d918aeec808f49fa7d5c8f46307d99a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 13:12:26 +0200 Subject: [PATCH 120/508] [BE] List type --- changelog-2.0.md | 5 ++-- conf/bleedingEdge.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - src/Analyser/MutatingScope.php | 17 ++++++------- src/Analyser/NodeScopeResolver.php | 6 ++--- src/Analyser/TypeSpecifier.php | 2 +- src/DependencyInjection/ContainerFactory.php | 2 -- src/PhpDoc/TypeNodeResolver.php | 12 ++++------ .../InitializerExprTypeResolver.php | 4 ++-- src/Rules/Functions/ArrayValuesRule.php | 5 ---- src/Type/Accessory/AccessoryArrayListType.php | 21 ---------------- src/Type/ArrayType.php | 6 ++--- src/Type/Constant/ConstantArrayType.php | 6 ++--- .../Constant/ConstantArrayTypeBuilder.php | 2 +- src/Type/Constant/OversizedArrayBuilder.php | 2 +- src/Type/MixedType.php | 6 ++--- .../ArrayChunkFunctionReturnTypeExtension.php | 4 ++-- ...ArrayColumnFunctionReturnTypeExtension.php | 2 +- .../ArrayFillFunctionReturnTypeExtension.php | 2 +- .../ArrayMapFunctionReturnTypeExtension.php | 2 +- ...ergeFunctionDynamicReturnTypeExtension.php | 2 +- ...lodeFunctionDynamicReturnTypeExtension.php | 2 +- ...lterVarArrayDynamicReturnTypeExtension.php | 4 ++-- ...atorToArrayFunctionReturnTypeExtension.php | 3 ++- .../PregSplitDynamicReturnTypeExtension.php | 2 +- .../Php/RangeFunctionReturnTypeExtension.php | 24 ++++++++++--------- src/Type/Php/RegexArrayShapeMatcher.php | 6 ++--- .../StrSplitFunctionReturnTypeExtension.php | 2 +- src/Type/TypeCombinator.php | 4 ++-- stubs/arrayFunctions.stub | 2 +- .../Php8SignatureMapProviderTest.php | 6 +++-- 32 files changed, 69 insertions(+), 97 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 8407fcacd1..643a7a532f 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -5,6 +5,9 @@ When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](h Major new features 🚀 ===================== +* **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! + * Lists are arrays with sequential integer keys starting at 0 + Bleeding edge (TODO move to other sections) ===================== @@ -30,8 +33,6 @@ Bleeding edge (TODO move to other sections) * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) * Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! -* **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! - * Lists are arrays with sequential integer keys starting at 0 * Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! * Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 1742fadfaf..177fbdc689 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -19,7 +19,6 @@ parameters: runtimeReflectionRules: true notAnalysedTrait: true curlSetOptTypes: true - listType: true abstractTraitMethod: true missingMagicSerializationRule: true nullContextForVoidReturningFunctions: true diff --git a/conf/config.neon b/conf/config.neon index 38c6cb6206..b9623abaa3 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -54,7 +54,6 @@ parameters: runtimeReflectionRules: false notAnalysedTrait: false curlSetOptTypes: false - listType: false abstractTraitMethod: false missingMagicSerializationRule: false nullContextForVoidReturningFunctions: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 6b8a6c44b7..f5b9ed153d 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -49,7 +49,6 @@ parametersSchema: runtimeReflectionRules: bool() notAnalysedTrait: bool() curlSetOptTypes: bool() - listType: bool() abstractTraitMethod: bool() missingMagicSerializationRule: bool() nullContextForVoidReturningFunctions: bool() diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 6de895a04b..441778bf21 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -526,10 +526,11 @@ public function getVariableType(string $variableName): Type return IntegerRangeType::fromInterval(1, null); } if ($variableName === 'argv') { - return AccessoryArrayListType::intersectWith(TypeCombinator::intersect( + return TypeCombinator::intersect( new ArrayType(new IntegerType(), new StringType()), new NonEmptyArrayType(), - )); + new AccessoryArrayListType(), + ); } if ($this->canAnyVariableExist()) { return new MixedType(); @@ -3175,7 +3176,7 @@ private function enterFunctionLike( if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()) { $parameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $parameterType); } else { - $parameterType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $parameterType)); + $parameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $parameterType), new AccessoryArrayListType()); } } $parameterNode = new Variable($parameter->getName()); @@ -3190,7 +3191,7 @@ private function enterFunctionLike( if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()) { $nativeParameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $nativeParameterType); } else { - $nativeParameterType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $nativeParameterType)); + $nativeParameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $nativeParameterType), new AccessoryArrayListType()); } } $nativeExpressionTypes[$paramExprString] = ExpressionTypeHolder::createYes($parameterNode, $nativeParameterType); @@ -3670,11 +3671,11 @@ public function getFunctionType($type, bool $isNullable, bool $isVariadic): Type )); } - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $this->getFunctionType( + return TypeCombinator::intersect(new ArrayType(new IntegerType(), $this->getFunctionType( $type, false, false, - ))); + )), new AccessoryArrayListType()); } if ($type instanceof Name) { @@ -5079,7 +5080,7 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type $resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType()); } if ($constantArraysA->isList()->yes() && $constantArraysB->isList()->yes()) { - $resultType = AccessoryArrayListType::intersectWith($resultType); + $resultType = TypeCombinator::intersect($resultType, new AccessoryArrayListType()); } $resultTypes[] = $resultType; } @@ -5122,7 +5123,7 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type $resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType()); } if ($generalArraysA->isList()->yes() && $generalArraysB->isList()->yes()) { - $resultType = AccessoryArrayListType::intersectWith($resultType); + $resultType = TypeCombinator::intersect($resultType, new AccessoryArrayListType()); } if ($generalArraysA->isOversizedArray()->yes() && $generalArraysB->isOversizedArray()->yes()) { $resultType = TypeCombinator::intersect($resultType, new OversizedArrayType()); diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 3bd5080928..8bcb6c1af2 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -2455,7 +2455,7 @@ static function (): void { $functionReflection !== null && in_array($functionReflection->getName(), ['fopen', 'file_get_contents'], true) ) { - $scope = $scope->assignVariable('http_response_header', AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())), new ArrayType(new IntegerType(), new StringType()), TrinaryLogic::createYes()); + $scope = $scope->assignVariable('http_response_header', TypeCombinator::intersect(new ArrayType(new IntegerType(), new StringType()), new AccessoryArrayListType()), new ArrayType(new IntegerType(), new StringType()), TrinaryLogic::createYes()); } if ( @@ -3841,7 +3841,7 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra ? TypeCombinator::intersect($array, new NonEmptyArrayType()) : $array; $constantArray = $isList - ? AccessoryArrayListType::intersectWith($constantArray) + ? TypeCombinator::intersect($constantArray, new AccessoryArrayListType()) : $constantArray; } @@ -3884,7 +3884,7 @@ private function getArraySortPreserveListFunctionType(Type $type): Type return $type; } - $newArrayType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $type->getIterableValueType())); + $newArrayType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $type->getIterableValueType()), new AccessoryArrayListType()); if ($isIterableAtLeastOnce->yes()) { $newArrayType = TypeCombinator::intersect($newArrayType, new NonEmptyArrayType()); } diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 5c349ce624..327acb7cf7 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -315,7 +315,7 @@ public function specifyTypesInCondition( if ($argType->isArray()->yes()) { $newType = new NonEmptyArrayType(); if ($context->true() && $argType->isList()->yes()) { - $newType = AccessoryArrayListType::intersectWith($newType); + $newType = TypeCombinator::intersect($newType, new AccessoryArrayListType()); } $result = $result->unionWith( diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index 4cd4dfc0db..1e980d2f32 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -31,7 +31,6 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\Accessory\AccessoryArrayListType; use PHPStan\Type\Generic\TemplateTypeVariance; use PHPStan\Type\ObjectType; use Symfony\Component\Finder\Finder; @@ -192,7 +191,6 @@ public static function postInitializeContainer(Container $container): void $container->getService('typeSpecifier'); BleedingEdgeToggle::setBleedingEdge($container->getParameter('featureToggles')['bleedingEdge']); - AccessoryArrayListType::setListTypeEnabled($container->getParameter('featureToggles')['listType']); TemplateTypeVariance::setInvarianceCompositionEnabled($container->getParameter('featureToggles')['invarianceComposition']); } diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php index ccfd16f32a..20df016e0c 100644 --- a/src/PhpDoc/TypeNodeResolver.php +++ b/src/PhpDoc/TypeNodeResolver.php @@ -409,15 +409,11 @@ private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameSco return new NonAcceptingNeverType(); case 'list': - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new MixedType())); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), new MixedType()), new AccessoryArrayListType()); case 'non-empty-list': - return AccessoryArrayListType::intersectWith(TypeCombinator::intersect( - new ArrayType(new IntegerType(), new MixedType()), - new NonEmptyArrayType(), - )); - case '__always-list': return TypeCombinator::intersect( new ArrayType(new IntegerType(), new MixedType()), + new NonEmptyArrayType(), new AccessoryArrayListType(), ); @@ -657,7 +653,7 @@ static function (string $variance): TemplateTypeVariance { return $arrayType; } elseif (in_array($mainTypeName, ['list', 'non-empty-list'], true)) { if (count($genericTypes) === 1) { // list - $listType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $genericTypes[0])); + $listType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $genericTypes[0]), new AccessoryArrayListType()); if ($mainTypeName === 'non-empty-list') { return TypeCombinator::intersect($listType, new NonEmptyArrayType()); } @@ -995,7 +991,7 @@ private function resolveArrayShapeNode(ArrayShapeNode $typeNode, NameScope $name $arrayType = $builder->getArray(); if ($typeNode->kind === ArrayShapeNode::KIND_LIST) { - $arrayType = AccessoryArrayListType::intersectWith($arrayType); + $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return $arrayType; diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 6d4734b397..b4beb587bf 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -568,7 +568,7 @@ public function getArrayType(Expr\Array_ $expr, callable $getTypeCallback): Type $arrayType = $arrayBuilder->getArray(); if ($isList === true) { - return AccessoryArrayListType::intersectWith($arrayType); + return TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return $arrayType; @@ -1041,7 +1041,7 @@ public function getPlusType(Expr $left, Expr $right, callable $getTypeCallback): $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($leftType->isList()->yes() && $rightType->isList()->yes()) { - $arrayType = AccessoryArrayListType::intersectWith($arrayType); + $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return $arrayType; diff --git a/src/Rules/Functions/ArrayValuesRule.php b/src/Rules/Functions/ArrayValuesRule.php index cf058b54a8..e2b44cf399 100644 --- a/src/Rules/Functions/ArrayValuesRule.php +++ b/src/Rules/Functions/ArrayValuesRule.php @@ -10,7 +10,6 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\Accessory\AccessoryArrayListType; use PHPStan\Type\VerbosityLevel; use function count; use function sprintf; @@ -39,10 +38,6 @@ public function processNode(Node $node, Scope $scope): array return []; } - if (AccessoryArrayListType::isListTypeEnabled() === false) { - return []; - } - if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { return []; } diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index f80ada4ad9..472bdeb1c1 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -39,8 +39,6 @@ class AccessoryArrayListType implements CompoundType, AccessoryType use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; - private static bool $enabled = false; - public function __construct() { } @@ -468,25 +466,6 @@ public static function __set_state(array $properties): Type return new self(); } - public static function setListTypeEnabled(bool $enabled): void - { - self::$enabled = $enabled; - } - - public static function isListTypeEnabled(): bool - { - return self::$enabled; - } - - public static function intersectWith(Type $type): Type - { - if (self::$enabled) { - return TypeCombinator::intersect($type, new self()); - } - - return $type; - } - public function exponentiate(Type $exponent): Type { return new ErrorType(); diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 061e002a46..33c3cdc439 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -198,12 +198,12 @@ public function generalizeValues(): self public function getKeysArray(): Type { - return AccessoryArrayListType::intersectWith(new self(new IntegerType(), $this->getIterableKeyType())); + return TypeCombinator::intersect(new self(new IntegerType(), $this->getIterableKeyType()), new AccessoryArrayListType()); } public function getValuesArray(): Type { - return AccessoryArrayListType::intersectWith(new self(new IntegerType(), $this->itemType)); + return TypeCombinator::intersect(new self(new IntegerType(), $this->itemType), new AccessoryArrayListType()); } public function isIterable(): TrinaryLogic @@ -569,7 +569,7 @@ public function shiftArray(): Type public function shuffleArray(): Type { - return AccessoryArrayListType::intersectWith(new self(new IntegerType(), $this->itemType)); + return TypeCombinator::intersect(new self(new IntegerType(), $this->itemType), new AccessoryArrayListType()); } public function isCallable(): TrinaryLogic diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 7d16286e4f..2df98dd219 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -904,7 +904,7 @@ public function shuffleArray(): Type $generalizedArray = TypeCombinator::intersect($generalizedArray, new NonEmptyArrayType()); } if ($valuesArray->isList->yes()) { - $generalizedArray = AccessoryArrayListType::intersectWith($generalizedArray); + $generalizedArray = TypeCombinator::intersect($generalizedArray, new AccessoryArrayListType()); } return $generalizedArray; @@ -1267,7 +1267,7 @@ public function generalize(GeneralizePrecision $precision): Type } if ($this->isList()->yes()) { - $arrayType = AccessoryArrayListType::intersectWith($arrayType); + $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } if (count($accessoryTypes) > 0) { @@ -1304,7 +1304,7 @@ public function generalizeToArray(): Type $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($this->isList->yes()) { - $arrayType = AccessoryArrayListType::intersectWith($arrayType); + $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return $arrayType; diff --git a/src/Type/Constant/ConstantArrayTypeBuilder.php b/src/Type/Constant/ConstantArrayTypeBuilder.php index a306833e8d..952254e1b9 100644 --- a/src/Type/Constant/ConstantArrayTypeBuilder.php +++ b/src/Type/Constant/ConstantArrayTypeBuilder.php @@ -306,7 +306,7 @@ public function getArray(): Type } if ($this->isList->yes()) { - $array = AccessoryArrayListType::intersectWith($array); + $array = TypeCombinator::intersect($array, new AccessoryArrayListType()); } return $array; diff --git a/src/Type/Constant/OversizedArrayBuilder.php b/src/Type/Constant/OversizedArrayBuilder.php index e6ac71ded5..026e305361 100644 --- a/src/Type/Constant/OversizedArrayBuilder.php +++ b/src/Type/Constant/OversizedArrayBuilder.php @@ -92,7 +92,7 @@ public function build(Array_ $expr, callable $getTypeCallback): Type $arrayType = new ArrayType($keyType, $valueType); if ($isList) { - $arrayType = AccessoryArrayListType::intersectWith($arrayType); + $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return TypeCombinator::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType()); diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index c45642f0d2..77d3f55bbc 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -177,7 +177,7 @@ public function getKeysArray(): Type return new ErrorType(); } - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new UnionType([new IntegerType(), new StringType()]))); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), new UnionType([new IntegerType(), new StringType()])), new AccessoryArrayListType()); } public function getValuesArray(): Type @@ -186,7 +186,7 @@ public function getValuesArray(): Type return new ErrorType(); } - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new MixedType($this->isExplicitMixed))); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), new MixedType($this->isExplicitMixed)), new AccessoryArrayListType()); } public function fillKeysArray(Type $valueType): Type @@ -258,7 +258,7 @@ public function shuffleArray(): Type return new ErrorType(); } - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new MixedType($this->isExplicitMixed))); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), new MixedType($this->isExplicitMixed)), new AccessoryArrayListType()); } public function isCallable(): TrinaryLogic diff --git a/src/Type/Php/ArrayChunkFunctionReturnTypeExtension.php b/src/Type/Php/ArrayChunkFunctionReturnTypeExtension.php index 1c8530ec3b..fbec2c7582 100644 --- a/src/Type/Php/ArrayChunkFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayChunkFunctionReturnTypeExtension.php @@ -83,7 +83,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $chunkType = self::getChunkType($arrayType, $preserveKeys); - $resultType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $chunkType)); + $resultType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $chunkType), new AccessoryArrayListType()); if ($arrayType->isIterableAtLeastOnce()->yes()) { $resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType()); } @@ -99,7 +99,7 @@ private static function getChunkType(Type $type, ?bool $preserveKeys): Type $chunkType = $type; } else { $chunkType = new ArrayType(new IntegerType(), $type->getIterableValueType()); - $chunkType = AccessoryArrayListType::intersectWith($chunkType); + $chunkType = TypeCombinator::intersect($chunkType, new AccessoryArrayListType()); } return TypeCombinator::intersect($chunkType, new NonEmptyArrayType()); diff --git a/src/Type/Php/ArrayColumnFunctionReturnTypeExtension.php b/src/Type/Php/ArrayColumnFunctionReturnTypeExtension.php index 7bca91ccd9..51d8999c2f 100644 --- a/src/Type/Php/ArrayColumnFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayColumnFunctionReturnTypeExtension.php @@ -99,7 +99,7 @@ private function handleAnyArray(Type $arrayType, Type $columnType, ?Type $indexT $returnType = TypeCombinator::intersect($returnType, new NonEmptyArrayType()); } if ($indexType === null) { - $returnType = AccessoryArrayListType::intersectWith($returnType); + $returnType = TypeCombinator::intersect($returnType, new AccessoryArrayListType()); } return $returnType; diff --git a/src/Type/Php/ArrayFillFunctionReturnTypeExtension.php b/src/Type/Php/ArrayFillFunctionReturnTypeExtension.php index 33ff1509e0..fbadbac593 100644 --- a/src/Type/Php/ArrayFillFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayFillFunctionReturnTypeExtension.php @@ -78,7 +78,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $resultType = new ArrayType(new IntegerType(), $valueType); if ((new ConstantIntegerType(0))->isSuperTypeOf($startIndexType)->yes()) { - $resultType = AccessoryArrayListType::intersectWith($resultType); + $resultType = TypeCombinator::intersect($resultType, new AccessoryArrayListType()); } if (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($numberType)->yes()) { $resultType = TypeCombinator::intersect($resultType, new NonEmptyArrayType()); diff --git a/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php b/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php index e8e9e3a457..5f8f7d1066 100644 --- a/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php @@ -94,7 +94,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, } $returnedArray = $returnedArrayBuilder->getArray(); if ($constantArray->isList()->yes()) { - $returnedArray = AccessoryArrayListType::intersectWith($returnedArray); + $returnedArray = TypeCombinator::intersect($returnedArray, new AccessoryArrayListType()); } $arrayTypes[] = $returnedArray; } diff --git a/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php b/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php index 5b177a9f68..58bb5fe1ad 100644 --- a/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php @@ -132,7 +132,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } if ($isList) { - $arrayType = AccessoryArrayListType::intersectWith($arrayType); + $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return $arrayType; diff --git a/src/Type/Php/ExplodeFunctionDynamicReturnTypeExtension.php b/src/Type/Php/ExplodeFunctionDynamicReturnTypeExtension.php index 9927cc252e..73f074aca6 100644 --- a/src/Type/Php/ExplodeFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/ExplodeFunctionDynamicReturnTypeExtension.php @@ -54,7 +54,7 @@ public function getTypeFromFunctionCall( return new ConstantBooleanType(false); } - $returnType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())); + $returnType = TypeCombinator::intersect(new ArrayType(new IntegerType(), new StringType()), new AccessoryArrayListType()); if ( !isset($args[2]) || IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($scope->getType($args[2]->value))->yes() diff --git a/src/Type/Php/FilterVarArrayDynamicReturnTypeExtension.php b/src/Type/Php/FilterVarArrayDynamicReturnTypeExtension.php index 2eaa4308b4..9f9a51cad3 100644 --- a/src/Type/Php/FilterVarArrayDynamicReturnTypeExtension.php +++ b/src/Type/Php/FilterVarArrayDynamicReturnTypeExtension.php @@ -88,7 +88,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, ); $arrayType = new ArrayType($inputArgType->getIterableKeyType(), $valueType); - return $isList ? AccessoryArrayListType::intersectWith($arrayType) : $arrayType; + return $isList ? TypeCombinator::intersect($arrayType, new AccessoryArrayListType()) : $arrayType; } // Override $add_empty option @@ -116,7 +116,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $addEmpty ? TypeCombinator::addNull($valueType) : $valueType, ); - return $isList ? AccessoryArrayListType::intersectWith($arrayType) : $arrayType; + return $isList ? TypeCombinator::intersect($arrayType, new AccessoryArrayListType()) : $arrayType; } return null; diff --git a/src/Type/Php/IteratorToArrayFunctionReturnTypeExtension.php b/src/Type/Php/IteratorToArrayFunctionReturnTypeExtension.php index 3eba789175..3d23ca59b2 100644 --- a/src/Type/Php/IteratorToArrayFunctionReturnTypeExtension.php +++ b/src/Type/Php/IteratorToArrayFunctionReturnTypeExtension.php @@ -10,6 +10,7 @@ use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\IntegerType; use PHPStan\Type\Type; +use PHPStan\Type\TypeCombinator; use function strtolower; final class IteratorToArrayFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension @@ -47,7 +48,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, ); if ($isList) { - $arrayType = AccessoryArrayListType::intersectWith($arrayType); + $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return $arrayType; diff --git a/src/Type/Php/PregSplitDynamicReturnTypeExtension.php b/src/Type/Php/PregSplitDynamicReturnTypeExtension.php index d898085584..d51b5314b0 100644 --- a/src/Type/Php/PregSplitDynamicReturnTypeExtension.php +++ b/src/Type/Php/PregSplitDynamicReturnTypeExtension.php @@ -43,7 +43,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, new IntegerType(), new ConstantArrayType([new ConstantIntegerType(0), new ConstantIntegerType(1)], [new StringType(), IntegerRangeType::fromInterval(0, null)], [2], [], TrinaryLogic::createYes()), ); - return TypeCombinator::union(AccessoryArrayListType::intersectWith($type), new ConstantBooleanType(false)); + return TypeCombinator::union(TypeCombinator::intersect($type, new AccessoryArrayListType()), new ConstantBooleanType(false)); } return null; diff --git a/src/Type/Php/RangeFunctionReturnTypeExtension.php b/src/Type/Php/RangeFunctionReturnTypeExtension.php index ed43f64f20..eec795c7ee 100644 --- a/src/Type/Php/RangeFunctionReturnTypeExtension.php +++ b/src/Type/Php/RangeFunctionReturnTypeExtension.php @@ -85,16 +85,17 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $startConstant = $endConstant; $endConstant = $tmp; } - return AccessoryArrayListType::intersectWith(TypeCombinator::intersect( + return TypeCombinator::intersect( new ArrayType( new IntegerType(), IntegerRangeType::fromInterval($startConstant->getValue(), $endConstant->getValue()), ), new NonEmptyArrayType(), - )); + new AccessoryArrayListType(), + ); } - return AccessoryArrayListType::intersectWith(TypeCombinator::intersect( + return TypeCombinator::intersect( new ArrayType( new IntegerType(), TypeCombinator::union( @@ -103,7 +104,8 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, ), ), new NonEmptyArrayType(), - )); + new AccessoryArrayListType(), + ); } $arrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach ($rangeValues as $value) { @@ -125,30 +127,30 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, if ($isInteger && $isStepInteger) { if ($argType instanceof IntegerRangeType) { - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $argType)); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), $argType), new AccessoryArrayListType()); } - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new IntegerType())); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), new IntegerType()), new AccessoryArrayListType()); } if ($argType->isFloat()->yes()) { - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new FloatType())); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), new FloatType()), new AccessoryArrayListType()); } $numberType = new UnionType([new IntegerType(), new FloatType()]); $isNumber = $numberType->isSuperTypeOf($argType)->yes(); $isNumericString = $argType->isNumericString()->yes(); if ($isNumber || $isNumericString) { - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $numberType)); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), $numberType), new AccessoryArrayListType()); } if ($argType->isString()->yes()) { - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), new StringType()), new AccessoryArrayListType()); } - return AccessoryArrayListType::intersectWith(new ArrayType( + return TypeCombinator::intersect(new ArrayType( new IntegerType(), new BenevolentUnionType([new IntegerType(), new FloatType(), new StringType()]), - )); + ), new AccessoryArrayListType()); } } diff --git a/src/Type/Php/RegexArrayShapeMatcher.php b/src/Type/Php/RegexArrayShapeMatcher.php index 63e44b3ea2..7923e9744c 100644 --- a/src/Type/Php/RegexArrayShapeMatcher.php +++ b/src/Type/Php/RegexArrayShapeMatcher.php @@ -354,7 +354,7 @@ private function buildArrayType( } if ($matchesAll && $this->containsSetOrder($flags)) { - $arrayType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $builder->getArray())); + $arrayType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $builder->getArray()), new AccessoryArrayListType()); if (!$wasMatched->yes()) { $arrayType = TypeCombinator::union( new ConstantArrayType([], []), @@ -382,7 +382,7 @@ private function createSubjectValueType(int $flags, bool $matchesAll): Type if ($matchesAll) { if ($this->containsPatternOrder($flags)) { - $subjectValueType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $subjectValueType)); + $subjectValueType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $subjectValueType), new AccessoryArrayListType()); } } @@ -433,7 +433,7 @@ private function createGroupValueType(RegexCapturingGroup $captureGroup, Trinary } if ($this->containsPatternOrder($flags)) { - $groupValueType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $groupValueType)); + $groupValueType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $groupValueType), new AccessoryArrayListType()); } return $groupValueType; diff --git a/src/Type/Php/StrSplitFunctionReturnTypeExtension.php b/src/Type/Php/StrSplitFunctionReturnTypeExtension.php index 34d58152dc..9c28bc3c69 100644 --- a/src/Type/Php/StrSplitFunctionReturnTypeExtension.php +++ b/src/Type/Php/StrSplitFunctionReturnTypeExtension.php @@ -103,7 +103,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, return TypeCombinator::union(...$results); } - $returnType = AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new StringType())); + $returnType = TypeCombinator::intersect(new ArrayType(new IntegerType(), new StringType()), new AccessoryArrayListType()); return $encoding === null && !$this->phpVersion->strSplitReturnsEmptyArray() ? TypeCombinator::intersect($returnType, new NonEmptyArrayType()) diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 745c1c2527..3d2edcc419 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -615,7 +615,7 @@ private static function processArrayAccessoryTypes(array $arrayTypes): array $constantArrays = $arrayType->getConstantArrays(); foreach ($constantArrays as $constantArray) { - if ($constantArray->isList()->yes() && AccessoryArrayListType::isListTypeEnabled()) { + if ($constantArray->isList()->yes()) { $list = new AccessoryArrayListType(); $accessoryTypes[$list->describe(VerbosityLevel::cache())][$i] = $list; } @@ -822,7 +822,7 @@ private static function optimizeConstantArrays(array $types): array $arrayType = new ArrayType($keyType, $valueType); if ($isList) { - $arrayType = AccessoryArrayListType::intersectWith($arrayType); + $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); } return TypeCombinator::intersect($arrayType, new NonEmptyArrayType(), new OversizedArrayType()); diff --git a/stubs/arrayFunctions.stub b/stubs/arrayFunctions.stub index 25c73249ec..4c28461391 100644 --- a/stubs/arrayFunctions.stub +++ b/stubs/arrayFunctions.stub @@ -64,6 +64,6 @@ function array_udiff( /** * @param array $value - * @return ($value is __always-list ? true : false) + * @return ($value is list ? true : false) */ function array_is_list(array $value): bool {} diff --git a/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php b/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php index 57cb091e19..f5511bfc33 100644 --- a/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php +++ b/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php @@ -11,6 +11,7 @@ use PHPStan\Reflection\Native\NativeParameterReflection; use PHPStan\Reflection\PassedByReference; use PHPStan\Testing\PHPStanTestCase; +use PHPStan\Type\Accessory\AccessoryArrayListType; use PHPStan\Type\ArrayType; use PHPStan\Type\BenevolentUnionType; use PHPStan\Type\BooleanType; @@ -22,6 +23,7 @@ use PHPStan\Type\FileTypeMapper; use PHPStan\Type\IntegerRangeType; use PHPStan\Type\IntegerType; +use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; @@ -98,9 +100,9 @@ public function dataFunctions(): array new ConstantStringType('errors'), ], [ IntegerRangeType::fromInterval(0, null), - new ArrayType(new IntegerType(), new StringType()), + new IntersectionType([new ArrayType(IntegerRangeType::fromInterval(0, null), new StringType()), new AccessoryArrayListType()]), IntegerRangeType::fromInterval(0, null), - new ArrayType(new IntegerType(), new StringType()), + new IntersectionType([new ArrayType(IntegerRangeType::fromInterval(0, null), new StringType()), new AccessoryArrayListType()]), ]), ]), new UnionType([ From 90da2bf1fb9477a47dd591018eddf555234f3234 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 17:43:45 +0200 Subject: [PATCH 121/508] Fix --- tests/PHPStan/Analyser/NodeScopeResolverTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 6ae400e802..8454435744 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -33,14 +33,14 @@ private static function findTestFiles(): iterable } if (PHP_VERSION_ID < 80000) { - yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4902.php'); + yield __DIR__ . '/data/bug-4902.php'; } if (PHP_VERSION_ID < 80300) { if (PHP_VERSION_ID >= 80200) { yield __DIR__ . '/data/mb-strlen-php82.php'; } elseif (PHP_VERSION_ID >= 80000) { - yield from $this->gatherAssertTypes(__DIR__ . '/data/mb-strlen-php8.php'); + yield __DIR__ . '/data/mb-strlen-php8.php'; } else { yield __DIR__ . '/data/mb-strlen-php73.php'; } From 1d517de1b9297a0e3cef0e10589458aad89d8cbe Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 16:11:41 +0200 Subject: [PATCH 122/508] Issue bot - let all comments about list type through --- issue-bot/src/Console/EvaluateCommand.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index 0f8d05a8d8..f18941039b 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,10 +158,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { - if (count($toPost) > 20) { - $output->writeln('Too many comments to post, something is probably wrong.'); - return 1; - } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From e5ad342b06374cf56e798a86b631bf9d25e18faa Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 16 Sep 2024 17:48:19 +0200 Subject: [PATCH 123/508] Revert "Issue bot - let all comments about list type through" This reverts commit 1d517de1b9297a0e3cef0e10589458aad89d8cbe. --- issue-bot/src/Console/EvaluateCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index f18941039b..0f8d05a8d8 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,6 +158,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { + if (count($toPost) > 20) { + $output->writeln('Too many comments to post, something is probably wrong.'); + return 1; + } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From f0b3d52184aa22e81c53ba6762c073f78be8374c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 17 Sep 2024 09:59:41 +0200 Subject: [PATCH 124/508] Dial back a bit --- src/Analyser/RuleErrorTransformer.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Analyser/RuleErrorTransformer.php b/src/Analyser/RuleErrorTransformer.php index 916f284505..b45ce15acd 100644 --- a/src/Analyser/RuleErrorTransformer.php +++ b/src/Analyser/RuleErrorTransformer.php @@ -8,6 +8,7 @@ use PHPStan\Rules\LineRuleError; use PHPStan\Rules\MetadataRuleError; use PHPStan\Rules\NonIgnorableRuleError; +use PHPStan\Rules\RuleError; use PHPStan\Rules\TipRuleError; final class RuleErrorTransformer @@ -17,7 +18,7 @@ final class RuleErrorTransformer * @param class-string $nodeType */ public function transform( - IdentifierRuleError $ruleError, + RuleError $ruleError, Scope $scope, string $nodeType, int $nodeLine, @@ -29,6 +30,7 @@ public function transform( $filePath = $scope->getFile(); $traitFilePath = null; $tip = null; + $identifier = null; $metadata = []; if ($scope->isInTrait()) { $traitReflection = $scope->getTraitReflection(); @@ -56,6 +58,10 @@ public function transform( $tip = $ruleError->getTip(); } + if ($ruleError instanceof IdentifierRuleError) { + $identifier = $ruleError->getIdentifier(); + } + if ($ruleError instanceof MetadataRuleError) { $metadata = $ruleError->getMetadata(); } @@ -74,7 +80,7 @@ public function transform( $tip, $nodeLine, $nodeType, - $ruleError->getIdentifier(), + $identifier, $metadata, ); } From aefc87a6cf9969ac1a361d5037981b78117b4f37 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 17 Sep 2024 10:18:33 +0200 Subject: [PATCH 125/508] Fix FileExcluder on Windows --- src/File/FileExcluder.php | 4 +++- tests/PHPStan/File/FileExcluderTest.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/File/FileExcluder.php b/src/File/FileExcluder.php index 7ebb938302..ba314cbb67 100644 --- a/src/File/FileExcluder.php +++ b/src/File/FileExcluder.php @@ -50,7 +50,7 @@ final class FileExcluder * @param string[] $analyseExcludes */ public function __construct( - FileHelper $fileHelper, + private FileHelper $fileHelper, array $analyseExcludes, ) { @@ -89,6 +89,8 @@ public function __construct( public function isExcludedFromAnalysing(string $file): bool { + $file = $this->fileHelper->normalizePath($file); + foreach ($this->literalAnalyseExcludes as $exclude) { if (str_starts_with($file, $exclude)) { return true; diff --git a/tests/PHPStan/File/FileExcluderTest.php b/tests/PHPStan/File/FileExcluderTest.php index 860b779e75..3c2d150290 100644 --- a/tests/PHPStan/File/FileExcluderTest.php +++ b/tests/PHPStan/File/FileExcluderTest.php @@ -64,7 +64,7 @@ public function dataExcludeOnWindows(): array ], [ __DIR__ . '\data\parse-error.php', - ['tests/PHPStan/File/data/*'], + ['*/tests/PHPStan/File/data/*'], true, ], [ From 8f2307e83c80a095af7554631da0c7876565a41b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Thu, 19 Sep 2024 09:22:18 +0200 Subject: [PATCH 126/508] Display parent class name for anonymous class like native php does --- .../BetterReflectionProvider.php | 16 +++++- .../Analyser/AnalyserIntegrationTest.php | 4 +- .../PHPStan/Levels/data/stubValidator-0.json | 4 +- .../AnonymousClassReflectionTest.php | 49 +++++++++++++++++++ .../Reflection/data/anonymous-classes.php | 20 ++++++++ .../Classes/RequireImplementsRuleTest.php | 2 +- .../MissingMethodImplementationRuleTest.php | 2 +- .../MissingReadOnlyPropertyAssignRuleTest.php | 2 +- 8 files changed, 90 insertions(+), 9 deletions(-) diff --git a/src/Reflection/BetterReflection/BetterReflectionProvider.php b/src/Reflection/BetterReflection/BetterReflectionProvider.php index 54b26ec9f8..be27dd03a0 100644 --- a/src/Reflection/BetterReflection/BetterReflectionProvider.php +++ b/src/Reflection/BetterReflection/BetterReflectionProvider.php @@ -51,6 +51,7 @@ use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Type; use function array_key_exists; +use function array_key_first; use function array_map; use function base64_decode; use function in_array; @@ -217,12 +218,23 @@ public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $ null, ); + $displayParentName = $reflectionClass->getParentClassName(); + if ($displayParentName === null) { + // https://3v4l.org/6FBuP + $classInterfaceNames = $reflectionClass->getInterfaceNames(); + if ($classInterfaceNames !== []) { + $displayParentName = $classInterfaceNames[array_key_first($classInterfaceNames)]; + } else { + $displayParentName = 'class'; + } + } + /** @var int|null $classLineIndex */ $classLineIndex = $classNode->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX); if ($classLineIndex === null) { - $displayName = sprintf('class@anonymous/%s:%s', $filename, $classNode->getStartLine()); + $displayName = sprintf('%s@anonymous/%s:%s', $displayParentName, $filename, $classNode->getStartLine()); } else { - $displayName = sprintf('class@anonymous/%s:%s:%d', $filename, $classNode->getStartLine(), $classLineIndex); + $displayName = sprintf('%s@anonymous/%s:%s:%d', $displayParentName, $filename, $classNode->getStartLine(), $classLineIndex); } self::$anonymousClasses[$className] = new ClassReflection( diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 6fb9c0f411..207ff22e0b 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -541,9 +541,9 @@ public function testBug6442(): void { $errors = $this->runAnalyse(__DIR__ . '/data/bug-6442.php'); $this->assertCount(2, $errors); - $this->assertSame('Dumped type: \'Bug6442\\\A\'', $errors[0]->getMessage()); + $this->assertSame('Dumped type: \'Bug6442\\\B\'', $errors[0]->getMessage()); $this->assertSame(9, $errors[0]->getLine()); - $this->assertSame('Dumped type: \'Bug6442\\\B\'', $errors[1]->getMessage()); + $this->assertSame('Dumped type: \'Bug6442\\\A\'', $errors[1]->getMessage()); $this->assertSame(9, $errors[1]->getLine()); } diff --git a/tests/PHPStan/Levels/data/stubValidator-0.json b/tests/PHPStan/Levels/data/stubValidator-0.json index 0517d298af..ce13d6e997 100644 --- a/tests/PHPStan/Levels/data/stubValidator-0.json +++ b/tests/PHPStan/Levels/data/stubValidator-0.json @@ -20,12 +20,12 @@ "ignorable": false }, { - "message": "Method class@anonymous/stubValidator/stubs.php:27::doFoo() has no return type specified.", + "message": "Method ArrayIterator@anonymous/stubValidator/stubs.php:27::doFoo() has no return type specified.", "line": 30, "ignorable": false }, { - "message": "Parameter $foo of method class@anonymous/stubValidator/stubs.php:27::doFoo() has invalid type StubValidator\\Foooooooo.", + "message": "Parameter $foo of method ArrayIterator@anonymous/stubValidator/stubs.php:27::doFoo() has invalid type StubValidator\\Foooooooo.", "line": 30, "ignorable": false } diff --git a/tests/PHPStan/Reflection/AnonymousClassReflectionTest.php b/tests/PHPStan/Reflection/AnonymousClassReflectionTest.php index 9310f617f1..b6ee413032 100644 --- a/tests/PHPStan/Reflection/AnonymousClassReflectionTest.php +++ b/tests/PHPStan/Reflection/AnonymousClassReflectionTest.php @@ -101,6 +101,55 @@ public function testReflection(): void ]), 9, ], + [ + implode("\n", [ + 'name: AnonymousClass1d622e3ff3a656e68d55eafbd25eaef1', + 'display name: AnonymousClassReflectionTest\A@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:17:1', + ]), + 17, + ], + [ + implode("\n", [ + 'name: AnonymousClass6e1acc8e948827c8d0439a2225fdbdd0', + 'display name: AnonymousClassReflectionTest\A@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:17:2', + ]), + 17, + ], + [ + implode("\n", [ + 'name: AnonymousClass2a49db3d44479dddd8beaea4ea8131fb', + 'display name: AnonymousClassReflectionTest\A@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:19:1', + ]), + 19, + ], + [ + implode("\n", [ + 'name: AnonymousClass337463cf86ee25e526f445630960b336', + 'display name: AnonymousClassReflectionTest\A@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:19:2', + ]), + 19, + ], + [ + implode("\n", [ + 'name: AnonymousClassda3e79cc45f826d60295f848abab37e7', + 'display name: AnonymousClassReflectionTest\U@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:29', + ]), + 29, + ], + [ + implode("\n", [ + 'name: AnonymousClassc06612bf3776bbe5e50870a8c3151186', + 'display name: AnonymousClassReflectionTest\U@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:31', + ]), + 31, + ], + [ + implode("\n", [ + 'name: AnonymousClassbee6eba8c721d73d649fcc9d361f5902', + 'display name: AnonymousClassReflectionTest\V@anonymous/tests/PHPStan/Reflection/data/anonymous-classes.php:33', + ]), + 33, + ], ]); } diff --git a/tests/PHPStan/Reflection/data/anonymous-classes.php b/tests/PHPStan/Reflection/data/anonymous-classes.php index 9336316ff9..4024445aec 100644 --- a/tests/PHPStan/Reflection/data/anonymous-classes.php +++ b/tests/PHPStan/Reflection/data/anonymous-classes.php @@ -11,3 +11,23 @@ public function __construct(object $object) { } }; + +class A {} + +new class extends A {}; new class extends A {}; + +new class (new class extends A {}) extends A { + public function __construct(object $object) + { + } +}; + +interface U {} + +interface V {} + +new class implements U {}; + +new class implements U, V {}; + +new class implements V, U {}; diff --git a/tests/PHPStan/Rules/Classes/RequireImplementsRuleTest.php b/tests/PHPStan/Rules/Classes/RequireImplementsRuleTest.php index a2fe9cf7a3..6a147e9398 100644 --- a/tests/PHPStan/Rules/Classes/RequireImplementsRuleTest.php +++ b/tests/PHPStan/Rules/Classes/RequireImplementsRuleTest.php @@ -57,7 +57,7 @@ public function testRule(): void 137, ], [ - 'Trait IncompatibleRequireImplements\ValidPsalmTrait requires using class to implement IncompatibleRequireImplements\RequiredInterface2, but class@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-implements.php:164 does not.', + 'Trait IncompatibleRequireImplements\ValidPsalmTrait requires using class to implement IncompatibleRequireImplements\RequiredInterface2, but IncompatibleRequireImplements\RequiredInterface@anonymous/tests/PHPStan/Rules/PhpDoc/data/incompatible-require-implements.php:164 does not.', 164, ], [ diff --git a/tests/PHPStan/Rules/Methods/MissingMethodImplementationRuleTest.php b/tests/PHPStan/Rules/Methods/MissingMethodImplementationRuleTest.php index 82240f467e..babaadaae2 100644 --- a/tests/PHPStan/Rules/Methods/MissingMethodImplementationRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MissingMethodImplementationRuleTest.php @@ -29,7 +29,7 @@ public function testRule(): void 24, ], [ - 'Non-abstract class class@anonymous/tests/PHPStan/Rules/Methods/data/missing-method-impl.php:41 contains abstract method doFoo() from interface MissingMethodImpl\Foo.', + 'Non-abstract class MissingMethodImpl\Foo@anonymous/tests/PHPStan/Rules/Methods/data/missing-method-impl.php:41 contains abstract method doFoo() from interface MissingMethodImpl\Foo.', 41, ], ]); diff --git a/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php b/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php index 02e81f3f55..3b481b8f14 100644 --- a/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php +++ b/tests/PHPStan/Rules/Properties/MissingReadOnlyPropertyAssignRuleTest.php @@ -307,7 +307,7 @@ public function testRedeclaredReadonlyProperties(): void 70, ], [ - 'Readonly property class@anonymous/tests/PHPStan/Rules/Properties/data/redeclare-readonly-property.php:117::$myProp is already assigned.', + 'Readonly property RedeclareReadonlyProperty\A@anonymous/tests/PHPStan/Rules/Properties/data/redeclare-readonly-property.php:117::$myProp is already assigned.', 121, ], [ From 105b9faa81e0b75483ddcfecdbbeca1ee7289b2c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 22 Sep 2024 13:01:31 +0200 Subject: [PATCH 127/508] Fix build --- .../Rules/Generics/MethodSignatureVarianceRuleTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/PHPStan/Rules/Generics/MethodSignatureVarianceRuleTest.php b/tests/PHPStan/Rules/Generics/MethodSignatureVarianceRuleTest.php index f01b15ba3d..ec893f0947 100644 --- a/tests/PHPStan/Rules/Generics/MethodSignatureVarianceRuleTest.php +++ b/tests/PHPStan/Rules/Generics/MethodSignatureVarianceRuleTest.php @@ -4,6 +4,7 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -236,6 +237,10 @@ public function testPr2465(): void public function testBug10609(): void { + if (PHP_VERSION_ID < 80000) { + self::markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/bug-10609.php'], [ [ 'Template type A is declared as covariant, but occurs in contravariant position in parameter fn of method Bug10609\Collection::tap().', From fac4b0af6dd70d2fffc4563750d612cb0de17430 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 22 Sep 2024 17:39:41 +0200 Subject: [PATCH 128/508] Regression tests Closes https://github.com/phpstan/phpstan/issues/11709 Closes https://github.com/phpstan/phpstan/issues/9524 --- .../Analyser/AnalyserIntegrationTest.php | 10 +++++++ tests/PHPStan/Analyser/data/bug-11709.php | 28 +++++++++++++++++++ .../Methods/OverridingMethodRuleTest.php | 6 ++++ tests/PHPStan/Rules/Methods/data/bug-9524.php | 11 ++++++++ 4 files changed, 55 insertions(+) create mode 100644 tests/PHPStan/Analyser/data/bug-11709.php create mode 100644 tests/PHPStan/Rules/Methods/data/bug-9524.php diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 207ff22e0b..38afaf662d 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -1455,6 +1455,16 @@ public function testBug11640(): void $this->assertNoErrors($errors); } + public function testBug11709(): void + { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0.'); + } + + $errors = $this->runAnalyse(__DIR__ . '/data/bug-11709.php'); + $this->assertNoErrors($errors); + } + /** * @param string[]|null $allAnalysedFiles * @return Error[] diff --git a/tests/PHPStan/Analyser/data/bug-11709.php b/tests/PHPStan/Analyser/data/bug-11709.php new file mode 100644 index 0000000000..2515e3dcb8 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-11709.php @@ -0,0 +1,28 @@ + : mixed) $value + * @phpstan-assert array $value + */ +function isArrayWithStringKeys(mixed $value): void +{ + if (!is_array($value)) { + throw new \Exception('Not an array'); + } + + foreach (array_keys($value) as $key) { + if (!is_string($key)) { + throw new \Exception('Non-string key'); + } + } +} + +function ($m): void { + isArrayWithStringKeys($m); + assertType('array', $m); +}; diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index 916532a7b9..dd90432f8f 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -808,4 +808,10 @@ public function testBug10165(): void $this->analyse([__DIR__ . '/data/bug-10165.php'], []); } + public function testBug9524(): void + { + $this->phpVersionId = PHP_VERSION_ID; + $this->analyse([__DIR__ . '/data/bug-9524.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-9524.php b/tests/PHPStan/Rules/Methods/data/bug-9524.php new file mode 100644 index 0000000000..9713e71a61 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-9524.php @@ -0,0 +1,11 @@ + Date: Sun, 22 Sep 2024 20:50:12 +0200 Subject: [PATCH 129/508] [BE] New RuleLevelHelper behaviour --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 2 - conf/parametersSchema.neon | 1 - phpstan-baseline.neon | 5 - src/Rules/RuleLevelHelper.php | 309 ++++-------------- .../Analyser/Bug9307CallMethodsRuleTest.php | 2 +- .../Arrays/AppendedArrayItemTypeRuleTest.php | 2 +- .../Arrays/ArrayDestructuringRuleTest.php | 2 +- .../Rules/Arrays/ArrayUnpackingRuleTest.php | 2 +- .../InvalidKeyInArrayDimFetchRuleTest.php | 2 +- .../Arrays/IterableInForeachRuleTest.php | 2 +- ...nexistentOffsetInArrayDimFetchRuleTest.php | 2 +- .../Arrays/OffsetAccessAssignOpRuleTest.php | 2 +- .../Arrays/OffsetAccessAssignmentRuleTest.php | 2 +- .../OffsetAccessValueAssignmentRuleTest.php | 2 +- .../Arrays/UnpackIterableInArrayRuleTest.php | 2 +- tests/PHPStan/Rules/Cast/EchoRuleTest.php | 2 +- .../Rules/Cast/InvalidCastRuleTest.php | 2 +- .../InvalidPartOfEncapsedStringRuleTest.php | 2 +- tests/PHPStan/Rules/Cast/PrintRuleTest.php | 2 +- .../Rules/Classes/ClassAttributesRuleTest.php | 2 +- .../ClassConstantAttributesRuleTest.php | 2 +- .../Rules/Classes/ClassConstantRuleTest.php | 2 +- .../ForbiddenNameCheckExtensionRuleTest.php | 2 +- .../Rules/Classes/InstantiationRuleTest.php | 2 +- .../DynamicClassConstantFetchRuleTest.php | 2 +- .../EnumCases/EnumCaseAttributesRuleTest.php | 2 +- .../Exceptions/ThrowExprTypeRuleTest.php | 2 +- .../ArrowFunctionAttributesRuleTest.php | 2 +- .../ArrowFunctionReturnTypeRuleTest.php | 1 - .../Rules/Functions/CallCallablesRuleTest.php | 2 +- .../CallToFunctionParametersRuleTest.php | 2 +- .../Rules/Functions/CallUserFuncRuleTest.php | 2 +- .../Functions/ClosureAttributesRuleTest.php | 2 +- .../Functions/ClosureReturnTypeRuleTest.php | 2 +- .../Functions/FunctionAttributesRuleTest.php | 2 +- .../Functions/FunctionCallableRuleTest.php | 2 +- ...plodeParameterCastableToStringRuleTest.php | 2 +- .../Functions/ParamAttributesRuleTest.php | 2 +- .../ParameterCastableToStringRuleTest.php | 2 +- .../Rules/Functions/ReturnTypeRuleTest.php | 2 +- .../SortParameterCastableToStringRuleTest.php | 2 +- .../Generators/YieldFromTypeRuleTest.php | 2 +- .../Rules/Generators/YieldTypeRuleTest.php | 2 +- .../Rules/Methods/CallMethodsRuleTest.php | 2 +- .../Methods/CallStaticMethodsRuleTest.php | 2 +- ...hodStatementWithoutSideEffectsRuleTest.php | 2 +- ...hodStatementWithoutSideEffectsRuleTest.php | 2 +- .../Methods/MethodAttributesRuleTest.php | 2 +- .../Rules/Methods/MethodCallableRuleTest.php | 2 +- .../Rules/Methods/ReturnTypeRuleTest.php | 2 +- .../Methods/StaticMethodCallableRuleTest.php | 2 +- .../InvalidBinaryOperationRuleTest.php | 2 +- .../InvalidComparisonOperationRuleTest.php | 2 +- .../InvalidIncDecOperationRuleTest.php | 2 +- .../InvalidUnaryOperationRuleTest.php | 2 +- .../AccessPropertiesInAssignRuleTest.php | 2 +- .../Properties/AccessPropertiesRuleTest.php | 2 +- ...AccessStaticPropertiesInAssignRuleTest.php | 2 +- .../AccessStaticPropertiesRuleTest.php | 2 +- .../PHPStan/Rules/Properties/Bug7074Test.php | 2 +- ...ValueTypesAssignedToPropertiesRuleTest.php | 2 +- .../Properties/PropertyAttributesRuleTest.php | 2 +- .../ReadingWriteOnlyPropertiesRuleTest.php | 2 +- .../TypesAssignedToPropertiesRuleTest.php | 2 +- .../WritingToReadOnlyPropertiesRuleTest.php | 2 +- .../ParameterOutAssignedTypeRuleTest.php | 2 +- .../ParameterOutExecutionEndTypeRuleTest.php | 2 +- .../Variables/VariableCloningRuleTest.php | 2 +- 70 files changed, 120 insertions(+), 327 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 643a7a532f..8538dba4fe 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -45,7 +45,6 @@ Bleeding edge (TODO move to other sections) * Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed * IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) -* New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23) * Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 * Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) * Stricter function signature map (https://github.com/phpstan/phpstan-src/commit/06b746d8e72cc0843707896ec161559bb6a81137, [#2163](https://github.com/phpstan/phpstan-src/pull/2163)), #7239, thanks @staabm! @@ -140,6 +139,7 @@ Improvements 🔧 * Returning plain strings as errors no longer supported, use RuleErrorBuilder * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) * Require identifier in custom rules (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) +* New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 177fbdc689..246fdc091a 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -32,7 +32,6 @@ parameters: disableUnreachableBranchesRules: true varTagType: true closureDefaultParameterTypeRule: true - newRuleLevelHelper: true instanceofType: true paramOutVariance: true strictStaticMethodTemplateTypeVariance: true diff --git a/conf/config.neon b/conf/config.neon index 88e6800df0..f2904ef641 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -67,7 +67,6 @@ parameters: disableUnreachableBranchesRules: false varTagType: false closureDefaultParameterTypeRule: false - newRuleLevelHelper: false instanceofType: false paramOutVariance: false @@ -1124,7 +1123,6 @@ services: checkUnionTypes: %checkUnionTypes% checkExplicitMixed: %checkExplicitMixed% checkImplicitMixed: %checkImplicitMixed% - newRuleLevelHelper: %featureToggles.newRuleLevelHelper% checkBenevolentUnionTypes: %checkBenevolentUnionTypes% - diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index b54bad125d..c5caacdd84 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -62,7 +62,6 @@ parametersSchema: disableUnreachableBranchesRules: bool() varTagType: bool() closureDefaultParameterTypeRule: bool() - newRuleLevelHelper: bool() instanceofType: bool() paramOutVariance: bool() strictStaticMethodTemplateTypeVariance: bool() diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index dc567692e9..69cef6f30e 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -621,11 +621,6 @@ parameters: count: 1 path: src/Rules/RuleLevelHelper.php - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" - count: 2 - path: src/Rules/RuleLevelHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" count: 1 diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php index 0f15683606..9869c16c62 100644 --- a/src/Rules/RuleLevelHelper.php +++ b/src/Rules/RuleLevelHelper.php @@ -15,7 +15,6 @@ use PHPStan\Type\NeverType; use PHPStan\Type\NullType; use PHPStan\Type\ObjectWithoutClassType; -use PHPStan\Type\StaticType; use PHPStan\Type\StrictMixedType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -23,7 +22,6 @@ use PHPStan\Type\TypeUtils; use PHPStan\Type\UnionType; use PHPStan\Type\VerbosityLevel; -use function array_merge; use function count; use function sprintf; use function str_contains; @@ -38,7 +36,6 @@ public function __construct( private bool $checkUnionTypes, private bool $checkExplicitMixed, private bool $checkImplicitMixed, - private bool $newRuleLevelHelper, private bool $checkBenevolentUnionTypes, ) { @@ -64,10 +61,6 @@ private function transformCommonType(Type $type): Type return TypeTraverser::map($type, function (Type $type, callable $traverse) { if ($type instanceof TemplateMixedType) { - if (!$this->newRuleLevelHelper) { - return $type->toStrictMixedType(); - } - if ($this->checkExplicitMixed) { return $type->toStrictMixedType(); } @@ -154,148 +147,10 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType): public function acceptsWithReason(Type $acceptingType, Type $acceptedType, bool $strictTypes): RuleLevelHelperAcceptsResult { - if ($this->newRuleLevelHelper) { - [$acceptedType, $checkForUnion] = $this->transformAcceptedType($acceptingType, $acceptedType); - $acceptingType = $this->transformCommonType($acceptingType); - - $accepts = $acceptingType->acceptsWithReason($acceptedType, $strictTypes); - - return new RuleLevelHelperAcceptsResult( - $checkForUnion ? $accepts->yes() : !$accepts->no(), - $accepts->reasons, - ); - } - - $checkForUnion = $this->checkUnionTypes; - - if ($this->checkBenevolentUnionTypes) { - $traverse = static function (Type $type, callable $traverse) use (&$checkForUnion): Type { - if ($type instanceof BenevolentUnionType) { - $checkForUnion = true; - return TypeUtils::toStrictUnion($type); - } - - return $traverse($type); - }; - - $acceptedType = TypeTraverser::map($acceptedType, $traverse); - } - - if ( - $this->checkExplicitMixed - ) { - $traverse = static function (Type $type, callable $traverse): Type { - if ($type instanceof TemplateMixedType) { - return $type->toStrictMixedType(); - } - if ( - $type instanceof MixedType - && $type->isExplicitMixed() - ) { - return new StrictMixedType(); - } - - return $traverse($type); - }; - $acceptingType = TypeTraverser::map($acceptingType, $traverse); - $acceptedType = TypeTraverser::map($acceptedType, $traverse); - } - - if ( - $this->checkImplicitMixed - ) { - $traverse = static function (Type $type, callable $traverse): Type { - if ($type instanceof TemplateMixedType) { - return $type->toStrictMixedType(); - } - if ( - $type instanceof MixedType - && !$type->isExplicitMixed() - ) { - return new StrictMixedType(); - } - - return $traverse($type); - }; - $acceptingType = TypeTraverser::map($acceptingType, $traverse); - $acceptedType = TypeTraverser::map($acceptedType, $traverse); - } - - if ( - !$this->checkNullables - && !$acceptingType instanceof NullType - && !$acceptedType instanceof NullType - && !$acceptedType instanceof BenevolentUnionType - ) { - $acceptedType = TypeCombinator::removeNull($acceptedType); - } + [$acceptedType, $checkForUnion] = $this->transformAcceptedType($acceptingType, $acceptedType); + $acceptingType = $this->transformCommonType($acceptingType); $accepts = $acceptingType->acceptsWithReason($acceptedType, $strictTypes); - if ($accepts->yes()) { - return new RuleLevelHelperAcceptsResult(true, $accepts->reasons); - } - if ($acceptingType instanceof UnionType) { - $reasons = []; - foreach ($acceptingType->getTypes() as $innerType) { - $accepts = self::acceptsWithReason($innerType, $acceptedType, $strictTypes); - if ($accepts->result) { - return $accepts; - } - - $reasons = array_merge($reasons, $accepts->reasons); - } - - return new RuleLevelHelperAcceptsResult(false, $reasons); - } - - if ( - $acceptedType->isArray()->yes() - && $acceptingType->isArray()->yes() - && ( - $acceptedType->isConstantArray()->no() - || !$acceptedType->isIterableAtLeastOnce()->no() - ) - && $acceptingType->isConstantArray()->no() - ) { - if ($acceptingType->isIterableAtLeastOnce()->yes() && !$acceptedType->isIterableAtLeastOnce()->yes()) { - $verbosity = VerbosityLevel::getRecommendedLevelByType($acceptingType, $acceptedType); - return new RuleLevelHelperAcceptsResult(false, [ - sprintf( - '%s %s empty.', - $acceptedType->describe($verbosity), - $acceptedType->isIterableAtLeastOnce()->no() ? 'is' : 'might be', - ), - ]); - } - - if ( - $acceptingType->isList()->yes() - && !$acceptedType->isList()->yes() - ) { - $report = $checkForUnion || $acceptedType->isList()->no(); - - if ($report) { - $verbosity = VerbosityLevel::getRecommendedLevelByType($acceptingType, $acceptedType); - return new RuleLevelHelperAcceptsResult(false, [ - sprintf( - '%s %s a list.', - $acceptedType->describe($verbosity), - $acceptedType->isList()->no() ? 'is not' : 'might not be', - ), - ]); - } - } - - return self::acceptsWithReason( - $acceptingType->getIterableKeyType(), - $acceptedType->getIterableKeyType(), - $strictTypes, - )->and(self::acceptsWithReason( - $acceptingType->getIterableValueType(), - $acceptedType->getIterableValueType(), - $strictTypes, - )); - } return new RuleLevelHelperAcceptsResult( $checkForUnion ? $accepts->yes() : !$accepts->no(), @@ -336,49 +191,24 @@ private function findTypeToCheckImplementation( $type = TypeCombinator::removeNull($type); } - if ($this->newRuleLevelHelper) { - if ( - ($this->checkExplicitMixed || $this->checkImplicitMixed) - && $type instanceof MixedType - && ($type->isExplicitMixed() ? $this->checkExplicitMixed : $this->checkImplicitMixed) - ) { - return new FoundTypeResult( - $type instanceof TemplateMixedType - ? $type->toStrictMixedType() - : new StrictMixedType(), - [], - [], - null, - ); - } - } else { - if ( - $this->checkExplicitMixed - && $type instanceof MixedType - && !$type instanceof TemplateMixedType - && $type->isExplicitMixed() - ) { - return new FoundTypeResult(new StrictMixedType(), [], [], null); - } - - if ( - $this->checkImplicitMixed - && $type instanceof MixedType - && !$type instanceof TemplateMixedType - && !$type->isExplicitMixed() - ) { - return new FoundTypeResult(new StrictMixedType(), [], [], null); - } + if ( + ($this->checkExplicitMixed || $this->checkImplicitMixed) + && $type instanceof MixedType + && ($type->isExplicitMixed() ? $this->checkExplicitMixed : $this->checkImplicitMixed) + ) { + return new FoundTypeResult( + $type instanceof TemplateMixedType + ? $type->toStrictMixedType() + : new StrictMixedType(), + [], + [], + null, + ); } if ($type instanceof MixedType || $type instanceof NeverType) { return new FoundTypeResult(new ErrorType(), [], [], null); } - if (!$this->newRuleLevelHelper) { - if ($isTopLevel && $type instanceof StaticType) { - $type = $type->getStaticObjectType(); - } - } $errors = []; $hasClassExistsClass = false; @@ -415,85 +245,58 @@ private function findTypeToCheckImplementation( return new FoundTypeResult(new ErrorType(), [], [], null); } - if ($this->newRuleLevelHelper) { - if ($type instanceof UnionType) { - $shouldFilterUnion = ( - !$this->checkUnionTypes - && !$type instanceof BenevolentUnionType - ) || ( - !$this->checkBenevolentUnionTypes - && $type instanceof BenevolentUnionType - ); - - $newTypes = []; + if ($type instanceof UnionType) { + $shouldFilterUnion = ( + !$this->checkUnionTypes + && !$type instanceof BenevolentUnionType + ) || ( + !$this->checkBenevolentUnionTypes + && $type instanceof BenevolentUnionType + ); - foreach ($type->getTypes() as $innerType) { - if ($shouldFilterUnion && !$unionTypeCriteriaCallback($innerType)) { - continue; - } + $newTypes = []; - $newTypes[] = $this->findTypeToCheckImplementation( - $scope, - $var, - $innerType, - $unknownClassErrorPattern, - $unionTypeCriteriaCallback, - )->getType(); + foreach ($type->getTypes() as $innerType) { + if ($shouldFilterUnion && !$unionTypeCriteriaCallback($innerType)) { + continue; } - if (count($newTypes) > 0) { - $newUnion = TypeCombinator::union(...$newTypes); - if ( - !$this->checkBenevolentUnionTypes - && $type instanceof BenevolentUnionType - ) { - $newUnion = TypeUtils::toBenevolentUnion($newUnion); - } - - return new FoundTypeResult($newUnion, $directClassNames, [], null); - } + $newTypes[] = $this->findTypeToCheckImplementation( + $scope, + $var, + $innerType, + $unknownClassErrorPattern, + $unionTypeCriteriaCallback, + )->getType(); } - if ($type instanceof IntersectionType) { - $newTypes = []; - - foreach ($type->getTypes() as $innerType) { - $newTypes[] = $this->findTypeToCheckImplementation( - $scope, - $var, - $innerType, - $unknownClassErrorPattern, - $unionTypeCriteriaCallback, - )->getType(); - } - - return new FoundTypeResult(TypeCombinator::intersect(...$newTypes), $directClassNames, [], null); - } - } else { - if ( - ( - !$this->checkUnionTypes - && $type instanceof UnionType - && !$type instanceof BenevolentUnionType - ) || ( + if (count($newTypes) > 0) { + $newUnion = TypeCombinator::union(...$newTypes); + if ( !$this->checkBenevolentUnionTypes && $type instanceof BenevolentUnionType - ) - ) { - $newTypes = []; - - foreach ($type->getTypes() as $innerType) { - if (!$unionTypeCriteriaCallback($innerType)) { - continue; - } - - $newTypes[] = $innerType; + ) { + $newUnion = TypeUtils::toBenevolentUnion($newUnion); } - if (count($newTypes) > 0) { - return new FoundTypeResult(TypeCombinator::union(...$newTypes), $directClassNames, [], null); - } + return new FoundTypeResult($newUnion, $directClassNames, [], null); + } + } + + if ($type instanceof IntersectionType) { + $newTypes = []; + + foreach ($type->getTypes() as $innerType) { + $newTypes[] = $this->findTypeToCheckImplementation( + $scope, + $var, + $innerType, + $unknownClassErrorPattern, + $unionTypeCriteriaCallback, + )->getType(); } + + return new FoundTypeResult(TypeCombinator::intersect(...$newTypes), $directClassNames, [], null); } $tip = null; diff --git a/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php b/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php index ff0a0daa9e..c7b4f688a3 100644 --- a/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php +++ b/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php @@ -23,7 +23,7 @@ class Bug9307CallMethodsRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, true, false, true, false); + $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false); return new CallMethodsRule( new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true), new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion(PHP_VERSION_ID), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), diff --git a/tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php b/tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php index ea09ce0cb4..3a6c6dfb4f 100644 --- a/tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php @@ -17,7 +17,7 @@ protected function getRule(): Rule { return new AppendedArrayItemTypeRule( new PropertyReflectionFinder(), - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), ); } diff --git a/tests/PHPStan/Rules/Arrays/ArrayDestructuringRuleTest.php b/tests/PHPStan/Rules/Arrays/ArrayDestructuringRuleTest.php index a536ce6cf5..840da52b49 100644 --- a/tests/PHPStan/Rules/Arrays/ArrayDestructuringRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/ArrayDestructuringRuleTest.php @@ -17,7 +17,7 @@ class ArrayDestructuringRuleTest extends RuleTestCase protected function getRule(): Rule { - $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false); + $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false); return new ArrayDestructuringRule( $ruleLevelHelper, diff --git a/tests/PHPStan/Rules/Arrays/ArrayUnpackingRuleTest.php b/tests/PHPStan/Rules/Arrays/ArrayUnpackingRuleTest.php index b733df51cd..cb14b900fe 100644 --- a/tests/PHPStan/Rules/Arrays/ArrayUnpackingRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/ArrayUnpackingRuleTest.php @@ -22,7 +22,7 @@ protected function getRule(): Rule { return new ArrayUnpackingRule( self::getContainer()->getByType(PhpVersion::class), - new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnions, false, false, true, $this->checkBenevolentUnions), + new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnions, false, false, $this->checkBenevolentUnions), ); } diff --git a/tests/PHPStan/Rules/Arrays/InvalidKeyInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/InvalidKeyInArrayDimFetchRuleTest.php index 70c671135a..df337d9bdf 100644 --- a/tests/PHPStan/Rules/Arrays/InvalidKeyInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/InvalidKeyInArrayDimFetchRuleTest.php @@ -15,7 +15,7 @@ class InvalidKeyInArrayDimFetchRuleTest extends RuleTestCase protected function getRule(): Rule { - $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false); + $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false); return new InvalidKeyInArrayDimFetchRule($ruleLevelHelper, true); } diff --git a/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php b/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php index 31407e99be..c83001b6a8 100644 --- a/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php @@ -21,7 +21,7 @@ class IterableInForeachRuleTest extends RuleTestCase protected function getRule(): Rule { - return new IterableInForeachRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false)); + return new IterableInForeachRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false)); } public function testCheckWithMaybes(): void diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index 8e0127cf5d..f7fa3224f9 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -25,7 +25,7 @@ class NonexistentOffsetInArrayDimFetchRuleTest extends RuleTestCase protected function getRule(): Rule { - $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false); + $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false); return new NonexistentOffsetInArrayDimFetchRule( $ruleLevelHelper, diff --git a/tests/PHPStan/Rules/Arrays/OffsetAccessAssignOpRuleTest.php b/tests/PHPStan/Rules/Arrays/OffsetAccessAssignOpRuleTest.php index 2daf7b7ed4..45750ac2a4 100644 --- a/tests/PHPStan/Rules/Arrays/OffsetAccessAssignOpRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/OffsetAccessAssignOpRuleTest.php @@ -17,7 +17,7 @@ class OffsetAccessAssignOpRuleTest extends RuleTestCase protected function getRule(): Rule { - $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnions, false, false, true, false); + $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnions, false, false, false); return new OffsetAccessAssignOpRule($ruleLevelHelper); } diff --git a/tests/PHPStan/Rules/Arrays/OffsetAccessAssignmentRuleTest.php b/tests/PHPStan/Rules/Arrays/OffsetAccessAssignmentRuleTest.php index 86420630c2..9049635db0 100644 --- a/tests/PHPStan/Rules/Arrays/OffsetAccessAssignmentRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/OffsetAccessAssignmentRuleTest.php @@ -17,7 +17,7 @@ class OffsetAccessAssignmentRuleTest extends RuleTestCase protected function getRule(): Rule { - $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnionTypes, false, false, true, false); + $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnionTypes, false, false, false); return new OffsetAccessAssignmentRule($ruleLevelHelper); } diff --git a/tests/PHPStan/Rules/Arrays/OffsetAccessValueAssignmentRuleTest.php b/tests/PHPStan/Rules/Arrays/OffsetAccessValueAssignmentRuleTest.php index 0129923ae8..38afbe6137 100644 --- a/tests/PHPStan/Rules/Arrays/OffsetAccessValueAssignmentRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/OffsetAccessValueAssignmentRuleTest.php @@ -15,7 +15,7 @@ class OffsetAccessValueAssignmentRuleTest extends RuleTestCase protected function getRule(): Rule { - return new OffsetAccessValueAssignmentRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false)); + return new OffsetAccessValueAssignmentRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Arrays/UnpackIterableInArrayRuleTest.php b/tests/PHPStan/Rules/Arrays/UnpackIterableInArrayRuleTest.php index c7de4bc7bf..ba43922b08 100644 --- a/tests/PHPStan/Rules/Arrays/UnpackIterableInArrayRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/UnpackIterableInArrayRuleTest.php @@ -21,7 +21,7 @@ class UnpackIterableInArrayRuleTest extends RuleTestCase protected function getRule(): Rule { - return new UnpackIterableInArrayRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false)); + return new UnpackIterableInArrayRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Cast/EchoRuleTest.php b/tests/PHPStan/Rules/Cast/EchoRuleTest.php index 81289f82f0..5804527769 100644 --- a/tests/PHPStan/Rules/Cast/EchoRuleTest.php +++ b/tests/PHPStan/Rules/Cast/EchoRuleTest.php @@ -16,7 +16,7 @@ class EchoRuleTest extends RuleTestCase protected function getRule(): Rule { return new EchoRule( - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), ); } diff --git a/tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php b/tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php index bc7cd35acb..ee36958b19 100644 --- a/tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php +++ b/tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php @@ -22,7 +22,7 @@ class InvalidCastRuleTest extends RuleTestCase protected function getRule(): Rule { $broker = $this->createReflectionProvider(); - return new InvalidCastRule($broker, new RuleLevelHelper($broker, true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false)); + return new InvalidCastRule($broker, new RuleLevelHelper($broker, true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Cast/InvalidPartOfEncapsedStringRuleTest.php b/tests/PHPStan/Rules/Cast/InvalidPartOfEncapsedStringRuleTest.php index 3ba7d5ce61..4503a788e8 100644 --- a/tests/PHPStan/Rules/Cast/InvalidPartOfEncapsedStringRuleTest.php +++ b/tests/PHPStan/Rules/Cast/InvalidPartOfEncapsedStringRuleTest.php @@ -19,7 +19,7 @@ protected function getRule(): Rule { return new InvalidPartOfEncapsedStringRule( new ExprPrinter(new Printer()), - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), ); } diff --git a/tests/PHPStan/Rules/Cast/PrintRuleTest.php b/tests/PHPStan/Rules/Cast/PrintRuleTest.php index c7a52e8123..b3a71307ec 100644 --- a/tests/PHPStan/Rules/Cast/PrintRuleTest.php +++ b/tests/PHPStan/Rules/Cast/PrintRuleTest.php @@ -16,7 +16,7 @@ class PrintRuleTest extends RuleTestCase protected function getRule(): Rule { return new PrintRule( - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), ); } diff --git a/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php b/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php index 6fa6252277..e261724d7d 100644 --- a/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php b/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php index b132e3fe08..69fd7a2c2b 100644 --- a/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Classes/ClassConstantRuleTest.php b/tests/PHPStan/Rules/Classes/ClassConstantRuleTest.php index 42378de1f2..d8bb82d141 100644 --- a/tests/PHPStan/Rules/Classes/ClassConstantRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ClassConstantRuleTest.php @@ -24,7 +24,7 @@ protected function getRule(): Rule $reflectionProvider = $this->createReflectionProvider(); return new ClassConstantRule( $reflectionProvider, - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php b/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php index 9d3ea64034..fa8b767c4b 100644 --- a/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php @@ -26,7 +26,7 @@ protected function getRule(): Rule $reflectionProvider = $this->createReflectionProvider(); return new InstantiationRule( $reflectionProvider, - new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php index 2f4b45065f..4271153e36 100644 --- a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php +++ b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php @@ -26,7 +26,7 @@ protected function getRule(): Rule $reflectionProvider = $this->createReflectionProvider(); return new InstantiationRule( $reflectionProvider, - new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Constants/DynamicClassConstantFetchRuleTest.php b/tests/PHPStan/Rules/Constants/DynamicClassConstantFetchRuleTest.php index 2806935226..16dbd9dfbf 100644 --- a/tests/PHPStan/Rules/Constants/DynamicClassConstantFetchRuleTest.php +++ b/tests/PHPStan/Rules/Constants/DynamicClassConstantFetchRuleTest.php @@ -18,7 +18,7 @@ protected function getRule(): TRule { return new DynamicClassConstantFetchRule( self::getContainer()->getByType(PhpVersion::class), - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), ); } diff --git a/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php b/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php index 26643e506c..bb81a1157e 100644 --- a/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php +++ b/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80100), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Exceptions/ThrowExprTypeRuleTest.php b/tests/PHPStan/Rules/Exceptions/ThrowExprTypeRuleTest.php index 9ece8025a0..b9ac08e1bd 100644 --- a/tests/PHPStan/Rules/Exceptions/ThrowExprTypeRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/ThrowExprTypeRuleTest.php @@ -15,7 +15,7 @@ class ThrowExprTypeRuleTest extends RuleTestCase protected function getRule(): Rule { - return new ThrowExprTypeRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false)); + return new ThrowExprTypeRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php index 7f3aab6ac2..44d564b8ff 100644 --- a/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Functions/ArrowFunctionReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ArrowFunctionReturnTypeRuleTest.php index 307db4e0a9..a3ba642464 100644 --- a/tests/PHPStan/Rules/Functions/ArrowFunctionReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ArrowFunctionReturnTypeRuleTest.php @@ -23,7 +23,6 @@ protected function getRule(): Rule true, false, false, - true, false, ))); } diff --git a/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php b/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php index bcd1c9ee87..97260fb244 100644 --- a/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php @@ -22,7 +22,7 @@ class CallCallablesRuleTest extends RuleTestCase protected function getRule(): Rule { - $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, false, true, false); + $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, false, false); return new CallCallablesRule( new FunctionCallParametersCheck( $ruleLevelHelper, diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index 802b0e11a8..a996359363 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -26,7 +26,7 @@ protected function getRule(): Rule $broker = $this->createReflectionProvider(); return new CallToFunctionParametersRule( $broker, - new FunctionCallParametersCheck(new RuleLevelHelper($broker, true, false, true, $this->checkExplicitMixed, false, true, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($broker, true, false, true, $this->checkExplicitMixed, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), ); } diff --git a/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php b/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php index d10eee8e48..4744b8f1ce 100644 --- a/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php @@ -21,7 +21,7 @@ class CallUserFuncRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - return new CallUserFuncRule($reflectionProvider, new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, true, false, true, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true)); + return new CallUserFuncRule($reflectionProvider, new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php index f4a3d5a1bb..5827cc181c 100644 --- a/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php index 2a7a309e1a..6ffeadca25 100644 --- a/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php @@ -15,7 +15,7 @@ class ClosureReturnTypeRuleTest extends RuleTestCase protected function getRule(): Rule { - return new ClosureReturnTypeRule(new FunctionReturnTypeCheck(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false))); + return new ClosureReturnTypeRule(new FunctionReturnTypeCheck(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false))); } public function testClosureReturnTypeRule(): void diff --git a/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php index 553ab6c462..5fe8fe58f8 100644 --- a/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Functions/FunctionCallableRuleTest.php b/tests/PHPStan/Rules/Functions/FunctionCallableRuleTest.php index 2a92e5f5a2..e13fc184fc 100644 --- a/tests/PHPStan/Rules/Functions/FunctionCallableRuleTest.php +++ b/tests/PHPStan/Rules/Functions/FunctionCallableRuleTest.php @@ -20,7 +20,7 @@ protected function getRule(): Rule return new FunctionCallableRule( $reflectionProvider, - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new PhpVersion(PHP_VERSION_ID), true, true, diff --git a/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php index 25f0facf27..e5003028bc 100644 --- a/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php @@ -17,7 +17,7 @@ class ImplodeParameterCastableToStringRuleTest extends RuleTestCase protected function getRule(): Rule { $broker = $this->createReflectionProvider(); - return new ImplodeParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, true, false))); + return new ImplodeParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false))); } public function testNamedArguments(): void diff --git a/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php index 60d620474c..3298bd5bb0 100644 --- a/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php index 8619497c4f..e577240cb8 100644 --- a/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php @@ -19,7 +19,7 @@ class ParameterCastableToStringRuleTest extends RuleTestCase protected function getRule(): Rule { $broker = $this->createReflectionProvider(); - return new ParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, true, false))); + return new ParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false))); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php index 5ba98544fb..bd993f3bca 100644 --- a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php @@ -20,7 +20,7 @@ class ReturnTypeRuleTest extends RuleTestCase protected function getRule(): Rule { - return new ReturnTypeRule(new FunctionReturnTypeCheck(new RuleLevelHelper($this->createReflectionProvider(), $this->checkNullables, false, true, $this->checkExplicitMixed, false, true, false))); + return new ReturnTypeRule(new FunctionReturnTypeCheck(new RuleLevelHelper($this->createReflectionProvider(), $this->checkNullables, false, true, $this->checkExplicitMixed, false, false))); } public function testReturnTypeRule(): void diff --git a/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php index 98076839d1..f0350b5179 100644 --- a/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php @@ -19,7 +19,7 @@ class SortParameterCastableToStringRuleTest extends RuleTestCase protected function getRule(): Rule { $broker = $this->createReflectionProvider(); - return new SortParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, true, false))); + return new SortParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false))); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Generators/YieldFromTypeRuleTest.php b/tests/PHPStan/Rules/Generators/YieldFromTypeRuleTest.php index 681d9abab1..5c84c216a6 100644 --- a/tests/PHPStan/Rules/Generators/YieldFromTypeRuleTest.php +++ b/tests/PHPStan/Rules/Generators/YieldFromTypeRuleTest.php @@ -14,7 +14,7 @@ class YieldFromTypeRuleTest extends RuleTestCase protected function getRule(): Rule { - return new YieldFromTypeRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false), true); + return new YieldFromTypeRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), true); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Generators/YieldTypeRuleTest.php b/tests/PHPStan/Rules/Generators/YieldTypeRuleTest.php index deec20a074..d658d3aeb4 100644 --- a/tests/PHPStan/Rules/Generators/YieldTypeRuleTest.php +++ b/tests/PHPStan/Rules/Generators/YieldTypeRuleTest.php @@ -14,7 +14,7 @@ class YieldTypeRuleTest extends RuleTestCase protected function getRule(): Rule { - return new YieldTypeRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false)); + return new YieldTypeRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 0436117153..845c826e5c 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -33,7 +33,7 @@ class CallMethodsRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, $this->checkNullables, $this->checkThisOnly, $this->checkUnionTypes, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false); + $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, $this->checkNullables, $this->checkThisOnly, $this->checkUnionTypes, $this->checkExplicitMixed, $this->checkImplicitMixed, false); return new CallMethodsRule( new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true), new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion($this->phpVersion), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), diff --git a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php index d46969bdf3..f13767c4ed 100644 --- a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php @@ -32,7 +32,7 @@ class CallStaticMethodsRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, $this->checkThisOnly, true, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false); + $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, $this->checkThisOnly, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false); return new CallStaticMethodsRule( new StaticMethodCallCheck( $reflectionProvider, diff --git a/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php b/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php index a75873ffd5..f9ca07781c 100644 --- a/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php @@ -16,7 +16,7 @@ class CallToMethodStatementWithoutSideEffectsRuleTest extends RuleTestCase protected function getRule(): Rule { - return new CallToMethodStatementWithoutSideEffectsRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false)); + return new CallToMethodStatementWithoutSideEffectsRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php b/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php index 953ca5f982..90564ff6d2 100644 --- a/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php @@ -16,7 +16,7 @@ protected function getRule(): Rule { $broker = $this->createReflectionProvider(); return new CallToStaticMethodStatementWithoutSideEffectsRule( - new RuleLevelHelper($broker, true, false, true, false, false, true, false), + new RuleLevelHelper($broker, true, false, true, false, false, false), $broker, ); } diff --git a/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php b/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php index 9ce75af6e6..03d672afd0 100644 --- a/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php @@ -30,7 +30,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion($this->phpVersion), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Methods/MethodCallableRuleTest.php b/tests/PHPStan/Rules/Methods/MethodCallableRuleTest.php index b5bc1f8efb..5058756f1c 100644 --- a/tests/PHPStan/Rules/Methods/MethodCallableRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodCallableRuleTest.php @@ -19,7 +19,7 @@ class MethodCallableRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false); + $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false); return new MethodCallableRule( new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true), diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index 5446ab66db..150b170ca3 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -22,7 +22,7 @@ class ReturnTypeRuleTest extends RuleTestCase protected function getRule(): Rule { - return new ReturnTypeRule(new FunctionReturnTypeCheck(new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnionTypes, $this->checkExplicitMixed, false, true, $this->checkBenevolentUnionTypes))); + return new ReturnTypeRule(new FunctionReturnTypeCheck(new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnionTypes, $this->checkExplicitMixed, false, $this->checkBenevolentUnionTypes))); } public function testReturnTypeRule(): void diff --git a/tests/PHPStan/Rules/Methods/StaticMethodCallableRuleTest.php b/tests/PHPStan/Rules/Methods/StaticMethodCallableRuleTest.php index c726ab7fdb..169acc6693 100644 --- a/tests/PHPStan/Rules/Methods/StaticMethodCallableRuleTest.php +++ b/tests/PHPStan/Rules/Methods/StaticMethodCallableRuleTest.php @@ -22,7 +22,7 @@ class StaticMethodCallableRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false); + $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false); return new StaticMethodCallableRule( new StaticMethodCallCheck( diff --git a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php index 190b83798b..625e2d615e 100644 --- a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php @@ -23,7 +23,7 @@ protected function getRule(): Rule { return new InvalidBinaryOperationRule( new ExprPrinter(new Printer()), - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), true, ); } diff --git a/tests/PHPStan/Rules/Operators/InvalidComparisonOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidComparisonOperationRuleTest.php index 3221658bc4..dc9d57f88e 100644 --- a/tests/PHPStan/Rules/Operators/InvalidComparisonOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidComparisonOperationRuleTest.php @@ -16,7 +16,7 @@ class InvalidComparisonOperationRuleTest extends RuleTestCase protected function getRule(): Rule { return new InvalidComparisonOperationRule( - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), ); } diff --git a/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php index a70d03a6e7..5dd8aae36f 100644 --- a/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php @@ -20,7 +20,7 @@ class InvalidIncDecOperationRuleTest extends RuleTestCase protected function getRule(): Rule { return new InvalidIncDecOperationRule( - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), true, false, ); diff --git a/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php index ddc41ed337..909472e091 100644 --- a/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php @@ -20,7 +20,7 @@ class InvalidUnaryOperationRuleTest extends RuleTestCase protected function getRule(): Rule { return new InvalidUnaryOperationRule( - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), true, ); } diff --git a/tests/PHPStan/Rules/Properties/AccessPropertiesInAssignRuleTest.php b/tests/PHPStan/Rules/Properties/AccessPropertiesInAssignRuleTest.php index 853f053bc7..b6ea917903 100644 --- a/tests/PHPStan/Rules/Properties/AccessPropertiesInAssignRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessPropertiesInAssignRuleTest.php @@ -16,7 +16,7 @@ protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); return new AccessPropertiesInAssignRule( - new AccessPropertiesRule($reflectionProvider, new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), true, true), + new AccessPropertiesRule($reflectionProvider, new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), true, true), ); } diff --git a/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php index 2809d62a9a..7e5d97a44b 100644 --- a/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php @@ -23,7 +23,7 @@ class AccessPropertiesRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - return new AccessPropertiesRule($reflectionProvider, new RuleLevelHelper($reflectionProvider, true, $this->checkThisOnly, $this->checkUnionTypes, false, false, true, false), true, $this->checkDynamicProperties); + return new AccessPropertiesRule($reflectionProvider, new RuleLevelHelper($reflectionProvider, true, $this->checkThisOnly, $this->checkUnionTypes, false, false, false), true, $this->checkDynamicProperties); } public function testAccessProperties(): void diff --git a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesInAssignRuleTest.php b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesInAssignRuleTest.php index 593aa13f97..ea4b27f4f8 100644 --- a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesInAssignRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesInAssignRuleTest.php @@ -21,7 +21,7 @@ protected function getRule(): Rule return new AccessStaticPropertiesInAssignRule( new AccessStaticPropertiesRule( $reflectionProvider, - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php index 0ae3edbc3c..822a048e1e 100644 --- a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php @@ -21,7 +21,7 @@ protected function getRule(): Rule $reflectionProvider = $this->createReflectionProvider(); return new AccessStaticPropertiesRule( $reflectionProvider, - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Properties/Bug7074Test.php b/tests/PHPStan/Rules/Properties/Bug7074Test.php index 3748675490..d3398ed7e7 100644 --- a/tests/PHPStan/Rules/Properties/Bug7074Test.php +++ b/tests/PHPStan/Rules/Properties/Bug7074Test.php @@ -15,7 +15,7 @@ class Bug7074Test extends RuleTestCase protected function getRule(): Rule { - return new DefaultValueTypesAssignedToPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false)); + return new DefaultValueTypesAssignedToPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php index 7f99a5ae72..eae03f029c 100644 --- a/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php @@ -14,7 +14,7 @@ class DefaultValueTypesAssignedToPropertiesRuleTest extends RuleTestCase protected function getRule(): Rule { - return new DefaultValueTypesAssignedToPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false)); + return new DefaultValueTypesAssignedToPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false)); } public function testDefaultValueTypesAssignedToProperties(): void diff --git a/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php b/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php index b6d394d30b..26f8969686 100644 --- a/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php @@ -27,7 +27,7 @@ protected function getRule(): Rule new AttributesCheck( $reflectionProvider, new FunctionCallParametersCheck( - new RuleLevelHelper($reflectionProvider, true, false, true, false, false, true, false), + new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), diff --git a/tests/PHPStan/Rules/Properties/ReadingWriteOnlyPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/ReadingWriteOnlyPropertiesRuleTest.php index d5834f4003..f3ba064bac 100644 --- a/tests/PHPStan/Rules/Properties/ReadingWriteOnlyPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/ReadingWriteOnlyPropertiesRuleTest.php @@ -16,7 +16,7 @@ class ReadingWriteOnlyPropertiesRuleTest extends RuleTestCase protected function getRule(): Rule { - return new ReadingWriteOnlyPropertiesRule(new PropertyDescriptor(), new PropertyReflectionFinder(), new RuleLevelHelper($this->createReflectionProvider(), true, $this->checkThisOnly, true, false, false, true, false), $this->checkThisOnly); + return new ReadingWriteOnlyPropertiesRule(new PropertyDescriptor(), new PropertyReflectionFinder(), new RuleLevelHelper($this->createReflectionProvider(), true, $this->checkThisOnly, true, false, false, false), $this->checkThisOnly); } public function testPropertyMustBeReadableInAssignOp(): void diff --git a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php index d5e84b66e1..59eb242e7c 100644 --- a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php @@ -17,7 +17,7 @@ class TypesAssignedToPropertiesRuleTest extends RuleTestCase protected function getRule(): Rule { - return new TypesAssignedToPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, false, true, false), new PropertyReflectionFinder()); + return new TypesAssignedToPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, false, false), new PropertyReflectionFinder()); } public function testTypesAssignedToProperties(): void diff --git a/tests/PHPStan/Rules/Properties/WritingToReadOnlyPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/WritingToReadOnlyPropertiesRuleTest.php index d3196aba89..fb64553a3b 100644 --- a/tests/PHPStan/Rules/Properties/WritingToReadOnlyPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/WritingToReadOnlyPropertiesRuleTest.php @@ -16,7 +16,7 @@ class WritingToReadOnlyPropertiesRuleTest extends RuleTestCase protected function getRule(): Rule { - return new WritingToReadOnlyPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false), new PropertyDescriptor(), new PropertyReflectionFinder(), $this->checkThisOnly); + return new WritingToReadOnlyPropertiesRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), new PropertyDescriptor(), new PropertyReflectionFinder(), $this->checkThisOnly); } public function testCheckThisOnlyProperties(): void diff --git a/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php b/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php index ed68b380b1..95e94df168 100644 --- a/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php +++ b/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php @@ -15,7 +15,7 @@ class ParameterOutAssignedTypeRuleTest extends RuleTestCase protected function getRule(): TRule { return new ParameterOutAssignedTypeRule( - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, true, false, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, true, false, false), ); } diff --git a/tests/PHPStan/Rules/Variables/ParameterOutExecutionEndTypeRuleTest.php b/tests/PHPStan/Rules/Variables/ParameterOutExecutionEndTypeRuleTest.php index 26157f4ffb..8f3b40c7b6 100644 --- a/tests/PHPStan/Rules/Variables/ParameterOutExecutionEndTypeRuleTest.php +++ b/tests/PHPStan/Rules/Variables/ParameterOutExecutionEndTypeRuleTest.php @@ -15,7 +15,7 @@ class ParameterOutExecutionEndTypeRuleTest extends RuleTestCase protected function getRule(): Rule { return new ParameterOutExecutionEndTypeRule( - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, true, false, true, false), + new RuleLevelHelper($this->createReflectionProvider(), true, false, true, true, false, false), ); } diff --git a/tests/PHPStan/Rules/Variables/VariableCloningRuleTest.php b/tests/PHPStan/Rules/Variables/VariableCloningRuleTest.php index 801d2b31f4..f1c3af3cc0 100644 --- a/tests/PHPStan/Rules/Variables/VariableCloningRuleTest.php +++ b/tests/PHPStan/Rules/Variables/VariableCloningRuleTest.php @@ -15,7 +15,7 @@ class VariableCloningRuleTest extends RuleTestCase protected function getRule(): Rule { - return new VariableCloningRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, true, false)); + return new VariableCloningRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false)); } public function testClone(): void From 12879e4d02567fbbba927162629a7f2219e3ca62 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 22 Sep 2024 21:04:19 +0200 Subject: [PATCH 130/508] Fix build --- src/Analyser/TypeSpecifier.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index e58f023c48..8c40e83826 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -832,10 +832,8 @@ public function specifyTypesInCondition( $var->dim, $narrowedKey, $context, - false, $scope, - $rootExpr, - ), + )->setRootExpr($expr), ); } } From 5834cf5b6e6ff9ca76c468d15cc2931d2b729c3e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 22 Sep 2024 21:07:48 +0200 Subject: [PATCH 131/508] [BE] Infer explicit mixed when instantiating generic class with unknown template types --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - src/Analyser/DirectInternalScopeFactory.php | 2 - src/Analyser/LazyInternalScopeFactory.php | 4 -- src/Analyser/MutatingScope.php | 52 +++++---------------- src/Testing/PHPStanTestCase.php | 1 - 8 files changed, 13 insertions(+), 51 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 8538dba4fe..a95e3c79e6 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -11,7 +11,6 @@ Major new features 🚀 Bleeding edge (TODO move to other sections) ===================== -* Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 * Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! * Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! * Lower memory consumption thanks to breaking up of reference cycles @@ -140,6 +139,7 @@ Improvements 🔧 * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) * Require identifier in custom rules (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) * New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23) +* Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 246fdc091a..119065aaf6 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -2,7 +2,6 @@ parameters: featureToggles: bleedingEdge: true skipCheckGenericClasses!: [] - explicitMixedInUnknownGenericNew: true explicitMixedForGlobalVariables: true explicitMixedViaIsArray: true arrayFilter: true diff --git a/conf/config.neon b/conf/config.neon index f2904ef641..cfc414dd36 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -36,7 +36,6 @@ parameters: - CachingIterator - RegexIterator - ReflectionEnum - explicitMixedInUnknownGenericNew: false explicitMixedForGlobalVariables: false explicitMixedViaIsArray: false arrayFilter: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index c5caacdd84..11267d2474 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -31,7 +31,6 @@ parametersSchema: bleedingEdge: bool(), disableRuntimeReflectionProvider: bool(), skipCheckGenericClasses: listOf(string()), - explicitMixedInUnknownGenericNew: bool(), explicitMixedForGlobalVariables: bool(), explicitMixedViaIsArray: bool(), arrayFilter: bool(), diff --git a/src/Analyser/DirectInternalScopeFactory.php b/src/Analyser/DirectInternalScopeFactory.php index 49a3395d2e..ed36ee647e 100644 --- a/src/Analyser/DirectInternalScopeFactory.php +++ b/src/Analyser/DirectInternalScopeFactory.php @@ -35,7 +35,6 @@ public function __construct( private Parser $parser, private NodeScopeResolver $nodeScopeResolver, private PhpVersion $phpVersion, - private bool $explicitMixedInUnknownGenericNew, private bool $explicitMixedForGlobalVariables, private ConstantResolver $constantResolver, ) @@ -103,7 +102,6 @@ public function create( $afterExtractCall, $parentScope, $nativeTypesPromoted, - $this->explicitMixedInUnknownGenericNew, $this->explicitMixedForGlobalVariables, ); } diff --git a/src/Analyser/LazyInternalScopeFactory.php b/src/Analyser/LazyInternalScopeFactory.php index fec1521768..d079e204e2 100644 --- a/src/Analyser/LazyInternalScopeFactory.php +++ b/src/Analyser/LazyInternalScopeFactory.php @@ -20,8 +20,6 @@ final class LazyInternalScopeFactory implements InternalScopeFactory { - private bool $explicitMixedInUnknownGenericNew; - private bool $explicitMixedForGlobalVariables; /** @@ -32,7 +30,6 @@ public function __construct( private Container $container, ) { - $this->explicitMixedInUnknownGenericNew = $this->container->getParameter('featureToggles')['explicitMixedInUnknownGenericNew']; $this->explicitMixedForGlobalVariables = $this->container->getParameter('featureToggles')['explicitMixedForGlobalVariables']; } @@ -97,7 +94,6 @@ public function create( $afterExtractCall, $parentScope, $nativeTypesPromoted, - $this->explicitMixedInUnknownGenericNew, $this->explicitMixedForGlobalVariables, ); } diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 395a0c41c2..17c0c34828 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -220,7 +220,6 @@ public function __construct( private bool $afterExtractCall = false, private ?Scope $parentScope = null, private bool $nativeTypesPromoted = false, - private bool $explicitMixedInUnknownGenericNew = false, private bool $explicitMixedForGlobalVariables = false, ) { @@ -5549,49 +5548,22 @@ private function exactInstantiation(New_ $node, string $className): ?Type $constructorMethod->getNamedArgumentsVariants(), ); - if ($this->explicitMixedInUnknownGenericNew) { - $resolvedTemplateTypeMap = $parametersAcceptor->getResolvedTemplateTypeMap(); - return TypeTraverser::map(new GenericObjectType( - $resolvedClassName, - $classReflection->typeMapToList($classReflection->getTemplateTypeMap()), - ), static function (Type $type, callable $traverse) use ($resolvedTemplateTypeMap): Type { - if ($type instanceof TemplateType && !$type->isArgument()) { - $newType = $resolvedTemplateTypeMap->getType($type->getName()); - if ($newType === null || $newType instanceof ErrorType) { - return $type->getBound(); - } - - return TemplateTypeHelper::generalizeInferredTemplateType($type, $newType); + $resolvedTemplateTypeMap = $parametersAcceptor->getResolvedTemplateTypeMap(); + return TypeTraverser::map(new GenericObjectType( + $resolvedClassName, + $classReflection->typeMapToList($classReflection->getTemplateTypeMap()), + ), static function (Type $type, callable $traverse) use ($resolvedTemplateTypeMap): Type { + if ($type instanceof TemplateType && !$type->isArgument()) { + $newType = $resolvedTemplateTypeMap->getType($type->getName()); + if ($newType === null || $newType instanceof ErrorType) { + return $type->getBound(); } - return $traverse($type); - }); - } - - $resolvedPhpDoc = $classReflection->getResolvedPhpDoc(); - if ($resolvedPhpDoc === null) { - return $objectType; - } - - $list = []; - $typeMap = $parametersAcceptor->getResolvedTemplateTypeMap(); - foreach ($resolvedPhpDoc->getTemplateTags() as $tag) { - $templateType = $typeMap->getType($tag->getName()); - if ($templateType !== null) { - $list[] = $templateType; - continue; + return TemplateTypeHelper::generalizeInferredTemplateType($type, $newType); } - $bound = $tag->getBound(); - if ($bound instanceof MixedType && $bound->isExplicitMixed()) { - $bound = new MixedType(false); - } - $list[] = $bound; - } - return new GenericObjectType( - $resolvedClassName, - $list, - ); + return $traverse($type); + }); } private function filterTypeWithMethod(Type $typeWithMethod, string $methodName): ?Type diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index 14efcc7480..8238b6ead9 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -188,7 +188,6 @@ public static function createScopeFactory(ReflectionProvider $reflectionProvider self::getParser(), $container->getByType(NodeScopeResolver::class), $container->getByType(PhpVersion::class), - $container->getParameter('featureToggles')['explicitMixedInUnknownGenericNew'], $container->getParameter('featureToggles')['explicitMixedForGlobalVariables'], $constantResolver, ), From 9db564b03a68adb8fefc9d9d771220c312126481 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 22 Sep 2024 21:09:43 +0200 Subject: [PATCH 132/508] [BE] Fix invariance composition --- changelog-2.0.md | 3 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - src/DependencyInjection/ContainerFactory.php | 2 - src/Type/Generic/TemplateTypeVariance.php | 9 +- .../Type/Generic/GenericObjectTypeTest.php | 318 +----------------- 7 files changed, 20 insertions(+), 315 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index a95e3c79e6..579cf43f38 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -37,7 +37,6 @@ Bleeding edge (TODO move to other sections) * Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) * Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! * Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) -* Fix invariance composition ([#2054](https://github.com/phpstan/phpstan-src/pull/2054)), thanks @jiripudil! * Validate inline PHPDoc `@var` tag type against native type (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones * Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! @@ -144,6 +143,8 @@ Improvements 🔧 Bugfixes 🐛 ===================== +* Fix invariance composition ([#2054](https://github.com/phpstan/phpstan-src/pull/2054)), thanks @jiripudil! + Function signature fixes 🤖 ======================= diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 119065aaf6..e011ee0bf7 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -26,7 +26,6 @@ parameters: duplicateStubs: true logicalXor: true betterNoop: true - invarianceComposition: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true varTagType: true diff --git a/conf/config.neon b/conf/config.neon index cfc414dd36..3593b506da 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -61,7 +61,6 @@ parameters: duplicateStubs: false logicalXor: false betterNoop: false - invarianceComposition: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false varTagType: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 11267d2474..234a86f02f 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -56,7 +56,6 @@ parametersSchema: duplicateStubs: bool() logicalXor: bool() betterNoop: bool() - invarianceComposition: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() varTagType: bool() diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index 1e980d2f32..2a491725bb 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -31,7 +31,6 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\ShouldNotHappenException; -use PHPStan\Type\Generic\TemplateTypeVariance; use PHPStan\Type\ObjectType; use Symfony\Component\Finder\Finder; use function array_diff_key; @@ -191,7 +190,6 @@ public static function postInitializeContainer(Container $container): void $container->getService('typeSpecifier'); BleedingEdgeToggle::setBleedingEdge($container->getParameter('featureToggles')['bleedingEdge']); - TemplateTypeVariance::setInvarianceCompositionEnabled($container->getParameter('featureToggles')['invarianceComposition']); } public function clearOldContainers(string $tempDirectory): void diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index 786c61302c..b3089b62eb 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -28,8 +28,6 @@ class TemplateTypeVariance /** @var self[] */ private static array $registry; - private static bool $invarianceCompositionEnabled = false; - private function __construct(private int $value) { } @@ -118,7 +116,7 @@ public function compose(self $other): self return self::createInvariant(); } - if (self::$invarianceCompositionEnabled && $this->invariant()) { + if ($this->invariant()) { return self::createInvariant(); } @@ -253,9 +251,4 @@ public static function __set_state(array $properties): self return new self($properties['value']); } - public static function setInvarianceCompositionEnabled(bool $enabled): void - { - self::$invarianceCompositionEnabled = $enabled; - } - } diff --git a/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php b/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php index 1012234740..74b558e8ca 100644 --- a/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php +++ b/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php @@ -477,7 +477,6 @@ public function dataGetReferencedTypeArguments(): array new GenericObjectType(D\Invariant::class, [ $templateType('T'), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -485,42 +484,11 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: Invariant' => [ - TemplateTypeVariance::createContravariant(), - new GenericObjectType(D\Invariant::class, [ - $templateType('T'), - ], null, null, [ - TemplateTypeVariance::createCovariant(), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createContravariant(), - ), - ], - ], - 'param: Invariant' => [ - TemplateTypeVariance::createContravariant(), - new GenericObjectType(D\Invariant::class, [ - $templateType('T'), - ], null, null, [ - TemplateTypeVariance::createContravariant(), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createCovariant(), - ), - ], - ], 'param: Out' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\Out::class, [ $templateType('T'), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -535,7 +503,6 @@ public function dataGetReferencedTypeArguments(): array $templateType('T'), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -552,7 +519,6 @@ public function dataGetReferencedTypeArguments(): array ]), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -565,7 +531,6 @@ public function dataGetReferencedTypeArguments(): array new GenericObjectType(D\In::class, [ $templateType('T'), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -580,7 +545,6 @@ public function dataGetReferencedTypeArguments(): array $templateType('T'), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -597,7 +561,6 @@ public function dataGetReferencedTypeArguments(): array ]), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -612,7 +575,6 @@ public function dataGetReferencedTypeArguments(): array $templateType('T'), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -627,7 +589,6 @@ public function dataGetReferencedTypeArguments(): array $templateType('T'), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -635,106 +596,11 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: Out>' => [ - TemplateTypeVariance::createContravariant(), - new GenericObjectType(D\Out::class, [ - new GenericObjectType(D\Invariant::class, [ - $templateType('T'), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createInvariant(), - ), - ], - ], - 'param: In>' => [ - TemplateTypeVariance::createContravariant(), - new GenericObjectType(D\In::class, [ - new GenericObjectType(D\Invariant::class, [ - $templateType('T'), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createInvariant(), - ), - ], - ], - 'param: Invariant>' => [ - TemplateTypeVariance::createContravariant(), - new GenericObjectType(D\Invariant::class, [ - new GenericObjectType(D\Out::class, [ - $templateType('T'), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createCovariant(), - ), - ], - ], - 'param: Invariant>' => [ - TemplateTypeVariance::createContravariant(), - new GenericObjectType(D\Invariant::class, [ - new GenericObjectType(D\In::class, [ - $templateType('T'), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createContravariant(), - ), - ], - ], - 'param: In>>' => [ - TemplateTypeVariance::createContravariant(), - new GenericObjectType(D\In::class, [ - new GenericObjectType(D\Invariant::class, [ - new GenericObjectType(D\Out::class, [ - $templateType('T'), - ]), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createCovariant(), - ), - ], - ], - 'param: Out>>' => [ - TemplateTypeVariance::createContravariant(), - new GenericObjectType(D\Out::class, [ - new GenericObjectType(D\Invariant::class, [ - new GenericObjectType(D\In::class, [ - $templateType('T'), - ]), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createContravariant(), - ), - ], - ], 'return: Invariant' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\Invariant::class, [ $templateType('T'), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -742,42 +608,11 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: Invariant' => [ - TemplateTypeVariance::createCovariant(), - new GenericObjectType(D\Invariant::class, [ - $templateType('T'), - ], null, null, [ - TemplateTypeVariance::createCovariant(), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createCovariant(), - ), - ], - ], - 'return: Invariant' => [ - TemplateTypeVariance::createCovariant(), - new GenericObjectType(D\Invariant::class, [ - $templateType('T'), - ], null, null, [ - TemplateTypeVariance::createContravariant(), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createContravariant(), - ), - ], - ], 'return: Out' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\Out::class, [ $templateType('T'), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -792,7 +627,6 @@ public function dataGetReferencedTypeArguments(): array $templateType('T'), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -809,7 +643,6 @@ public function dataGetReferencedTypeArguments(): array ]), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -822,7 +655,6 @@ public function dataGetReferencedTypeArguments(): array new GenericObjectType(D\In::class, [ $templateType('T'), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -837,7 +669,6 @@ public function dataGetReferencedTypeArguments(): array $templateType('T'), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -854,7 +685,6 @@ public function dataGetReferencedTypeArguments(): array ]), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -869,7 +699,6 @@ public function dataGetReferencedTypeArguments(): array $templateType('T'), ]), ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -884,101 +713,6 @@ public function dataGetReferencedTypeArguments(): array $templateType('T'), ]), ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createContravariant(), - ), - ], - ], - 'return: Out>' => [ - TemplateTypeVariance::createCovariant(), - new GenericObjectType(D\Out::class, [ - new GenericObjectType(D\Invariant::class, [ - $templateType('T'), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createInvariant(), - ), - ], - ], - 'return: In>' => [ - TemplateTypeVariance::createCovariant(), - new GenericObjectType(D\In::class, [ - new GenericObjectType(D\Invariant::class, [ - $templateType('T'), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createInvariant(), - ), - ], - ], - 'return: Invariant>' => [ - TemplateTypeVariance::createCovariant(), - new GenericObjectType(D\Invariant::class, [ - new GenericObjectType(D\Out::class, [ - $templateType('T'), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createCovariant(), - ), - ], - ], - 'return: Invariant>' => [ - TemplateTypeVariance::createCovariant(), - new GenericObjectType(D\Invariant::class, [ - new GenericObjectType(D\In::class, [ - $templateType('T'), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createContravariant(), - ), - ], - ], - 'return: In>>' => [ - TemplateTypeVariance::createCovariant(), - new GenericObjectType(D\In::class, [ - new GenericObjectType(D\Invariant::class, [ - new GenericObjectType(D\Out::class, [ - $templateType('T'), - ]), - ]), - ]), - false, - [ - new TemplateTypeReference( - $templateType('T'), - TemplateTypeVariance::createCovariant(), - ), - ], - ], - 'return: Out>>' => [ - TemplateTypeVariance::createCovariant(), - new GenericObjectType(D\Out::class, [ - new GenericObjectType(D\Invariant::class, [ - new GenericObjectType(D\In::class, [ - $templateType('T'), - ]), - ]), - ]), - false, [ new TemplateTypeReference( $templateType('T'), @@ -986,14 +720,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: Out> (with invariance composition)' => [ + 'param: Out>' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\Out::class, [ new GenericObjectType(D\Invariant::class, [ $templateType('T'), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1001,14 +734,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: In> (with invariance composition)' => [ + 'param: In>' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\In::class, [ new GenericObjectType(D\Invariant::class, [ $templateType('T'), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1016,14 +748,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: Invariant> (with invariance composition)' => [ + 'param: Invariant>' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\Invariant::class, [ new GenericObjectType(D\Out::class, [ $templateType('T'), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1031,14 +762,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: Invariant> (with invariance composition)' => [ + 'param: Invariant>' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\Invariant::class, [ new GenericObjectType(D\In::class, [ $templateType('T'), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1046,7 +776,7 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: In>> (with invariance composition)' => [ + 'param: In>>' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\In::class, [ new GenericObjectType(D\Invariant::class, [ @@ -1055,7 +785,6 @@ public function dataGetReferencedTypeArguments(): array ]), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1063,7 +792,7 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: Out>> (with invariance composition)' => [ + 'param: Out>>' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\Out::class, [ new GenericObjectType(D\Invariant::class, [ @@ -1072,7 +801,6 @@ public function dataGetReferencedTypeArguments(): array ]), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1080,14 +808,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: Invariant (with invariance composition)' => [ + 'param: Invariant' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\Invariant::class, [ $templateType('T'), ], null, null, [ TemplateTypeVariance::createCovariant(), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1095,14 +822,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'param: Invariant (with invariance composition)' => [ + 'param: Invariant' => [ TemplateTypeVariance::createContravariant(), new GenericObjectType(D\Invariant::class, [ $templateType('T'), ], null, null, [ TemplateTypeVariance::createContravariant(), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1110,14 +836,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: Out> (with invariance composition)' => [ + 'return: Out>' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\Out::class, [ new GenericObjectType(D\Invariant::class, [ $templateType('T'), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1125,14 +850,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: In> (with invariance composition)' => [ + 'return: In>' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\In::class, [ new GenericObjectType(D\Invariant::class, [ $templateType('T'), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1140,14 +864,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: Invariant> (with invariance composition)' => [ + 'return: Invariant>' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\Invariant::class, [ new GenericObjectType(D\Out::class, [ $templateType('T'), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1155,14 +878,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: Invariant> (with invariance composition)' => [ + 'return: Invariant>' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\Invariant::class, [ new GenericObjectType(D\In::class, [ $templateType('T'), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1170,7 +892,7 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: In>> (with invariance composition)' => [ + 'return: In>>' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\In::class, [ new GenericObjectType(D\Invariant::class, [ @@ -1179,7 +901,6 @@ public function dataGetReferencedTypeArguments(): array ]), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1187,7 +908,7 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: Out>> (with invariance composition)' => [ + 'return: Out>>' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\Out::class, [ new GenericObjectType(D\Invariant::class, [ @@ -1196,7 +917,6 @@ public function dataGetReferencedTypeArguments(): array ]), ]), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1204,14 +924,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: Invariant (with invariance composition)' => [ + 'return: Invariant' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\Invariant::class, [ $templateType('T'), ], null, null, [ TemplateTypeVariance::createCovariant(), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1219,14 +938,13 @@ public function dataGetReferencedTypeArguments(): array ), ], ], - 'return: Invariant (with invariance composition)' => [ + 'return: Invariant' => [ TemplateTypeVariance::createCovariant(), new GenericObjectType(D\Invariant::class, [ $templateType('T'), ], null, null, [ TemplateTypeVariance::createContravariant(), ]), - true, [ new TemplateTypeReference( $templateType('T'), @@ -1242,10 +960,8 @@ public function dataGetReferencedTypeArguments(): array * * @param array $expectedReferences */ - public function testGetReferencedTypeArguments(TemplateTypeVariance $positionVariance, Type $type, bool $invarianceComposition, array $expectedReferences): void + public function testGetReferencedTypeArguments(TemplateTypeVariance $positionVariance, Type $type, array $expectedReferences): void { - TemplateTypeVariance::setInvarianceCompositionEnabled($invarianceComposition); - $result = []; foreach ($type->getReferencedTemplateTypes($positionVariance) as $r) { $result[] = $r; From ae5f990c9ced8e656c5eade5230c8321a3cd3b66 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 22 Sep 2024 21:25:25 +0200 Subject: [PATCH 133/508] [BE] Use explicit mixed for global array variables --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - src/Analyser/DirectInternalScopeFactory.php | 2 -- src/Analyser/LazyInternalScopeFactory.php | 4 ---- src/Analyser/MutatingScope.php | 3 +-- src/Testing/PHPStanTestCase.php | 1 - 8 files changed, 2 insertions(+), 13 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 579cf43f38..c106985a82 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -30,7 +30,6 @@ Bleeding edge (TODO move to other sections) * ApiInstanceofRule * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) -* Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! @@ -139,6 +138,7 @@ Improvements 🔧 * Require identifier in custom rules (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) * New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23) * Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 +* Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index e011ee0bf7..44d842cb00 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -2,7 +2,6 @@ parameters: featureToggles: bleedingEdge: true skipCheckGenericClasses!: [] - explicitMixedForGlobalVariables: true explicitMixedViaIsArray: true arrayFilter: true arrayUnpacking: true diff --git a/conf/config.neon b/conf/config.neon index 3593b506da..8953eab15b 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -36,7 +36,6 @@ parameters: - CachingIterator - RegexIterator - ReflectionEnum - explicitMixedForGlobalVariables: false explicitMixedViaIsArray: false arrayFilter: false arrayUnpacking: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 234a86f02f..2381e94d6e 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -31,7 +31,6 @@ parametersSchema: bleedingEdge: bool(), disableRuntimeReflectionProvider: bool(), skipCheckGenericClasses: listOf(string()), - explicitMixedForGlobalVariables: bool(), explicitMixedViaIsArray: bool(), arrayFilter: bool(), arrayUnpacking: bool(), diff --git a/src/Analyser/DirectInternalScopeFactory.php b/src/Analyser/DirectInternalScopeFactory.php index ed36ee647e..c48074c1dd 100644 --- a/src/Analyser/DirectInternalScopeFactory.php +++ b/src/Analyser/DirectInternalScopeFactory.php @@ -35,7 +35,6 @@ public function __construct( private Parser $parser, private NodeScopeResolver $nodeScopeResolver, private PhpVersion $phpVersion, - private bool $explicitMixedForGlobalVariables, private ConstantResolver $constantResolver, ) { @@ -102,7 +101,6 @@ public function create( $afterExtractCall, $parentScope, $nativeTypesPromoted, - $this->explicitMixedForGlobalVariables, ); } diff --git a/src/Analyser/LazyInternalScopeFactory.php b/src/Analyser/LazyInternalScopeFactory.php index d079e204e2..0c904d0d3b 100644 --- a/src/Analyser/LazyInternalScopeFactory.php +++ b/src/Analyser/LazyInternalScopeFactory.php @@ -20,8 +20,6 @@ final class LazyInternalScopeFactory implements InternalScopeFactory { - private bool $explicitMixedForGlobalVariables; - /** * @param class-string $scopeClass */ @@ -30,7 +28,6 @@ public function __construct( private Container $container, ) { - $this->explicitMixedForGlobalVariables = $this->container->getParameter('featureToggles')['explicitMixedForGlobalVariables']; } /** @@ -94,7 +91,6 @@ public function create( $afterExtractCall, $parentScope, $nativeTypesPromoted, - $this->explicitMixedForGlobalVariables, ); } diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 17c0c34828..62786fe77a 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -220,7 +220,6 @@ public function __construct( private bool $afterExtractCall = false, private ?Scope $parentScope = null, private bool $nativeTypesPromoted = false, - private bool $explicitMixedForGlobalVariables = false, ) { if ($namespace === '') { @@ -537,7 +536,7 @@ public function getVariableType(string $variableName): Type } if ($this->isGlobalVariable($variableName)) { - return new ArrayType(new BenevolentUnionType([new IntegerType(), new StringType()]), new MixedType($this->explicitMixedForGlobalVariables)); + return new ArrayType(new BenevolentUnionType([new IntegerType(), new StringType()]), new MixedType(true)); } if ($this->hasVariableType($variableName)->no()) { diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index 8238b6ead9..f4ab2a470d 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -188,7 +188,6 @@ public static function createScopeFactory(ReflectionProvider $reflectionProvider self::getParser(), $container->getByType(NodeScopeResolver::class), $container->getByType(PhpVersion::class), - $container->getParameter('featureToggles')['explicitMixedForGlobalVariables'], $constantResolver, ), ); From a63334e9245150924f0be509af5038262dd23ab1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 22 Sep 2024 21:26:34 +0200 Subject: [PATCH 134/508] Fix build --- tests/PHPStan/Type/Generic/GenericObjectTypeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php b/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php index 74b558e8ca..273394c6b6 100644 --- a/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php +++ b/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php @@ -461,7 +461,7 @@ public function testResolveTemplateTypes(Type $received, Type $template, array $ ); } - /** @return array}> */ + /** @return array}> */ public function dataGetReferencedTypeArguments(): array { $templateType = static fn ($name, ?Type $bound = null): Type => TemplateTypeFactory::create( From d7246a08e4a0f6687f7dce817cdd0e1b82643397 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 22 Sep 2024 21:29:27 +0200 Subject: [PATCH 135/508] [BE] Consider implicit throw points when the only explicit one is `Throw_` --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 2 -- conf/parametersSchema.neon | 1 - src/Analyser/NodeScopeResolver.php | 6 +----- src/Testing/RuleTestCase.php | 1 - src/Testing/TypeInferenceTestCase.php | 1 - tests/PHPStan/Analyser/AnalyserTest.php | 1 - 8 files changed, 2 insertions(+), 13 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index c106985a82..baf8f62323 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -92,7 +92,6 @@ Bleeding edge (TODO move to other sections) * More precise types for bcmath function parameters ([#2217](https://github.com/phpstan/phpstan-src/pull/2217)), thanks @Warxcell! * Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 * Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) -* Consider implicit throw points when the only explicit one is Throw_ (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4) * Check existing classes in `@param-out` (https://github.com/phpstan/phpstan-src/commit/30c4b9e80f51af8b5f166ba3aae93d8409c9c0ea), #10260 * Check existing classes in `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/2fa539a39e06bcc3155b109fd8d246703ceb176d), #10933 * Check invalid `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/95c0a5806c65c975201b9d3a464873f75a04c8b8), #10932 @@ -139,6 +138,7 @@ Improvements 🔧 * New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23) * Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 * Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! +* Consider implicit throw points when the only explicit one is `Throw_` (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 44d842cb00..cbd47d326c 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -49,6 +49,5 @@ parameters: preciseMissingReturn: true validatePregQuote: true tooWidePropertyType: true - explicitThrow: true absentTypeChecks: true requireFileExists: true diff --git a/conf/config.neon b/conf/config.neon index 8953eab15b..48d550549f 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -87,7 +87,6 @@ parameters: requireFileExists: false narrowPregMatches: true tooWidePropertyType: false - explicitThrow: false absentTypeChecks: false fileExtensions: - php @@ -534,7 +533,6 @@ services: universalObjectCratesClasses: %universalObjectCratesClasses% paramOutType: %featureToggles.paramOutType% preciseMissingReturn: %featureToggles.preciseMissingReturn% - explicitThrow: %featureToggles.explicitThrow% - class: PHPStan\Analyser\ConstantResolver diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 2381e94d6e..a42dd03e8a 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -80,7 +80,6 @@ parametersSchema: validatePregQuote: bool() narrowPregMatches: bool() tooWidePropertyType: bool() - explicitThrow: bool() absentTypeChecks: bool() requireFileExists: bool() ]) diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 8bcb6c1af2..f80ae02945 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -262,7 +262,6 @@ public function __construct( private readonly bool $detectDeadTypeInMultiCatch, private readonly bool $paramOutType, private readonly bool $preciseMissingReturn, - private readonly bool $explicitThrow, ) { $earlyTerminatingMethodNames = []; @@ -1565,10 +1564,7 @@ private function processStmtNode( } // implicit only - if ( - count($matchingThrowPoints) === 0 - || ($this->explicitThrow && $onlyExplicitIsThrow) - ) { + if (count($matchingThrowPoints) === 0 || $onlyExplicitIsThrow) { foreach ($throwPoints as $throwPointIndex => $throwPoint) { if ($throwPoint->isExplicit()) { continue; diff --git a/src/Testing/RuleTestCase.php b/src/Testing/RuleTestCase.php index 6e88b1ab68..5814357192 100644 --- a/src/Testing/RuleTestCase.php +++ b/src/Testing/RuleTestCase.php @@ -108,7 +108,6 @@ private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], self::getContainer()->getParameter('featureToggles')['paramOutType'], self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], - self::getContainer()->getParameter('featureToggles')['explicitThrow'], ); $fileAnalyser = new FileAnalyser( $this->createScopeFactory($reflectionProvider, $typeSpecifier), diff --git a/src/Testing/TypeInferenceTestCase.php b/src/Testing/TypeInferenceTestCase.php index ca350a16b3..a87e4b47e4 100644 --- a/src/Testing/TypeInferenceTestCase.php +++ b/src/Testing/TypeInferenceTestCase.php @@ -88,7 +88,6 @@ public static function processFile( self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], self::getContainer()->getParameter('featureToggles')['paramOutType'], self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], - self::getContainer()->getParameter('featureToggles')['explicitThrow'], ); $resolver->setAnalysedFiles(array_map(static fn (string $file): string => $fileHelper->normalizePath($file), array_merge([$file], static::getAdditionalAnalysedFiles()))); diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index 39155bdb6f..3be2818253 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -731,7 +731,6 @@ private function createAnalyser(): Analyser self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], self::getContainer()->getParameter('featureToggles')['paramOutType'], self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], - self::getContainer()->getParameter('featureToggles')['explicitThrow'], ); $lexer = new Lexer(); $fileAnalyser = new FileAnalyser( From 707ec771ec4875dd583f97cbadd76189297d5f3d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 09:11:40 +0200 Subject: [PATCH 136/508] [BE] `@param-out` changes --- changelog-2.0.md | 8 ++++---- conf/bleedingEdge.neon | 1 - conf/config.level3.neon | 12 ++---------- conf/config.level4.neon | 11 ++--------- conf/config.level6.neon | 16 ++-------------- conf/config.neon | 2 -- conf/parametersSchema.neon | 1 - src/Analyser/NodeScopeResolver.php | 3 --- src/PhpDoc/StubValidator.php | 4 ++-- .../MissingFunctionParameterTypehintRule.php | 4 ---- .../MissingMethodParameterTypehintRule.php | 4 ---- src/Testing/RuleTestCase.php | 1 - src/Testing/TypeInferenceTestCase.php | 1 - tests/PHPStan/Analyser/AnalyserTest.php | 1 - .../MissingFunctionParameterTypehintRuleTest.php | 2 +- .../MissingMethodParameterTypehintRuleTest.php | 2 +- 16 files changed, 14 insertions(+), 59 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index baf8f62323..7b7dfedae2 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -7,6 +7,9 @@ Major new features 🚀 * **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! * Lists are arrays with sequential integer keys starting at 0 +* **Enhancements in Handling Parameters Passed by Reference** + * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) + * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! Bleeding edge (TODO move to other sections) ===================== @@ -71,9 +74,6 @@ Bleeding edge (TODO move to other sections) * Report unused results of `and` and `or` (https://github.com/phpstan/phpstan-src/commit/1d8fff637d70a9e9ed3f11dee5d61b9f796cbf1a) * Report unused result of ternary (https://github.com/phpstan/phpstan-src/commit/9664f7a9d2223c07e750f0dfc949c3accfa6b65e) * Report unused results of `&&` and `||` (https://github.com/phpstan/phpstan-src/commit/cf2c8bbd9ebd2ebe300dbd310e136ad603d7def3) -* **Enhancements in Handling Parameters Passed by Reference** - * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) - * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! * Add option `reportAnyTypeWideningInVarTag` ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! * `array_values` rule (report when a `list` type is always passed in) ([#2917](https://github.com/phpstan/phpstan-src/pull/2917)), thanks @kamil-zacek! * Fix checking generic `mixed` type based on config ([#2885](https://github.com/phpstan/phpstan-src/pull/2885)), thanks @schlndh! @@ -84,7 +84,6 @@ Bleeding edge (TODO move to other sections) * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! * BetterNoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 -* Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) @@ -139,6 +138,7 @@ Improvements 🔧 * Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 * Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! * Consider implicit throw points when the only explicit one is `Throw_` (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4) +* Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index cbd47d326c..b3e0abb5c3 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -41,7 +41,6 @@ parameters: callUserFunc: true finalByPhpDoc: true magicConstantOutOfContext: true - paramOutType: true pure: true checkParameterCastableToStringFunctions: true uselessReturnValue: true diff --git a/conf/config.level3.neon b/conf/config.level3.neon index f205db23b6..dfbfc00454 100644 --- a/conf/config.level3.neon +++ b/conf/config.level3.neon @@ -8,10 +8,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRule: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% - PHPStan\Rules\Variables\ParameterOutAssignedTypeRule: - phpstan.rules.rule: %featureToggles.paramOutType% - PHPStan\Rules\Variables\ParameterOutExecutionEndTypeRule: - phpstan.rules.rule: %featureToggles.paramOutType% rules: - PHPStan\Rules\Arrays\ArrayDestructuringRule @@ -30,6 +26,8 @@ rules: - PHPStan\Rules\Properties\ReadOnlyPropertyAssignRule - PHPStan\Rules\Properties\ReadOnlyPropertyAssignRefRule - PHPStan\Rules\Properties\TypesAssignedToPropertiesRule + - PHPStan\Rules\Variables\ParameterOutAssignedTypeRule + - PHPStan\Rules\Variables\ParameterOutExecutionEndTypeRule - PHPStan\Rules\Variables\VariableCloningRule parameters: @@ -95,9 +93,3 @@ services: - class: PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRule - - - - class: PHPStan\Rules\Variables\ParameterOutAssignedTypeRule - - - - class: PHPStan\Rules\Variables\ParameterOutExecutionEndTypeRule diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 349523c3a0..199a794a53 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -14,6 +14,8 @@ rules: - PHPStan\Rules\TooWideTypehints\TooWideArrowFunctionReturnTypehintRule - PHPStan\Rules\TooWideTypehints\TooWideClosureReturnTypehintRule - PHPStan\Rules\TooWideTypehints\TooWideFunctionReturnTypehintRule + - PHPStan\Rules\TooWideTypehints\TooWideFunctionParameterOutTypeRule + - PHPStan\Rules\TooWideTypehints\TooWideMethodParameterOutTypeRule conditionalTags: PHPStan\Rules\Comparison\ConstantLooseComparisonRule: @@ -28,10 +30,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.logicalXor% PHPStan\Rules\DeadCode\BetterNoopRule: phpstan.rules.rule: %featureToggles.betterNoop% - PHPStan\Rules\TooWideTypehints\TooWideFunctionParameterOutTypeRule: - phpstan.rules.rule: %featureToggles.paramOutType% - PHPStan\Rules\TooWideTypehints\TooWideMethodParameterOutTypeRule: - phpstan.rules.rule: %featureToggles.paramOutType% PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule: phpstan.rules.rule: %featureToggles.pure% PHPStan\Rules\DeadCode\PossiblyPureNewCollector: @@ -322,11 +320,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\TooWideTypehints\TooWideFunctionParameterOutTypeRule - - - - class: PHPStan\Rules\TooWideTypehints\TooWideMethodParameterOutTypeRule - class: PHPStan\Rules\TooWideTypehints\TooWidePropertyTypeRule diff --git a/conf/config.level6.neon b/conf/config.level6.neon index 1029bcdba0..2b50d58d83 100644 --- a/conf/config.level6.neon +++ b/conf/config.level6.neon @@ -9,7 +9,9 @@ parameters: rules: - PHPStan\Rules\Constants\MissingClassConstantTypehintRule + - PHPStan\Rules\Functions\MissingFunctionParameterTypehintRule - PHPStan\Rules\Functions\MissingFunctionReturnTypehintRule + - PHPStan\Rules\Methods\MissingMethodParameterTypehintRule - PHPStan\Rules\Methods\MissingMethodReturnTypehintRule - PHPStan\Rules\Properties\MissingPropertyTypehintRule @@ -18,19 +20,5 @@ conditionalTags: phpstan.rules.rule: %featureToggles.absentTypeChecks% services: - - - class: PHPStan\Rules\Functions\MissingFunctionParameterTypehintRule - arguments: - paramOut: %featureToggles.paramOutType% - tags: - - phpstan.rules.rule - - - - class: PHPStan\Rules\Methods\MissingMethodParameterTypehintRule - arguments: - paramOut: %featureToggles.paramOutType% - tags: - - phpstan.rules.rule - - class: PHPStan\Rules\Methods\MissingMethodSelfOutTypeRule diff --git a/conf/config.neon b/conf/config.neon index 48d550549f..f21201c707 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -77,7 +77,6 @@ parameters: callUserFunc: false finalByPhpDoc: false magicConstantOutOfContext: false - paramOutType: false pure: false checkParameterCastableToStringFunctions: false uselessReturnValue: false @@ -531,7 +530,6 @@ services: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% detectDeadTypeInMultiCatch: %featureToggles.detectDeadTypeInMultiCatch% universalObjectCratesClasses: %universalObjectCratesClasses% - paramOutType: %featureToggles.paramOutType% preciseMissingReturn: %featureToggles.preciseMissingReturn% - diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index a42dd03e8a..96140b3296 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -71,7 +71,6 @@ parametersSchema: callUserFunc: bool() finalByPhpDoc: bool() magicConstantOutOfContext: bool() - paramOutType: bool() pure: bool() checkParameterCastableToStringFunctions: bool() uselessReturnValue: bool() diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index f80ae02945..4e7f170897 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -260,7 +260,6 @@ public function __construct( private readonly bool $implicitThrows, private readonly bool $treatPhpDocTypesAsCertain, private readonly bool $detectDeadTypeInMultiCatch, - private readonly bool $paramOutType, private readonly bool $preciseMissingReturn, ) { @@ -4748,13 +4747,11 @@ private function processArgs( } elseif ( $calleeReflection instanceof MethodReflection && !$calleeReflection->getDeclaringClass()->isBuiltin() - && $this->paramOutType ) { $byRefType = $currentParameter->getType(); } elseif ( $calleeReflection instanceof FunctionReflection && !$calleeReflection->isBuiltin() - && $this->paramOutType ) { $byRefType = $currentParameter->getType(); } diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index 0c5d975f2f..e866f7081b 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -228,9 +228,9 @@ private function getRuleRegistry(Container $container): RuleRegistry new InvalidThrowsPhpDocValueRule($fileTypeMapper), // level 6 - new MissingFunctionParameterTypehintRule($missingTypehintCheck, $container->getParameter('featureToggles')['paramOutType']), + new MissingFunctionParameterTypehintRule($missingTypehintCheck), new MissingFunctionReturnTypehintRule($missingTypehintCheck), - new MissingMethodParameterTypehintRule($missingTypehintCheck, $container->getParameter('featureToggles')['paramOutType']), + new MissingMethodParameterTypehintRule($missingTypehintCheck), new MissingMethodReturnTypehintRule($missingTypehintCheck), new MissingPropertyTypehintRule($missingTypehintCheck), ]; diff --git a/src/Rules/Functions/MissingFunctionParameterTypehintRule.php b/src/Rules/Functions/MissingFunctionParameterTypehintRule.php index 73782fcf53..3b7a264656 100644 --- a/src/Rules/Functions/MissingFunctionParameterTypehintRule.php +++ b/src/Rules/Functions/MissingFunctionParameterTypehintRule.php @@ -25,7 +25,6 @@ final class MissingFunctionParameterTypehintRule implements Rule public function __construct( private MissingTypehintCheck $missingTypehintCheck, - private bool $paramOut, ) { } @@ -51,9 +50,6 @@ public function processNode(Node $node, Scope $scope): array } } - if (!$this->paramOut) { - continue; - } if ($parameterReflection->getOutType() === null) { continue; } diff --git a/src/Rules/Methods/MissingMethodParameterTypehintRule.php b/src/Rules/Methods/MissingMethodParameterTypehintRule.php index 5ef4db93d1..8fe57003b7 100644 --- a/src/Rules/Methods/MissingMethodParameterTypehintRule.php +++ b/src/Rules/Methods/MissingMethodParameterTypehintRule.php @@ -25,7 +25,6 @@ final class MissingMethodParameterTypehintRule implements Rule public function __construct( private MissingTypehintCheck $missingTypehintCheck, - private bool $paramOut, ) { } @@ -51,9 +50,6 @@ public function processNode(Node $node, Scope $scope): array } } - if (!$this->paramOut) { - continue; - } if ($parameterReflection->getOutType() === null) { continue; } diff --git a/src/Testing/RuleTestCase.php b/src/Testing/RuleTestCase.php index 5814357192..802be9e599 100644 --- a/src/Testing/RuleTestCase.php +++ b/src/Testing/RuleTestCase.php @@ -106,7 +106,6 @@ private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser self::getContainer()->getParameter('exceptions')['implicitThrows'], $this->shouldTreatPhpDocTypesAsCertain(), self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], - self::getContainer()->getParameter('featureToggles')['paramOutType'], self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], ); $fileAnalyser = new FileAnalyser( diff --git a/src/Testing/TypeInferenceTestCase.php b/src/Testing/TypeInferenceTestCase.php index a87e4b47e4..9089e0dd37 100644 --- a/src/Testing/TypeInferenceTestCase.php +++ b/src/Testing/TypeInferenceTestCase.php @@ -86,7 +86,6 @@ public static function processFile( self::getContainer()->getParameter('exceptions')['implicitThrows'], self::getContainer()->getParameter('treatPhpDocTypesAsCertain'), self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], - self::getContainer()->getParameter('featureToggles')['paramOutType'], self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], ); $resolver->setAnalysedFiles(array_map(static fn (string $file): string => $fileHelper->normalizePath($file), array_merge([$file], static::getAdditionalAnalysedFiles()))); diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index 3be2818253..e693b1beb9 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -729,7 +729,6 @@ private function createAnalyser(): Analyser true, $this->shouldTreatPhpDocTypesAsCertain(), self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], - self::getContainer()->getParameter('featureToggles')['paramOutType'], self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], ); $lexer = new Lexer(); diff --git a/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php b/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php index a12ee381e9..73a197f3a5 100644 --- a/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingFunctionParameterTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingFunctionParameterTypehintRule(new MissingTypehintCheck(true, true, true, true, []), true); + return new MissingFunctionParameterTypehintRule(new MissingTypehintCheck(true, true, true, true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php b/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php index fecb8a1045..48c0c6acde 100644 --- a/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingMethodParameterTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingMethodParameterTypehintRule(new MissingTypehintCheck(true, true, true, true, []), true); + return new MissingMethodParameterTypehintRule(new MissingTypehintCheck(true, true, true, true, [])); } public function testRule(): void From 5d4eefce786073c800011121c07b965a7e9de5ba Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 09:20:49 +0200 Subject: [PATCH 137/508] [BE] Precise missing return --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 2 -- conf/parametersSchema.neon | 1 - src/Analyser/NodeScopeResolver.php | 3 +-- src/Testing/RuleTestCase.php | 1 - src/Testing/TypeInferenceTestCase.php | 1 - tests/PHPStan/Analyser/AnalyserTest.php | 1 - 8 files changed, 2 insertions(+), 10 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 7b7dfedae2..1352fbce3d 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -110,7 +110,6 @@ Bleeding edge (TODO move to other sections) * Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! * Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! -* Report "missing return" error closer to where the return is missing (https://github.com/phpstan/phpstan-src/commit/04f8636e6577cbcaefc944725eed74c0d7865ead) * Stricter ++/-- operator check ([#3255](https://github.com/phpstan/phpstan-src/pull/3255)), thanks @schlndh! * Check preg_quote delimiter sanity ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3! @@ -139,6 +138,7 @@ Improvements 🔧 * Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! * Consider implicit throw points when the only explicit one is `Throw_` (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4) * Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) +* Report "missing return" error closer to where the return is missing (https://github.com/phpstan/phpstan-src/commit/04f8636e6577cbcaefc944725eed74c0d7865ead) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index b3e0abb5c3..c476e5106c 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -45,7 +45,6 @@ parameters: checkParameterCastableToStringFunctions: true uselessReturnValue: true printfArrayParameters: true - preciseMissingReturn: true validatePregQuote: true tooWidePropertyType: true absentTypeChecks: true diff --git a/conf/config.neon b/conf/config.neon index f21201c707..6cca06d109 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -81,7 +81,6 @@ parameters: checkParameterCastableToStringFunctions: false uselessReturnValue: false printfArrayParameters: false - preciseMissingReturn: false validatePregQuote: false requireFileExists: false narrowPregMatches: true @@ -530,7 +529,6 @@ services: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% detectDeadTypeInMultiCatch: %featureToggles.detectDeadTypeInMultiCatch% universalObjectCratesClasses: %universalObjectCratesClasses% - preciseMissingReturn: %featureToggles.preciseMissingReturn% - class: PHPStan\Analyser\ConstantResolver diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 96140b3296..447f4eedb6 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -75,7 +75,6 @@ parametersSchema: checkParameterCastableToStringFunctions: bool() uselessReturnValue: bool() printfArrayParameters: bool() - preciseMissingReturn: bool() validatePregQuote: bool() narrowPregMatches: bool() tooWidePropertyType: bool() diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 4e7f170897..8ee2e80fcd 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -260,7 +260,6 @@ public function __construct( private readonly bool $implicitThrows, private readonly bool $treatPhpDocTypesAsCertain, private readonly bool $detectDeadTypeInMultiCatch, - private readonly bool $preciseMissingReturn, ) { $earlyTerminatingMethodNames = []; @@ -359,7 +358,7 @@ public function processStmtNodes( $parentNode = $parentNode; $endStatements = $statementResult->getEndStatements(); - if ($this->preciseMissingReturn && count($endStatements) > 0) { + if (count($endStatements) > 0) { foreach ($endStatements as $endStatement) { $endStatementResult = $endStatement->getResult(); $nodeCallback(new ExecutionEndNode( diff --git a/src/Testing/RuleTestCase.php b/src/Testing/RuleTestCase.php index 802be9e599..716f13bc79 100644 --- a/src/Testing/RuleTestCase.php +++ b/src/Testing/RuleTestCase.php @@ -106,7 +106,6 @@ private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser self::getContainer()->getParameter('exceptions')['implicitThrows'], $this->shouldTreatPhpDocTypesAsCertain(), self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], - self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], ); $fileAnalyser = new FileAnalyser( $this->createScopeFactory($reflectionProvider, $typeSpecifier), diff --git a/src/Testing/TypeInferenceTestCase.php b/src/Testing/TypeInferenceTestCase.php index 9089e0dd37..d406cc4bf5 100644 --- a/src/Testing/TypeInferenceTestCase.php +++ b/src/Testing/TypeInferenceTestCase.php @@ -86,7 +86,6 @@ public static function processFile( self::getContainer()->getParameter('exceptions')['implicitThrows'], self::getContainer()->getParameter('treatPhpDocTypesAsCertain'), self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], - self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], ); $resolver->setAnalysedFiles(array_map(static fn (string $file): string => $fileHelper->normalizePath($file), array_merge([$file], static::getAdditionalAnalysedFiles()))); diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index e693b1beb9..ee8c645bd0 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -729,7 +729,6 @@ private function createAnalyser(): Analyser true, $this->shouldTreatPhpDocTypesAsCertain(), self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], - self::getContainer()->getParameter('featureToggles')['preciseMissingReturn'], ); $lexer = new Lexer(); $fileAnalyser = new FileAnalyser( From ee565dbd2f2a31811e19e7fbc181526d33b3b4d6 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 09:24:56 +0200 Subject: [PATCH 138/508] Regression tests Closes https://github.com/phpstan/phpstan/issues/11119 Closes https://github.com/phpstan/phpstan/issues/4174 Closes https://github.com/phpstan/phpstan/issues/7082 Closes https://github.com/phpstan/phpstan/issues/4912 Closes https://github.com/phpstan/phpstan/issues/1953 --- changelog-2.0.md | 6 +- .../IfConstantConditionRuleTest.php | 6 ++ .../Rules/Comparison/data/bug-4912.php | 27 ++++++ .../CallToFunctionParametersRuleTest.php | 11 +++ .../PHPStan/Rules/Functions/data/bug-7082.php | 12 +++ .../Rules/Methods/CallMethodsRuleTest.php | 14 +++ tests/PHPStan/Rules/Methods/data/bug-1953.php | 13 +++ .../InvalidComparisonOperationRuleTest.php | 5 + .../Rules/Operators/data/bug-11119.php | 17 ++++ .../TypesAssignedToPropertiesRuleTest.php | 6 ++ .../Rules/Properties/data/bug-4174.php | 95 +++++++++++++++++++ 11 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 tests/PHPStan/Rules/Comparison/data/bug-4912.php create mode 100644 tests/PHPStan/Rules/Functions/data/bug-7082.php create mode 100644 tests/PHPStan/Rules/Methods/data/bug-1953.php create mode 100644 tests/PHPStan/Rules/Operators/data/bug-11119.php create mode 100644 tests/PHPStan/Rules/Properties/data/bug-4174.php diff --git a/changelog-2.0.md b/changelog-2.0.md index 1352fbce3d..31fb869728 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -133,10 +133,10 @@ Improvements 🔧 * Returning plain strings as errors no longer supported, use RuleErrorBuilder * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) * Require identifier in custom rules (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) -* New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23) +* New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23), #11119, #4174 * Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 -* Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), thanks @herndlm! -* Consider implicit throw points when the only explicit one is `Throw_` (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4) +* Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), #7082, thanks @herndlm! +* Consider implicit throw points when the only explicit one is `Throw_` (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4), #4912 * Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) * Report "missing return" error closer to where the return is missing (https://github.com/phpstan/phpstan-src/commit/04f8636e6577cbcaefc944725eed74c0d7865ead) diff --git a/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php index 479f5db928..840839ac9b 100644 --- a/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php @@ -169,4 +169,10 @@ public function testBug10561(): void $this->analyse([__DIR__ . '/data/bug-10561.php'], []); } + public function testBug4912(): void + { + $this->treatPhpDocTypesAsCertain = true; + $this->analyse([__DIR__ . '/data/bug-4912.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-4912.php b/tests/PHPStan/Rules/Comparison/data/bug-4912.php new file mode 100644 index 0000000000..cdbb585f9a --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-4912.php @@ -0,0 +1,27 @@ +analyse([__DIR__ . '/data/bug-9224.php'], []); } + public function testBug7082(): void + { + $this->checkExplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-7082.php'], [ + [ + 'Parameter #1 $val of function Bug7082\takesStr expects string, mixed given.', + 11, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Functions/data/bug-7082.php b/tests/PHPStan/Rules/Functions/data/bug-7082.php new file mode 100644 index 0000000000..0984dce665 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-7082.php @@ -0,0 +1,12 @@ +analyse([__DIR__ . '/data/bug-10159.php'], []); } + public function testBug1953(): void + { + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->checkExplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-1953.php'], [ + [ + 'Cannot call method bar() on string.', + 12, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-1953.php b/tests/PHPStan/Rules/Methods/data/bug-1953.php new file mode 100644 index 0000000000..c70978996c --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-1953.php @@ -0,0 +1,13 @@ +bar(); +}; diff --git a/tests/PHPStan/Rules/Operators/InvalidComparisonOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidComparisonOperationRuleTest.php index dc9d57f88e..c6879f2dc1 100644 --- a/tests/PHPStan/Rules/Operators/InvalidComparisonOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidComparisonOperationRuleTest.php @@ -168,4 +168,9 @@ public function testRuleWithNullsafeVariant(): void ]); } + public function testBug11119(): void + { + $this->analyse([__DIR__ . '/data/bug-11119.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Operators/data/bug-11119.php b/tests/PHPStan/Rules/Operators/data/bug-11119.php new file mode 100644 index 0000000000..c0fe6b5feb --- /dev/null +++ b/tests/PHPStan/Rules/Operators/data/bug-11119.php @@ -0,0 +1,17 @@ + ($carry instanceof DateTime && $carry < $time) ? $carry : $time, + null + ); +}; diff --git a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php index 59eb242e7c..3616824c7f 100644 --- a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php @@ -670,4 +670,10 @@ public function testBug11617(): void ]); } + public function testBug4174(): void + { + $this->checkExplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-4174.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Properties/data/bug-4174.php b/tests/PHPStan/Rules/Properties/data/bug-4174.php new file mode 100644 index 0000000000..9e4d4e7b09 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/bug-4174.php @@ -0,0 +1,95 @@ + + */ + public static function getArrayConstAsKey(): array { + return [ + self::NUMBER_TYPE_OFF => 'Off', + self::NUMBER_TYPE_HEAD => 'Head', + self::NUMBER_TYPE_POSITION => 'Position', + ]; + } + + /** + * @return list + */ + public static function getArrayConstAsValue(): array { + return [ + self::NUMBER_TYPE_OFF, + self::NUMBER_TYPE_HEAD, + self::NUMBER_TYPE_POSITION, + ]; + } + + public function checkConstViaArrayKey(): void + { + $numberArray = self::getArrayConstAsKey(); + + // --- + + $newvalue = $this->getIntFromPost('newValue'); + + if ($newvalue && array_key_exists($newvalue, $numberArray)) { + $this->newValue = $newvalue; + } + + if (isset($numberArray[$newvalue])) { + $this->newValue = $newvalue; + } + + // --- + + $newvalue = $this->getIntFromPostWithoutNull('newValue'); + + if ($newvalue && array_key_exists($newvalue, $numberArray)) { + $this->newValue = $newvalue; + } + + if (isset($numberArray[$newvalue])) { + $this->newValue = $newvalue; + } + } + + public function checkConstViaArrayValue(): void + { + $numberArray = self::getArrayConstAsValue(); + + // --- + + $newvalue = $this->getIntFromPost('newValue'); + + if ($newvalue && in_array($newvalue, $numberArray, true)) { + $this->newValue = $newvalue; + } + + // --- + + $newvalue = $this->getIntFromPostWithoutNull('newValue'); + + if ($newvalue && in_array($newvalue, $numberArray, true)) { + $this->newValue = $newvalue; + } + } + + public function getIntFromPost(string $key): ?int { + return isset($_POST[$key]) ? (int)$_POST[$key] : null; + } + + public function getIntFromPostWithoutNull(string $key): int { + return isset($_POST[$key]) ? (int)$_POST[$key] : 0; + } +} From 84308056ae9cf2e0b4f9eca2d6b5cbbcd9f7f780 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 09:44:14 +0200 Subject: [PATCH 139/508] [BE] Report dead types even in multi-exception catch --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 2 - conf/parametersSchema.neon | 1 - src/Analyser/NodeScopeResolver.php | 14 ++---- src/Testing/RuleTestCase.php | 1 - src/Testing/TypeInferenceTestCase.php | 1 - tests/PHPStan/Analyser/AnalyserTest.php | 1 - ...xceptionRuleWithDisabledMultiCatchTest.php | 48 ------------------- .../disable-detect-multi-catch.neon | 3 -- 10 files changed, 5 insertions(+), 69 deletions(-) delete mode 100644 tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleWithDisabledMultiCatchTest.php delete mode 100644 tests/PHPStan/Rules/Exceptions/disable-detect-multi-catch.neon diff --git a/changelog-2.0.md b/changelog-2.0.md index 31fb869728..8af379cecf 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -58,7 +58,6 @@ Bleeding edge (TODO move to other sections) * More precise `file()` flags args ([#2476](https://github.com/phpstan/phpstan-src/pull/2476), [#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! * More precise `flock()` operation flags ([#2477](https://github.com/phpstan/phpstan-src/pull/2477)), thanks @staabm! * Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! -* Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! * `error_log` errors with `message_type=2` ([#2428](https://github.com/phpstan/phpstan-src/pull/2428)), #9380, thanks @staabm! * Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! * More precise `stream_socket_client()` signature ([#2519](https://github.com/phpstan/phpstan-src/pull/2519)), thanks @staabm! @@ -139,6 +138,7 @@ Improvements 🔧 * Consider implicit throw points when the only explicit one is `Throw_` (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4), #4912 * Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) * Report "missing return" error closer to where the return is missing (https://github.com/phpstan/phpstan-src/commit/04f8636e6577cbcaefc944725eed74c0d7865ead) +* Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index c476e5106c..bd47059f3c 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -35,7 +35,6 @@ parameters: propertyVariance: true genericPrototypeMessage: true stricterFunctionMap: true - detectDeadTypeInMultiCatch: true zeroFiles: true projectServicesNotInAnalysedPaths: true callUserFunc: true diff --git a/conf/config.neon b/conf/config.neon index 6cca06d109..5fe45a5ef6 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -71,7 +71,6 @@ parameters: propertyVariance: false genericPrototypeMessage: false stricterFunctionMap: false - detectDeadTypeInMultiCatch: false zeroFiles: false projectServicesNotInAnalysedPaths: false callUserFunc: false @@ -527,7 +526,6 @@ services: earlyTerminatingFunctionCalls: %earlyTerminatingFunctionCalls% implicitThrows: %exceptions.implicitThrows% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - detectDeadTypeInMultiCatch: %featureToggles.detectDeadTypeInMultiCatch% universalObjectCratesClasses: %universalObjectCratesClasses% - diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 447f4eedb6..61294c35f5 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -65,7 +65,6 @@ parametersSchema: propertyVariance: bool() genericPrototypeMessage: bool() stricterFunctionMap: bool() - detectDeadTypeInMultiCatch: bool() zeroFiles: bool() projectServicesNotInAnalysedPaths: bool() callUserFunc: bool() diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 8ee2e80fcd..ba87e0f164 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -259,7 +259,6 @@ public function __construct( private readonly array $universalObjectCratesClasses, private readonly bool $implicitThrows, private readonly bool $treatPhpDocTypesAsCertain, - private readonly bool $detectDeadTypeInMultiCatch, ) { $earlyTerminatingMethodNames = []; @@ -1593,19 +1592,14 @@ private function processStmtNode( } // emit error - if ($this->detectDeadTypeInMultiCatch) { - foreach ($matchingCatchTypes as $catchTypeIndex => $matched) { - if ($matched) { - continue; - } - $nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchTypes[$catchTypeIndex], $originalCatchTypes[$catchTypeIndex]), $scope); + foreach ($matchingCatchTypes as $catchTypeIndex => $matched) { + if ($matched) { + continue; } + $nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchTypes[$catchTypeIndex], $originalCatchTypes[$catchTypeIndex]), $scope); } if (count($matchingThrowPoints) === 0) { - if (!$this->detectDeadTypeInMultiCatch) { - $nodeCallback(new CatchWithUnthrownExceptionNode($catchNode, $catchType, $originalCatchType), $scope); - } continue; } diff --git a/src/Testing/RuleTestCase.php b/src/Testing/RuleTestCase.php index 716f13bc79..5aac77f772 100644 --- a/src/Testing/RuleTestCase.php +++ b/src/Testing/RuleTestCase.php @@ -105,7 +105,6 @@ private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser self::getContainer()->getParameter('universalObjectCratesClasses'), self::getContainer()->getParameter('exceptions')['implicitThrows'], $this->shouldTreatPhpDocTypesAsCertain(), - self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], ); $fileAnalyser = new FileAnalyser( $this->createScopeFactory($reflectionProvider, $typeSpecifier), diff --git a/src/Testing/TypeInferenceTestCase.php b/src/Testing/TypeInferenceTestCase.php index d406cc4bf5..02fea01cc0 100644 --- a/src/Testing/TypeInferenceTestCase.php +++ b/src/Testing/TypeInferenceTestCase.php @@ -85,7 +85,6 @@ public static function processFile( self::getContainer()->getParameter('universalObjectCratesClasses'), self::getContainer()->getParameter('exceptions')['implicitThrows'], self::getContainer()->getParameter('treatPhpDocTypesAsCertain'), - self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], ); $resolver->setAnalysedFiles(array_map(static fn (string $file): string => $fileHelper->normalizePath($file), array_merge([$file], static::getAdditionalAnalysedFiles()))); diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index ee8c645bd0..0a27ee2889 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -728,7 +728,6 @@ private function createAnalyser(): Analyser [stdClass::class], true, $this->shouldTreatPhpDocTypesAsCertain(), - self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'], ); $lexer = new Lexer(); $fileAnalyser = new FileAnalyser( diff --git a/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleWithDisabledMultiCatchTest.php b/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleWithDisabledMultiCatchTest.php deleted file mode 100644 index debb459f03..0000000000 --- a/tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleWithDisabledMultiCatchTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - */ -class CatchWithUnthrownExceptionRuleWithDisabledMultiCatchTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new CatchWithUnthrownExceptionRule(new DefaultExceptionTypeResolver( - $this->createReflectionProvider(), - [], - [], - [], - [], - ), true); - } - - public static function getAdditionalConfigFiles(): array - { - return array_merge( - parent::getAdditionalConfigFiles(), - [__DIR__ . '/disable-detect-multi-catch.neon'], - ); - } - - public function testMultiCatchBackwardCompatible(): void - { - $this->analyse([__DIR__ . '/data/unthrown-exception-multi.php'], [ - [ - 'Dead catch - InvalidArgumentException is already caught above.', - 145, - ], - [ - 'Dead catch - InvalidArgumentException is already caught above.', - 156, - ], - ]); - } - -} diff --git a/tests/PHPStan/Rules/Exceptions/disable-detect-multi-catch.neon b/tests/PHPStan/Rules/Exceptions/disable-detect-multi-catch.neon deleted file mode 100644 index e763557205..0000000000 --- a/tests/PHPStan/Rules/Exceptions/disable-detect-multi-catch.neon +++ /dev/null @@ -1,3 +0,0 @@ -parameters: - featureToggles: - detectDeadTypeInMultiCatch: false From 7a701eab2c3b23f5f468907eb017b9826c638e38 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 09:47:38 +0200 Subject: [PATCH 140/508] [BE] MethodSignatureRule - look at abstract trait method --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 2 - conf/parametersSchema.neon | 1 - src/PhpDoc/StubValidator.php | 2 +- src/Rules/Methods/MethodSignatureRule.php | 43 +++++++++---------- .../Rules/Methods/MethodSignatureRuleTest.php | 2 +- .../Methods/OverridingMethodRuleTest.php | 2 +- 8 files changed, 24 insertions(+), 31 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 8af379cecf..98d047542b 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -64,7 +64,6 @@ Bleeding edge (TODO move to other sections) * More precise `scandir()` signature ([#2518](https://github.com/phpstan/phpstan-src/pull/2518)), thanks @staabm! * More precise `extract()` signature ([#2517](https://github.com/phpstan/phpstan-src/pull/2517)), thanks @staabm! * Detect overriding `@final` method in OverridingMethodRule, #9135 -* MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) @@ -139,6 +138,7 @@ Improvements 🔧 * Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) * Report "missing return" error closer to where the return is missing (https://github.com/phpstan/phpstan-src/commit/04f8636e6577cbcaefc944725eed74c0d7865ead) * Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! +* MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index bd47059f3c..589c51b4c2 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -17,7 +17,6 @@ parameters: runtimeReflectionRules: true notAnalysedTrait: true curlSetOptTypes: true - abstractTraitMethod: true missingMagicSerializationRule: true nullContextForVoidReturningFunctions: true unescapeStrings: true diff --git a/conf/config.neon b/conf/config.neon index 5fe45a5ef6..81d10a1624 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -52,7 +52,6 @@ parameters: runtimeReflectionRules: false notAnalysedTrait: false curlSetOptTypes: false - abstractTraitMethod: false missingMagicSerializationRule: false nullContextForVoidReturningFunctions: false unescapeStrings: false @@ -1046,7 +1045,6 @@ services: arguments: reportMaybes: %reportMaybesInMethodSignatures% reportStatic: %reportStaticMethodSignatures% - abstractTraitMethod: %featureToggles.abstractTraitMethod% - class: PHPStan\Rules\Methods\MethodParameterComparisonHelper diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 61294c35f5..6685779c13 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -47,7 +47,6 @@ parametersSchema: runtimeReflectionRules: bool() notAnalysedTrait: bool() curlSetOptTypes: bool() - abstractTraitMethod: bool() missingMagicSerializationRule: bool() nullContextForVoidReturningFunctions: bool() unescapeStrings: bool() diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index e866f7081b..dd1461ecf4 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -196,7 +196,7 @@ private function getRuleRegistry(Container $container): RuleRegistry new ExistingClassesInTypehintsRule($functionDefinitionCheck), new \PHPStan\Rules\Functions\ExistingClassesInTypehintsRule($functionDefinitionCheck), new ExistingClassesInPropertiesRule($reflectionProvider, $classNameCheck, $unresolvableTypeHelper, $phpVersion, true, false), - new OverridingMethodRule($phpVersion, new MethodSignatureRule($phpClassReflectionExtension, true, true, $container->getParameter('featureToggles')['abstractTraitMethod']), true, new MethodParameterComparisonHelper($phpVersion, $container->getParameter('featureToggles')['genericPrototypeMessage']), $phpClassReflectionExtension, $container->getParameter('featureToggles')['genericPrototypeMessage'], $container->getParameter('featureToggles')['finalByPhpDoc'], $container->getParameter('checkMissingOverrideMethodAttribute')), + new OverridingMethodRule($phpVersion, new MethodSignatureRule($phpClassReflectionExtension, true, true), true, new MethodParameterComparisonHelper($phpVersion, $container->getParameter('featureToggles')['genericPrototypeMessage']), $phpClassReflectionExtension, $container->getParameter('featureToggles')['genericPrototypeMessage'], $container->getParameter('featureToggles')['finalByPhpDoc'], $container->getParameter('checkMissingOverrideMethodAttribute')), new DuplicateDeclarationRule(), new LocalTypeAliasesRule($localTypeAliasesCheck), new LocalTypeTraitAliasesRule($localTypeAliasesCheck, $reflectionProvider), diff --git a/src/Rules/Methods/MethodSignatureRule.php b/src/Rules/Methods/MethodSignatureRule.php index 1e9d6b1ba2..194a41d74c 100644 --- a/src/Rules/Methods/MethodSignatureRule.php +++ b/src/Rules/Methods/MethodSignatureRule.php @@ -44,7 +44,6 @@ public function __construct( private PhpClassReflectionExtension $phpClassReflectionExtension, private bool $reportMaybes, private bool $reportStatic, - private bool $abstractTraitMethod, ) { } @@ -169,30 +168,28 @@ private function collectParentMethods(string $methodName, ClassReflection $class $parentMethods[] = [$method, $method->getDeclaringClass()]; } - if ($this->abstractTraitMethod) { - foreach ($class->getTraits(true) as $trait) { - $nativeTraitReflection = $trait->getNativeReflection(); - if (!$nativeTraitReflection->hasMethod($methodName)) { - continue; - } - - $methodReflection = $nativeTraitReflection->getMethod($methodName); - $isAbstract = $methodReflection->isAbstract(); - if (!$isAbstract) { - continue; - } + foreach ($class->getTraits(true) as $trait) { + $nativeTraitReflection = $trait->getNativeReflection(); + if (!$nativeTraitReflection->hasMethod($methodName)) { + continue; + } - $declaringTrait = $trait->getNativeMethod($methodName)->getDeclaringClass(); - $parentMethods[] = [ - $this->phpClassReflectionExtension->createUserlandMethodReflection( - $trait, - $class, - new NativeBuiltinMethodReflection($methodReflection), - $declaringTrait->getName(), - ), - $declaringTrait, - ]; + $methodReflection = $nativeTraitReflection->getMethod($methodName); + $isAbstract = $methodReflection->isAbstract(); + if (!$isAbstract) { + continue; } + + $declaringTrait = $trait->getNativeMethod($methodName)->getDeclaringClass(); + $parentMethods[] = [ + $this->phpClassReflectionExtension->createUserlandMethodReflection( + $trait, + $class, + new NativeBuiltinMethodReflection($methodReflection), + $declaringTrait->getName(), + ), + $declaringTrait, + ]; } return $parentMethods; diff --git a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php index cbdac548bc..6fd66f7e28 100644 --- a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php @@ -26,7 +26,7 @@ protected function getRule(): Rule return new OverridingMethodRule( $phpVersion, - new MethodSignatureRule($phpClassReflectionExtension, $this->reportMaybes, $this->reportStatic, true), + new MethodSignatureRule($phpClassReflectionExtension, $this->reportMaybes, $this->reportStatic), true, new MethodParameterComparisonHelper($phpVersion, true), $phpClassReflectionExtension, diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index dd90432f8f..722dcf7747 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule return new OverridingMethodRule( $phpVersion, - new MethodSignatureRule($phpClassReflectionExtension, true, true, true), + new MethodSignatureRule($phpClassReflectionExtension, true, true), false, new MethodParameterComparisonHelper($phpVersion, true), $phpClassReflectionExtension, From 870aa060438b91cbeb71a16c47e6d4d7d8a9aad5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 09:50:48 +0200 Subject: [PATCH 141/508] [BE] OverridingMethodRule - include template types in prototype declaring class description --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 1 - conf/config.neon | 3 --- conf/parametersSchema.neon | 1 - src/PhpDoc/StubValidator.php | 2 +- .../MethodParameterComparisonHelper.php | 22 ++++++++-------- src/Rules/Methods/OverridingMethodRule.php | 25 +++++++++---------- .../Rules/Methods/MethodSignatureRuleTest.php | 3 +-- .../Methods/OverridingMethodRuleTest.php | 3 +-- 10 files changed, 27 insertions(+), 36 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 98d047542b..ac4b73f38c 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -51,7 +51,6 @@ Bleeding edge (TODO move to other sections) * Specify `Imagick` parameter types ([#2334](https://github.com/phpstan/phpstan-src/pull/2334)), thanks @zonuexe! * Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! * Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! -* OverridingMethodRule - include template types in prototype declaring class description (https://github.com/phpstan/phpstan-src/commit/ca2c66cc4dff59ba44d52b82cb9e0aa3256240f3) * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) @@ -139,6 +138,7 @@ Improvements 🔧 * Report "missing return" error closer to where the return is missing (https://github.com/phpstan/phpstan-src/commit/04f8636e6577cbcaefc944725eed74c0d7865ead) * Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! * MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) +* OverridingMethodRule - include template types in prototype declaring class description (https://github.com/phpstan/phpstan-src/commit/ca2c66cc4dff59ba44d52b82cb9e0aa3256240f3) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 589c51b4c2..543fb682a3 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -32,7 +32,6 @@ parameters: paramOutVariance: true strictStaticMethodTemplateTypeVariance: true propertyVariance: true - genericPrototypeMessage: true stricterFunctionMap: true zeroFiles: true projectServicesNotInAnalysedPaths: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 1382d99ee1..efa06ccb5d 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -178,7 +178,6 @@ services: class: PHPStan\Rules\Methods\OverridingMethodRule arguments: checkPhpDocMethodSignatures: %checkPhpDocMethodSignatures% - genericPrototypeMessage: %featureToggles.genericPrototypeMessage% finalByPhpDoc: %featureToggles.finalByPhpDoc% checkMissingOverrideMethodAttribute: %checkMissingOverrideMethodAttribute% tags: diff --git a/conf/config.neon b/conf/config.neon index 81d10a1624..de2f0d05a9 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -68,7 +68,6 @@ parameters: strictStaticMethodTemplateTypeVariance: false propertyVariance: false - genericPrototypeMessage: false stricterFunctionMap: false zeroFiles: false projectServicesNotInAnalysedPaths: false @@ -1048,8 +1047,6 @@ services: - class: PHPStan\Rules\Methods\MethodParameterComparisonHelper - arguments: - genericPrototypeMessage: %featureToggles.genericPrototypeMessage% - class: PHPStan\Rules\MissingTypehintCheck diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 6685779c13..8b7291a6d7 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -62,7 +62,6 @@ parametersSchema: paramOutVariance: bool() strictStaticMethodTemplateTypeVariance: bool() propertyVariance: bool() - genericPrototypeMessage: bool() stricterFunctionMap: bool() zeroFiles: bool() projectServicesNotInAnalysedPaths: bool() diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index dd1461ecf4..04223a005e 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -196,7 +196,7 @@ private function getRuleRegistry(Container $container): RuleRegistry new ExistingClassesInTypehintsRule($functionDefinitionCheck), new \PHPStan\Rules\Functions\ExistingClassesInTypehintsRule($functionDefinitionCheck), new ExistingClassesInPropertiesRule($reflectionProvider, $classNameCheck, $unresolvableTypeHelper, $phpVersion, true, false), - new OverridingMethodRule($phpVersion, new MethodSignatureRule($phpClassReflectionExtension, true, true), true, new MethodParameterComparisonHelper($phpVersion, $container->getParameter('featureToggles')['genericPrototypeMessage']), $phpClassReflectionExtension, $container->getParameter('featureToggles')['genericPrototypeMessage'], $container->getParameter('featureToggles')['finalByPhpDoc'], $container->getParameter('checkMissingOverrideMethodAttribute')), + new OverridingMethodRule($phpVersion, new MethodSignatureRule($phpClassReflectionExtension, true, true), true, new MethodParameterComparisonHelper($phpVersion), $phpClassReflectionExtension, $container->getParameter('featureToggles')['finalByPhpDoc'], $container->getParameter('checkMissingOverrideMethodAttribute')), new DuplicateDeclarationRule(), new LocalTypeAliasesRule($localTypeAliasesCheck), new LocalTypeTraitAliasesRule($localTypeAliasesCheck, $reflectionProvider), diff --git a/src/Rules/Methods/MethodParameterComparisonHelper.php b/src/Rules/Methods/MethodParameterComparisonHelper.php index 284152b9c9..a9b741979a 100644 --- a/src/Rules/Methods/MethodParameterComparisonHelper.php +++ b/src/Rules/Methods/MethodParameterComparisonHelper.php @@ -24,7 +24,7 @@ final class MethodParameterComparisonHelper { - public function __construct(private PhpVersion $phpVersion, private bool $genericPrototypeMessage) + public function __construct(private PhpVersion $phpVersion) { } @@ -47,7 +47,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr 'Method %s::%s() overrides method %s::%s() but misses parameter #%d $%s.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), $i + 1, $prototypeParameter->getName(), @@ -73,7 +73,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $method->getName(), $i + 1, $prototypeParameter->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('parameter.byRef'); @@ -92,7 +92,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $method->getName(), $i + 1, $prototypeParameter->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('parameter.notByRef'); @@ -133,7 +133,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $method->getName(), $i + 1, $prototypeParameter->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('parameter.notVariadic'); @@ -178,7 +178,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $i + $j + 1, $remainingPrototypeParameter->getName(), $remainingPrototypeParameter->getNativeType()->describe(VerbosityLevel::typeOnly()), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('method.childParameterType'); @@ -198,7 +198,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $method->getName(), $i + 1, $prototypeParameter->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('parameter.variadic'); @@ -220,7 +220,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $method->getName(), $i + 1, $prototypeParameter->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('parameter.notOptional'); @@ -246,7 +246,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $i + 1, $prototypeParameter->getName(), $prototypeParameterType->describe(VerbosityLevel::typeOnly()), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('method.childParameterType'); @@ -274,7 +274,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $i + 1, $prototypeParameter->getName(), $prototypeParameterType->describe(VerbosityLevel::typeOnly()), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('method.childParameterType'); @@ -294,7 +294,7 @@ public function compare(ExtendedMethodReflection $prototype, ClassReflection $pr $i + 1, $prototypeParameter->getName(), $prototypeParameterType->describe(VerbosityLevel::typeOnly()), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('method.childParameterType'); diff --git a/src/Rules/Methods/OverridingMethodRule.php b/src/Rules/Methods/OverridingMethodRule.php index 99f3b1866e..da41d2b685 100644 --- a/src/Rules/Methods/OverridingMethodRule.php +++ b/src/Rules/Methods/OverridingMethodRule.php @@ -38,7 +38,6 @@ public function __construct( private bool $checkPhpDocMethodSignatures, private MethodParameterComparisonHelper $methodParameterComparisonHelper, private PhpClassReflectionExtension $phpClassReflectionExtension, - private bool $genericPrototypeMessage, private bool $finalByPhpDoc, private bool $checkMissingOverrideMethodAttribute, ) @@ -65,7 +64,7 @@ public function processNode(Node $node, Scope $scope): array 'Method %s::%s() overrides final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $parent->getDisplayName($this->genericPrototypeMessage), + $parent->getDisplayName(true), $parentConstructor->getName(), )) ->nonIgnorable() @@ -79,7 +78,7 @@ public function processNode(Node $node, Scope $scope): array 'Method %s::%s() overrides @final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $parent->getDisplayName($this->genericPrototypeMessage), + $parent->getDisplayName(true), $parentConstructor->getName(), ))->identifier('method.parentMethodFinalByPhpDoc') ->build(), @@ -116,7 +115,7 @@ public function processNode(Node $node, Scope $scope): array 'Method %s::%s() overrides method %s::%s() but is missing the #[\Override] attribute.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('method.missingOverride')->build(); } @@ -125,7 +124,7 @@ public function processNode(Node $node, Scope $scope): array 'Method %s::%s() overrides final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), )) ->nonIgnorable() @@ -136,7 +135,7 @@ public function processNode(Node $node, Scope $scope): array 'Method %s::%s() overrides @final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), ))->identifier('method.parentMethodFinalByPhpDoc') ->build(); @@ -148,7 +147,7 @@ public function processNode(Node $node, Scope $scope): array 'Non-static method %s::%s() overrides static method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), )) ->nonIgnorable() @@ -160,7 +159,7 @@ public function processNode(Node $node, Scope $scope): array 'Static method %s::%s() overrides non-static method %s::%s().', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), )) ->nonIgnorable() @@ -176,7 +175,7 @@ public function processNode(Node $node, Scope $scope): array $method->isPrivate() ? 'Private' : 'Protected', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), )) ->nonIgnorable() @@ -188,7 +187,7 @@ public function processNode(Node $node, Scope $scope): array 'Private method %s::%s() overriding protected method %s::%s() should be protected or public.', $method->getDeclaringClass()->getDisplayName(), $method->getName(), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), )) ->nonIgnorable() @@ -223,7 +222,7 @@ public function processNode(Node $node, Scope $scope): array $method->getDeclaringClass()->getDisplayName(), $method->getName(), $realPrototype->getTentativeReturnType()->describe(VerbosityLevel::typeOnly()), - $realPrototype->getDeclaringClass()->getDisplayName($this->genericPrototypeMessage), + $realPrototype->getDeclaringClass()->getDisplayName(true), $realPrototype->getName(), )) ->tip('Make it covariant, or use the #[\ReturnTypeWillChange] attribute to temporarily suppress the error.') @@ -273,7 +272,7 @@ public function processNode(Node $node, Scope $scope): array $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeReturnType->describe(VerbosityLevel::typeOnly()), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), )) ->nonIgnorable() @@ -286,7 +285,7 @@ public function processNode(Node $node, Scope $scope): array $method->getDeclaringClass()->getDisplayName(), $method->getName(), $prototypeReturnType->describe(VerbosityLevel::typeOnly()), - $prototypeDeclaringClass->getDisplayName($this->genericPrototypeMessage), + $prototypeDeclaringClass->getDisplayName(true), $prototype->getName(), )) ->nonIgnorable() diff --git a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php index 6fd66f7e28..5ad57bd6c5 100644 --- a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php @@ -28,10 +28,9 @@ protected function getRule(): Rule $phpVersion, new MethodSignatureRule($phpClassReflectionExtension, $this->reportMaybes, $this->reportStatic), true, - new MethodParameterComparisonHelper($phpVersion, true), + new MethodParameterComparisonHelper($phpVersion), $phpClassReflectionExtension, true, - true, false, ); } diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index 722dcf7747..abae064fb7 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -30,10 +30,9 @@ protected function getRule(): Rule $phpVersion, new MethodSignatureRule($phpClassReflectionExtension, true, true), false, - new MethodParameterComparisonHelper($phpVersion, true), + new MethodParameterComparisonHelper($phpVersion), $phpClassReflectionExtension, true, - true, $this->checkMissingOverrideMethodAttribute, ); } From 84ab800f690237eeb3fe2f42cba58d50ff187fb2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 10:00:06 +0200 Subject: [PATCH 142/508] [BE] Detect overriding `@final` method in OverridingMethodRule --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - src/PhpDoc/StubValidator.php | 2 +- src/Rules/Methods/OverridingMethodRule.php | 5 ++--- tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php | 1 - tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php | 1 - 9 files changed, 4 insertions(+), 11 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index ac4b73f38c..4467e39234 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -62,7 +62,6 @@ Bleeding edge (TODO move to other sections) * More precise `stream_socket_client()` signature ([#2519](https://github.com/phpstan/phpstan-src/pull/2519)), thanks @staabm! * More precise `scandir()` signature ([#2518](https://github.com/phpstan/phpstan-src/pull/2518)), thanks @staabm! * More precise `extract()` signature ([#2517](https://github.com/phpstan/phpstan-src/pull/2517)), thanks @staabm! -* Detect overriding `@final` method in OverridingMethodRule, #9135 * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) @@ -139,6 +138,7 @@ Improvements 🔧 * Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! * MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) * OverridingMethodRule - include template types in prototype declaring class description (https://github.com/phpstan/phpstan-src/commit/ca2c66cc4dff59ba44d52b82cb9e0aa3256240f3) +* Detect overriding `@final` method in OverridingMethodRule, #9135 Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 543fb682a3..a4e2926ed4 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -36,7 +36,6 @@ parameters: zeroFiles: true projectServicesNotInAnalysedPaths: true callUserFunc: true - finalByPhpDoc: true magicConstantOutOfContext: true pure: true checkParameterCastableToStringFunctions: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index efa06ccb5d..7a9c5c6c42 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -178,7 +178,6 @@ services: class: PHPStan\Rules\Methods\OverridingMethodRule arguments: checkPhpDocMethodSignatures: %checkPhpDocMethodSignatures% - finalByPhpDoc: %featureToggles.finalByPhpDoc% checkMissingOverrideMethodAttribute: %checkMissingOverrideMethodAttribute% tags: - phpstan.rules.rule diff --git a/conf/config.neon b/conf/config.neon index de2f0d05a9..1c97e2d9c2 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -72,7 +72,6 @@ parameters: zeroFiles: false projectServicesNotInAnalysedPaths: false callUserFunc: false - finalByPhpDoc: false magicConstantOutOfContext: false pure: false checkParameterCastableToStringFunctions: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 8b7291a6d7..10db8d0910 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -66,7 +66,6 @@ parametersSchema: zeroFiles: bool() projectServicesNotInAnalysedPaths: bool() callUserFunc: bool() - finalByPhpDoc: bool() magicConstantOutOfContext: bool() pure: bool() checkParameterCastableToStringFunctions: bool() diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index 04223a005e..dc930e386d 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -196,7 +196,7 @@ private function getRuleRegistry(Container $container): RuleRegistry new ExistingClassesInTypehintsRule($functionDefinitionCheck), new \PHPStan\Rules\Functions\ExistingClassesInTypehintsRule($functionDefinitionCheck), new ExistingClassesInPropertiesRule($reflectionProvider, $classNameCheck, $unresolvableTypeHelper, $phpVersion, true, false), - new OverridingMethodRule($phpVersion, new MethodSignatureRule($phpClassReflectionExtension, true, true), true, new MethodParameterComparisonHelper($phpVersion), $phpClassReflectionExtension, $container->getParameter('featureToggles')['finalByPhpDoc'], $container->getParameter('checkMissingOverrideMethodAttribute')), + new OverridingMethodRule($phpVersion, new MethodSignatureRule($phpClassReflectionExtension, true, true), true, new MethodParameterComparisonHelper($phpVersion), $phpClassReflectionExtension, $container->getParameter('checkMissingOverrideMethodAttribute')), new DuplicateDeclarationRule(), new LocalTypeAliasesRule($localTypeAliasesCheck), new LocalTypeTraitAliasesRule($localTypeAliasesCheck, $reflectionProvider), diff --git a/src/Rules/Methods/OverridingMethodRule.php b/src/Rules/Methods/OverridingMethodRule.php index da41d2b685..01fbaff3dc 100644 --- a/src/Rules/Methods/OverridingMethodRule.php +++ b/src/Rules/Methods/OverridingMethodRule.php @@ -38,7 +38,6 @@ public function __construct( private bool $checkPhpDocMethodSignatures, private MethodParameterComparisonHelper $methodParameterComparisonHelper, private PhpClassReflectionExtension $phpClassReflectionExtension, - private bool $finalByPhpDoc, private bool $checkMissingOverrideMethodAttribute, ) { @@ -72,7 +71,7 @@ public function processNode(Node $node, Scope $scope): array ->build(), ], $node, $scope); } - if ($parentConstructor->isFinal()->yes() && $this->finalByPhpDoc) { + if ($parentConstructor->isFinal()->yes()) { return $this->addErrors([ RuleErrorBuilder::message(sprintf( 'Method %s::%s() overrides @final method %s::%s().', @@ -130,7 +129,7 @@ public function processNode(Node $node, Scope $scope): array ->nonIgnorable() ->identifier('method.parentMethodFinal') ->build(); - } elseif ($prototype->isFinal()->yes() && $this->finalByPhpDoc) { + } elseif ($prototype->isFinal()->yes()) { $messages[] = RuleErrorBuilder::message(sprintf( 'Method %s::%s() overrides @final method %s::%s().', $method->getDeclaringClass()->getDisplayName(), diff --git a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php index 5ad57bd6c5..5f75cd0554 100644 --- a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php @@ -30,7 +30,6 @@ protected function getRule(): Rule true, new MethodParameterComparisonHelper($phpVersion), $phpClassReflectionExtension, - true, false, ); } diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index abae064fb7..5a8b677229 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -32,7 +32,6 @@ protected function getRule(): Rule false, new MethodParameterComparisonHelper($phpVersion), $phpClassReflectionExtension, - true, $this->checkMissingOverrideMethodAttribute, ); } From 5b34cdba40e3a8aebd868689a3466bc322aab9c8 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 10:02:37 +0200 Subject: [PATCH 143/508] [BE] Absent type checks --- changelog-2.0.md | 32 +++++------ conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 6 +-- conf/config.level2.neon | 53 ++++--------------- conf/config.level6.neon | 9 +--- conf/config.neon | 5 -- conf/parametersSchema.neon | 1 - src/PhpDoc/StubValidator.php | 33 +++++------- src/Rules/Classes/LocalTypeAliasesCheck.php | 5 -- src/Rules/Classes/MixinCheck.php | 5 -- src/Rules/FunctionDefinitionCheck.php | 15 +++--- src/Rules/Generics/GenericAncestorsCheck.php | 15 ++---- .../Classes/LocalTypeAliasesRuleTest.php | 1 - .../Classes/LocalTypeTraitAliasesRuleTest.php | 1 - .../LocalTypeTraitUseAliasesRuleTest.php | 1 - tests/PHPStan/Rules/Classes/MixinRuleTest.php | 1 - .../Rules/Classes/MixinTraitRuleTest.php | 1 - .../Rules/Classes/MixinTraitUseRuleTest.php | 1 - ...lassesInArrowFunctionTypehintsRuleTest.php | 1 - ...stingClassesInClosureTypehintsRuleTest.php | 1 - .../ExistingClassesInTypehintsRuleTest.php | 1 - .../Rules/Generics/ClassAncestorsRuleTest.php | 1 - .../Rules/Generics/EnumAncestorsRuleTest.php | 1 - .../Generics/InterfaceAncestorsRuleTest.php | 1 - .../Rules/Generics/UsedTraitsRuleTest.php | 1 - .../ExistingClassesInTypehintsRuleTest.php | 1 - 26 files changed, 52 insertions(+), 142 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 4467e39234..37f6429f1b 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -10,6 +10,23 @@ Major new features 🚀 * **Enhancements in Handling Parameters Passed by Reference** * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! +* Added previously absent type checks (level 0) + * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) + * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) + * Check unresolvable types in local type aliases (https://github.com/phpstan/phpstan-src/commit/5f7d12b2fb2809525ab0e96eeae95093204ea4d3) + * Check generics in local type aliases (https://github.com/phpstan/phpstan-src/commit/5a2d4416d94ab77a2a2e7e1bfaba4c5ed2a13c25) + * Check existing classes in `@param-out` (https://github.com/phpstan/phpstan-src/commit/30c4b9e80f51af8b5f166ba3aae93d8409c9c0ea), #10260 + * Check existing classes in `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/2fa539a39e06bcc3155b109fd8d246703ceb176d), #10933 +* Added previously absent type checks (level 2) + * Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) + * Check `@extends`, `@implements`, `@use` for unresolvable types (https://github.com/phpstan/phpstan-src/commit/2bb528233edb75312614166e282776f279cf2018), #11552 + * Check types in `@method` tags (https://github.com/phpstan/phpstan-src/commit/5b7e474680eaf33874b7ed6a227677adcbed9ca5) + * Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) + * Check types in `@property` tags (https://github.com/phpstan/phpstan-src/commit/55ea2ae516df22a071ab873fdd6f748a3af0520e), #10752, #9356 +* Added previously absent type checks (level 6) + * Check missing types in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/892b319f25f04bc1b55c3d0063b607909612fe6d) + * Check missing types in local type aliases (https://github.com/phpstan/phpstan-src/commit/ce7ffaf02d624a7fb9d38f8e5dffc9739f1233fc) + * Check missing types in `@mixin` (https://github.com/phpstan/phpstan-src/commit/3175c81f26fd5bcb4a161b24e774921870ed2533) Bleeding edge (TODO move to other sections) ===================== @@ -82,25 +99,10 @@ Bleeding edge (TODO move to other sections) * BetterNoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! -* Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) -* Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) * More precise types for bcmath function parameters ([#2217](https://github.com/phpstan/phpstan-src/pull/2217)), thanks @Warxcell! * Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 * Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) -* Check existing classes in `@param-out` (https://github.com/phpstan/phpstan-src/commit/30c4b9e80f51af8b5f166ba3aae93d8409c9c0ea), #10260 -* Check existing classes in `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/2fa539a39e06bcc3155b109fd8d246703ceb176d), #10933 -* Check invalid `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/95c0a5806c65c975201b9d3a464873f75a04c8b8), #10932 * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 -* Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) -* Check missing types in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/892b319f25f04bc1b55c3d0063b607909612fe6d) -* Check missing types in local type aliases (https://github.com/phpstan/phpstan-src/commit/ce7ffaf02d624a7fb9d38f8e5dffc9739f1233fc) -* Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) -* Check unresolvable types in local type aliases (https://github.com/phpstan/phpstan-src/commit/5f7d12b2fb2809525ab0e96eeae95093204ea4d3) -* Check generics in local type aliases (https://github.com/phpstan/phpstan-src/commit/5a2d4416d94ab77a2a2e7e1bfaba4c5ed2a13c25) -* Check missing types in `@mixin` (https://github.com/phpstan/phpstan-src/commit/3175c81f26fd5bcb4a161b24e774921870ed2533) -* Check types in `@property` tags (https://github.com/phpstan/phpstan-src/commit/55ea2ae516df22a071ab873fdd6f748a3af0520e), #10752, #9356 -* Check types in `@method` tags (https://github.com/phpstan/phpstan-src/commit/5b7e474680eaf33874b7ed6a227677adcbed9ca5) -* Check `@extends`, `@implements`, `@use` for unresolvable types (https://github.com/phpstan/phpstan-src/commit/2bb528233edb75312614166e282776f279cf2018), #11552 * RegularExpressionPatternRule: validate preg_quote'd patterns ([#3270](https://github.com/phpstan/phpstan-src/pull/3270)), thanks @staabm! * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index a4e2926ed4..d0b7eba94b 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -43,5 +43,4 @@ parameters: printfArrayParameters: true validatePregQuote: true tooWidePropertyType: true - absentTypeChecks: true requireFileExists: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 7a9c5c6c42..60f2e7e5fc 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -32,8 +32,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.validatePregQuote% PHPStan\Rules\Keywords\RequireFileExistsRule: phpstan.rules.rule: %featureToggles.requireFileExists% - PHPStan\Rules\Classes\LocalTypeTraitUseAliasesRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% rules: - PHPStan\Rules\Api\ApiInstantiationRule @@ -63,6 +61,7 @@ rules: - PHPStan\Rules\Classes\InstantiationCallableRule - PHPStan\Rules\Classes\InvalidPromotedPropertiesRule - PHPStan\Rules\Classes\LocalTypeAliasesRule + - PHPStan\Rules\Classes\LocalTypeTraitUseAliasesRule - PHPStan\Rules\Classes\LocalTypeTraitAliasesRule - PHPStan\Rules\Classes\NewStaticRule - PHPStan\Rules\Classes\NonClassAttributeClassRule @@ -150,9 +149,6 @@ services: arguments: checkClassCaseSensitivity: %checkClassCaseSensitivity% - - - class: PHPStan\Rules\Classes\LocalTypeTraitUseAliasesRule - - class: PHPStan\Rules\Exceptions\CaughtExceptionExistenceRule tags: diff --git a/conf/config.level2.neon b/conf/config.level2.neon index 29234ebe71..6ff60ddf87 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -12,6 +12,14 @@ rules: - PHPStan\Rules\Cast\InvalidPartOfEncapsedStringRule - PHPStan\Rules\Cast\PrintRule - PHPStan\Rules\Classes\AccessPrivateConstantThroughStaticRule + - PHPStan\Rules\Classes\MethodTagRule + - PHPStan\Rules\Classes\MethodTagTraitRule + - PHPStan\Rules\Classes\MethodTagTraitUseRule + - PHPStan\Rules\Classes\PropertyTagRule + - PHPStan\Rules\Classes\PropertyTagTraitRule + - PHPStan\Rules\Classes\PropertyTagTraitUseRule + - PHPStan\Rules\Classes\MixinTraitRule + - PHPStan\Rules\Classes\MixinTraitUseRule - PHPStan\Rules\Comparison\UsageOfVoidMatchExpressionRule - PHPStan\Rules\Constants\ValueAssignedToClassConstantRule - PHPStan\Rules\Functions\IncompatibleDefaultParameterTypeRule @@ -25,6 +33,7 @@ rules: - PHPStan\Rules\Generics\InterfaceTemplateTypeRule - PHPStan\Rules\Generics\MethodTemplateTypeRule - PHPStan\Rules\Generics\MethodTagTemplateTypeRule + - PHPStan\Rules\Generics\MethodTagTemplateTypeTraitRule - PHPStan\Rules\Generics\MethodSignatureVarianceRule - PHPStan\Rules\Generics\TraitTemplateTypeRule - PHPStan\Rules\Generics\UsedTraitsRule @@ -49,28 +58,10 @@ rules: - PHPStan\Rules\PhpDoc\RequireExtendsDefinitionTraitRule conditionalTags: - PHPStan\Rules\Classes\MethodTagRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% - PHPStan\Rules\Classes\MethodTagTraitRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% - PHPStan\Rules\Classes\MethodTagTraitUseRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% - PHPStan\Rules\Classes\MixinTraitRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% - PHPStan\Rules\Classes\MixinTraitUseRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% - PHPStan\Rules\Classes\PropertyTagRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% - PHPStan\Rules\Classes\PropertyTagTraitRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% - PHPStan\Rules\Classes\PropertyTagTraitUseRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% PHPStan\Rules\Functions\IncompatibleArrowFunctionDefaultParameterTypeRule: phpstan.rules.rule: %featureToggles.closureDefaultParameterTypeRule% PHPStan\Rules\Functions\IncompatibleClosureDefaultParameterTypeRule: phpstan.rules.rule: %featureToggles.closureDefaultParameterTypeRule% - PHPStan\Rules\Generics\MethodTagTemplateTypeTraitRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% PHPStan\Rules\Methods\IllegalConstructorMethodCallRule: phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% PHPStan\Rules\Methods\IllegalConstructorStaticCallRule: @@ -90,30 +81,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Classes\MixinTraitRule - - - - class: PHPStan\Rules\Classes\MixinTraitUseRule - - - - class: PHPStan\Rules\Classes\MethodTagRule - - - - class: PHPStan\Rules\Classes\MethodTagTraitRule - - - - class: PHPStan\Rules\Classes\MethodTagTraitUseRule - - - - class: PHPStan\Rules\Classes\PropertyTagRule - - - - class: PHPStan\Rules\Classes\PropertyTagTraitRule - - - - class: PHPStan\Rules\Classes\PropertyTagTraitUseRule - - class: PHPStan\Rules\PhpDoc\RequireExtendsCheck arguments: @@ -137,8 +104,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Generics\MethodTagTemplateTypeTraitRule - class: PHPStan\Rules\Methods\IllegalConstructorMethodCallRule - diff --git a/conf/config.level6.neon b/conf/config.level6.neon index 2b50d58d83..e49ad444b9 100644 --- a/conf/config.level6.neon +++ b/conf/config.level6.neon @@ -13,12 +13,5 @@ rules: - PHPStan\Rules\Functions\MissingFunctionReturnTypehintRule - PHPStan\Rules\Methods\MissingMethodParameterTypehintRule - PHPStan\Rules\Methods\MissingMethodReturnTypehintRule + - PHPStan\Rules\Methods\MissingMethodSelfOutTypeRule - PHPStan\Rules\Properties\MissingPropertyTypehintRule - -conditionalTags: - PHPStan\Rules\Methods\MissingMethodSelfOutTypeRule: - phpstan.rules.rule: %featureToggles.absentTypeChecks% - -services: - - - class: PHPStan\Rules\Methods\MissingMethodSelfOutTypeRule diff --git a/conf/config.neon b/conf/config.neon index 1c97e2d9c2..1e7fc5ed63 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -81,7 +81,6 @@ parameters: requireFileExists: false narrowPregMatches: true tooWidePropertyType: false - absentTypeChecks: false fileExtensions: - php checkAdvancedIsset: false @@ -906,7 +905,6 @@ services: globalTypeAliases: %typeAliases% checkMissingTypehints: %checkMissingTypehints% checkClassCaseSensitivity: %checkClassCaseSensitivity% - absentTypeChecks: %featureToggles.absentTypeChecks% - class: PHPStan\Rules\Classes\MethodTagCheck @@ -918,7 +916,6 @@ services: class: PHPStan\Rules\Classes\MixinCheck arguments: checkClassCaseSensitivity: %checkClassCaseSensitivity% - absentTypeChecks: %featureToggles.absentTypeChecks% checkMissingTypehints: %checkMissingTypehints% - @@ -984,7 +981,6 @@ services: arguments: checkClassCaseSensitivity: %checkClassCaseSensitivity% checkThisOnly: %checkThisOnly% - absentTypeChecks: %featureToggles.absentTypeChecks% - class: PHPStan\Rules\FunctionReturnTypeCheck @@ -999,7 +995,6 @@ services: arguments: checkGenericClassInNonGenericObjectType: %checkGenericClassInNonGenericObjectType% skipCheckGenericClasses: %featureToggles.skipCheckGenericClasses% - absentTypeChecks: %featureToggles.absentTypeChecks% - class: PHPStan\Rules\Generics\GenericObjectTypeCheck diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 10db8d0910..f797b4608b 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -74,7 +74,6 @@ parametersSchema: validatePregQuote: bool() narrowPregMatches: bool() tooWidePropertyType: bool() - absentTypeChecks: bool() requireFileExists: bool() ]) fileExtensions: listOf(string()) diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index dc930e386d..e37624c68b 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -186,6 +186,8 @@ private function getRuleRegistry(Container $container): RuleRegistry $genericCallableRuleHelper = $container->getByType(GenericCallableRuleHelper::class); $methodTagTemplateTypeCheck = $container->getByType(MethodTagTemplateTypeCheck::class); $mixinCheck = $container->getByType(MixinCheck::class); + $methodTagCheck = new MethodTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true); + $propertyTagCheck = new PropertyTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true); $rules = [ // level 0 @@ -200,6 +202,7 @@ private function getRuleRegistry(Container $container): RuleRegistry new DuplicateDeclarationRule(), new LocalTypeAliasesRule($localTypeAliasesCheck), new LocalTypeTraitAliasesRule($localTypeAliasesCheck, $reflectionProvider), + new LocalTypeTraitUseAliasesRule($localTypeAliasesCheck), // level 2 new ClassAncestorsRule($genericAncestorsCheck, $crossCheckInterfacesHelper), @@ -226,6 +229,16 @@ private function getRuleRegistry(Container $container): RuleRegistry $container->getByType(PhpDocParser::class), ), new InvalidThrowsPhpDocValueRule($fileTypeMapper), + new MixinTraitRule($mixinCheck, $reflectionProvider), + new MixinRule($mixinCheck), + new MixinTraitUseRule($mixinCheck), + new MethodTagRule($methodTagCheck), + new MethodTagTraitRule($methodTagCheck, $reflectionProvider), + new MethodTagTraitUseRule($methodTagCheck), + new MethodTagTemplateTypeTraitRule($methodTagTemplateTypeCheck, $reflectionProvider), + new PropertyTagRule($propertyTagCheck), + new PropertyTagTraitRule($propertyTagCheck, $reflectionProvider), + new PropertyTagTraitUseRule($propertyTagCheck), // level 6 new MissingFunctionParameterTypehintRule($missingTypehintCheck), @@ -233,6 +246,7 @@ private function getRuleRegistry(Container $container): RuleRegistry new MissingMethodParameterTypehintRule($missingTypehintCheck), new MissingMethodReturnTypehintRule($missingTypehintCheck), new MissingPropertyTypehintRule($missingTypehintCheck), + new MissingMethodSelfOutTypeRule($missingTypehintCheck), ]; if ($this->duplicateStubs) { @@ -242,25 +256,6 @@ private function getRuleRegistry(Container $container): RuleRegistry $rules[] = new DuplicateFunctionDeclarationRule($reflector, $relativePathHelper); } - if ((bool) $container->getParameter('featureToggles')['absentTypeChecks']) { - $rules[] = new MissingMethodSelfOutTypeRule($missingTypehintCheck); - - $methodTagCheck = new MethodTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true); - $rules[] = new MethodTagRule($methodTagCheck); - $rules[] = new MethodTagTraitRule($methodTagCheck, $reflectionProvider); - $rules[] = new MethodTagTraitUseRule($methodTagCheck); - - $propertyTagCheck = new PropertyTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true); - $rules[] = new PropertyTagRule($propertyTagCheck); - $rules[] = new PropertyTagTraitRule($propertyTagCheck, $reflectionProvider); - $rules[] = new PropertyTagTraitUseRule($propertyTagCheck); - $rules[] = new MixinRule($mixinCheck); - $rules[] = new MixinTraitRule($mixinCheck, $reflectionProvider); - $rules[] = new MixinTraitUseRule($mixinCheck); - $rules[] = new LocalTypeTraitUseAliasesRule($localTypeAliasesCheck); - $rules[] = new MethodTagTemplateTypeTraitRule($methodTagTemplateTypeCheck, $reflectionProvider); - } - return new DirectRuleRegistry($rules); } diff --git a/src/Rules/Classes/LocalTypeAliasesCheck.php b/src/Rules/Classes/LocalTypeAliasesCheck.php index 5347681a90..fdc99bed07 100644 --- a/src/Rules/Classes/LocalTypeAliasesCheck.php +++ b/src/Rules/Classes/LocalTypeAliasesCheck.php @@ -44,7 +44,6 @@ public function __construct( private GenericObjectTypeCheck $genericObjectTypeCheck, private bool $checkMissingTypehints, private bool $checkClassCaseSensitivity, - private bool $absentTypeChecks, ) { } @@ -182,10 +181,6 @@ public function checkInTraitDefinitionContext(ClassReflection $reflection): arra continue; } - if (!$this->absentTypeChecks) { - continue; - } - if (!$this->checkMissingTypehints) { continue; } diff --git a/src/Rules/Classes/MixinCheck.php b/src/Rules/Classes/MixinCheck.php index a17ef3d200..6e5611b0f8 100644 --- a/src/Rules/Classes/MixinCheck.php +++ b/src/Rules/Classes/MixinCheck.php @@ -27,7 +27,6 @@ public function __construct( private MissingTypehintCheck $missingTypehintCheck, private UnresolvableTypeHelper $unresolvableTypeHelper, private bool $checkClassCaseSensitivity, - private bool $absentTypeChecks, private bool $checkMissingTypehints, ) { @@ -65,10 +64,6 @@ public function checkInTraitDefinitionContext(ClassReflection $classReflection): continue; } - if (!$this->absentTypeChecks) { - continue; - } - if (!$this->checkMissingTypehints) { continue; } diff --git a/src/Rules/FunctionDefinitionCheck.php b/src/Rules/FunctionDefinitionCheck.php index 3942cc1b40..9fcea27964 100644 --- a/src/Rules/FunctionDefinitionCheck.php +++ b/src/Rules/FunctionDefinitionCheck.php @@ -55,7 +55,6 @@ public function __construct( private PhpVersion $phpVersion, private bool $checkClassCaseSensitivity, private bool $checkThisOnly, - private bool $absentTypeChecks, ) { } @@ -274,7 +273,7 @@ public function checkClassMethod( ); $selfOutType = $methodReflection->getSelfOutType(); - if ($selfOutType !== null && $this->absentTypeChecks) { + if ($selfOutType !== null) { $selfOutTypeReferencedClasses = $selfOutType->getReferencedClasses(); foreach ($selfOutTypeReferencedClasses as $class) { @@ -646,13 +645,11 @@ private function getParameterReferencedClasses(ParameterReflection $parameter): } $moreClasses = []; - if ($this->absentTypeChecks) { - if ($parameter->getOutType() !== null) { - $moreClasses = array_merge($moreClasses, $parameter->getOutType()->getReferencedClasses()); - } - if ($parameter->getClosureThisType() !== null) { - $moreClasses = array_merge($moreClasses, $parameter->getClosureThisType()->getReferencedClasses()); - } + if ($parameter->getOutType() !== null) { + $moreClasses = array_merge($moreClasses, $parameter->getOutType()->getReferencedClasses()); + } + if ($parameter->getClosureThisType() !== null) { + $moreClasses = array_merge($moreClasses, $parameter->getClosureThisType()->getReferencedClasses()); } return array_merge( diff --git a/src/Rules/Generics/GenericAncestorsCheck.php b/src/Rules/Generics/GenericAncestorsCheck.php index ef9ce469b5..201b5d3dc2 100644 --- a/src/Rules/Generics/GenericAncestorsCheck.php +++ b/src/Rules/Generics/GenericAncestorsCheck.php @@ -35,7 +35,6 @@ public function __construct( private UnresolvableTypeHelper $unresolvableTypeHelper, private bool $checkGenericClassInNonGenericObjectType, private array $skipCheckGenericClasses, - private bool $absentTypeChecks, ) { } @@ -103,12 +102,10 @@ public function check( ); $messages = array_merge($messages, $genericObjectTypeCheckMessages); - if ($this->absentTypeChecks) { - if ($this->unresolvableTypeHelper->containsUnresolvableType($ancestorType)) { - $messages[] = RuleErrorBuilder::message($unresolvableTypeMessage) - ->identifier('generics.unresolvable') - ->build(); - } + if ($this->unresolvableTypeHelper->containsUnresolvableType($ancestorType)) { + $messages[] = RuleErrorBuilder::message($unresolvableTypeMessage) + ->identifier('generics.unresolvable') + ->build(); } foreach ($ancestorType->getReferencedClasses() as $referencedClass) { @@ -119,10 +116,6 @@ public function check( continue; } - if (!$this->absentTypeChecks) { - continue; - } - if ($referencedClass === $ancestorType->getClassName()) { continue; } diff --git a/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php index e8c07ca171..7455afc8cc 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php @@ -37,7 +37,6 @@ protected function getRule(): Rule new GenericObjectTypeCheck(), true, true, - true, ), ); } diff --git a/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php index fb443854df..a598bbd9df 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php @@ -36,7 +36,6 @@ protected function getRule(): Rule new GenericObjectTypeCheck(), true, true, - true, ), $this->createReflectionProvider(), ); diff --git a/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php index 58ddda39a4..05f8fe03ff 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php @@ -36,7 +36,6 @@ protected function getRule(): Rule new GenericObjectTypeCheck(), true, true, - true, ), ); } diff --git a/tests/PHPStan/Rules/Classes/MixinRuleTest.php b/tests/PHPStan/Rules/Classes/MixinRuleTest.php index b1a1bb39ca..acaf1974b0 100644 --- a/tests/PHPStan/Rules/Classes/MixinRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinRuleTest.php @@ -34,7 +34,6 @@ protected function getRule(): Rule new UnresolvableTypeHelper(), true, true, - true, ), ); } diff --git a/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php b/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php index a16f6ac23f..f23e120458 100644 --- a/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php @@ -33,7 +33,6 @@ protected function getRule(): Rule new UnresolvableTypeHelper(), true, true, - true, ), $reflectionProvider, ); diff --git a/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php b/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php index 08d3bb1c02..dbc7906da5 100644 --- a/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php @@ -33,7 +33,6 @@ protected function getRule(): Rule new UnresolvableTypeHelper(), true, true, - true, ), ); } diff --git a/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php b/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php index a409df4391..5b603724ec 100644 --- a/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ExistingClassesInArrowFunctionTypehintsRuleTest.php @@ -34,7 +34,6 @@ protected function getRule(): Rule new PhpVersion($this->phpVersionId), true, false, - true, ), new PhpVersion(PHP_VERSION_ID), ); diff --git a/tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php b/tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php index 657dc19df2..db80402633 100644 --- a/tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ExistingClassesInClosureTypehintsRuleTest.php @@ -34,7 +34,6 @@ protected function getRule(): Rule new PhpVersion($this->phpVersionId), true, false, - true, ), ); } diff --git a/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php b/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php index 06957666f5..46e872ec74 100644 --- a/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ExistingClassesInTypehintsRuleTest.php @@ -34,7 +34,6 @@ protected function getRule(): Rule new PhpVersion($this->phpVersionId), true, false, - true, ), ); } diff --git a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php index 05963f5576..4fc2eb30e8 100644 --- a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule new UnresolvableTypeHelper(), true, [], - true, ), new CrossCheckInterfacesHelper(), ); diff --git a/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php index 017065a4a8..034d8044b8 100644 --- a/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php @@ -23,7 +23,6 @@ protected function getRule(): Rule new UnresolvableTypeHelper(), true, [], - true, ), new CrossCheckInterfacesHelper(), ); diff --git a/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php index 3a9d430ec0..1c46e94d0c 100644 --- a/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule new UnresolvableTypeHelper(), true, [], - true, ), new CrossCheckInterfacesHelper(), ); diff --git a/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php b/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php index 196e663c7b..4656dd37c6 100644 --- a/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule new UnresolvableTypeHelper(), true, [], - true, ), ); } diff --git a/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php b/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php index 359d220880..4ca35ed5e0 100644 --- a/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ExistingClassesInTypehintsRuleTest.php @@ -34,7 +34,6 @@ protected function getRule(): Rule new PhpVersion($this->phpVersionId), true, false, - true, ), ); } From bea577235633b57143dbbf74987d8cb0f9841eee Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 10:50:52 +0200 Subject: [PATCH 144/508] [BE] Improve error wording --- changelog-2.0.md | 2 +- conf/config.level4.neon | 2 - conf/config.neon | 1 - .../NonexistentOffsetInArrayDimFetchCheck.php | 10 +- .../BooleanAndConstantConditionRule.php | 3 +- .../BooleanOrConstantConditionRule.php | 3 +- .../Arrays/ArrayDestructuringRuleTest.php | 4 +- ...nexistentOffsetInArrayDimFetchRuleTest.php | 152 +----------------- .../BooleanAndConstantConditionRuleTest.php | 87 ---------- .../BooleanOrConstantConditionRuleTest.php | 78 --------- 10 files changed, 9 insertions(+), 333 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 37f6429f1b..c2df639285 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -51,7 +51,6 @@ Bleeding edge (TODO move to other sections) * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! -* Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! * Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) * Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! @@ -141,6 +140,7 @@ Improvements 🔧 * MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) * OverridingMethodRule - include template types in prototype declaring class description (https://github.com/phpstan/phpstan-src/commit/ca2c66cc4dff59ba44d52b82cb9e0aa3256240f3) * Detect overriding `@final` method in OverridingMethodRule, #9135 +* Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! Bugfixes 🐛 ===================== diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 199a794a53..327f98e113 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -73,7 +73,6 @@ services: class: PHPStan\Rules\Comparison\BooleanAndConstantConditionRule arguments: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - bleedingEdge: %featureToggles.bleedingEdge% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% tags: @@ -83,7 +82,6 @@ services: class: PHPStan\Rules\Comparison\BooleanOrConstantConditionRule arguments: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - bleedingEdge: %featureToggles.bleedingEdge% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% tags: diff --git a/conf/config.neon b/conf/config.neon index 1e7fc5ed63..cb61959d66 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -884,7 +884,6 @@ services: class: PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchCheck arguments: reportMaybes: %reportMaybes% - bleedingEdge: %featureToggles.bleedingEdge% reportPossiblyNonexistentGeneralArrayOffset: %reportPossiblyNonexistentGeneralArrayOffset% reportPossiblyNonexistentConstantArrayOffset: %reportPossiblyNonexistentConstantArrayOffset% diff --git a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php index 7b329d01a4..8f78c9023b 100644 --- a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php +++ b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php @@ -22,7 +22,6 @@ final class NonexistentOffsetInArrayDimFetchCheck public function __construct( private RuleLevelHelper $ruleLevelHelper, private bool $reportMaybes, - private bool $bleedingEdge, private bool $reportPossiblyNonexistentGeneralArrayOffset, private bool $reportPossiblyNonexistentConstantArrayOffset, ) @@ -104,15 +103,8 @@ public function check( } if ($report) { - if ($this->bleedingEdge || $this->reportPossiblyNonexistentGeneralArrayOffset || $this->reportPossiblyNonexistentConstantArrayOffset) { - return [ - RuleErrorBuilder::message(sprintf('Offset %s might not exist on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value()))) - ->identifier('offsetAccess.notFound') - ->build(), - ]; - } return [ - RuleErrorBuilder::message(sprintf('Offset %s does not exist on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value()))) + RuleErrorBuilder::message(sprintf('Offset %s might not exist on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value()))) ->identifier('offsetAccess.notFound') ->build(), ]; diff --git a/src/Rules/Comparison/BooleanAndConstantConditionRule.php b/src/Rules/Comparison/BooleanAndConstantConditionRule.php index 5c05e8ac09..013e6b4b81 100644 --- a/src/Rules/Comparison/BooleanAndConstantConditionRule.php +++ b/src/Rules/Comparison/BooleanAndConstantConditionRule.php @@ -21,7 +21,6 @@ final class BooleanAndConstantConditionRule implements Rule public function __construct( private ConstantConditionRuleHelper $helper, private bool $treatPhpDocTypesAsCertain, - private bool $bleedingEdge, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertainTip, ) @@ -40,7 +39,7 @@ public function processNode( { $errors = []; $originalNode = $node->getOriginalNode(); - $nodeText = $this->bleedingEdge ? $originalNode->getOperatorSigil() : '&&'; + $nodeText = $originalNode->getOperatorSigil(); $leftType = $this->helper->getBooleanType($scope, $originalNode->left); $identifierType = $originalNode instanceof Node\Expr\BinaryOp\BooleanAnd ? 'booleanAnd' : 'logicalAnd'; if ($leftType instanceof ConstantBooleanType) { diff --git a/src/Rules/Comparison/BooleanOrConstantConditionRule.php b/src/Rules/Comparison/BooleanOrConstantConditionRule.php index f728505cad..b991f45981 100644 --- a/src/Rules/Comparison/BooleanOrConstantConditionRule.php +++ b/src/Rules/Comparison/BooleanOrConstantConditionRule.php @@ -21,7 +21,6 @@ final class BooleanOrConstantConditionRule implements Rule public function __construct( private ConstantConditionRuleHelper $helper, private bool $treatPhpDocTypesAsCertain, - private bool $bleedingEdge, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertainTip, ) @@ -39,7 +38,7 @@ public function processNode( ): array { $originalNode = $node->getOriginalNode(); - $nodeText = $this->bleedingEdge ? $originalNode->getOperatorSigil() : '||'; + $nodeText = $originalNode->getOperatorSigil(); $messages = []; $leftType = $this->helper->getBooleanType($scope, $originalNode->left); $identifierType = $originalNode instanceof Node\Expr\BinaryOp\BooleanOr ? 'booleanOr' : 'logicalOr'; diff --git a/tests/PHPStan/Rules/Arrays/ArrayDestructuringRuleTest.php b/tests/PHPStan/Rules/Arrays/ArrayDestructuringRuleTest.php index 840da52b49..d37f09084b 100644 --- a/tests/PHPStan/Rules/Arrays/ArrayDestructuringRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/ArrayDestructuringRuleTest.php @@ -13,15 +13,13 @@ class ArrayDestructuringRuleTest extends RuleTestCase { - private bool $bleedingEdge = false; - protected function getRule(): Rule { $ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false); return new ArrayDestructuringRule( $ruleLevelHelper, - new NonexistentOffsetInArrayDimFetchCheck($ruleLevelHelper, true, $this->bleedingEdge, false, false), + new NonexistentOffsetInArrayDimFetchCheck($ruleLevelHelper, true, false, false), ); } diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index f7fa3224f9..3862059b02 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -17,8 +17,6 @@ class NonexistentOffsetInArrayDimFetchRuleTest extends RuleTestCase private bool $checkImplicitMixed = false; - private bool $bleedingEdge = false; - private bool $reportPossiblyNonexistentGeneralArrayOffset = false; private bool $reportPossiblyNonexistentConstantArrayOffset = false; @@ -29,154 +27,13 @@ protected function getRule(): Rule return new NonexistentOffsetInArrayDimFetchRule( $ruleLevelHelper, - new NonexistentOffsetInArrayDimFetchCheck($ruleLevelHelper, true, $this->bleedingEdge, $this->reportPossiblyNonexistentGeneralArrayOffset, $this->reportPossiblyNonexistentConstantArrayOffset), + new NonexistentOffsetInArrayDimFetchCheck($ruleLevelHelper, true, $this->reportPossiblyNonexistentGeneralArrayOffset, $this->reportPossiblyNonexistentConstantArrayOffset), true, ); } public function testRule(): void { - $this->analyse([__DIR__ . '/data/nonexistent-offset.php'], [ - [ - 'Offset \'b\' does not exist on array{a: stdClass, 0: 2}.', - 17, - ], - [ - 'Offset 1 does not exist on array{a: stdClass, 0: 2}.', - 18, - ], - [ - 'Offset \'a\' does not exist on array{b: 1}.', - 55, - ], - [ - 'Access to offset \'bar\' on an unknown class NonexistentOffset\Bar.', - 101, - 'Learn more at https://phpstan.org/user-guide/discovering-symbols', - ], - [ - 'Access to an offset on an unknown class NonexistentOffset\Bar.', - 102, - 'Learn more at https://phpstan.org/user-guide/discovering-symbols', - ], - [ - 'Offset 0 does not exist on array.', - 111, - ], - [ - 'Offset \'0\' does not exist on array.', - 112, - ], - [ - 'Offset int does not exist on array.', - 114, - ], - [ - 'Offset \'test\' does not exist on null.', - 126, - ], - [ - 'Cannot access offset 42 on int.', - 142, - ], - [ - 'Cannot access offset 42 on float.', - 143, - ], - [ - 'Cannot access offset 42 on bool.', - 144, - ], - [ - 'Cannot access offset 42 on resource.', - 145, - ], - [ - 'Offset \'c\' does not exist on array{c: false}|array{c: true}|array{e: true}.', - 171, - ], - [ - 'Offset int does not exist on array{}|array{1: 1, 2: 2}|array{3: 3, 4: 4}.', - 190, - ], - [ - 'Offset int does not exist on array{}|array{1: 1, 2: 2}|array{3: 3, 4: 4}.', - 193, - ], - [ - 'Offset \'b\' does not exist on array{a: \'blabla\'}.', - 225, - ], - [ - 'Offset \'b\' does not exist on array{a: \'blabla\'}.', - 228, - ], - [ - 'Cannot access offset \'a\' on Closure(): void.', - 253, - ], - [ - 'Cannot access offset \'a\' on array{a: 1, b: 1}|(Closure(): void).', - 258, - ], - [ - 'Offset null does not exist on array.', - 310, - ], - [ - 'Offset int does not exist on array.', - 312, - ], - [ - 'Offset \'baz\' does not exist on array{bar: 1, baz?: 2}.', - 344, - ], - [ - 'Offset \'foo\' does not exist on ArrayAccess.', - 411, - ], - [ - 'Cannot access offset \'foo\' on stdClass.', - 423, - ], - [ - 'Cannot access offset \'foo\' on true.', - 426, - ], - [ - 'Cannot access offset \'foo\' on false.', - 429, - ], - [ - 'Cannot access offset \'foo\' on resource.', - 433, - ], - [ - 'Cannot access offset \'foo\' on 42.', - 436, - ], - [ - 'Cannot access offset \'foo\' on 4.141.', - 439, - ], - [ - 'Cannot access offset \'foo\' on array|int.', - 443, - ], - [ - 'Offset \'feature_pretty…\' does not exist on array{version: non-falsy-string, commit: string|null, pretty_version: string|null, feature_version: non-falsy-string, feature_pretty_version?: string|null}.', - 504, - ], - [ - "Cannot access offset 'foo' on bool.", - 517, - ], - ]); - } - - public function testRuleBleedingEdge(): void - { - $this->bleedingEdge = true; $this->analyse([__DIR__ . '/data/nonexistent-offset.php'], [ [ 'Offset \'b\' does not exist on array{a: stdClass, 0: 2}.', @@ -327,11 +184,11 @@ public function testStrings(): void 13, ], [ - 'Offset \'foo\' does not exist on array|string.', + 'Offset \'foo\' might not exist on array|string.', 24, ], [ - 'Offset 12.34 does not exist on array|string.', + 'Offset 12.34 might not exist on array|string.', 28, ], ]); @@ -531,7 +388,7 @@ public function testBug7000(): void { $this->analyse([__DIR__ . '/data/bug-7000.php'], [ [ - "Offset 'require'|'require-dev' does not exist on array{require?: array, require-dev?: array}.", + "Offset 'require'|'require-dev' might not exist on array{require?: array, require-dev?: array}.", 16, ], ]); @@ -692,7 +549,6 @@ public function testBug6243(): void public function testBug8356(): void { - $this->bleedingEdge = true; $this->analyse([__DIR__ . '/data/bug-8356.php'], [ [ "Offset 'x' might not exist on array|string.", diff --git a/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php index b0d674c716..e84e4956c7 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php @@ -13,8 +13,6 @@ class BooleanAndConstantConditionRuleTest extends RuleTestCase private bool $treatPhpDocTypesAsCertain; - private bool $bleedingEdge = false; - private bool $reportAlwaysTrueInLastCondition = false; protected function getRule(): Rule @@ -32,7 +30,6 @@ protected function getRule(): Rule true, ), $this->treatPhpDocTypesAsCertain, - $this->bleedingEdge, $this->reportAlwaysTrueInLastCondition, true, ); @@ -140,90 +137,6 @@ public function testRuleLogicalAnd(): void { $this->treatPhpDocTypesAsCertain = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->analyse([__DIR__ . '/data/boolean-logical-and.php'], [ - [ - 'Left side of && is always true.', - 15, - ], - [ - 'Right side of && is always true.', - 19, - ], - [ - 'Left side of && is always false.', - 24, - ], - [ - 'Right side of && is always false.', - 27, - ], - [ - 'Result of && is always false.', - 30, - ], - [ - 'Right side of && is always true.', - 33, - ], - [ - 'Right side of && is always true.', - 36, - ], - [ - 'Right side of && is always true.', - 39, - ], - [ - 'Result of && is always false.', - 50, - ], - [ - 'Result of && is always true.', - 54, - $tipText, - ], - [ - 'Result of && is always false.', - 60, - ], - [ - 'Result of && is always true.', - 64, - //$tipText, - ], - [ - 'Result of && is always false.', - 66, - //$tipText, - ], - [ - 'Result of && is always false.', - 125, - ], - [ - 'Left side of && is always false.', - 139, - ], - [ - 'Right side of && is always false.', - 141, - ], - [ - 'Left side of && is always true.', - 145, - ], - [ - 'Right side of && is always true.', - 147, - ], - ]); - } - - public function testRuleLogicalAndBleedingEdge(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->bleedingEdge = true; - $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; $this->analyse([__DIR__ . '/data/boolean-logical-and.php'], [ [ 'Left side of and is always true.', diff --git a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php index 38092ce153..b5d52ba9a0 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php @@ -14,8 +14,6 @@ class BooleanOrConstantConditionRuleTest extends RuleTestCase private bool $treatPhpDocTypesAsCertain; - private bool $bleedingEdge = false; - private bool $reportAlwaysTrueInLastCondition = false; protected function getRule(): Rule @@ -33,7 +31,6 @@ protected function getRule(): Rule true, ), $this->treatPhpDocTypesAsCertain, - $this->bleedingEdge, $this->reportAlwaysTrueInLastCondition, true, ); @@ -132,81 +129,6 @@ public function testRuleLogicalOr(): void { $this->treatPhpDocTypesAsCertain = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->analyse([__DIR__ . '/data/boolean-logical-or.php'], [ - [ - 'Left side of || is always true.', - 15, - ], - [ - 'Right side of || is always true.', - 19, - ], - [ - 'Left side of || is always false.', - 24, - ], - [ - 'Right side of || is always false.', - 27, - ], - [ - 'Right side of || is always true.', - 30, - ], - [ - 'Result of || is always true.', - 33, - ], - [ - 'Right side of || is always false.', - 36, - ], - [ - 'Right side of || is always false.', - 39, - ], - [ - 'Result of || is always true.', - 50, - $tipText, - ], - [ - 'Result of || is always true.', - 54, - $tipText, - ], - [ - 'Result of || is always true.', - 61, - ], - [ - 'Result of || is always true.', - 65, - ], - [ - 'Left side of || is always false.', - 77, - ], - [ - 'Right side of || is always false.', - 79, - ], - [ - 'Left side of || is always true.', - 83, - ], - [ - 'Right side of || is always true.', - 85, - ], - ]); - } - - public function testRuleLogicalOrBleedingEdge(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->bleedingEdge = true; - $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; $this->analyse([__DIR__ . '/data/boolean-logical-or.php'], [ [ 'Left side of or is always true.', From 3d61987490899e76cb7d23a06b0b099693445aba Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 10:57:36 +0200 Subject: [PATCH 145/508] [BE] Stricter ++/-- operator check --- changelog-2.0.md | 2 +- conf/config.level0.neon | 9 +---- .../Operators/InvalidIncDecOperationRule.php | 34 +++++-------------- .../InvalidIncDecOperationRuleTest.php | 2 -- 4 files changed, 11 insertions(+), 36 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index c2df639285..2027c9081c 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -107,7 +107,6 @@ Bleeding edge (TODO move to other sections) * Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! * Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! -* Stricter ++/-- operator check ([#3255](https://github.com/phpstan/phpstan-src/pull/3255)), thanks @schlndh! * Check preg_quote delimiter sanity ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3! * Check array functions which require stringish values ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! @@ -141,6 +140,7 @@ Improvements 🔧 * OverridingMethodRule - include template types in prototype declaring class description (https://github.com/phpstan/phpstan-src/commit/ca2c66cc4dff59ba44d52b82cb9e0aa3256240f3) * Detect overriding `@final` method in OverridingMethodRule, #9135 * Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! +* Stricter ++/-- operator check ([#3255](https://github.com/phpstan/phpstan-src/pull/3255)), thanks @schlndh! Bugfixes 🐛 ===================== diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 60f2e7e5fc..1d5325aefa 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -106,6 +106,7 @@ rules: - PHPStan\Rules\Methods\StaticMethodCallableRule - PHPStan\Rules\Names\UsedNamesRule - PHPStan\Rules\Operators\InvalidAssignVarRule + - PHPStan\Rules\Operators\InvalidIncDecOperationRule - PHPStan\Rules\Properties\AccessPropertiesInAssignRule - PHPStan\Rules\Properties\AccessStaticPropertiesInAssignRule - PHPStan\Rules\Properties\InvalidCallablePropertyTypeRule @@ -203,14 +204,6 @@ services: arguments: checkFunctionNameCase: %checkFunctionNameCase% - - - class: PHPStan\Rules\Operators\InvalidIncDecOperationRule - tags: - - phpstan.rules.rule - arguments: - bleedingEdge: %featureToggles.bleedingEdge% - checkThisOnly: %checkThisOnly% - - class: PHPStan\Rules\Properties\AccessPropertiesRule tags: diff --git a/src/Rules/Operators/InvalidIncDecOperationRule.php b/src/Rules/Operators/InvalidIncDecOperationRule.php index 6f3382d829..8283936e73 100644 --- a/src/Rules/Operators/InvalidIncDecOperationRule.php +++ b/src/Rules/Operators/InvalidIncDecOperationRule.php @@ -29,8 +29,6 @@ final class InvalidIncDecOperationRule implements Rule public function __construct( private RuleLevelHelper $ruleLevelHelper, - private bool $bleedingEdge, - private bool $checkThisOnly, ) { } @@ -87,30 +85,16 @@ public function processNode(Node $node, Scope $scope): array ]; } - if (!$this->bleedingEdge) { - if ($this->checkThisOnly) { - return []; - } + $allowedTypes = new UnionType([new BooleanType(), new FloatType(), new IntegerType(), new StringType(), new NullType(), new ObjectType('SimpleXMLElement')]); + $varType = $this->ruleLevelHelper->findTypeToCheck( + $scope, + $node->var, + '', + static fn (Type $type): bool => $allowedTypes->isSuperTypeOf($type)->yes(), + )->getType(); - $varType = $scope->getType($node->var); - if (!$varType->toString() instanceof ErrorType) { - return []; - } - if (!$varType->toNumber() instanceof ErrorType) { - return []; - } - } else { - $allowedTypes = new UnionType([new BooleanType(), new FloatType(), new IntegerType(), new StringType(), new NullType(), new ObjectType('SimpleXMLElement')]); - $varType = $this->ruleLevelHelper->findTypeToCheck( - $scope, - $node->var, - '', - static fn (Type $type): bool => $allowedTypes->isSuperTypeOf($type)->yes(), - )->getType(); - - if ($varType instanceof ErrorType || $allowedTypes->isSuperTypeOf($varType)->yes()) { - return []; - } + if ($varType instanceof ErrorType || $allowedTypes->isSuperTypeOf($varType)->yes()) { + return []; } return [ diff --git a/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php index 5dd8aae36f..63c757ecc8 100644 --- a/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidIncDecOperationRuleTest.php @@ -21,8 +21,6 @@ protected function getRule(): Rule { return new InvalidIncDecOperationRule( new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), - true, - false, ); } From f9cd2a061d0b73c665c3c9b1d300091edf9b6a36 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 11:01:18 +0200 Subject: [PATCH 146/508] [BE] Check mixed in binary and unary operators --- changelog-2.0.md | 4 +- conf/config.level2.neon | 14 +---- .../Operators/InvalidBinaryOperationRule.php | 5 -- .../Operators/InvalidUnaryOperationRule.php | 53 +++++++++---------- .../InvalidBinaryOperationRuleTest.php | 1 - .../InvalidUnaryOperationRuleTest.php | 1 - 6 files changed, 28 insertions(+), 50 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 2027c9081c..64b626d8af 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -104,9 +104,7 @@ Bleeding edge (TODO move to other sections) * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 * RegularExpressionPatternRule: validate preg_quote'd patterns ([#3270](https://github.com/phpstan/phpstan-src/pull/3270)), thanks @staabm! * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! -* Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! -* Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! * Check preg_quote delimiter sanity ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3! * Check array functions which require stringish values ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! @@ -141,6 +139,8 @@ Improvements 🔧 * Detect overriding `@final` method in OverridingMethodRule, #9135 * Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! * Stricter ++/-- operator check ([#3255](https://github.com/phpstan/phpstan-src/pull/3255)), thanks @schlndh! +* Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! +* Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! Bugfixes 🐛 ===================== diff --git a/conf/config.level2.neon b/conf/config.level2.neon index 6ff60ddf87..715f1089a8 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -39,7 +39,9 @@ rules: - PHPStan\Rules\Generics\UsedTraitsRule - PHPStan\Rules\Methods\CallPrivateMethodThroughStaticRule - PHPStan\Rules\Methods\IncompatibleDefaultParameterTypeRule + - PHPStan\Rules\Operators\InvalidBinaryOperationRule - PHPStan\Rules\Operators\InvalidComparisonOperationRule + - PHPStan\Rules\Operators\InvalidUnaryOperationRule - PHPStan\Rules\PhpDoc\FunctionConditionalReturnTypeRule - PHPStan\Rules\PhpDoc\MethodConditionalReturnTypeRule - PHPStan\Rules\PhpDoc\FunctionAssertRule @@ -140,15 +142,3 @@ services: - class: PHPStan\Rules\Pure\PureMethodRule - - - class: PHPStan\Rules\Operators\InvalidBinaryOperationRule - arguments: - bleedingEdge: %featureToggles.bleedingEdge% - tags: - - phpstan.rules.rule - - - class: PHPStan\Rules\Operators\InvalidUnaryOperationRule - arguments: - bleedingEdge: %featureToggles.bleedingEdge% - tags: - - phpstan.rules.rule diff --git a/src/Rules/Operators/InvalidBinaryOperationRule.php b/src/Rules/Operators/InvalidBinaryOperationRule.php index 77653e1f1a..e44b2178d5 100644 --- a/src/Rules/Operators/InvalidBinaryOperationRule.php +++ b/src/Rules/Operators/InvalidBinaryOperationRule.php @@ -27,7 +27,6 @@ final class InvalidBinaryOperationRule implements Rule public function __construct( private ExprPrinter $exprPrinter, private RuleLevelHelper $ruleLevelHelper, - private bool $bleedingEdge, ) { } @@ -46,10 +45,6 @@ public function processNode(Node $node, Scope $scope): array return []; } - if (!$scope->getType($node) instanceof ErrorType && !$this->bleedingEdge) { - return []; - } - $leftName = '__PHPSTAN__LEFT__'; $rightName = '__PHPSTAN__RIGHT__'; $leftVariable = new Node\Expr\Variable($leftName); diff --git a/src/Rules/Operators/InvalidUnaryOperationRule.php b/src/Rules/Operators/InvalidUnaryOperationRule.php index cf823a82bf..6600cce4ad 100644 --- a/src/Rules/Operators/InvalidUnaryOperationRule.php +++ b/src/Rules/Operators/InvalidUnaryOperationRule.php @@ -23,7 +23,6 @@ final class InvalidUnaryOperationRule implements Rule public function __construct( private RuleLevelHelper $ruleLevelHelper, - private bool $bleedingEdge, ) { } @@ -43,38 +42,34 @@ public function processNode(Node $node, Scope $scope): array return []; } - if ($this->bleedingEdge) { - $varName = '__PHPSTAN__LEFT__'; - $variable = new Node\Expr\Variable($varName); - $newNode = clone $node; - $newNode->setAttribute('phpstan_cache_printer', null); - $newNode->expr = $variable; + $varName = '__PHPSTAN__LEFT__'; + $variable = new Node\Expr\Variable($varName); + $newNode = clone $node; + $newNode->setAttribute('phpstan_cache_printer', null); + $newNode->expr = $variable; - if ($node instanceof Node\Expr\BitwiseNot) { - $callback = static fn (Type $type): bool => $type->isString()->yes() || $type->isInteger()->yes() || $type->isFloat()->yes(); - } else { - $callback = static fn (Type $type): bool => !$type->toNumber() instanceof ErrorType; - } + if ($node instanceof Node\Expr\BitwiseNot) { + $callback = static fn (Type $type): bool => $type->isString()->yes() || $type->isInteger()->yes() || $type->isFloat()->yes(); + } else { + $callback = static fn (Type $type): bool => !$type->toNumber() instanceof ErrorType; + } - $exprType = $this->ruleLevelHelper->findTypeToCheck( - $scope, - $node->expr, - '', - $callback, - )->getType(); - if ($exprType instanceof ErrorType) { - return []; - } + $exprType = $this->ruleLevelHelper->findTypeToCheck( + $scope, + $node->expr, + '', + $callback, + )->getType(); + if ($exprType instanceof ErrorType) { + return []; + } - if (!$scope instanceof MutatingScope) { - throw new ShouldNotHappenException(); - } + if (!$scope instanceof MutatingScope) { + throw new ShouldNotHappenException(); + } - $scope = $scope->assignVariable($varName, $exprType, $exprType, TrinaryLogic::createYes()); - if (!$scope->getType($newNode) instanceof ErrorType) { - return []; - } - } elseif (!$scope->getType($node) instanceof ErrorType) { + $scope = $scope->assignVariable($varName, $exprType, $exprType, TrinaryLogic::createYes()); + if (!$scope->getType($newNode) instanceof ErrorType) { return []; } diff --git a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php index 625e2d615e..24ae397dbb 100644 --- a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule return new InvalidBinaryOperationRule( new ExprPrinter(new Printer()), new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), - true, ); } diff --git a/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php index 909472e091..afd0611e89 100644 --- a/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidUnaryOperationRuleTest.php @@ -21,7 +21,6 @@ protected function getRule(): Rule { return new InvalidUnaryOperationRule( new RuleLevelHelper($this->createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), - true, ); } From b7d10c89f40a652a351d5154ea361d76b79ab56f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 11:07:01 +0200 Subject: [PATCH 147/508] [BCB] Removed `checkMissingIterableValueType` config option --- UPGRADING.md | 13 +++++++++++ changelog-2.0.md | 1 - conf/bleedingEdge.neon | 1 - conf/config.level6.neon | 1 - conf/config.neon | 4 ---- conf/config.stubValidator.neon | 1 - conf/parametersSchema.neon | 2 -- src/Command/CommandHelper.php | 22 ------------------- src/Rules/MissingTypehintCheck.php | 8 ------- .../Classes/LocalTypeAliasesRuleTest.php | 2 +- .../Classes/LocalTypeTraitAliasesRuleTest.php | 2 +- .../LocalTypeTraitUseAliasesRuleTest.php | 2 +- .../Rules/Classes/MethodTagRuleTest.php | 2 +- .../Rules/Classes/MethodTagTraitRuleTest.php | 2 +- .../Classes/MethodTagTraitUseRuleTest.php | 2 +- tests/PHPStan/Rules/Classes/MixinRuleTest.php | 2 +- .../Rules/Classes/MixinTraitRuleTest.php | 2 +- .../Rules/Classes/MixinTraitUseRuleTest.php | 2 +- .../Rules/Classes/PropertyTagRuleTest.php | 2 +- .../Classes/PropertyTagTraitRuleTest.php | 2 +- .../Classes/PropertyTagTraitUseRuleTest.php | 2 +- .../MissingClassConstantTypehintRuleTest.php | 2 +- ...ssingFunctionParameterTypehintRuleTest.php | 2 +- .../MissingFunctionReturnTypehintRuleTest.php | 2 +- ...MissingMethodParameterTypehintRuleTest.php | 2 +- .../MissingMethodReturnTypehintRuleTest.php | 2 +- .../MissingMethodSelfOutTypeRuleTest.php | 2 +- .../InvalidPhpDocVarTagTypeRuleTest.php | 2 +- .../MissingPropertyTypehintRuleTest.php | 2 +- 29 files changed, 33 insertions(+), 60 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index f31af1f3d3..07238f106c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -32,6 +32,19 @@ Don't forget to update [3rd party PHPStan extensions](https://phpstan.org/user-g After changing your `composer.json`, run `composer update 'phpstan/*' -W`. +### Removed option `checkMissingIterableValueType` + +It's strongly recommended to add the missing array typehints. + +If you want to continue ignoring missing typehints from arrays, add `missingType.iterableValue` error identifier to your `ignoreErrors`: + +```neon +parameters: + ignoreErrors: + - + identifier: missingType.iterableValue +``` + ### Paths in `excludePaths` and `ignoreErrors` have to be a valid file path or a fnmatch pattern If you are excluding a file path that might not exist but you still want to have it in `excludePaths`, append `(?)`: diff --git a/changelog-2.0.md b/changelog-2.0.md index 64b626d8af..bcda7deb8c 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -38,7 +38,6 @@ Bleeding edge (TODO move to other sections) * In testing the memory consumption was reduced by 50–70 %. * ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! * Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! -* `checkMissingIterableValueType: false` no longer does anything (https://github.com/phpstan/phpstan-src/commit/50d0c8e23ea85da508ab8481f1ff2c89148cc80b) * ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) * Unresolvable parameters ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index d0b7eba94b..b910eaa88e 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -8,7 +8,6 @@ parameters: arrayValues: true nodeConnectingVisitorCompatibility: false nodeConnectingVisitorRule: true - disableCheckMissingIterableValueType: true strictUnnecessaryNullsafePropertyFetch: true looseComparison: true consistentConstructor: true diff --git a/conf/config.level6.neon b/conf/config.level6.neon index e49ad444b9..ec0c815769 100644 --- a/conf/config.level6.neon +++ b/conf/config.level6.neon @@ -3,7 +3,6 @@ includes: parameters: checkGenericClassInNonGenericObjectType: true - checkMissingIterableValueType: true checkMissingVarTagTypehint: true checkMissingTypehints: true diff --git a/conf/config.neon b/conf/config.neon index cb61959d66..a5fdd2eb72 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -43,7 +43,6 @@ parameters: nodeConnectingVisitorCompatibility: true nodeConnectingVisitorRule: false illegalConstructorMethodCall: false - disableCheckMissingIterableValueType: false strictUnnecessaryNullsafePropertyFetch: false looseComparison: false consistentConstructor: false @@ -96,7 +95,6 @@ parameters: checkFunctionNameCase: false checkGenericClassInNonGenericObjectType: false checkInternalClassCaseSensitivity: false - checkMissingIterableValueType: false checkMissingCallableSignature: false checkMissingVarTagTypehint: false checkArgumentsPassedByReference: false @@ -1044,8 +1042,6 @@ services: - class: PHPStan\Rules\MissingTypehintCheck arguments: - checkMissingIterableValueType: %checkMissingIterableValueType% - disableCheckMissingIterableValueType: %featureToggles.disableCheckMissingIterableValueType% checkGenericClassInNonGenericObjectType: %checkGenericClassInNonGenericObjectType% checkMissingCallableSignature: %checkMissingCallableSignature% skipCheckGenericClasses: %featureToggles.skipCheckGenericClasses% diff --git a/conf/config.stubValidator.neon b/conf/config.stubValidator.neon index ae22e5ccdc..c33dc1edf2 100644 --- a/conf/config.stubValidator.neon +++ b/conf/config.stubValidator.neon @@ -2,7 +2,6 @@ parameters: checkThisOnly: false checkClassCaseSensitivity: true checkGenericClassInNonGenericObjectType: true - checkMissingIterableValueType: true checkMissingTypehints: true checkMissingCallableSignature: false __validate: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index f797b4608b..3c8b147a88 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -38,7 +38,6 @@ parametersSchema: nodeConnectingVisitorCompatibility: bool(), nodeConnectingVisitorRule: bool(), illegalConstructorMethodCall: bool(), - disableCheckMissingIterableValueType: bool(), strictUnnecessaryNullsafePropertyFetch: bool(), looseComparison: bool(), consistentConstructor: bool() @@ -90,7 +89,6 @@ parametersSchema: checkFunctionNameCase: bool() checkGenericClassInNonGenericObjectType: bool() checkInternalClassCaseSensitivity: bool() - checkMissingIterableValueType: bool() checkMissingCallableSignature: bool() checkMissingVarTagTypehint: bool() checkArgumentsPassedByReference: bool() diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index c899ccc8cc..bd25174977 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -547,28 +547,6 @@ public static function begin( if ($projectConfig !== null) { $parameters = $projectConfig['parameters'] ?? []; - /** @var bool $checkMissingIterableValueType */ - $checkMissingIterableValueType = $parameters['checkMissingIterableValueType'] ?? true; - if (!$checkMissingIterableValueType) { - $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option checkMissingIterableValueType ⚠️️'); - $errorOutput->writeLineFormatted(''); - - $featureToggles = $container->getParameter('featureToggles'); - if (!((bool) $featureToggles['bleedingEdge'])) { - $errorOutput->writeLineFormatted('It\'s strongly recommended to remove it from your configuration file'); - $errorOutput->writeLineFormatted('and add the missing array typehints.'); - $errorOutput->writeLineFormatted(''); - } - - $errorOutput->writeLineFormatted('If you want to continue ignoring missing typehints from arrays,'); - $errorOutput->writeLineFormatted('add missingType.iterableValue error identifier to your ignoreErrors:'); - $errorOutput->writeLineFormatted(''); - $errorOutput->writeLineFormatted('parameters:'); - $errorOutput->writeLineFormatted("\tignoreErrors:"); - $errorOutput->writeLineFormatted("\t\t-"); - $errorOutput->writeLineFormatted("\t\t\tidentifier: missingType.iterableValue"); - $errorOutput->writeLineFormatted(''); - } /** @var bool $checkGenericClassInNonGenericObjectType */ $checkGenericClassInNonGenericObjectType = $parameters['checkGenericClassInNonGenericObjectType'] ?? true; diff --git a/src/Rules/MissingTypehintCheck.php b/src/Rules/MissingTypehintCheck.php index d6c55e62ec..50e081b0e5 100644 --- a/src/Rules/MissingTypehintCheck.php +++ b/src/Rules/MissingTypehintCheck.php @@ -43,8 +43,6 @@ final class MissingTypehintCheck * @param string[] $skipCheckGenericClasses */ public function __construct( - private bool $disableCheckMissingIterableValueType, - private bool $checkMissingIterableValueType, private bool $checkGenericClassInNonGenericObjectType, private bool $checkMissingCallableSignature, private array $skipCheckGenericClasses, @@ -57,12 +55,6 @@ public function __construct( */ public function getIterableTypesWithMissingValueTypehint(Type $type): array { - if (!$this->checkMissingIterableValueType) { - if (!$this->disableCheckMissingIterableValueType) { - return []; - } - } - $iterablesWithMissingValueTypehint = []; TypeTraverser::map($type, function (Type $type, callable $traverse) use (&$iterablesWithMissingValueTypehint): Type { if ($type instanceof TemplateType) { diff --git a/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php index 7455afc8cc..9bf5516553 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule ['GlobalTypeAlias' => 'int|string'], $this->createReflectionProvider(), self::getContainer()->getByType(TypeNodeResolver::class), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php index a598bbd9df..1dec5922bf 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php @@ -27,7 +27,7 @@ protected function getRule(): Rule ['GlobalTypeAlias' => 'int|string'], $this->createReflectionProvider(), self::getContainer()->getByType(TypeNodeResolver::class), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php index 05f8fe03ff..d78a5c795e 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php @@ -27,7 +27,7 @@ protected function getRule(): Rule ['GlobalTypeAlias' => 'int|string'], $this->createReflectionProvider(), self::getContainer()->getByType(TypeNodeResolver::class), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/MethodTagRuleTest.php b/tests/PHPStan/Rules/Classes/MethodTagRuleTest.php index 7766e03bd8..8a8489dc5e 100644 --- a/tests/PHPStan/Rules/Classes/MethodTagRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MethodTagRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php b/tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php index 74f70ca72d..6c048e0674 100644 --- a/tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php b/tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php index 7839c99123..3a2e328b99 100644 --- a/tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php @@ -30,7 +30,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MixinRuleTest.php b/tests/PHPStan/Rules/Classes/MixinRuleTest.php index acaf1974b0..101500b183 100644 --- a/tests/PHPStan/Rules/Classes/MixinRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinRuleTest.php @@ -30,7 +30,7 @@ protected function getRule(): Rule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php b/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php index f23e120458..87dbaaf1f9 100644 --- a/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): Rule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php b/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php index dbc7906da5..2fc73704ee 100644 --- a/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): Rule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php b/tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php index 7b36d89e90..43dc3e29f9 100644 --- a/tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php +++ b/tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php b/tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php index 3e6ff6c953..e4b92673e5 100644 --- a/tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php +++ b/tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/PropertyTagTraitUseRuleTest.php b/tests/PHPStan/Rules/Classes/PropertyTagTraitUseRuleTest.php index 76b4342abe..50212df3db 100644 --- a/tests/PHPStan/Rules/Classes/PropertyTagTraitUseRuleTest.php +++ b/tests/PHPStan/Rules/Classes/PropertyTagTraitUseRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php b/tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php index 89b6302e8a..e3cccffa5f 100644 --- a/tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php @@ -15,7 +15,7 @@ class MissingClassConstantTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingClassConstantTypehintRule(new MissingTypehintCheck(true, true, true, true, [])); + return new MissingClassConstantTypehintRule(new MissingTypehintCheck(true, true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php b/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php index 73a197f3a5..6eb78628d2 100644 --- a/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingFunctionParameterTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingFunctionParameterTypehintRule(new MissingTypehintCheck(true, true, true, true, [])); + return new MissingFunctionParameterTypehintRule(new MissingTypehintCheck(true, true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php b/tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php index 37cd3ffb81..0a93340e1f 100644 --- a/tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingFunctionReturnTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingFunctionReturnTypehintRule(new MissingTypehintCheck(true, true, true, true, [])); + return new MissingFunctionReturnTypehintRule(new MissingTypehintCheck(true, true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php b/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php index 48c0c6acde..a7ce5312ca 100644 --- a/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingMethodParameterTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingMethodParameterTypehintRule(new MissingTypehintCheck(true, true, true, true, [])); + return new MissingMethodParameterTypehintRule(new MissingTypehintCheck(true, true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Methods/MissingMethodReturnTypehintRuleTest.php b/tests/PHPStan/Rules/Methods/MissingMethodReturnTypehintRuleTest.php index 0762900901..742d3f0287 100644 --- a/tests/PHPStan/Rules/Methods/MissingMethodReturnTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MissingMethodReturnTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingMethodReturnTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingMethodReturnTypehintRule(new MissingTypehintCheck(true, true, true, true, [])); + return new MissingMethodReturnTypehintRule(new MissingTypehintCheck(true, true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php b/tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php index 373e46494a..9f3af68ae6 100644 --- a/tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php @@ -14,7 +14,7 @@ class MissingMethodSelfOutTypeRuleTest extends RuleTestCase protected function getRule(): TRule { - return new MissingMethodSelfOutTypeRule(new MissingTypehintCheck(true, true, true, true, [])); + return new MissingMethodSelfOutTypeRule(new MissingTypehintCheck(true, true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocVarTagTypeRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocVarTagTypeRuleTest.php index 9d4dc0bb3e..e432a8b7a9 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocVarTagTypeRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocVarTagTypeRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): Rule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Properties/MissingPropertyTypehintRuleTest.php b/tests/PHPStan/Rules/Properties/MissingPropertyTypehintRuleTest.php index bd92fe752e..a334333851 100644 --- a/tests/PHPStan/Rules/Properties/MissingPropertyTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Properties/MissingPropertyTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingPropertyTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingPropertyTypehintRule(new MissingTypehintCheck(true, true, true, true, [])); + return new MissingPropertyTypehintRule(new MissingTypehintCheck(true, true, [])); } public function testRule(): void From 47dc2e65fd3019a56e737fb8e540c02cb64e69a2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 11:13:44 +0200 Subject: [PATCH 148/508] [BCB] Removed `checkGenericClassInNonGenericObjectType` config option --- UPGRADING.md | 13 +++++++ conf/config.level6.neon | 1 - conf/config.neon | 3 -- conf/config.stubValidator.neon | 1 - conf/parametersSchema.neon | 1 - src/Command/CommandHelper.php | 22 ----------- src/Rules/Generics/GenericAncestorsCheck.php | 39 +++++++++---------- src/Rules/MissingTypehintCheck.php | 5 --- .../Classes/LocalTypeAliasesRuleTest.php | 2 +- .../Classes/LocalTypeTraitAliasesRuleTest.php | 2 +- .../LocalTypeTraitUseAliasesRuleTest.php | 2 +- .../Rules/Classes/MethodTagRuleTest.php | 2 +- .../Rules/Classes/MethodTagTraitRuleTest.php | 2 +- .../Classes/MethodTagTraitUseRuleTest.php | 2 +- tests/PHPStan/Rules/Classes/MixinRuleTest.php | 2 +- .../Rules/Classes/MixinTraitRuleTest.php | 2 +- .../Rules/Classes/MixinTraitUseRuleTest.php | 2 +- .../Rules/Classes/PropertyTagRuleTest.php | 2 +- .../Classes/PropertyTagTraitRuleTest.php | 2 +- .../Classes/PropertyTagTraitUseRuleTest.php | 2 +- .../MissingClassConstantTypehintRuleTest.php | 2 +- ...ssingFunctionParameterTypehintRuleTest.php | 2 +- .../MissingFunctionReturnTypehintRuleTest.php | 2 +- .../Rules/Generics/ClassAncestorsRuleTest.php | 1 - .../Rules/Generics/EnumAncestorsRuleTest.php | 1 - .../Generics/InterfaceAncestorsRuleTest.php | 1 - .../Rules/Generics/UsedTraitsRuleTest.php | 1 - ...MissingMethodParameterTypehintRuleTest.php | 2 +- .../MissingMethodReturnTypehintRuleTest.php | 2 +- .../MissingMethodSelfOutTypeRuleTest.php | 2 +- .../InvalidPhpDocVarTagTypeRuleTest.php | 2 +- .../MissingPropertyTypehintRuleTest.php | 2 +- 32 files changed, 51 insertions(+), 78 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 07238f106c..752970842b 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -45,6 +45,19 @@ parameters: identifier: missingType.iterableValue ``` +### Removed option `checkGenericClassInNonGenericObjectType` + +It's strongly recommended to add the missing generic typehints. + +If you want to continue ignoring missing typehints from generics, add `missingType.generics` error identifier to your `ignoreErrors`: + +```neon +parameters: + ignoreErrors: + - + identifier: missingType.generics +``` + ### Paths in `excludePaths` and `ignoreErrors` have to be a valid file path or a fnmatch pattern If you are excluding a file path that might not exist but you still want to have it in `excludePaths`, append `(?)`: diff --git a/conf/config.level6.neon b/conf/config.level6.neon index ec0c815769..25214e97dd 100644 --- a/conf/config.level6.neon +++ b/conf/config.level6.neon @@ -2,7 +2,6 @@ includes: - config.level5.neon parameters: - checkGenericClassInNonGenericObjectType: true checkMissingVarTagTypehint: true checkMissingTypehints: true diff --git a/conf/config.neon b/conf/config.neon index a5fdd2eb72..801e3fe8b6 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -93,7 +93,6 @@ parameters: checkImplicitMixed: false checkFunctionArgumentTypes: false checkFunctionNameCase: false - checkGenericClassInNonGenericObjectType: false checkInternalClassCaseSensitivity: false checkMissingCallableSignature: false checkMissingVarTagTypehint: false @@ -990,7 +989,6 @@ services: - class: PHPStan\Rules\Generics\GenericAncestorsCheck arguments: - checkGenericClassInNonGenericObjectType: %checkGenericClassInNonGenericObjectType% skipCheckGenericClasses: %featureToggles.skipCheckGenericClasses% - @@ -1042,7 +1040,6 @@ services: - class: PHPStan\Rules\MissingTypehintCheck arguments: - checkGenericClassInNonGenericObjectType: %checkGenericClassInNonGenericObjectType% checkMissingCallableSignature: %checkMissingCallableSignature% skipCheckGenericClasses: %featureToggles.skipCheckGenericClasses% diff --git a/conf/config.stubValidator.neon b/conf/config.stubValidator.neon index c33dc1edf2..07390c7b8f 100644 --- a/conf/config.stubValidator.neon +++ b/conf/config.stubValidator.neon @@ -1,7 +1,6 @@ parameters: checkThisOnly: false checkClassCaseSensitivity: true - checkGenericClassInNonGenericObjectType: true checkMissingTypehints: true checkMissingCallableSignature: false __validate: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 3c8b147a88..0919020939 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -87,7 +87,6 @@ parametersSchema: checkImplicitMixed: bool() checkFunctionArgumentTypes: bool() checkFunctionNameCase: bool() - checkGenericClassInNonGenericObjectType: bool() checkInternalClassCaseSensitivity: bool() checkMissingCallableSignature: bool() checkMissingVarTagTypehint: bool() diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index bd25174977..f380cfdbd0 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -545,28 +545,6 @@ public static function begin( $errorOutput->writeLineFormatted(sprintf('Please implement PHPStan\Type\ExpressionTypeResolverExtension interface instead and register it as a service.')); } - if ($projectConfig !== null) { - $parameters = $projectConfig['parameters'] ?? []; - - /** @var bool $checkGenericClassInNonGenericObjectType */ - $checkGenericClassInNonGenericObjectType = $parameters['checkGenericClassInNonGenericObjectType'] ?? true; - if (!$checkGenericClassInNonGenericObjectType) { - $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option checkGenericClassInNonGenericObjectType ⚠️️'); - $errorOutput->writeLineFormatted(''); - $errorOutput->writeLineFormatted('It\'s strongly recommended to remove it from your configuration file'); - $errorOutput->writeLineFormatted('and add the missing generic typehints.'); - $errorOutput->writeLineFormatted(''); - $errorOutput->writeLineFormatted('If you want to continue ignoring missing typehints from generics,'); - $errorOutput->writeLineFormatted('add missingType.generics error identifier to your ignoreErrors:'); - $errorOutput->writeLineFormatted(''); - $errorOutput->writeLineFormatted('parameters:'); - $errorOutput->writeLineFormatted("\tignoreErrors:"); - $errorOutput->writeLineFormatted("\t\t-"); - $errorOutput->writeLineFormatted("\t\t\tidentifier: missingType.generics"); - $errorOutput->writeLineFormatted(''); - } - } - $tempResultCachePath = $container->getParameter('tempResultCachePath'); $createDir($tempResultCachePath); diff --git a/src/Rules/Generics/GenericAncestorsCheck.php b/src/Rules/Generics/GenericAncestorsCheck.php index 201b5d3dc2..8dc3830cad 100644 --- a/src/Rules/Generics/GenericAncestorsCheck.php +++ b/src/Rules/Generics/GenericAncestorsCheck.php @@ -33,7 +33,6 @@ public function __construct( private GenericObjectTypeCheck $genericObjectTypeCheck, private VarianceCheck $varianceCheck, private UnresolvableTypeHelper $unresolvableTypeHelper, - private bool $checkGenericClassInNonGenericObjectType, private array $skipCheckGenericClasses, ) { @@ -152,28 +151,26 @@ public function check( } } - if ($this->checkGenericClassInNonGenericObjectType) { - foreach (array_keys($unusedNames) as $unusedName) { - if (!$this->reflectionProvider->hasClass($unusedName)) { - continue; - } - - $unusedNameClassReflection = $this->reflectionProvider->getClass($unusedName); - if (in_array($unusedNameClassReflection->getName(), $this->skipCheckGenericClasses, true)) { - continue; - } - if (!$unusedNameClassReflection->isGeneric()) { - continue; - } + foreach (array_keys($unusedNames) as $unusedName) { + if (!$this->reflectionProvider->hasClass($unusedName)) { + continue; + } - $messages[] = RuleErrorBuilder::message(sprintf( - $genericClassInNonGenericObjectType, - $unusedName, - implode(', ', array_keys($unusedNameClassReflection->getTemplateTypeMap()->getTypes())), - )) - ->identifier('missingType.generics') - ->build(); + $unusedNameClassReflection = $this->reflectionProvider->getClass($unusedName); + if (in_array($unusedNameClassReflection->getName(), $this->skipCheckGenericClasses, true)) { + continue; } + if (!$unusedNameClassReflection->isGeneric()) { + continue; + } + + $messages[] = RuleErrorBuilder::message(sprintf( + $genericClassInNonGenericObjectType, + $unusedName, + implode(', ', array_keys($unusedNameClassReflection->getTemplateTypeMap()->getTypes())), + )) + ->identifier('missingType.generics') + ->build(); } return $messages; diff --git a/src/Rules/MissingTypehintCheck.php b/src/Rules/MissingTypehintCheck.php index 50e081b0e5..dd0d451478 100644 --- a/src/Rules/MissingTypehintCheck.php +++ b/src/Rules/MissingTypehintCheck.php @@ -43,7 +43,6 @@ final class MissingTypehintCheck * @param string[] $skipCheckGenericClasses */ public function __construct( - private bool $checkGenericClassInNonGenericObjectType, private bool $checkMissingCallableSignature, private array $skipCheckGenericClasses, ) @@ -92,10 +91,6 @@ public function getIterableTypesWithMissingValueTypehint(Type $type): array */ public function getNonGenericObjectTypesWithGenericClass(Type $type): array { - if (!$this->checkGenericClassInNonGenericObjectType) { - return []; - } - $objectTypes = []; TypeTraverser::map($type, function (Type $type, callable $traverse) use (&$objectTypes): Type { if ($type instanceof GenericObjectType) { diff --git a/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php index 9bf5516553..47b81f1ea1 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php @@ -28,7 +28,7 @@ protected function getRule(): Rule ['GlobalTypeAlias' => 'int|string'], $this->createReflectionProvider(), self::getContainer()->getByType(TypeNodeResolver::class), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php index 1dec5922bf..76dc96f81c 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeTraitAliasesRuleTest.php @@ -27,7 +27,7 @@ protected function getRule(): Rule ['GlobalTypeAlias' => 'int|string'], $this->createReflectionProvider(), self::getContainer()->getByType(TypeNodeResolver::class), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php b/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php index d78a5c795e..a84377316b 100644 --- a/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/LocalTypeTraitUseAliasesRuleTest.php @@ -27,7 +27,7 @@ protected function getRule(): Rule ['GlobalTypeAlias' => 'int|string'], $this->createReflectionProvider(), self::getContainer()->getByType(TypeNodeResolver::class), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/MethodTagRuleTest.php b/tests/PHPStan/Rules/Classes/MethodTagRuleTest.php index 8a8489dc5e..ae7ff38ec5 100644 --- a/tests/PHPStan/Rules/Classes/MethodTagRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MethodTagRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php b/tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php index 6c048e0674..fce38f5d98 100644 --- a/tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php b/tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php index 3a2e328b99..5317938620 100644 --- a/tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php @@ -30,7 +30,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MixinRuleTest.php b/tests/PHPStan/Rules/Classes/MixinRuleTest.php index 101500b183..e05283e71b 100644 --- a/tests/PHPStan/Rules/Classes/MixinRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinRuleTest.php @@ -30,7 +30,7 @@ protected function getRule(): Rule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php b/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php index 87dbaaf1f9..9465723963 100644 --- a/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): Rule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php b/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php index 2fc73704ee..c94636b5e1 100644 --- a/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): Rule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php b/tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php index 43dc3e29f9..4ec02315e1 100644 --- a/tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php +++ b/tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php b/tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php index e4b92673e5..1266a5a553 100644 --- a/tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php +++ b/tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Classes/PropertyTagTraitUseRuleTest.php b/tests/PHPStan/Rules/Classes/PropertyTagTraitUseRuleTest.php index 50212df3db..f45a1b894d 100644 --- a/tests/PHPStan/Rules/Classes/PropertyTagTraitUseRuleTest.php +++ b/tests/PHPStan/Rules/Classes/PropertyTagTraitUseRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): TRule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php b/tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php index e3cccffa5f..13e745a3d1 100644 --- a/tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Constants/MissingClassConstantTypehintRuleTest.php @@ -15,7 +15,7 @@ class MissingClassConstantTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingClassConstantTypehintRule(new MissingTypehintCheck(true, true, [])); + return new MissingClassConstantTypehintRule(new MissingTypehintCheck(true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php b/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php index 6eb78628d2..c88fb550da 100644 --- a/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Functions/MissingFunctionParameterTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingFunctionParameterTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingFunctionParameterTypehintRule(new MissingTypehintCheck(true, true, [])); + return new MissingFunctionParameterTypehintRule(new MissingTypehintCheck(true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php b/tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php index 0a93340e1f..2b64aba5ba 100644 --- a/tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingFunctionReturnTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingFunctionReturnTypehintRule(new MissingTypehintCheck(true, true, [])); + return new MissingFunctionReturnTypehintRule(new MissingTypehintCheck(true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php index 4fc2eb30e8..867cff2e50 100644 --- a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php @@ -20,7 +20,6 @@ protected function getRule(): Rule new GenericObjectTypeCheck(), new VarianceCheck(true, true), new UnresolvableTypeHelper(), - true, [], ), new CrossCheckInterfacesHelper(), diff --git a/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php index 034d8044b8..0978f6c7c5 100644 --- a/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php @@ -21,7 +21,6 @@ protected function getRule(): Rule new GenericObjectTypeCheck(), new VarianceCheck(true, true), new UnresolvableTypeHelper(), - true, [], ), new CrossCheckInterfacesHelper(), diff --git a/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php index 1c46e94d0c..8d7a275278 100644 --- a/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php @@ -20,7 +20,6 @@ protected function getRule(): Rule new GenericObjectTypeCheck(), new VarianceCheck(true, true), new UnresolvableTypeHelper(), - true, [], ), new CrossCheckInterfacesHelper(), diff --git a/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php b/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php index 4656dd37c6..c62ce6fc24 100644 --- a/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule new GenericObjectTypeCheck(), new VarianceCheck(true, true), new UnresolvableTypeHelper(), - true, [], ), ); diff --git a/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php b/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php index a7ce5312ca..f19534b281 100644 --- a/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MissingMethodParameterTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingMethodParameterTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingMethodParameterTypehintRule(new MissingTypehintCheck(true, true, [])); + return new MissingMethodParameterTypehintRule(new MissingTypehintCheck(true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Methods/MissingMethodReturnTypehintRuleTest.php b/tests/PHPStan/Rules/Methods/MissingMethodReturnTypehintRuleTest.php index 742d3f0287..87a2f4c46b 100644 --- a/tests/PHPStan/Rules/Methods/MissingMethodReturnTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MissingMethodReturnTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingMethodReturnTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingMethodReturnTypehintRule(new MissingTypehintCheck(true, true, [])); + return new MissingMethodReturnTypehintRule(new MissingTypehintCheck(true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php b/tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php index 9f3af68ae6..cc74d519e9 100644 --- a/tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MissingMethodSelfOutTypeRuleTest.php @@ -14,7 +14,7 @@ class MissingMethodSelfOutTypeRuleTest extends RuleTestCase protected function getRule(): TRule { - return new MissingMethodSelfOutTypeRule(new MissingTypehintCheck(true, true, [])); + return new MissingMethodSelfOutTypeRule(new MissingTypehintCheck(true, [])); } public function testRule(): void diff --git a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocVarTagTypeRuleTest.php b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocVarTagTypeRuleTest.php index e432a8b7a9..e5152569d1 100644 --- a/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocVarTagTypeRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/InvalidPhpDocVarTagTypeRuleTest.php @@ -29,7 +29,7 @@ protected function getRule(): Rule new ClassForbiddenNameCheck(self::getContainer()), ), new GenericObjectTypeCheck(), - new MissingTypehintCheck(true, true, []), + new MissingTypehintCheck(true, []), new UnresolvableTypeHelper(), true, true, diff --git a/tests/PHPStan/Rules/Properties/MissingPropertyTypehintRuleTest.php b/tests/PHPStan/Rules/Properties/MissingPropertyTypehintRuleTest.php index a334333851..2338b63afb 100644 --- a/tests/PHPStan/Rules/Properties/MissingPropertyTypehintRuleTest.php +++ b/tests/PHPStan/Rules/Properties/MissingPropertyTypehintRuleTest.php @@ -14,7 +14,7 @@ class MissingPropertyTypehintRuleTest extends RuleTestCase protected function getRule(): Rule { - return new MissingPropertyTypehintRule(new MissingTypehintCheck(true, true, [])); + return new MissingPropertyTypehintRule(new MissingTypehintCheck(true, [])); } public function testRule(): void From 222abe52c685b3e12916813a4bff0b8a882efaf9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 11:23:12 +0200 Subject: [PATCH 149/508] [BCB] Removed `excludes_analyse` config option --- UPGRADING.md | 4 ++++ conf/config.neon | 4 +--- conf/parametersSchema.neon | 5 ++--- src/Command/CommandHelper.php | 15 --------------- src/DependencyInjection/NeonAdapter.php | 3 +-- src/File/FileExcluderFactory.php | 14 ++------------ src/Testing/TestCase.neon | 1 - src/Testing/TestCaseSourceLocatorFactory.php | 3 --- 8 files changed, 10 insertions(+), 39 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 752970842b..263be4f14e 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -58,6 +58,10 @@ parameters: identifier: missingType.generics ``` +### Removed option `excludes_analyse` + +It has been replaced with [`excludePaths`](https://phpstan.org/user-guide/ignoring-errors#excluding-whole-files). + ### Paths in `excludePaths` and `ignoreErrors` have to be a valid file path or a fnmatch pattern If you are excluding a file path that might not exist but you still want to have it in `excludePaths`, append `(?)`: diff --git a/conf/config.neon b/conf/config.neon index 801e3fe8b6..d9d8d98dc5 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -7,8 +7,7 @@ parameters: - ../stubs/runtime/ReflectionAttribute.php - ../stubs/runtime/Attribute.php - ../stubs/runtime/ReflectionIntersectionType.php - excludes_analyse: [] - excludePaths: null + excludePaths: [] level: null paths: [] exceptions: @@ -653,7 +652,6 @@ services: - class: PHPStan\File\FileExcluderFactory arguments: - obsoleteExcludesAnalyse: %excludes_analyse% excludePaths: %excludePaths% - diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 0919020939..f91e092b72 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -1,7 +1,6 @@ parametersSchema: bootstrapFiles: listOf(string()) - excludes_analyse: listOf(string()) - excludePaths: schema(anyOf( + excludePaths: anyOf( structure([ analyse: listOf(string()), ]), @@ -12,7 +11,7 @@ parametersSchema: analyse: listOf(string()), analyseAndScan: listOf(string()) ]) - ), nullable()) + ) level: schema(anyOf(int(), string()), nullable()) paths: listOf(string()) exceptions: structure([ diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index f380cfdbd0..0fe6f1c7f2 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -524,21 +524,6 @@ public static function begin( throw new InceptionNotSuccessfulException(); } - $excludesAnalyse = $container->getParameter('excludes_analyse'); - $excludePaths = $container->getParameter('excludePaths'); - if (count($excludesAnalyse) > 0 && $excludePaths !== null) { - $errorOutput->writeLineFormatted(sprintf('Configuration parameters excludes_analyse and excludePaths cannot be used at the same time.')); - $errorOutput->writeLineFormatted(''); - $errorOutput->writeLineFormatted(sprintf('Parameter excludes_analyse has been deprecated so use excludePaths only from now on.')); - $errorOutput->writeLineFormatted(''); - - throw new InceptionNotSuccessfulException(); - } elseif (count($excludesAnalyse) > 0) { - $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option excludes_analyse. ⚠️️'); - $errorOutput->writeLineFormatted(''); - $errorOutput->writeLineFormatted(sprintf('Parameter excludes_analyse has been deprecated so use excludePaths only from now on.')); - } - if ($container->hasParameter('scopeClass') && $container->getParameter('scopeClass') !== MutatingScope::class) { $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option scopeClass. ⚠️️'); $errorOutput->writeLineFormatted(''); diff --git a/src/DependencyInjection/NeonAdapter.php b/src/DependencyInjection/NeonAdapter.php index bfc45d6c3e..4fb9f47156 100644 --- a/src/DependencyInjection/NeonAdapter.php +++ b/src/DependencyInjection/NeonAdapter.php @@ -31,7 +31,7 @@ final class NeonAdapter implements Adapter { - public const CACHE_KEY = 'v28-ignore-errors'; + public const CACHE_KEY = 'v29-excludes-analyse'; private const PREVENT_MERGING_SUFFIX = '!'; @@ -121,7 +121,6 @@ public function process(array $arr, string $fileKey, string $file): array if (in_array($keyToResolve, [ '[parameters][paths][]', - '[parameters][excludes_analyse][]', '[parameters][excludePaths][]', '[parameters][excludePaths][analyse][]', '[parameters][excludePaths][analyseAndScan][]', diff --git a/src/File/FileExcluderFactory.php b/src/File/FileExcluderFactory.php index c15b426f6e..0bdae44c20 100644 --- a/src/File/FileExcluderFactory.php +++ b/src/File/FileExcluderFactory.php @@ -11,23 +11,17 @@ final class FileExcluderFactory { /** - * @param string[] $obsoleteExcludesAnalyse - * @param array{analyse?: array, analyseAndScan?: array}|null $excludePaths + * @param array{analyse?: array, analyseAndScan?: array} $excludePaths */ public function __construct( private FileExcluderRawFactory $fileExcluderRawFactory, - private array $obsoleteExcludesAnalyse, - private ?array $excludePaths, + private array $excludePaths, ) { } public function createAnalyseFileExcluder(): FileExcluder { - if ($this->excludePaths === null) { - return $this->fileExcluderRawFactory->create($this->obsoleteExcludesAnalyse); - } - $paths = []; if (array_key_exists('analyse', $this->excludePaths)) { $paths = $this->excludePaths['analyse']; @@ -41,10 +35,6 @@ public function createAnalyseFileExcluder(): FileExcluder public function createScanFileExcluder(): FileExcluder { - if ($this->excludePaths === null) { - return $this->fileExcluderRawFactory->create($this->obsoleteExcludesAnalyse); - } - $paths = []; if (array_key_exists('analyseAndScan', $this->excludePaths)) { $paths = $this->excludePaths['analyseAndScan']; diff --git a/src/Testing/TestCase.neon b/src/Testing/TestCase.neon index cfa21959b9..a5ed7689b6 100644 --- a/src/Testing/TestCase.neon +++ b/src/Testing/TestCase.neon @@ -10,7 +10,6 @@ services: phpParser: @phpParserDecorator php8Parser: @php8PhpParser fileExtensions: %fileExtensions% - obsoleteExcludesAnalyse: %excludes_analyse% excludePaths: %excludePaths% cacheStorage: diff --git a/src/Testing/TestCaseSourceLocatorFactory.php b/src/Testing/TestCaseSourceLocatorFactory.php index a4921c9201..724380955e 100644 --- a/src/Testing/TestCaseSourceLocatorFactory.php +++ b/src/Testing/TestCaseSourceLocatorFactory.php @@ -31,7 +31,6 @@ final class TestCaseSourceLocatorFactory /** * @param string[] $fileExtensions - * @param string[] $obsoleteExcludesAnalyse * @param array{analyse?: array, analyseAndScan?: array}|null $excludePaths */ public function __construct( @@ -43,7 +42,6 @@ public function __construct( private ReflectionSourceStubber $reflectionSourceStubber, private PhpVersion $phpVersion, private array $fileExtensions, - private array $obsoleteExcludesAnalyse, private ?array $excludePaths, ) { @@ -56,7 +54,6 @@ public function create(): SourceLocator $cacheKey = sha1(serialize([ $this->phpVersion->getVersionId(), $this->fileExtensions, - $this->obsoleteExcludesAnalyse, $this->excludePaths, ])); if ($classLoaderReflection->hasProperty('vendorDir') && ! isset(self::$composerSourceLocatorsCache[$cacheKey])) { From 1cdffcc033a2eb8303d43330caf100af16c9b72d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 11:26:18 +0200 Subject: [PATCH 150/508] Removed note about obsolete Docker image --- src/Command/AnalyseCommand.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index 5e4aa61443..a81115e108 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -183,15 +183,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $errorOutput = $inceptionResult->getErrorOutput(); - $obsoleteDockerImage = $_SERVER['PHPSTAN_OBSOLETE_DOCKER_IMAGE'] ?? 'false'; - if ($obsoleteDockerImage === 'true') { - $errorOutput->writeLineFormatted('⚠️ You\'re using an obsolete PHPStan Docker image. ⚠️️'); - $errorOutput->writeLineFormatted(' You can obtain the current one from ghcr.io/phpstan/phpstan.'); - $errorOutput->writeLineFormatted(' Read more about it here:'); - $errorOutput->writeLineFormatted(' https://phpstan.org/user-guide/docker'); - $errorOutput->writeLineFormatted(''); - } - $errorFormat = $input->getOption('error-format'); if (!is_string($errorFormat) && $errorFormat !== null) { From 688e65083af831af7b87d29227c13bf3c1df1bc5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 11:26:52 +0200 Subject: [PATCH 151/508] [BCB] Remove `cache.nodesByFileCountMax` --- UPGRADING.md | 1 + conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 263be4f14e..e4d362aa37 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -147,3 +147,4 @@ This method now longer accepts `Expr $rootExpr`. If you want to change it, call * Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required * Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required * ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) +* Removed config parameter `cache.nodesByFileCountMax` diff --git a/conf/config.neon b/conf/config.neon index d9d8d98dc5..99cebcaa70 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -148,7 +148,6 @@ parameters: ignoreErrors: [] internalErrorsCountLimit: 50 cache: - nodesByFileCountMax: 1024 nodesByStringCountMax: 256 reportUnmatchedIgnoredErrors: true scopeClass: PHPStan\Analyser\MutatingScope diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index f91e092b72..e0a7bb3a98 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -176,7 +176,6 @@ parametersSchema: ) internalErrorsCountLimit: int() cache: structure([ - nodesByFileCountMax: int() nodesByStringCountMax: int() ]) reportUnmatchedIgnoredErrors: bool() From cad69ee0c8d5236dfb617e6487b20cc5b3a8c174 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 11:27:58 +0200 Subject: [PATCH 152/508] [BCB] Remove `memoryLimitFile` --- UPGRADING.md | 3 ++- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php | 5 ----- tests/PHPStan/Command/CommandHelperTest.php | 1 - tests/PHPStan/Command/relative-paths/root.neon | 1 - 6 files changed, 2 insertions(+), 10 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index e4d362aa37..aa9b5b5bbe 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -147,4 +147,5 @@ This method now longer accepts `Expr $rootExpr`. If you want to change it, call * Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required * Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required * ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) -* Removed config parameter `cache.nodesByFileCountMax` +* Removed unused config parameter `cache.nodesByFileCountMax` +* Removed unused config parameter `memoryLimitFile` diff --git a/conf/config.neon b/conf/config.neon index 99cebcaa70..f354735cf7 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -182,7 +182,6 @@ parameters: - ../stubs/Countable.stub earlyTerminatingMethodCalls: [] earlyTerminatingFunctionCalls: [] - memoryLimitFile: %tmpDir%/.memory_limit tempResultCachePath: %tmpDir%/resultCaches resultCachePath: %tmpDir%/resultCache.php resultCacheChecksProjectExtensionFilesDependencies: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index e0a7bb3a98..908950b191 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -185,7 +185,6 @@ parametersSchema: stubFiles: listOf(string()) earlyTerminatingMethodCalls: arrayOf(listOf(string())) earlyTerminatingFunctionCalls: listOf(string()) - memoryLimitFile: string() tempResultCachePath: string() resultCachePath: string() resultCacheChecksProjectExtensionFilesDependencies: bool() diff --git a/tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php b/tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php index a7cb8997d8..0c4bee2f63 100644 --- a/tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php +++ b/tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php @@ -65,8 +65,6 @@ private function runPath(string $path, int $expectedStatusCode): string new \PHPStan\Command\Symfony\SymfonyStyle(new SymfonyStyle($this->createMock(InputInterface::class), $output)), ); - $memoryLimitFile = self::getContainer()->getParameter('memoryLimitFile'); - $relativePathHelper = new FuzzyRelativePathHelper(new NullRelativePathHelper(), __DIR__, [], DIRECTORY_SEPARATOR); $errorFormatter = new TableErrorFormatter( $relativePathHelper, @@ -90,9 +88,6 @@ private function runPath(string $path, int $expectedStatusCode): string null, $this->createMock(InputInterface::class), ); - if (file_exists($memoryLimitFile)) { - unlink($memoryLimitFile); - } $statusCode = $errorFormatter->formatErrors($analysisResult, $symfonyOutput); rewind($output->getStream()); diff --git a/tests/PHPStan/Command/CommandHelperTest.php b/tests/PHPStan/Command/CommandHelperTest.php index 817dea23f8..ab4b4b793a 100644 --- a/tests/PHPStan/Command/CommandHelperTest.php +++ b/tests/PHPStan/Command/CommandHelperTest.php @@ -186,7 +186,6 @@ public function dataParameters(): array 'paths' => [ __DIR__ . DIRECTORY_SEPARATOR . 'relative-paths' . DIRECTORY_SEPARATOR . 'src', ], - 'memoryLimitFile' => __DIR__ . DIRECTORY_SEPARATOR . 'relative-paths' . DIRECTORY_SEPARATOR . '.memory_limit', 'excludePaths' => [ 'analyseAndScan' => [ __DIR__ . DIRECTORY_SEPARATOR . 'relative-paths' . DIRECTORY_SEPARATOR . 'src', diff --git a/tests/PHPStan/Command/relative-paths/root.neon b/tests/PHPStan/Command/relative-paths/root.neon index 834bcfd001..eb1330b4fc 100644 --- a/tests/PHPStan/Command/relative-paths/root.neon +++ b/tests/PHPStan/Command/relative-paths/root.neon @@ -11,7 +11,6 @@ parameters: - %rootDir%/conf paths: - src - memoryLimitFile: .memory_limit excludePaths: - src - src/*/data From d453064e929d15840ff94bf99e29f3321d1dddec Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 11:30:45 +0200 Subject: [PATCH 153/508] [BCB] Removed config option `scopeClass` --- UPGRADING.md | 12 ++++++++++-- conf/config.neon | 3 --- conf/parametersSchema.neon | 1 - phpstan-baseline.neon | 10 ---------- src/Analyser/DirectInternalScopeFactory.php | 16 +++------------- src/Analyser/InternalScopeFactory.php | 3 ++- src/Analyser/LazyInternalScopeFactory.php | 16 +++------------- src/Command/CommandHelper.php | 7 ------- src/Testing/PHPStanTestCase.php | 1 - 9 files changed, 18 insertions(+), 51 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index aa9b5b5bbe..cb182fbd3d 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -83,6 +83,12 @@ parameters: Appending `(?)` in `ignoreErrors` is not supported. +### Minor backward compatibility breaks + +* Removed unused config parameter `cache.nodesByFileCountMax` +* Removed unused config parameter `memoryLimitFile` + + ## Upgrading guide for extension developers ### PHPStan now uses nikic/php-parser v5 @@ -142,10 +148,12 @@ If you want to change `$overwrite` or `$rootExpr` (previous parameters also used This method now longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable). +### Removed config parameter `scopeClass` + +As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtension`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.ExpressionTypeResolverExtension.html) interface instead and register it as a service. + ### Minor backward compatibility breaks * Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required * Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required * ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) -* Removed unused config parameter `cache.nodesByFileCountMax` -* Removed unused config parameter `memoryLimitFile` diff --git a/conf/config.neon b/conf/config.neon index f354735cf7..8e53e03343 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -150,7 +150,6 @@ parameters: cache: nodesByStringCountMax: 256 reportUnmatchedIgnoredErrors: true - scopeClass: PHPStan\Analyser\MutatingScope typeAliases: [] universalObjectCratesClasses: - stdClass @@ -496,8 +495,6 @@ services: - class: PHPStan\Analyser\LazyInternalScopeFactory - arguments: - scopeClass: %scopeClass% autowired: - PHPStan\Analyser\InternalScopeFactory diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 908950b191..c5d8a0b821 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -179,7 +179,6 @@ parametersSchema: nodesByStringCountMax: int() ]) reportUnmatchedIgnoredErrors: bool() - scopeClass: string() typeAliases: arrayOf(string()) universalObjectCratesClasses: listOf(string()) stubFiles: listOf(string()) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 69cef6f30e..edb70aafe7 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -5,21 +5,11 @@ parameters: count: 1 path: src/Analyser/AnalyserResultFinalizer.php - - - message: "#^Function is_a\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" - count: 1 - path: src/Analyser/DirectInternalScopeFactory.php - - message: "#^Cannot assign offset 'realCount' to array\\|string\\.$#" count: 1 path: src/Analyser/Ignore/IgnoredErrorHelperResult.php - - - message: "#^Function is_a\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" - count: 1 - path: src/Analyser/LazyInternalScopeFactory.php - - message: """ #^Call to deprecated method getAnyArrays\\(\\) of class PHPStan\\\\Type\\\\TypeUtils\\: diff --git a/src/Analyser/DirectInternalScopeFactory.php b/src/Analyser/DirectInternalScopeFactory.php index c48074c1dd..a696c24777 100644 --- a/src/Analyser/DirectInternalScopeFactory.php +++ b/src/Analyser/DirectInternalScopeFactory.php @@ -7,6 +7,7 @@ use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Parser\Parser; use PHPStan\Php\PhpVersion; +use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\MethodReflection; @@ -14,17 +15,11 @@ use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Properties\PropertyReflectionFinder; -use PHPStan\ShouldNotHappenException; -use function is_a; final class DirectInternalScopeFactory implements InternalScopeFactory { - /** - * @param class-string $scopeClass - */ public function __construct( - private string $scopeClass, private ReflectionProvider $reflectionProvider, private InitializerExprTypeResolver $initializerExprTypeResolver, private DynamicReturnTypeExtensionRegistryProvider $dynamicReturnTypeExtensionRegistryProvider, @@ -51,7 +46,7 @@ public function __construct( public function create( ScopeContext $context, bool $declareStrictTypes = false, - FunctionReflection|MethodReflection|null $function = null, + FunctionReflection|ExtendedMethodReflection|null $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], @@ -67,12 +62,7 @@ public function create( bool $nativeTypesPromoted = false, ): MutatingScope { - $scopeClass = $this->scopeClass; - if (!is_a($scopeClass, MutatingScope::class, true)) { - throw new ShouldNotHappenException(); - } - - return new $scopeClass( + return new MutatingScope( $this, $this->reflectionProvider, $this->initializerExprTypeResolver, diff --git a/src/Analyser/InternalScopeFactory.php b/src/Analyser/InternalScopeFactory.php index fdacebc9ec..83c943f917 100644 --- a/src/Analyser/InternalScopeFactory.php +++ b/src/Analyser/InternalScopeFactory.php @@ -2,6 +2,7 @@ namespace PHPStan\Analyser; +use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParameterReflection; @@ -22,7 +23,7 @@ interface InternalScopeFactory public function create( ScopeContext $context, bool $declareStrictTypes = false, - FunctionReflection|MethodReflection|null $function = null, + FunctionReflection|ExtendedMethodReflection|null $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], diff --git a/src/Analyser/LazyInternalScopeFactory.php b/src/Analyser/LazyInternalScopeFactory.php index 0c904d0d3b..073bc6baef 100644 --- a/src/Analyser/LazyInternalScopeFactory.php +++ b/src/Analyser/LazyInternalScopeFactory.php @@ -7,6 +7,7 @@ use PHPStan\DependencyInjection\Type\ExpressionTypeResolverExtensionRegistryProvider; use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Php\PhpVersion; +use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\MethodReflection; @@ -14,17 +15,11 @@ use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Properties\PropertyReflectionFinder; -use PHPStan\ShouldNotHappenException; -use function is_a; final class LazyInternalScopeFactory implements InternalScopeFactory { - /** - * @param class-string $scopeClass - */ public function __construct( - private string $scopeClass, private Container $container, ) { @@ -41,7 +36,7 @@ public function __construct( public function create( ScopeContext $context, bool $declareStrictTypes = false, - FunctionReflection|MethodReflection|null $function = null, + FunctionReflection|ExtendedMethodReflection|null $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], @@ -57,12 +52,7 @@ public function create( bool $nativeTypesPromoted = false, ): MutatingScope { - $scopeClass = $this->scopeClass; - if (!is_a($scopeClass, MutatingScope::class, true)) { - throw new ShouldNotHappenException(); - } - - return new $scopeClass( + return new MutatingScope( $this, $this->container->getByType(ReflectionProvider::class), $this->container->getByType(InitializerExprTypeResolver::class), diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index 0fe6f1c7f2..c3cfbbedfd 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -12,7 +12,6 @@ use Nette\Schema\ValidationException; use Nette\Utils\AssertionException; use Nette\Utils\Strings; -use PHPStan\Analyser\MutatingScope; use PHPStan\Command\Symfony\SymfonyOutput; use PHPStan\Command\Symfony\SymfonyStyle; use PHPStan\DependencyInjection\Container; @@ -524,12 +523,6 @@ public static function begin( throw new InceptionNotSuccessfulException(); } - if ($container->hasParameter('scopeClass') && $container->getParameter('scopeClass') !== MutatingScope::class) { - $errorOutput->writeLineFormatted('⚠️ You\'re using a deprecated config option scopeClass. ⚠️️'); - $errorOutput->writeLineFormatted(''); - $errorOutput->writeLineFormatted(sprintf('Please implement PHPStan\Type\ExpressionTypeResolverExtension interface instead and register it as a service.')); - } - $tempResultCachePath = $container->getParameter('tempResultCachePath'); $createDir($tempResultCachePath); diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index f4ab2a470d..b62d258607 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -170,7 +170,6 @@ public static function createScopeFactory(ReflectionProvider $reflectionProvider return new ScopeFactory( new DirectInternalScopeFactory( - MutatingScope::class, $reflectionProvider, new InitializerExprTypeResolver( $constantResolver, From 6105cac187a594b817bc94b1731ab8330f820a0f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 13:12:31 +0200 Subject: [PATCH 154/508] Fix CS --- src/Testing/PHPStanTestCase.php | 1 - tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index b62d258607..c5d0a651a6 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -5,7 +5,6 @@ use PHPStan\Analyser\ConstantResolver; use PHPStan\Analyser\DirectInternalScopeFactory; use PHPStan\Analyser\Error; -use PHPStan\Analyser\MutatingScope; use PHPStan\Analyser\NodeScopeResolver; use PHPStan\Analyser\ScopeFactory; use PHPStan\Analyser\TypeSpecifier; diff --git a/tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php b/tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php index 0c4bee2f63..e84ac78e28 100644 --- a/tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php +++ b/tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php @@ -16,12 +16,10 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Style\SymfonyStyle; -use function file_exists; use function fopen; use function rewind; use function sprintf; use function stream_get_contents; -use function unlink; use const DIRECTORY_SEPARATOR; class AnalyseApplicationIntegrationTest extends PHPStanTestCase From 74b2185e8d23ef4e88d1464590fd3ca8072c4852 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 13:22:37 +0200 Subject: [PATCH 155/508] [BE] Stricter function map --- changelog-2.0.md | 29 +- conf/bleedingEdge.neon | 3 +- resources/functionMap.php | 274 +++++++++--------- resources/functionMap_bleedingEdge.php | 152 +--------- resources/functionMap_php80delta.php | 12 +- .../functionMap_php80delta_bleedingEdge.php | 11 +- 6 files changed, 166 insertions(+), 315 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index bcda7deb8c..d84b7cf2e8 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -62,23 +62,13 @@ Bleeding edge (TODO move to other sections) * IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) * Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 * Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) -* Stricter function signature map (https://github.com/phpstan/phpstan-src/commit/06b746d8e72cc0843707896ec161559bb6a81137, [#2163](https://github.com/phpstan/phpstan-src/pull/2163)), #7239, thanks @staabm! -* Specify `Imagick` parameter types ([#2334](https://github.com/phpstan/phpstan-src/pull/2334)), thanks @zonuexe! * Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! * Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) -* More precise `file()` flags args ([#2476](https://github.com/phpstan/phpstan-src/pull/2476), [#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! -* More precise `flock()` operation flags ([#2477](https://github.com/phpstan/phpstan-src/pull/2477)), thanks @staabm! * Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! -* `error_log` errors with `message_type=2` ([#2428](https://github.com/phpstan/phpstan-src/pull/2428)), #9380, thanks @staabm! -* Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! -* More precise `stream_socket_client()` signature ([#2519](https://github.com/phpstan/phpstan-src/pull/2519)), thanks @staabm! -* More precise `scandir()` signature ([#2518](https://github.com/phpstan/phpstan-src/pull/2518)), thanks @staabm! -* More precise `extract()` signature ([#2517](https://github.com/phpstan/phpstan-src/pull/2517)), thanks @staabm! * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! -* More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) * LogicalXorConstantConditionRule (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * NoopRule - report top-level `xor` because that's probably not what the user intended to do (https://github.com/phpstan/phpstan-src/commit/a1fffb3346e09f1e8e8d987d4282263295a55142), #10267 @@ -97,7 +87,6 @@ Bleeding edge (TODO move to other sections) * BetterNoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! -* More precise types for bcmath function parameters ([#2217](https://github.com/phpstan/phpstan-src/pull/2217)), thanks @Warxcell! * Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 * Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 @@ -105,7 +94,6 @@ Bleeding edge (TODO move to other sections) * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! * Check preg_quote delimiter sanity ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! -* Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3! * Check array functions which require stringish values ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! Improvements 🔧 @@ -150,6 +138,23 @@ Function signature fixes 🤖 ======================= * Countable stub with `0|positive-int` ([#1027](https://github.com/phpstan/phpstan-src/pull/1027)), thanks @staabm! +* More precise types for bcmath function parameters ([#2217](https://github.com/phpstan/phpstan-src/pull/2217)), thanks @Warxcell! +* Specify `Imagick` parameter types ([#2334](https://github.com/phpstan/phpstan-src/pull/2334)), thanks @zonuexe! +* `max()`/`min()` should expect non-empty-array ([#2163](https://github.com/phpstan/phpstan-src/pull/2163)), thanks @staabm! +* Narrow `Closure::bind` `$newScope` param ([#2817](https://github.com/phpstan/phpstan-src/pull/2817)), thanks @mvorisek! +* `error_log` errors with `message_type=2` ([#2428](https://github.com/phpstan/phpstan-src/pull/2428)), #9380, thanks @staabm! +* Update functionMap ([#2699](https://github.com/phpstan/phpstan-src/pull/2699), [#2783](https://github.com/phpstan/phpstan-src/pull/2783)), thanks @zonuexe! +* Improve image related functions signature ([#3127](https://github.com/phpstan/phpstan-src/pull/3127)), thanks @thg2k! +* Support `FILE_NO_DEFAULT_CONTEXT` in `file()` ([#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! +* Fix ftp related function signatures ([#2551](https://github.com/phpstan/phpstan-src/pull/2551)), thanks @thg2k! +* More precise `file()` flags args ([#2476](https://github.com/phpstan/phpstan-src/pull/2476), [#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! +* More precise `flock()` operation flags ([#2477](https://github.com/phpstan/phpstan-src/pull/2477)), thanks @staabm! +* More precise `stream_socket_client()` signature ([#2519](https://github.com/phpstan/phpstan-src/pull/2519)), thanks @staabm! +* More precise `scandir()` signature ([#2518](https://github.com/phpstan/phpstan-src/pull/2518)), thanks @staabm! +* More precise `extract()` signature ([#2517](https://github.com/phpstan/phpstan-src/pull/2517)), thanks @staabm! +* More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! +* Update `Locale` signatures ([#2880](https://github.com/phpstan/phpstan-src/pull/2880)), thanks @devnix! +* Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3!* Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! Internals 🔍 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index b910eaa88e..6c988343b3 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -2,6 +2,8 @@ parameters: featureToggles: bleedingEdge: true skipCheckGenericClasses!: [] + stricterFunctionMap: true + explicitMixedViaIsArray: true arrayFilter: true arrayUnpacking: true @@ -31,7 +33,6 @@ parameters: paramOutVariance: true strictStaticMethodTemplateTypeVariance: true propertyVariance: true - stricterFunctionMap: true zeroFiles: true projectServicesNotInAnalysedPaths: true callUserFunc: true diff --git a/resources/functionMap.php b/resources/functionMap.php index 2b9537b98e..c9f98dbe47 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -417,11 +417,11 @@ 'bbcode_parse' => ['string', 'bbcode_container'=>'resource', 'to_parse'=>'string'], 'bbcode_set_arg_parser' => ['bool', 'bbcode_container'=>'resource', 'bbcode_arg_parser'=>'resource'], 'bbcode_set_flags' => ['bool', 'bbcode_container'=>'resource', 'flags'=>'int', 'mode='=>'int'], -'bcadd' => ['numeric-string', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], -'bccomp' => ['int', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], -'bcdiv' => ['numeric-string|null', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], -'bcmod' => ['numeric-string|null', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], -'bcmul' => ['numeric-string', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], +'bcadd' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], +'bccomp' => ['int', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], +'bcdiv' => ['numeric-string|null', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], +'bcmod' => ['numeric-string|null', 'left_operand'=>'string', 'right_operand'=>'numeric-string', 'scale='=>'int'], +'bcmul' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bcompiler_load' => ['bool', 'filename'=>'string'], 'bcompiler_load_exe' => ['bool', 'filename'=>'string'], 'bcompiler_parse_class' => ['bool', 'class'=>'string', 'callback'=>'string'], @@ -435,11 +435,11 @@ 'bcompiler_write_functions_from_file' => ['bool', 'filehandle'=>'resource', 'filename'=>'string'], 'bcompiler_write_header' => ['bool', 'filehandle'=>'resource', 'write_ver='=>'string'], 'bcompiler_write_included_filename' => ['bool', 'filehandle'=>'resource', 'filename'=>'string'], -'bcpow' => ['numeric-string', 'base'=>'string', 'exponent'=>'string', 'scale='=>'int'], -'bcpowmod' => ['numeric-string|null', 'base'=>'string', 'exponent'=>'string', 'modulus'=>'string', 'scale='=>'int'], +'bcpow' => ['numeric-string', 'base'=>'numeric-string', 'exponent'=>'numeric-string', 'scale='=>'int'], +'bcpowmod' => ['numeric-string|null', 'base'=>'numeric-string', 'exponent'=>'numeric-string', 'modulus'=>'string', 'scale='=>'int'], 'bcscale' => ['int', 'scale='=>'int'], -'bcsqrt' => ['numeric-string', 'operand'=>'string', 'scale='=>'int'], -'bcsub' => ['numeric-string', 'left_operand'=>'string', 'right_operand'=>'string', 'scale='=>'int'], +'bcsqrt' => ['numeric-string', 'operand'=>'numeric-string', 'scale='=>'int'], +'bcsub' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bin2hex' => ['string', 'data'=>'string'], 'bind_textdomain_codeset' => ['string|false', 'domain'=>'string', 'codeset'=>'string'], 'bindec' => ['float|int', 'binary_number'=>'string'], @@ -994,8 +994,8 @@ 'closelog' => ['bool'], 'Closure::__construct' => ['void'], 'Closure::__invoke' => ['', '...args='=>''], -'Closure::bind' => ['Closure', 'old'=>'Closure', 'to'=>'?object', 'scope='=>'object|string|null'], -'Closure::bindTo' => ['Closure', 'new'=>'?object', 'newscope='=>'object|string|null'], +'Closure::bind' => ['Closure', 'old'=>'Closure', 'to'=>'?object', 'scope='=>'object|class-string|\'static\'|null'], +'Closure::bindTo' => ['Closure', 'new'=>'?object', 'newscope='=>'object|class-string|\'static\'|null'], 'Closure::call' => ['', 'to'=>'object', '...parameters='=>''], 'Closure::fromCallable' => ['Closure', 'callable'=>'callable'], 'clusterObj::convertToString' => ['string'], @@ -1363,7 +1363,7 @@ 'Couchbase\WildcardSearchQuery::jsonSerialize' => ['array'], 'Couchbase\zlibCompress' => ['string', 'data'=>'string'], 'Couchbase\zlibDecompress' => ['string', 'data'=>'string'], -'count' => ['0|positive-int', 'var'=>'Countable|array', 'mode='=>'int'], +'count' => ['0|positive-int', 'var'=>'Countable|array', 'mode='=>'0|1'], 'count_chars' => ['mixed', 'input'=>'string', 'mode='=>'0|1|2|3|4'], 'Countable::count' => ['0|positive-int'], 'crack_check' => ['bool', 'dictionary'=>'', 'password'=>'string'], @@ -2334,7 +2334,7 @@ 'Error::getTraceAsString' => ['string'], 'error_clear_last' => ['void'], 'error_get_last' => ['?array{type:int,message:string,file:string,line:int}'], -'error_log' => ['bool', 'message'=>'string', 'message_type='=>'int', 'destination='=>'string', 'extra_headers='=>'string'], +'error_log' => ['bool', 'message'=>'string', 'message_type='=>'0|1|2|3|4', 'destination='=>'string', 'extra_headers='=>'string'], 'error_reporting' => ['int', 'new_error_level='=>'int'], 'ErrorException::__clone' => ['void'], 'ErrorException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'severity='=>'int', 'filename='=>'string', 'lineno='=>'int', 'previous='=>'(?Throwable)|(?ErrorException)'], @@ -2637,7 +2637,7 @@ 'explode' => ['list|false', 'separator'=>'string', 'str'=>'string', 'limit='=>'int'], 'expm1' => ['float', 'number'=>'float'], 'extension_loaded' => ['bool', 'extension_name'=>'string'], -'extract' => ['0|positive-int', '&rw_var_array'=>'array', 'extract_type='=>'int', 'prefix='=>'string|null'], +'extract' => ['0|positive-int', '&rw_var_array'=>'array', 'extract_type='=>'EXTR_OVERWRITE|EXTR_SKIP|EXTR_PREFIX_SAME|EXTR_PREFIX_ALL|EXTR_PREFIX_INVALID|EXTR_IF_EXISTS|EXTR_PREFIX_IF_EXISTS|EXTR_REFS', 'prefix='=>'string|null'], 'ezmlm_hash' => ['int', 'addr'=>'string'], 'fam_cancel_monitor' => ['bool', 'fam'=>'resource', 'fam_monitor'=>'resource'], 'fam_close' => ['void', 'fam'=>'resource'], @@ -2935,7 +2935,7 @@ 'fgetcsv' => ['list|array{0: null}|false|null', 'fp'=>'resource', 'length='=>'0|positive-int', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'fgets' => ['string|false', 'fp'=>'resource', 'length='=>'0|positive-int'], 'fgetss' => ['string|false', 'fp'=>'resource', 'length='=>'0|positive-int', 'allowable_tags='=>'string'], -'file' => ['list|false', 'filename'=>'string', 'flags='=>'int', 'context='=>'resource'], +'file' => ['list|false', 'filename'=>'string', 'flags='=>'int-mask', 'context='=>'resource'], 'file_exists' => ['bool', 'filename'=>'string'], 'file_get_contents' => ['string|false', 'filename'=>'string', 'use_include_path='=>'bool', 'context='=>'?resource', 'offset='=>'int', 'maxlen='=>'0|positive-int'], 'file_put_contents' => ['0|positive-int|false', 'file'=>'string', 'data'=>'mixed', 'flags='=>'int', 'context='=>'?resource'], @@ -2988,7 +2988,7 @@ 'finfo_open' => ['resource|false', 'options='=>'int', 'arg='=>'string'], 'finfo_set_flags' => ['bool', 'finfo'=>'resource', 'options'=>'int'], 'floatval' => ['float', 'var'=>'scalar|array|resource|null'], -'flock' => ['bool', 'fp'=>'resource', 'operation'=>'int', '&w_wouldblock='=>'int'], +'flock' => ['bool', 'fp'=>'resource', 'operation'=>'int-mask', '&w_wouldblock='=>'0|1'], 'floor' => ['__benevolent', 'number'=>'float'], 'flush' => ['void'], 'fmod' => ['float', 'x'=>'float', 'y'=>'float'], @@ -3011,7 +3011,7 @@ 'ftell' => ['int|false', 'fp'=>'resource'], 'ftok' => ['int', 'pathname'=>'string', 'proj'=>'string'], 'ftp_alloc' => ['bool', 'stream'=>'resource', 'size'=>'int', '&w_response='=>'string'], -'ftp_append' => ['bool', 'ftp'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int'], +'ftp_append' => ['bool', 'ftp'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY'], 'ftp_cdup' => ['bool', 'stream'=>'resource'], 'ftp_chdir' => ['bool', 'stream'=>'resource', 'directory'=>'string'], 'ftp_chmod' => ['int|false', 'stream'=>'resource', 'mode'=>'int', 'filename'=>'string'], @@ -3019,22 +3019,22 @@ 'ftp_connect' => ['resource|false', 'host'=>'string', 'port='=>'int', 'timeout='=>'int'], 'ftp_delete' => ['bool', 'stream'=>'resource', 'file'=>'string'], 'ftp_exec' => ['bool', 'stream'=>'resource', 'command'=>'string'], -'ftp_fget' => ['bool', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'int', 'resumepos='=>'int'], -'ftp_fput' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'int', 'startpos='=>'int'], -'ftp_get' => ['bool', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'int', 'resume_pos='=>'int'], +'ftp_fget' => ['bool', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'resumepos='=>'int'], +'ftp_fput' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'FTP_ASCII|FTP_BINARY', 'startpos='=>'int'], +'ftp_get' => ['bool', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'resume_pos='=>'int'], 'ftp_get_option' => ['mixed', 'stream'=>'resource', 'option'=>'int'], 'ftp_login' => ['bool', 'stream'=>'resource', 'username'=>'string', 'password'=>'string'], 'ftp_mdtm' => ['int', 'stream'=>'resource', 'filename'=>'string'], 'ftp_mkdir' => ['string|false', 'stream'=>'resource', 'directory'=>'string'], 'ftp_mlsd' => ['array|false', 'ftp_stream'=>'resource', 'directory'=>'string'], 'ftp_nb_continue' => ['int', 'stream'=>'resource'], -'ftp_nb_fget' => ['int', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'int', 'resumepos='=>'int'], -'ftp_nb_fput' => ['int', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'int', 'startpos='=>'int'], -'ftp_nb_get' => ['int|false', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'int', 'resume_pos='=>'int'], -'ftp_nb_put' => ['int|false', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int', 'startpos='=>'int'], +'ftp_nb_fget' => ['int', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'resumepos='=>'int'], +'ftp_nb_fput' => ['int', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'FTP_ASCII|FTP_BINARY', 'startpos='=>'int'], +'ftp_nb_get' => ['int|false', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'resume_pos='=>'int'], +'ftp_nb_put' => ['int|false', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'startpos='=>'int'], 'ftp_nlist' => ['array|false', 'stream'=>'resource', 'directory'=>'string'], 'ftp_pasv' => ['bool', 'stream'=>'resource', 'pasv'=>'bool'], -'ftp_put' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'int', 'startpos='=>'int'], +'ftp_put' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'startpos='=>'int'], 'ftp_pwd' => ['string|false', 'stream'=>'resource'], 'ftp_raw' => ['array', 'stream'=>'resource', 'command'=>'string'], 'ftp_rawlist' => ['array|false', 'stream'=>'resource', 'directory'=>'string', 'recursive='=>'bool'], @@ -4542,19 +4542,19 @@ 'imagebmp' => ['bool', 'image'=>'resource', 'to='=>'string|resource|null', 'compressed='=>'bool'], 'imagechar' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'c'=>'string', 'col'=>'int'], 'imagecharup' => ['bool', 'im'=>'resource', 'font'=>'int', 'x'=>'int', 'y'=>'int', 'c'=>'string', 'col'=>'int'], -'imagecolorallocate' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], -'imagecolorallocatealpha' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], +'imagecolorallocate' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], +'imagecolorallocatealpha' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha'=>'int<0, 127>'], 'imagecolorat' => ['int<0, max>|false', 'im'=>'resource', 'x'=>'int', 'y'=>'int'], -'imagecolorclosest' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], -'imagecolorclosestalpha' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], -'imagecolorclosesthwb' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], +'imagecolorclosest' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], +'imagecolorclosestalpha' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha'=>'int<0, 127>'], +'imagecolorclosesthwb' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], 'imagecolordeallocate' => ['bool', 'im'=>'resource', 'index'=>'int'], -'imagecolorexact' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], -'imagecolorexactalpha' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], +'imagecolorexact' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], +'imagecolorexactalpha' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha'=>'int<0, 127>'], 'imagecolormatch' => ['bool', 'im1'=>'resource', 'im2'=>'resource'], -'imagecolorresolve' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], -'imagecolorresolvealpha' => ['int<0, max>', 'im'=>'resource', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha'=>'int'], -'imagecolorset' => ['void', 'im'=>'resource', 'col'=>'int', 'red'=>'int', 'green'=>'int', 'blue'=>'int', 'alpha='=>'int'], +'imagecolorresolve' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], +'imagecolorresolvealpha' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha'=>'int<0, 127>'], +'imagecolorset' => ['void', 'im'=>'resource', 'col'=>'int', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha='=>'int<0, 127>'], 'imagecolorsforindex' => ['array{red: int<0, 255>, green: int<0, 255>, blue: int<0, 255>, alpha: int<0, 127>}', 'im'=>'resource', 'col'=>'int'], 'imagecolorstotal' => ['int<0, 256>', 'im'=>'resource'], 'imagecolortransparent' => ['int', 'im'=>'resource', 'col='=>'int'], @@ -4564,7 +4564,7 @@ 'imagecopymergegray' => ['bool', 'src_im'=>'resource', 'dst_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'src_w'=>'int', 'src_h'=>'int', 'pct'=>'int'], 'imagecopyresampled' => ['bool', 'dst_im'=>'resource', 'src_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'dst_w'=>'int', 'dst_h'=>'int', 'src_w'=>'int', 'src_h'=>'int'], 'imagecopyresized' => ['bool', 'dst_im'=>'resource', 'src_im'=>'resource', 'dst_x'=>'int', 'dst_y'=>'int', 'src_x'=>'int', 'src_y'=>'int', 'dst_w'=>'int', 'dst_h'=>'int', 'src_w'=>'int', 'src_h'=>'int'], -'imagecreate' => ['__benevolent', 'x_size'=>'int', 'y_size'=>'int'], +'imagecreate' => ['__benevolent', 'x_size'=>'int<1, max>', 'y_size'=>'int<1, max>'], 'imagecreatefrombmp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd' => ['resource|false', 'filename'=>'string'], 'imagecreatefromgd2' => ['resource|false', 'filename'=>'string'], @@ -4577,7 +4577,7 @@ 'imagecreatefromwebp' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxbm' => ['resource|false', 'filename'=>'string'], 'imagecreatefromxpm' => ['resource|false', 'filename'=>'string'], -'imagecreatetruecolor' => ['__benevolent', 'x_size'=>'int', 'y_size'=>'int'], +'imagecreatetruecolor' => ['__benevolent', 'x_size'=>'int<1, max>', 'y_size'=>'int<1, max>'], 'imagecrop' => ['resource|false', 'im'=>'resource', 'rect'=>'array'], 'imagecropauto' => ['resource|false', 'im'=>'resource', 'mode='=>'int', 'threshold='=>'float', 'color='=>'int'], 'imagedashedline' => ['bool', 'im'=>'resource', 'x1'=>'int', 'y1'=>'int', 'x2'=>'int', 'y2'=>'int', 'col'=>'int'], @@ -4648,25 +4648,25 @@ 'imagexbm' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'foreground='=>'int'], 'Imagick::__construct' => ['void', 'files='=>''], 'Imagick::__toString' => ['string'], -'Imagick::adaptiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], +'Imagick::adaptiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::adaptiveResizeImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'bestfit='=>'bool'], -'Imagick::adaptiveSharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], +'Imagick::adaptiveSharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::adaptiveThresholdImage' => ['bool', 'width'=>'int', 'height'=>'int', 'offset'=>'int'], 'Imagick::addImage' => ['bool', 'source'=>'imagick'], -'Imagick::addNoiseImage' => ['bool', 'noise_type'=>'int', 'channel='=>'int'], +'Imagick::addNoiseImage' => ['bool', 'noise_type'=>'Imagick::NOISE_*', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::affineTransformImage' => ['bool', 'matrix'=>'imagickdraw'], 'Imagick::animateImages' => ['bool', 'x_server'=>'string'], 'Imagick::annotateImage' => ['bool', 'draw_settings'=>'imagickdraw', 'x'=>'float', 'y'=>'float', 'angle'=>'float', 'text'=>'string'], 'Imagick::appendImages' => ['Imagick', 'stack'=>'bool'], -'Imagick::autoGammaImage' => ['bool', 'channel='=>'int'], -'Imagick::autoLevelImage' => ['bool', 'channel='=>'int'], +'Imagick::autoGammaImage' => ['bool', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::autoLevelImage' => ['bool', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::autoOrient' => ['bool'], 'Imagick::averageImages' => ['Imagick'], 'Imagick::blackThresholdImage' => ['bool', 'threshold'=>'mixed'], 'Imagick::blueShiftImage' => ['bool', 'factor='=>'float'], -'Imagick::blurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], +'Imagick::blurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::borderImage' => ['bool', 'bordercolor'=>'mixed', 'width'=>'int', 'height'=>'int'], -'Imagick::brightnessContrastImage' => ['bool', 'brightness'=>'float', 'contrast'=>'float', 'channel='=>'int'], +'Imagick::brightnessContrastImage' => ['bool', 'brightness'=>'float', 'contrast'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::charcoalImage' => ['bool', 'radius'=>'float', 'sigma'=>'float'], 'Imagick::chopImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::clampImage' => ['bool', 'channel='=>'int'], @@ -4680,16 +4680,16 @@ 'Imagick::colorFloodfillImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int'], 'Imagick::colorizeImage' => ['bool', 'colorize'=>'mixed', 'opacity'=>'mixed'], 'Imagick::colorMatrixImage' => ['bool', 'color_matrix'=>'array'], -'Imagick::combineImages' => ['Imagick', 'channeltype'=>'int'], +'Imagick::combineImages' => ['Imagick', 'channeltype'=>'Imagick::CHANNEL_*'], 'Imagick::commentImage' => ['bool', 'comment'=>'string'], -'Imagick::compareImageChannels' => ['array{Imagick,float}', 'image'=>'imagick', 'channeltype'=>'int', 'metrictype'=>'int'], -'Imagick::compareImageLayers' => ['Imagick', 'method'=>'int'], -'Imagick::compareImages' => ['array{Imagick,float}', 'compare'=>'imagick', 'metric'=>'int'], -'Imagick::compositeImage' => ['bool', 'composite_object'=>'imagick', 'composite'=>'int', 'x'=>'int', 'y'=>'int', 'channel='=>'int'], +'Imagick::compareImageChannels' => ['array{Imagick,float}', 'image'=>'imagick', 'channeltype'=>'Imagick::CHANNEL_*', 'metrictype'=>'Imagick::METRIC_*'], +'Imagick::compareImageLayers' => ['Imagick', 'method'=>'Imagick::LAYERMETHOD_*'], +'Imagick::compareImages' => ['array{Imagick,float}', 'compare'=>'imagick', 'metric'=>'Imagick::METRIC_*'], +'Imagick::compositeImage' => ['bool', 'composite_object'=>'imagick', 'composite'=>'Imagick::COMPOSITE_*', 'x'=>'int', 'y'=>'int', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::compositeImageGravity' => ['bool', 'imagick'=>'Imagick', 'COMPOSITE_CONSTANT'=>'int', 'GRAVITY_CONSTANT'=>'int'], 'Imagick::contrastImage' => ['bool', 'sharpen'=>'bool'], -'Imagick::contrastStretchImage' => ['bool', 'black_point'=>'float', 'white_point'=>'float', 'channel='=>'int'], -'Imagick::convolveImage' => ['bool', 'kernel'=>'array', 'channel='=>'int'], +'Imagick::contrastStretchImage' => ['bool', 'black_point'=>'float', 'white_point'=>'float', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::convolveImage' => ['bool', 'kernel'=>'array', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::count' => ['0|positive-int', 'mode='=>'int'], 'Imagick::cropImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::cropThumbnailImage' => ['bool', 'width'=>'int', 'height'=>'int', 'legacy='=>'bool'], @@ -4704,28 +4704,28 @@ 'Imagick::destroy' => ['bool'], 'Imagick::displayImage' => ['bool', 'servername'=>'string'], 'Imagick::displayImages' => ['bool', 'servername'=>'string'], -'Imagick::distortImage' => ['bool', 'method'=>'int', 'arguments'=>'array', 'bestfit'=>'bool'], +'Imagick::distortImage' => ['bool', 'method'=>'Imagick::DISTORTION_*', 'arguments'=>'array', 'bestfit'=>'bool'], 'Imagick::drawImage' => ['bool', 'draw'=>'imagickdraw'], 'Imagick::edgeImage' => ['bool', 'radius'=>'float'], 'Imagick::embossImage' => ['bool', 'radius'=>'float', 'sigma'=>'float'], 'Imagick::encipherImage' => ['bool', 'passphrase'=>'string'], 'Imagick::enhanceImage' => ['bool'], 'Imagick::equalizeImage' => ['bool'], -'Imagick::evaluateImage' => ['bool', 'op'=>'int', 'constant'=>'float', 'channel='=>'int'], +'Imagick::evaluateImage' => ['bool', 'op'=>'Imagick::EVALUATE_*', 'constant'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::evaluateImages' => ['bool', 'EVALUATE_CONSTANT'=>'int'], -'Imagick::exportImagePixels' => ['list', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'int'], +'Imagick::exportImagePixels' => ['list', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'Imagick::PIXEL_*'], 'Imagick::extentImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::filter' => ['bool', 'ImagickKernel'=>'ImagickKernel', 'CHANNEL='=>'int'], 'Imagick::flattenImages' => ['Imagick'], 'Imagick::flipImage' => ['bool'], -'Imagick::floodFillPaintImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'target'=>'mixed', 'x'=>'int', 'y'=>'int', 'invert'=>'bool', 'channel='=>'int'], +'Imagick::floodFillPaintImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'target'=>'mixed', 'x'=>'int', 'y'=>'int', 'invert'=>'bool', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::flopImage' => ['bool'], 'Imagick::forwardFourierTransformimage' => ['bool', 'magnitude'=>'bool'], 'Imagick::frameImage' => ['bool', 'matte_color'=>'mixed', 'width'=>'int', 'height'=>'int', 'inner_bevel'=>'int', 'outer_bevel'=>'int'], -'Imagick::functionImage' => ['bool', 'function'=>'int', 'arguments'=>'array', 'channel='=>'int'], -'Imagick::fxImage' => ['Imagick', 'expression'=>'string', 'channel='=>'int'], -'Imagick::gammaImage' => ['bool', 'gamma'=>'float', 'channel='=>'int'], -'Imagick::gaussianBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], +'Imagick::functionImage' => ['bool', 'function'=>'Imagick::FUNCTION_*', 'arguments'=>'array', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::fxImage' => ['Imagick', 'expression'=>'string', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::gammaImage' => ['bool', 'gamma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::gaussianBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::getColorspace' => ['Imagick::COLORSPACE_*'], 'Imagick::getCompression' => ['Imagick::COMPRESSION_*'], 'Imagick::getCompressionQuality' => ['int'], @@ -4746,13 +4746,13 @@ 'Imagick::getImageBlob' => ['string'], 'Imagick::getImageBluePrimary' => ['array{x:float,y:float}'], 'Imagick::getImageBorderColor' => ['ImagickPixel'], -'Imagick::getImageChannelDepth' => ['int', 'channel'=>'int'], -'Imagick::getImageChannelDistortion' => ['float', 'reference'=>'imagick', 'channel'=>'int', 'metric'=>'int'], -'Imagick::getImageChannelDistortions' => ['float', 'reference'=>'imagick', 'metric'=>'int', 'channel='=>'int'], -'Imagick::getImageChannelExtrema' => ['array{minima:0|positive-int,maxima:0|positive-int}', 'channel'=>'int'], -'Imagick::getImageChannelKurtosis' => ['array{kurtosis:float,skewness:float}', 'channel='=>'int'], -'Imagick::getImageChannelMean' => ['array{mean:float,standardDeviation:float}', 'channel'=>'int'], -'Imagick::getImageChannelRange' => ['array{minima:float,maxima:float}', 'channel'=>'int'], +'Imagick::getImageChannelDepth' => ['int', 'channel'=>'Imagick::CHANNEL_*'], +'Imagick::getImageChannelDistortion' => ['float', 'reference'=>'imagick', 'channel'=>'Imagick::CHANNEL_*', 'metric'=>'Imagick::METRIC_*'], +'Imagick::getImageChannelDistortions' => ['float', 'reference'=>'imagick', 'metric'=>'Imagick::METRIC_*', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::getImageChannelExtrema' => ['array{minima:0|positive-int,maxima:0|positive-int}', 'channel'=>'Imagick::CHANNEL_*'], +'Imagick::getImageChannelKurtosis' => ['array{kurtosis:float,skewness:float}', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::getImageChannelMean' => ['array{mean:float,standardDeviation:float}', 'channel'=>'Imagick::CHANNEL_*'], +'Imagick::getImageChannelRange' => ['array{minima:float,maxima:float}', 'channel'=>'Imagick::CHANNEL_*'], 'Imagick::getImageChannelStatistics' => ['array{mean:float,minima:float,maxima:float,standardDeviation:float,depth:int}'], 'Imagick::getImageClipMask' => ['Imagick'], 'Imagick::getImageColormapColor' => ['ImagickPixel', 'index'=>'int'], @@ -4764,7 +4764,7 @@ 'Imagick::getImageDelay' => ['int'], 'Imagick::getImageDepth' => ['int'], 'Imagick::getImageDispose' => ['Imagick::DISPOSE_*'], -'Imagick::getImageDistortion' => ['float', 'reference'=>'magickwand', 'metric'=>'int'], +'Imagick::getImageDistortion' => ['float', 'reference'=>'magickwand', 'metric'=>'Imagick::METRIC_*'], 'Imagick::getImageExtrema' => ['array{min:0|positive-int,max:0|positive-int}'], 'Imagick::getImageFilename' => ['string'], 'Imagick::getImageFormat' => ['string'], @@ -4819,8 +4819,8 @@ 'Imagick::getQuantumRange' => ['array{quantumRangeLong:0|positive-int,quantumRangeString:numeric-string}'], 'Imagick::getRegistry' => ['string', 'key'=>'string'], 'Imagick::getReleaseDate' => ['string'], -'Imagick::getResource' => ['int', 'type'=>'int'], -'Imagick::getResourceLimit' => ['int', 'type'=>'int'], +'Imagick::getResource' => ['int', 'type'=>'Imagick::RESOURCETYPE_*'], +'Imagick::getResourceLimit' => ['int', 'type'=>'Imagick::RESOURCETYPE_*'], 'Imagick::getSamplingFactors' => ['list'], 'Imagick::getSize' => ['array{columns:0|positive-int,rows:0|positive-int}'], 'Imagick::getSizeOffset' => ['int'], @@ -4832,11 +4832,11 @@ 'Imagick::identifyImage' => ['array{imageName:string,mimetype:string,format:string,units:string,colorSpace:string,type:string,compression:string,fileSize:string,geometry:array{width:0|positive-int,height:0|positive-int},resolution:array{x:float,y:float},signature:string}', 'appendrawoutput='=>'bool'], 'Imagick::identifyImageType' => ['int'], 'Imagick::implodeImage' => ['bool', 'radius'=>'float'], -'Imagick::importImagePixels' => ['bool', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'int', 'pixels'=>'array'], +'Imagick::importImagePixels' => ['bool', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'Imagick::PIXEL_*', 'pixels'=>'array'], 'Imagick::inverseFourierTransformImage' => ['bool', 'complement'=>'Imagick', 'magnitude'=>'bool'], 'Imagick::key' => ['int|string'], 'Imagick::labelImage' => ['bool', 'label'=>'string'], -'Imagick::levelImage' => ['bool', 'blackpoint'=>'float', 'gamma'=>'float', 'whitepoint'=>'float', 'channel='=>'int'], +'Imagick::levelImage' => ['bool', 'blackpoint'=>'float', 'gamma'=>'float', 'whitepoint'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::linearStretchImage' => ['bool', 'blackpoint'=>'float', 'whitepoint'=>'float'], 'Imagick::liquidRescaleImage' => ['bool', 'width'=>'int', 'height'=>'int', 'delta_x'=>'float', 'rigidity'=>'float'], 'Imagick::listRegistry' => ['array'], @@ -4845,26 +4845,26 @@ 'Imagick::mapImage' => ['bool', 'map'=>'imagick', 'dither'=>'bool'], 'Imagick::matteFloodfillImage' => ['bool', 'alpha'=>'float', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int'], 'Imagick::medianFilterImage' => ['bool', 'radius'=>'float'], -'Imagick::mergeImageLayers' => ['Imagick', 'layer_method'=>'int'], +'Imagick::mergeImageLayers' => ['Imagick', 'layer_method'=>'Imagick::LAYERMETHOD_*'], 'Imagick::minifyImage' => ['bool'], 'Imagick::modulateImage' => ['bool', 'brightness'=>'float', 'saturation'=>'float', 'hue'=>'float'], -'Imagick::montageImage' => ['Imagick', 'draw'=>'imagickdraw', 'tile_geometry'=>'string', 'thumbnail_geometry'=>'string', 'mode'=>'int', 'frame'=>'string'], +'Imagick::montageImage' => ['Imagick', 'draw'=>'imagickdraw', 'tile_geometry'=>'string', 'thumbnail_geometry'=>'string', 'mode'=>'Imagick::MONTAGEMODE_*', 'frame'=>'string'], 'Imagick::morphImages' => ['Imagick', 'number_frames'=>'int'], -'Imagick::morphology' => ['bool', 'morphologyMethod'=>'int', 'iterations'=>'int', 'ImagickKernel'=>'ImagickKernel', 'channel='=>'int'], +'Imagick::morphology' => ['bool', 'morphologyMethod'=>'Imagick::MORPHOLOGY_*', 'iterations'=>'int', 'ImagickKernel'=>'ImagickKernel', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::mosaicImages' => ['Imagick'], -'Imagick::motionBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float', 'channel='=>'int'], -'Imagick::negateImage' => ['bool', 'gray'=>'bool', 'channel='=>'int'], +'Imagick::motionBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::negateImage' => ['bool', 'gray'=>'bool', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::newImage' => ['bool', 'cols'=>'int', 'rows'=>'int', 'background'=>'mixed', 'format='=>'string'], 'Imagick::newPseudoImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'pseudostring'=>'string'], 'Imagick::next' => ['void'], 'Imagick::nextImage' => ['bool'], -'Imagick::normalizeImage' => ['bool', 'channel='=>'int'], +'Imagick::normalizeImage' => ['bool', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::oilPaintImage' => ['bool', 'radius'=>'float'], -'Imagick::opaquePaintImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'invert'=>'bool', 'channel='=>'int'], +'Imagick::opaquePaintImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'invert'=>'bool', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::optimizeImageLayers' => ['bool'], -'Imagick::orderedPosterizeImage' => ['bool', 'threshold_map'=>'string', 'channel='=>'int'], -'Imagick::paintFloodfillImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int', 'channel='=>'int'], -'Imagick::paintOpaqueImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'channel='=>'int'], +'Imagick::orderedPosterizeImage' => ['bool', 'threshold_map'=>'string', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::paintFloodfillImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::paintOpaqueImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::paintTransparentImage' => ['bool', 'target'=>'mixed', 'alpha'=>'float', 'fuzz'=>'float'], 'Imagick::pingImage' => ['bool', 'filename'=>'string'], 'Imagick::pingImageBlob' => ['bool', 'image'=>'string'], @@ -4879,16 +4879,16 @@ 'Imagick::queryFontMetrics' => ['array{characterWidth:float,characterHeight:float,ascender:float,descender:float,textWidth:float,textHeight:float,maxHorizontalAdvance:float,boundingBox:array{x1:float,x2:float,y1:float,y2:float},originX:float,originY:float}', 'properties'=>'imagickdraw', 'text'=>'string', 'multiline='=>'bool'], 'Imagick::queryFonts' => ['list', 'pattern='=>'string'], 'Imagick::queryFormats' => ['list', 'pattern='=>'string'], -'Imagick::radialBlurImage' => ['bool', 'angle'=>'float', 'channel='=>'int'], +'Imagick::radialBlurImage' => ['bool', 'angle'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::raiseImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int', 'raise'=>'bool'], -'Imagick::randomThresholdImage' => ['bool', 'low'=>'float', 'high'=>'float', 'channel='=>'int'], +'Imagick::randomThresholdImage' => ['bool', 'low'=>'float', 'high'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::readImage' => ['bool', 'filename'=>'string'], 'Imagick::readImageBlob' => ['bool', 'image'=>'string', 'filename='=>'string'], 'Imagick::readImageFile' => ['bool', 'filehandle'=>'resource', 'filename='=>'string'], 'Imagick::readImages' => ['Imagick', 'filenames'=>'string'], 'Imagick::recolorImage' => ['bool', 'matrix'=>'array'], 'Imagick::reduceNoiseImage' => ['bool', 'radius'=>'float'], -'Imagick::remapImage' => ['bool', 'replacement'=>'imagick', 'dither'=>'int'], +'Imagick::remapImage' => ['bool', 'replacement'=>'imagick', 'dither'=>'Imagick::DITHERMETHOD_*'], 'Imagick::removeImage' => ['bool'], 'Imagick::removeImageProfile' => ['string', 'name'=>'string'], 'Imagick::render' => ['bool'], @@ -4899,28 +4899,28 @@ 'Imagick::rewind' => ['void'], 'Imagick::rollImage' => ['bool', 'x'=>'int', 'y'=>'int'], 'Imagick::rotateImage' => ['bool', 'background'=>'mixed', 'degrees'=>'float'], -'Imagick::rotationalBlurImage' => ['bool', 'float'=>'string', 'channel='=>'int'], +'Imagick::rotationalBlurImage' => ['bool', 'float'=>'string', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::roundCorners' => ['bool', 'x_rounding'=>'float', 'y_rounding'=>'float', 'stroke_width='=>'float', 'displace='=>'float', 'size_correction='=>'float'], 'Imagick::roundCornersImage' => ['bool', 'x_rounding'=>'', 'y_rounding'=>'', 'stroke_width='=>'', 'displace='=>'', 'size_correction='=>''], 'Imagick::sampleImage' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::scaleImage' => ['bool', 'cols'=>'int', 'rows'=>'int', 'bestfit='=>'bool', 'legacy='=>'bool'], -'Imagick::segmentImage' => ['bool', 'colorspace'=>'int', 'cluster_threshold'=>'float', 'smooth_threshold'=>'float', 'verbose='=>'bool'], -'Imagick::selectiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'threshold'=>'float', 'channel='=>'int'], -'Imagick::separateImageChannel' => ['bool', 'channel'=>'int'], +'Imagick::segmentImage' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*', 'cluster_threshold'=>'float', 'smooth_threshold'=>'float', 'verbose='=>'bool'], +'Imagick::selectiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'threshold'=>'float', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::separateImageChannel' => ['bool', 'channel'=>'Imagick::CHANNEL_*'], 'Imagick::sepiaToneImage' => ['bool', 'threshold'=>'float'], 'Imagick::setAntiAlias' => ['int', 'antialias'=>'bool'], 'Imagick::setBackgroundColor' => ['bool', 'background'=>'mixed'], -'Imagick::setColorspace' => ['bool', 'colorspace'=>'int'], -'Imagick::setCompression' => ['bool', 'compression'=>'int'], +'Imagick::setColorspace' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*'], +'Imagick::setCompression' => ['bool', 'compression'=>'Imagick::COMPRESSION_*'], 'Imagick::setCompressionQuality' => ['bool', 'quality'=>'int'], 'Imagick::setFilename' => ['bool', 'filename'=>'string'], 'Imagick::setFirstIterator' => ['bool'], 'Imagick::setFont' => ['bool', 'font'=>'string'], 'Imagick::setFormat' => ['bool', 'format'=>'string'], -'Imagick::setGravity' => ['bool', 'gravity'=>'int'], +'Imagick::setGravity' => ['bool', 'gravity'=>'Imagick::GRAVITY_*'], 'Imagick::setImage' => ['bool', 'replace'=>'imagick'], 'Imagick::setImageAlpha' => ['bool', 'alpha'=>'float'], -'Imagick::setImageAlphaChannel' => ['bool', 'mode'=>'int'], +'Imagick::setImageAlphaChannel' => ['bool', 'mode'=>'Imagick::ALPHACHANNEL_*'], 'Imagick::setImageArtifact' => ['bool', 'artifact'=>'string', 'value'=>'string'], 'Imagick::setImageAttribute' => ['bool', 'key'=>'string', 'value'=>'string'], 'Imagick::setImageBackgroundColor' => ['bool', 'background'=>'mixed'], @@ -4928,41 +4928,41 @@ 'Imagick::setImageBiasQuantum' => ['void', 'bias'=>'string'], 'Imagick::setImageBluePrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageBorderColor' => ['bool', 'border'=>'mixed'], -'Imagick::setImageChannelDepth' => ['bool', 'channel'=>'int', 'depth'=>'int'], -'Imagick::setImageChannelMask' => ['', 'channel'=>'int'], +'Imagick::setImageChannelDepth' => ['bool', 'channel'=>'Imagick::CHANNEL_*', 'depth'=>'int'], +'Imagick::setImageChannelMask' => ['', 'channel'=>'Imagick::CHANNEL_*'], 'Imagick::setImageClipMask' => ['bool', 'clip_mask'=>'imagick'], 'Imagick::setImageColormapColor' => ['bool', 'index'=>'int', 'color'=>'imagickpixel'], -'Imagick::setImageColorspace' => ['bool', 'colorspace'=>'int'], -'Imagick::setImageCompose' => ['bool', 'compose'=>'int'], -'Imagick::setImageCompression' => ['bool', 'compression'=>'int'], +'Imagick::setImageColorspace' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*'], +'Imagick::setImageCompose' => ['bool', 'compose'=>'Imagick::COMPOSITE_*'], +'Imagick::setImageCompression' => ['bool', 'compression'=>'Imagick::COMPRESSION_*'], 'Imagick::setImageCompressionQuality' => ['bool', 'quality'=>'int'], 'Imagick::setImageDelay' => ['bool', 'delay'=>'int'], 'Imagick::setImageDepth' => ['bool', 'depth'=>'int'], -'Imagick::setImageDispose' => ['bool', 'dispose'=>'int'], +'Imagick::setImageDispose' => ['bool', 'dispose'=>'Imagick::DISPOSE_*'], 'Imagick::setImageExtent' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::setImageFilename' => ['bool', 'filename'=>'string'], 'Imagick::setImageFormat' => ['bool', 'format'=>'string'], 'Imagick::setImageGamma' => ['bool', 'gamma'=>'float'], -'Imagick::setImageGravity' => ['bool', 'gravity'=>'int'], +'Imagick::setImageGravity' => ['bool', 'gravity'=>'Imagick::GRAVITY_*'], 'Imagick::setImageGreenPrimary' => ['bool', 'x'=>'float', 'y'=>'float'], 'Imagick::setImageIndex' => ['bool', 'index'=>'int'], -'Imagick::setImageInterlaceScheme' => ['bool', 'interlace_scheme'=>'int'], -'Imagick::setImageInterpolateMethod' => ['bool', 'method'=>'int'], +'Imagick::setImageInterlaceScheme' => ['bool', 'interlace_scheme'=>'Imagick::INTERLACE_*'], +'Imagick::setImageInterpolateMethod' => ['bool', 'method'=>'Imagick::INTERPOLATE_*'], 'Imagick::setImageIterations' => ['bool', 'iterations'=>'int'], 'Imagick::setImageMatte' => ['bool', 'matte'=>'bool'], 'Imagick::setImageMatteColor' => ['bool', 'matte'=>'mixed'], 'Imagick::setImageOpacity' => ['bool', 'opacity'=>'float'], -'Imagick::setImageOrientation' => ['bool', 'orientation'=>'int'], +'Imagick::setImageOrientation' => ['bool', 'orientation'=>'Imagick::ORIENTATION_*'], 'Imagick::setImagePage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::setImageProfile' => ['bool', 'name'=>'string', 'profile'=>'string'], 'Imagick::setImageProgressMonitor' => ['', 'filename'=>''], 'Imagick::setImageProperty' => ['bool', 'name'=>'string', 'value'=>'string'], 'Imagick::setImageRedPrimary' => ['bool', 'x'=>'float', 'y'=>'float'], -'Imagick::setImageRenderingIntent' => ['bool', 'rendering_intent'=>'int'], +'Imagick::setImageRenderingIntent' => ['bool', 'rendering_intent'=>'Imagick::RENDERINGINTENT_*'], 'Imagick::setImageResolution' => ['bool', 'x_resolution'=>'float', 'y_resolution'=>'float'], 'Imagick::setImageScene' => ['bool', 'scene'=>'int'], 'Imagick::setImageTicksPerSecond' => ['bool', 'ticks_per_second'=>'int'], -'Imagick::setImageType' => ['bool', 'image_type'=>'int'], +'Imagick::setImageType' => ['bool', 'image_type'=>'Imagick::IMGTYPE_*'], 'Imagick::setImageUnits' => ['bool', 'units'=>'int'], 'Imagick::setImageVirtualPixelMethod' => ['bool', 'method'=>'int'], 'Imagick::setImageWhitePoint' => ['bool', 'x'=>'float', 'y'=>'float'], @@ -4979,38 +4979,38 @@ 'Imagick::setSamplingFactors' => ['bool', 'factors'=>'array'], 'Imagick::setSize' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::setSizeOffset' => ['bool', 'columns'=>'int', 'rows'=>'int', 'offset'=>'int'], -'Imagick::setType' => ['bool', 'image_type'=>'int'], +'Imagick::setType' => ['bool', 'image_type'=>'Imagick::IMGTYPE_*'], 'Imagick::shadeImage' => ['bool', 'gray'=>'bool', 'azimuth'=>'float', 'elevation'=>'float'], 'Imagick::shadowImage' => ['bool', 'opacity'=>'float', 'sigma'=>'float', 'x'=>'int', 'y'=>'int'], -'Imagick::sharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'int'], +'Imagick::sharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::shaveImage' => ['bool', 'columns'=>'int', 'rows'=>'int'], 'Imagick::shearImage' => ['bool', 'background'=>'mixed', 'x_shear'=>'float', 'y_shear'=>'float'], -'Imagick::sigmoidalContrastImage' => ['bool', 'sharpen'=>'bool', 'alpha'=>'float', 'beta'=>'float', 'channel='=>'int'], -'Imagick::similarityImage' => ['Imagick', 'imagick'=>'Imagick', '&bestMatch'=>'array', '&similarity'=>'float', 'similarity_threshold'=>'float', 'metric'=>'int'], +'Imagick::sigmoidalContrastImage' => ['bool', 'sharpen'=>'bool', 'alpha'=>'float', 'beta'=>'float', 'channel='=>'Imagick::CHANNEL_*'], +'Imagick::similarityImage' => ['Imagick', 'imagick'=>'Imagick', '&bestMatch'=>'array', '&similarity'=>'float', 'similarity_threshold'=>'float', 'metric'=>'Imagick::METRIC_*'], 'Imagick::sketchImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float'], 'Imagick::smushImages' => ['Imagick', 'stack'=>'bool', 'offset'=>'int'], 'Imagick::solarizeImage' => ['bool', 'threshold'=>'0|positive-int'], -'Imagick::sparseColorImage' => ['bool', 'sparse_method'=>'int', 'arguments'=>'array', 'channel='=>'int'], +'Imagick::sparseColorImage' => ['bool', 'sparse_method'=>'Imagick::SPARSECOLORMETHOD_*', 'arguments'=>'array', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::spliceImage' => ['bool', 'width'=>'int', 'height'=>'int', 'x'=>'int', 'y'=>'int'], 'Imagick::spreadImage' => ['bool', 'radius'=>'float'], -'Imagick::statisticImage' => ['bool', 'type'=>'int', 'width'=>'int', 'height'=>'int', 'channel='=>'int'], +'Imagick::statisticImage' => ['bool', 'type'=>'Imagick::STATISTIC_*', 'width'=>'int', 'height'=>'int', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::steganoImage' => ['Imagick', 'watermark_wand'=>'imagick', 'offset'=>'int'], 'Imagick::stereoImage' => ['bool', 'offset_wand'=>'imagick'], 'Imagick::stripImage' => ['bool'], 'Imagick::subImageMatch' => ['Imagick', 'Imagick'=>'Imagick', '&w_offset='=>'array', '&w_similarity='=>'float'], 'Imagick::swirlImage' => ['bool', 'degrees'=>'float'], 'Imagick::textureImage' => ['Imagick', 'texture_wand'=>'imagick'], -'Imagick::thresholdImage' => ['bool', 'threshold'=>'float', 'channel='=>'int'], +'Imagick::thresholdImage' => ['bool', 'threshold'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::thumbnailImage' => ['bool', 'columns'=>'int', 'rows'=>'int', 'bestfit='=>'bool', 'fill='=>'bool', 'legacy='=>'bool'], 'Imagick::tintImage' => ['bool', 'tint'=>'mixed', 'opacity'=>'mixed'], 'Imagick::transformImage' => ['Imagick', 'crop'=>'string', 'geometry'=>'string'], -'Imagick::transformImageColorspace' => ['bool', 'colorspace'=>'int'], +'Imagick::transformImageColorspace' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*'], 'Imagick::transparentPaintImage' => ['bool', 'target'=>'mixed', 'alpha'=>'float', 'fuzz'=>'float', 'invert'=>'bool'], 'Imagick::transposeImage' => ['bool'], 'Imagick::transverseImage' => ['bool'], 'Imagick::trimImage' => ['bool', 'fuzz'=>'float'], 'Imagick::uniqueImageColors' => ['bool'], -'Imagick::unsharpMaskImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'amount'=>'float', 'threshold'=>'float', 'channel='=>'int'], +'Imagick::unsharpMaskImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'amount'=>'float', 'threshold'=>'float', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::valid' => ['bool'], 'Imagick::vignetteImage' => ['bool', 'blackpoint'=>'float', 'whitepoint'=>'float', 'x'=>'int', 'y'=>'int'], 'Imagick::waveImage' => ['bool', 'amplitude'=>'float', 'length'=>'float'], @@ -5027,9 +5027,9 @@ 'ImagickDraw::circle' => ['bool', 'ox'=>'float', 'oy'=>'float', 'px'=>'float', 'py'=>'float'], 'ImagickDraw::clear' => ['bool'], 'ImagickDraw::clone' => ['ImagickDraw'], -'ImagickDraw::color' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'int'], +'ImagickDraw::color' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'Imagick::PAINT_*'], 'ImagickDraw::comment' => ['bool', 'comment'=>'string'], -'ImagickDraw::composite' => ['bool', 'compose'=>'int', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float', 'compositewand'=>'imagick'], +'ImagickDraw::composite' => ['bool', 'compose'=>'Imagick::COMPOSITE_*', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float', 'compositewand'=>'imagick'], 'ImagickDraw::destroy' => ['bool'], 'ImagickDraw::ellipse' => ['bool', 'ox'=>'float', 'oy'=>'float', 'rx'=>'float', 'ry'=>'float', 'start'=>'float', 'end'=>'float'], 'ImagickDraw::getBorderColor' => ['ImagickPixel'], @@ -5069,7 +5069,7 @@ 'ImagickDraw::getTextUnderColor' => ['ImagickPixel'], 'ImagickDraw::getVectorGraphics' => ['string'], 'ImagickDraw::line' => ['bool', 'sx'=>'float', 'sy'=>'float', 'ex'=>'float', 'ey'=>'float'], -'ImagickDraw::matte' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'int'], +'ImagickDraw::matte' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'Imagick::PAINT_*'], 'ImagickDraw::pathClose' => ['bool'], 'ImagickDraw::pathCurveToAbsolute' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x2'=>'float', 'y2'=>'float', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::pathCurveToQuadraticBezierAbsolute' => ['bool', 'x1'=>'float', 'y1'=>'float', 'x'=>'float', 'y'=>'float'], @@ -5110,22 +5110,22 @@ 'ImagickDraw::scale' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::setBorderColor' => ['bool', 'color'=>'ImagickPixel|string'], 'ImagickDraw::setClipPath' => ['bool', 'clip_mask'=>'string'], -'ImagickDraw::setClipRule' => ['bool', 'fill_rule'=>'int'], +'ImagickDraw::setClipRule' => ['bool', 'fill_rule'=>'Imagick::FILLRULE_*'], 'ImagickDraw::setClipUnits' => ['bool', 'clip_units'=>'int'], 'ImagickDraw::setDensity' => ['bool', 'density_string'=>'string'], 'ImagickDraw::setFillAlpha' => ['bool', 'opacity'=>'float'], 'ImagickDraw::setFillColor' => ['bool', 'fill_pixel'=>'ImagickPixel|string'], 'ImagickDraw::setFillOpacity' => ['bool', 'fillopacity'=>'float'], 'ImagickDraw::setFillPatternURL' => ['bool', 'fill_url'=>'string'], -'ImagickDraw::setFillRule' => ['bool', 'fill_rule'=>'int'], +'ImagickDraw::setFillRule' => ['bool', 'fill_rule'=>'Imagick::FILLRULE_*'], 'ImagickDraw::setFont' => ['bool', 'font_name'=>'string'], 'ImagickDraw::setFontFamily' => ['bool', 'font_family'=>'string'], 'ImagickDraw::setFontResolution' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickDraw::setFontSize' => ['bool', 'pointsize'=>'float'], -'ImagickDraw::setFontStretch' => ['bool', 'fontstretch'=>'int'], -'ImagickDraw::setFontStyle' => ['bool', 'style'=>'int'], +'ImagickDraw::setFontStretch' => ['bool', 'fontstretch'=>'Imagick::STRETCH_*'], +'ImagickDraw::setFontStyle' => ['bool', 'style'=>'Imagick::STYLE_*'], 'ImagickDraw::setFontWeight' => ['bool', 'font_weight'=>'int'], -'ImagickDraw::setGravity' => ['bool', 'gravity'=>'int'], +'ImagickDraw::setGravity' => ['bool', 'gravity'=>'Imagick::GRAVITY_*'], 'ImagickDraw::setOpacity' => ['void', 'opacity'=>'float'], 'ImagickDraw::setResolution' => ['void', 'x_resolution'=>'float', 'y_resolution'=>'float'], 'ImagickDraw::setStrokeAlpha' => ['bool', 'opacity'=>'float'], @@ -5133,15 +5133,15 @@ 'ImagickDraw::setStrokeColor' => ['bool', 'stroke_pixel'=>'ImagickPixel|string'], 'ImagickDraw::setStrokeDashArray' => ['bool', 'dasharray'=>'array'], 'ImagickDraw::setStrokeDashOffset' => ['bool', 'dash_offset'=>'float'], -'ImagickDraw::setStrokeLineCap' => ['bool', 'linecap'=>'int'], -'ImagickDraw::setStrokeLineJoin' => ['bool', 'linejoin'=>'int'], +'ImagickDraw::setStrokeLineCap' => ['bool', 'linecap'=>'Imagick::LINECAP_*'], +'ImagickDraw::setStrokeLineJoin' => ['bool', 'linejoin'=>'Imagick::LINEJOIN_*'], 'ImagickDraw::setStrokeMiterLimit' => ['bool', 'miterlimit'=>'int'], 'ImagickDraw::setStrokeOpacity' => ['bool', 'stroke_opacity'=>'float'], 'ImagickDraw::setStrokePatternURL' => ['bool', 'stroke_url'=>'string'], 'ImagickDraw::setStrokeWidth' => ['bool', 'stroke_width'=>'float'], -'ImagickDraw::setTextAlignment' => ['bool', 'alignment'=>'int'], +'ImagickDraw::setTextAlignment' => ['bool', 'alignment'=>'Imagick::ALIGN_*'], 'ImagickDraw::setTextAntialias' => ['bool', 'antialias'=>'bool'], -'ImagickDraw::setTextDecoration' => ['bool', 'decoration'=>'int'], +'ImagickDraw::setTextDecoration' => ['bool', 'decoration'=>'Imagick::DECORATION_*'], 'ImagickDraw::setTextDirection' => ['bool', 'direction'=>'int'], 'ImagickDraw::setTextEncoding' => ['bool', 'encoding'=>'string'], 'ImagickDraw::setTextInterlineSpacing' => ['void', 'spacing'=>'float'], @@ -5155,10 +5155,10 @@ 'ImagickDraw::translate' => ['bool', 'x'=>'float', 'y'=>'float'], 'ImagickKernel::addKernel' => ['void', 'ImagickKernel'=>'ImagickKernel'], 'ImagickKernel::addUnityKernel' => ['void'], -'ImagickKernel::fromBuiltin' => ['ImagickKernel', 'kernelType'=>'int', 'kernelString'=>'string'], +'ImagickKernel::fromBuiltin' => ['ImagickKernel', 'kernelType'=>'Imagick::KERNEL_*', 'kernelString'=>'string'], 'ImagickKernel::fromMatrix' => ['ImagickKernel', 'matrix'=>'array', 'origin='=>'array'], 'ImagickKernel::getMatrix' => ['list>'], -'ImagickKernel::scale' => ['void', 'scale'=>'float', 'normalizeFlag'=>'int'], +'ImagickKernel::scale' => ['void', 'scale'=>'float', 'normalizeFlag'=>'Imagick::NORMALIZE_KERNEL_*'], 'ImagickKernel::separate' => ['array'], 'ImagickPixel::__construct' => ['void', 'color='=>'string'], 'ImagickPixel::clear' => ['bool'], @@ -5953,7 +5953,7 @@ 'litespeed_response_headers' => ['array|false'], 'Locale::acceptFromHttp' => ['non-empty-string|false', 'header'=>'string'], 'Locale::canonicalize' => ['non-empty-string|null', 'locale'=>'string'], -'Locale::composeLocale' => ['string|false', 'subtags'=>'array'], +'Locale::composeLocale' => ['string|false', 'subtags'=>'array{language:string, script?:string, region?:string, variant?:array, private?:array, extlang?:array, variant0?:string, variant1?:string, variant2?:string, variant3?:string, variant4?:string, variant5?:string, variant6?:string, variant7?:string, variant8?:string, variant9?:string, variant10?:string, variant11?:string, variant12?:string, variant13?:string, variant14?:string, private0?:string, private1?:string, private2?:string, private3?:string, private4?:string, private5?:string, private6?:string, private7?:string, private8?:string, private9?:string, private10?:string, private11?:string, private12?:string, private13?:string, private14?:string, extlang0?:string, extlang1?:string, extlang2?:string}'], 'Locale::filterMatches' => ['bool|null', 'langtag'=>'string', 'locale'=>'string', 'canonicalize='=>'bool'], 'Locale::getAllVariants' => ['array|null', 'locale'=>'string'], 'Locale::getDefault' => ['non-empty-string'], @@ -5971,7 +5971,7 @@ 'Locale::setDefault' => ['bool', 'locale'=>'string'], 'locale_accept_from_http' => ['non-empty-string|false', 'header'=>'string'], 'locale_canonicalize' => ['non-empty-string|null', 'locale'=>'string'], -'locale_compose' => ['string|false', 'subtags'=>'array'], +'locale_compose' => ['string|false', 'subtags'=>'array{language:string, script?:string, region?:string, variant?:array, private?:array, extlang?:array, variant0?:string, variant1?:string, variant2?:string, variant3?:string, variant4?:string, variant5?:string, variant6?:string, variant7?:string, variant8?:string, variant9?:string, variant10?:string, variant11?:string, variant12?:string, variant13?:string, variant14?:string, private0?:string, private1?:string, private2?:string, private3?:string, private4?:string, private5?:string, private6?:string, private7?:string, private8?:string, private9?:string, private10?:string, private11?:string, private12?:string, private13?:string, private14?:string, extlang0?:string, extlang1?:string, extlang2?:string}'], 'locale_filter_matches' => ['bool|null', 'langtag'=>'string', 'locale'=>'string', 'canonicalize='=>'bool'], 'locale_get_all_variants' => ['array|null', 'locale'=>'string'], 'locale_get_default' => ['non-empty-string'], @@ -6142,7 +6142,7 @@ 'mapObj::zoomPoint' => ['int', 'nZoomFactor'=>'int', 'oPixelPos'=>'pointObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj'], 'mapObj::zoomRectangle' => ['int', 'oPixelExt'=>'rectObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj'], 'mapObj::zoomScale' => ['int', 'nScaleDenom'=>'float', 'oPixelPos'=>'pointObj', 'nImageWidth'=>'int', 'nImageHeight'=>'int', 'oGeorefExt'=>'rectObj', 'oMaxGeorefExt'=>'rectObj'], -'max' => ['', '...arg1'=>'array'], +'max' => ['', '...arg1'=>'non-empty-array'], 'max\'1' => ['', 'arg1'=>'', 'arg2'=>'', '...args='=>''], 'maxdb::__construct' => ['void', 'host='=>'string', 'username='=>'string', 'passwd='=>'string', 'dbname='=>'string', 'port='=>'int', 'socket='=>'string'], 'maxdb::affected_rows' => ['int', 'link'=>''], @@ -6318,7 +6318,7 @@ 'mb_decode_mimeheader' => ['string', 'string'=>'string'], 'mb_decode_numericentity' => ['string', 'string'=>'string', 'convmap'=>'array', 'encoding'=>'string'], 'mb_detect_encoding' => ['string|false', 'str'=>'string', 'encoding_list='=>'mixed', 'strict='=>'bool'], -'mb_detect_order' => ['bool|list', 'encoding_list='=>'mixed'], +'mb_detect_order' => ['bool|list', 'encoding_list='=>'non-empty-list|non-falsy-string'], 'mb_encode_mimeheader' => ['string', 'str'=>'string', 'charset='=>'string', 'transfer_encoding='=>'string', 'linefeed='=>'string', 'indent='=>'int'], 'mb_encode_numericentity' => ['string', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string', 'is_hex='=>'bool'], 'mb_encoding_aliases' => ['list|false', 'encoding'=>'string'], @@ -6514,7 +6514,7 @@ 'mhash_keygen_s2k' => ['string|false', 'hash'=>'int', 'input_password'=>'string', 'salt'=>'string', 'bytes'=>'int'], 'microtime' => ['mixed', 'get_as_float='=>'bool'], 'mime_content_type' => ['string|false', 'filename_or_stream'=>'string|resource'], -'min' => ['', '...arg1'=>'array'], +'min' => ['', '...arg1'=>'non-empty-array'], 'min\'1' => ['', 'arg1'=>'', 'arg2'=>'', '...args='=>''], 'ming_keypress' => ['int', 'char'=>'string'], 'ming_setcubicthreshold' => ['void', 'threshold'=>'int'], @@ -9438,7 +9438,7 @@ 'RecursiveFilterIterator::hasChildren' => ['bool'], 'RecursiveIterator::getChildren' => ['RecursiveIterator'], 'RecursiveIterator::hasChildren' => ['bool'], -'RecursiveIteratorIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator|IteratorAggregate', 'mode='=>'int', 'flags='=>'int'], +'RecursiveIteratorIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator|IteratorAggregate', 'mode='=>'RecursiveIteratorIterator::LEAVES_ONLY|RecursiveIteratorIterator::SELF_FIRST|RecursiveIteratorIterator::CHILD_FIRST', 'flags='=>'0|RecursiveIteratorIterator::CATCH_GET_CHILD'], 'RecursiveIteratorIterator::beginChildren' => ['void'], 'RecursiveIteratorIterator::beginIteration' => ['RecursiveIterator'], 'RecursiveIteratorIterator::callGetChildren' => ['RecursiveIterator'], @@ -10283,7 +10283,7 @@ 'scalebarObj::set' => ['int', 'property_name'=>'string', 'new_value'=>''], 'scalebarObj::setImageColor' => ['int', 'red'=>'int', 'green'=>'int', 'blue'=>'int'], 'scalebarObj::updateFromString' => ['int', 'snippet'=>'string'], -'scandir' => ['list|false', 'dir'=>'string', 'sorting_order='=>'int', 'context='=>'resource'], +'scandir' => ['list|false', 'dir'=>'string', 'sorting_order='=>'SCANDIR_SORT_ASCENDING|SCANDIR_SORT_DESCENDING| SCANDIR_SORT_NONE', 'context='=>'resource'], 'SDO_DAS_ChangeSummary::beginLogging' => [''], 'SDO_DAS_ChangeSummary::endLogging' => [''], 'SDO_DAS_ChangeSummary::getChangedDataObjects' => ['SDO_List'], @@ -11581,7 +11581,7 @@ 'SplFileObject::fgetcsv' => ['list|array{0: null}|false|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::fgets' => ['string'], 'SplFileObject::fgetss' => ['string|false', 'allowable_tags='=>'string'], -'SplFileObject::flock' => ['bool', 'operation'=>'int', '&w_wouldblock='=>'int'], +'SplFileObject::flock' => ['bool', 'operation'=>'int-mask', '&w_wouldblock='=>'0|1'], 'SplFileObject::fpassthru' => ['int'], 'SplFileObject::fputcsv' => ['int|false', 'fields'=>'array', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::fread' => ['string|false', 'length'=>'int'], @@ -12026,8 +12026,8 @@ 'stream_set_timeout' => ['bool', 'stream'=>'resource', 'seconds'=>'int', 'microseconds='=>'int'], 'stream_set_write_buffer' => ['int', 'fp'=>'resource', 'buffer'=>'int'], 'stream_socket_accept' => ['resource|false', 'serverstream'=>'resource', 'timeout='=>'float', '&w_peername='=>'string'], -'stream_socket_client' => ['resource|false', 'remoteaddress'=>'string', '&w_errcode='=>'int', '&w_errstring='=>'string', 'timeout='=>'float', 'flags='=>'int', 'context='=>'resource'], -'stream_socket_enable_crypto' => ['0|bool', 'stream'=>'resource', 'enable'=>'bool', 'cryptokind='=>'int', 'sessionstream='=>'resource'], +'stream_socket_client' => ['resource|false', 'remoteaddress'=>'string', '&w_errcode='=>'int', '&w_errstring='=>'string', 'timeout='=>'float', 'flags='=>'int-mask', 'context='=>'resource'], +'stream_socket_enable_crypto' => ['0|bool', 'stream'=>'resource', 'enable'=>'bool', 'crypto_method='=>'STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT|STREAM_CRYPTO_METHOD_SSLv23_CLIENT|STREAM_CRYPTO_METHOD_ANY_CLIENT|STREAM_CRYPTO_METHOD_TLS_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT|STREAM_CRYPTO_METHOD_SSLv2_SERVER|STREAM_CRYPTO_METHOD_SSLv3_SERVER|STREAM_CRYPTO_METHOD_SSLv23_SERVER|STREAM_CRYPTO_METHOD_ANY_SERVER|STREAM_CRYPTO_METHOD_TLS_SERVER|STREAM_CRYPTO_METHOD_TLSv1_0_SERVER|STREAM_CRYPTO_METHOD_TLSv1_1_SERVER|STREAM_CRYPTO_METHOD_TLSv1_2_SERVER|STREAM_CRYPTO_METHOD_TLSv1_3_SERVER', 'session_stream='=>'resource'], 'stream_socket_get_name' => ['string|false', 'stream'=>'resource', 'want_peer'=>'bool'], 'stream_socket_pair' => ['resource[]|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'], 'stream_socket_recvfrom' => ['string|false', 'stream'=>'resource', 'amount'=>'int', 'flags='=>'int', '&w_remote_addr='=>'string'], diff --git a/resources/functionMap_bleedingEdge.php b/resources/functionMap_bleedingEdge.php index 11dd4fa773..92f41e9db0 100644 --- a/resources/functionMap_bleedingEdge.php +++ b/resources/functionMap_bleedingEdge.php @@ -2,157 +2,7 @@ return [ 'new' => [ - 'bcadd' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], - 'bccomp' => ['int', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], - 'bcdiv' => ['numeric-string|null', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], - 'bcmod' => ['numeric-string|null', 'left_operand'=>'string', 'right_operand'=>'numeric-string', 'scale='=>'int'], - 'bcmul' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], - 'bcpow' => ['numeric-string', 'base'=>'numeric-string', 'exponent'=>'numeric-string', 'scale='=>'int'], - 'bcpowmod' => ['numeric-string|null', 'base'=>'numeric-string', 'exponent'=>'numeric-string', 'modulus'=>'string', 'scale='=>'int'], - 'bcsqrt' => ['numeric-string', 'operand'=>'numeric-string', 'scale='=>'int'], - 'bcsub' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], - 'Closure::bind' => ['Closure', 'old'=>'Closure', 'to'=>'?object', 'scope='=>'object|class-string|\'static\'|null'], - 'Closure::bindTo' => ['Closure', 'new'=>'?object', 'newscope='=>'object|class-string|\'static\'|null'], - 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'0|1|2|3|4', 'destination='=>'string', 'extra_headers='=>'string'], - 'SplFileObject::flock' => ['bool', 'operation'=>'int-mask', '&w_wouldblock='=>'0|1'], - 'Imagick::adaptiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::adaptiveSharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::addNoiseImage' => ['bool', 'noise_type'=>'Imagick::NOISE_*', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::autoGammaImage' => ['bool', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::autoLevelImage' => ['bool', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::blurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::brightnessContrastImage' => ['bool', 'brightness'=>'float', 'contrast'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::clampImage' => ['bool', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::combineImages' => ['Imagick', 'channeltype'=>'Imagick::CHANNEL_*'], - 'Imagick::compareImageChannels' => ['array{Imagick,float}', 'image'=>'imagick', 'channeltype'=>'Imagick::CHANNEL_*', 'metrictype'=>'Imagick::METRIC_*'], - 'Imagick::compareImageLayers' => ['Imagick', 'method'=>'Imagick::LAYERMETHOD_*'], - 'Imagick::compareImages' => ['array{Imagick,float}', 'compare'=>'imagick', 'metric'=>'Imagick::METRIC_*'], - 'Imagick::compositeImage' => ['bool', 'composite_object'=>'imagick', 'composite'=>'Imagick::COMPOSITE_*', 'x'=>'int', 'y'=>'int', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::contrastStretchImage' => ['bool', 'black_point'=>'float', 'white_point'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::convolveImage' => ['bool', 'kernel'=>'array', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::distortImage' => ['bool', 'method'=>'Imagick::DISTORTION_*', 'arguments'=>'array', 'bestfit'=>'bool'], - 'Imagick::evaluateImage' => ['bool', 'op'=>'Imagick::EVALUATE_*', 'constant'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::exportImagePixels' => ['list', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'Imagick::PIXEL_*'], - 'Imagick::floodFillPaintImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'target'=>'mixed', 'x'=>'int', 'y'=>'int', 'invert'=>'bool', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::functionImage' => ['bool', 'function'=>'Imagick::FUNCTION_*', 'arguments'=>'array', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::fxImage' => ['Imagick', 'expression'=>'string', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::gammaImage' => ['bool', 'gamma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::gaussianBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::getImageChannelDepth' => ['int', 'channel'=>'Imagick::CHANNEL_*'], - 'Imagick::getImageChannelDistortion' => ['float', 'reference'=>'imagick', 'channel'=>'Imagick::CHANNEL_*', 'metric'=>'Imagick::METRIC_*'], - 'Imagick::getImageChannelDistortions' => ['float', 'reference'=>'imagick', 'metric'=>'Imagick::METRIC_*', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::getImageChannelExtrema' => ['array{minima:0|positive-int,maxima:0|positive-int}', 'channel'=>'Imagick::CHANNEL_*'], - 'Imagick::getImageChannelKurtosis' => ['array{kurtosis:float,skewness:float}', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::getImageChannelMean' => ['array{mean:float,standardDeviation:float}', 'channel'=>'Imagick::CHANNEL_*'], - 'Imagick::getImageChannelRange' => ['array{minima:float,maxima:float}', 'channel'=>'Imagick::CHANNEL_*'], - 'Imagick::getImageDistortion' => ['float', 'reference'=>'magickwand', 'metric'=>'Imagick::METRIC_*'], - 'Imagick::getResource' => ['int', 'type'=>'Imagick::RESOURCETYPE_*'], - 'Imagick::getResourceLimit' => ['int', 'type'=>'Imagick::RESOURCETYPE_*'], - 'Imagick::importImagePixels' => ['bool', 'x'=>'int', 'y'=>'int', 'width'=>'int', 'height'=>'int', 'map'=>'string', 'storage'=>'Imagick::PIXEL_*', 'pixels'=>'array'], - 'Imagick::levelImage' => ['bool', 'blackpoint'=>'float', 'gamma'=>'float', 'whitepoint'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::mergeImageLayers' => ['Imagick', 'layer_method'=>'Imagick::LAYERMETHOD_*'], - 'Imagick::montageImage' => ['Imagick', 'draw'=>'imagickdraw', 'tile_geometry'=>'string', 'thumbnail_geometry'=>'string', 'mode'=>'Imagick::MONTAGEMODE_*', 'frame'=>'string'], - 'Imagick::morphology' => ['bool', 'morphologyMethod'=>'Imagick::MORPHOLOGY_*', 'iterations'=>'int', 'ImagickKernel'=>'ImagickKernel', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::motionBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'angle'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::negateImage' => ['bool', 'gray'=>'bool', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::normalizeImage' => ['bool', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::opaquePaintImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'invert'=>'bool', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::orderedPosterizeImage' => ['bool', 'threshold_map'=>'string', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::paintFloodfillImage' => ['bool', 'fill'=>'mixed', 'fuzz'=>'float', 'bordercolor'=>'mixed', 'x'=>'int', 'y'=>'int', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::paintOpaqueImage' => ['bool', 'target'=>'mixed', 'fill'=>'mixed', 'fuzz'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::radialBlurImage' => ['bool', 'angle'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::randomThresholdImage' => ['bool', 'low'=>'float', 'high'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::remapImage' => ['bool', 'replacement'=>'imagick', 'dither'=>'Imagick::DITHERMETHOD_*'], - 'Imagick::rotationalBlurImage' => ['bool', 'float'=>'string', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::segmentImage' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*', 'cluster_threshold'=>'float', 'smooth_threshold'=>'float', 'verbose='=>'bool'], - 'Imagick::selectiveBlurImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'threshold'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::separateImageChannel' => ['bool', 'channel'=>'Imagick::CHANNEL_*'], - 'Imagick::setColorspace' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*'], - 'Imagick::setCompression' => ['bool', 'compression'=>'Imagick::COMPRESSION_*'], - 'Imagick::setGravity' => ['bool', 'gravity'=>'Imagick::GRAVITY_*'], - 'Imagick::setImageAlphaChannel' => ['bool', 'mode'=>'Imagick::ALPHACHANNEL_*'], - 'Imagick::setImageChannelDepth' => ['bool', 'channel'=>'Imagick::CHANNEL_*', 'depth'=>'int'], - 'Imagick::setImageChannelMask' => ['', 'channel'=>'Imagick::CHANNEL_*'], - 'Imagick::setImageClipMask' => ['bool', 'clip_mask'=>'imagick'], - 'Imagick::setImageColormapColor' => ['bool', 'index'=>'int', 'color'=>'imagickpixel'], - 'Imagick::setImageColorspace' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*'], - 'Imagick::setImageCompose' => ['bool', 'compose'=>'Imagick::COMPOSITE_*'], - 'Imagick::setImageCompression' => ['bool', 'compression'=>'Imagick::COMPRESSION_*'], - 'Imagick::setImageDispose' => ['bool', 'dispose'=>'Imagick::DISPOSE_*'], - 'Imagick::setImageGravity' => ['bool', 'gravity'=>'Imagick::GRAVITY_*'], - 'Imagick::setImageInterlaceScheme' => ['bool', 'interlace_scheme'=>'Imagick::INTERLACE_*'], - 'Imagick::setImageInterpolateMethod' => ['bool', 'method'=>'Imagick::INTERPOLATE_*'], - 'Imagick::setImageOrientation' => ['bool', 'orientation'=>'Imagick::ORIENTATION_*'], - 'Imagick::setImageRenderingIntent' => ['bool', 'rendering_intent'=>'Imagick::RENDERINGINTENT_*'], - 'Imagick::setImageType' => ['bool', 'image_type'=>'Imagick::IMGTYPE_*'], - 'Imagick::setType' => ['bool', 'image_type'=>'Imagick::IMGTYPE_*'], - 'Imagick::sharpenImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::sigmoidalContrastImage' => ['bool', 'sharpen'=>'bool', 'alpha'=>'float', 'beta'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::similarityImage' => ['Imagick', 'imagick'=>'Imagick', '&bestMatch'=>'array', '&similarity'=>'float', 'similarity_threshold'=>'float', 'metric'=>'Imagick::METRIC_*'], - 'Imagick::sparseColorImage' => ['bool', 'sparse_method'=>'Imagick::SPARSECOLORMETHOD_*', 'arguments'=>'array', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::statisticImage' => ['bool', 'type'=>'Imagick::STATISTIC_*', 'width'=>'int', 'height'=>'int', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::thresholdImage' => ['bool', 'threshold'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'Imagick::transformImageColorspace' => ['bool', 'colorspace'=>'Imagick::COLORSPACE_*'], - 'Imagick::unsharpMaskImage' => ['bool', 'radius'=>'float', 'sigma'=>'float', 'amount'=>'float', 'threshold'=>'float', 'channel='=>'Imagick::CHANNEL_*'], - 'ImagickDraw::color' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'Imagick::PAINT_*'], - 'ImagickDraw::composite' => ['bool', 'compose'=>'Imagick::COMPOSITE_*', 'x'=>'float', 'y'=>'float', 'width'=>'float', 'height'=>'float', 'compositewand'=>'imagick'], - 'ImagickDraw::getFillRule' => ['Imagick::FILLRULE_*'], - 'ImagickDraw::getFontStretch' => ['Imagick::STRETCH_*'], - 'ImagickDraw::getFontStyle' => ['Imagick::STYLE_*'], - 'ImagickDraw::getGravity' => ['Imagick::GRAVITY_*'], - 'ImagickDraw::getStrokeLineCap' => ['Imagick::LINECAP_*'], - 'ImagickDraw::getStrokeLineJoin' => ['Imagick::LINEJOIN_*'], - 'ImagickDraw::getTextAlignment' => ['Imagick::ALIGN_*'], - 'ImagickDraw::getTextDecoration' => ['Imagick::DECORATION_*'], - 'ImagickDraw::matte' => ['bool', 'x'=>'float', 'y'=>'float', 'paintmethod'=>'Imagick::PAINT_*'], - 'ImagickDraw::setClipRule' => ['bool', 'fill_rule'=>'Imagick::FILLRULE_*'], - 'ImagickDraw::setFillRule' => ['bool', 'fill_rule'=>'Imagick::FILLRULE_*'], - 'ImagickDraw::setFontStretch' => ['bool', 'fontstretch'=>'Imagick::STRETCH_*'], - 'ImagickDraw::setFontStyle' => ['bool', 'style'=>'Imagick::STYLE_*'], - 'ImagickDraw::setGravity' => ['bool', 'gravity'=>'Imagick::GRAVITY_*'], - 'ImagickDraw::setStrokeLineCap' => ['bool', 'linecap'=>'Imagick::LINECAP_*'], - 'ImagickDraw::setStrokeLineJoin' => ['bool', 'linejoin'=>'Imagick::LINEJOIN_*'], - 'ImagickDraw::setTextAlignment' => ['bool', 'alignment'=>'Imagick::ALIGN_*'], - 'ImagickDraw::setTextAntialias' => ['bool', 'antialias'=>'bool'], - 'ImagickDraw::setTextDecoration' => ['bool', 'decoration'=>'Imagick::DECORATION_*'], - 'ImagickKernel::fromBuiltin' => ['ImagickKernel', 'kernelType'=>'Imagick::KERNEL_*', 'kernelString'=>'string'], - 'ImagickKernel::scale' => ['void', 'scale'=>'float', 'normalizeFlag'=>'Imagick::NORMALIZE_KERNEL_*'], - 'imagecolorallocate' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], - 'imagecolorallocatealpha' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha'=>'int<0, 127>'], - 'imagecolorclosest' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], - 'imagecolorclosestalpha' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha'=>'int<0, 127>'], - 'imagecolorclosesthwb' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], - 'imagecolorexact' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], - 'imagecolorexactalpha' => ['int<0, max>|false', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha'=>'int<0, 127>'], - 'imagecolorresolve' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>'], - 'imagecolorresolvealpha' => ['int<0, max>', 'im'=>'resource', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha'=>'int<0, 127>'], - 'imagecolorset' => ['void', 'im'=>'resource', 'col'=>'int', 'red'=>'int<0, 255>', 'green'=>'int<0, 255>', 'blue'=>'int<0, 255>', 'alpha='=>'int<0, 127>'], - 'imagecreate' => ['__benevolent', 'x_size'=>'int<1, max>', 'y_size'=>'int<1, max>'], - 'imagecreatetruecolor' => ['__benevolent', 'x_size'=>'int<1, max>', 'y_size'=>'int<1, max>'], - 'max' => ['', '...arg1'=>'non-empty-array'], - 'mb_detect_order' => ['bool|list', 'encoding_list='=>'non-empty-list|non-falsy-string'], - 'min' => ['', '...arg1'=>'non-empty-array'], - 'file' => ['list|false', 'filename'=>'string', 'flags='=>'int-mask', 'context='=>'resource'], - 'flock' => ['bool', 'fp'=>'resource', 'operation'=>'int-mask', '&w_wouldblock='=>'0|1'], - 'ftp_append' => ['bool', 'ftp'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY'], - 'ftp_fget' => ['bool', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'resumepos='=>'int'], - 'ftp_fput' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'FTP_ASCII|FTP_BINARY', 'startpos='=>'int'], - 'ftp_get' => ['bool', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'resume_pos='=>'int'], - 'ftp_nb_fget' => ['int', 'stream'=>'resource', 'fp'=>'resource', 'remote_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'resumepos='=>'int'], - 'ftp_nb_fput' => ['int', 'stream'=>'resource', 'remote_file'=>'string', 'fp'=>'resource', 'mode='=>'FTP_ASCII|FTP_BINARY', 'startpos='=>'int'], - 'ftp_nb_get' => ['int|false', 'stream'=>'resource', 'local_file'=>'string', 'remote_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'resume_pos='=>'int'], - 'ftp_nb_put' => ['int|false', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'startpos='=>'int'], - 'ftp_put' => ['bool', 'stream'=>'resource', 'remote_file'=>'string', 'local_file'=>'string', 'mode='=>'FTP_ASCII|FTP_BINARY', 'startpos='=>'int'], - 'scandir' => ['list|false', 'dir'=>'string', 'sorting_order='=>'SCANDIR_SORT_ASCENDING|SCANDIR_SORT_DESCENDING| SCANDIR_SORT_NONE', 'context='=>'resource'], - 'stream_socket_client' => ['resource|false', 'remoteaddress'=>'string', '&w_errcode='=>'int', '&w_errstring='=>'string', 'timeout='=>'float', 'flags='=>'int-mask', 'context='=>'resource'], - 'stream_socket_enable_crypto' => ['0|bool', 'stream'=>'resource', 'enable'=>'bool', 'crypto_method='=>'STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT|STREAM_CRYPTO_METHOD_SSLv23_CLIENT|STREAM_CRYPTO_METHOD_ANY_CLIENT|STREAM_CRYPTO_METHOD_TLS_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT|STREAM_CRYPTO_METHOD_SSLv2_SERVER|STREAM_CRYPTO_METHOD_SSLv3_SERVER|STREAM_CRYPTO_METHOD_SSLv23_SERVER|STREAM_CRYPTO_METHOD_ANY_SERVER|STREAM_CRYPTO_METHOD_TLS_SERVER|STREAM_CRYPTO_METHOD_TLSv1_0_SERVER|STREAM_CRYPTO_METHOD_TLSv1_1_SERVER|STREAM_CRYPTO_METHOD_TLSv1_2_SERVER|STREAM_CRYPTO_METHOD_TLSv1_3_SERVER', 'session_stream='=>'resource'], - 'extract' => ['0|positive-int', '&rw_var_array'=>'array', 'extract_type='=>'EXTR_OVERWRITE|EXTR_SKIP|EXTR_PREFIX_SAME|EXTR_PREFIX_ALL|EXTR_PREFIX_INVALID|EXTR_IF_EXISTS|EXTR_PREFIX_IF_EXISTS|EXTR_REFS', 'prefix='=>'string|null'], - 'RecursiveIteratorIterator::__construct' => ['void', 'iterator'=>'RecursiveIterator|IteratorAggregate', 'mode='=>'RecursiveIteratorIterator::LEAVES_ONLY|RecursiveIteratorIterator::SELF_FIRST|RecursiveIteratorIterator::CHILD_FIRST', 'flags='=>'0|RecursiveIteratorIterator::CATCH_GET_CHILD'], - 'Locale::composeLocale' => ['string|false', 'subtags'=>'array{language:string, script?:string, region?:string, variant?:array, private?:array, extlang?:array, variant0?:string, variant1?:string, variant2?:string, variant3?:string, variant4?:string, variant5?:string, variant6?:string, variant7?:string, variant8?:string, variant9?:string, variant10?:string, variant11?:string, variant12?:string, variant13?:string, variant14?:string, private0?:string, private1?:string, private2?:string, private3?:string, private4?:string, private5?:string, private6?:string, private7?:string, private8?:string, private9?:string, private10?:string, private11?:string, private12?:string, private13?:string, private14?:string, extlang0?:string, extlang1?:string, extlang2?:string}'], - 'locale_compose' => ['string|false', 'subtags'=>'array{language:string, script?:string, region?:string, variant?:array, private?:array, extlang?:array, variant0?:string, variant1?:string, variant2?:string, variant3?:string, variant4?:string, variant5?:string, variant6?:string, variant7?:string, variant8?:string, variant9?:string, variant10?:string, variant11?:string, variant12?:string, variant13?:string, variant14?:string, private0?:string, private1?:string, private2?:string, private3?:string, private4?:string, private5?:string, private6?:string, private7?:string, private8?:string, private9?:string, private10?:string, private11?:string, private12?:string, private13?:string, private14?:string, extlang0?:string, extlang1?:string, extlang2?:string}'], - 'count' => ['0|positive-int', 'var'=>'Countable|array', 'mode='=>'0|1'], ], 'old' => [ - - ] + ], ]; diff --git a/resources/functionMap_php80delta.php b/resources/functionMap_php80delta.php index 1b234d2280..8b5c5b9f42 100644 --- a/resources/functionMap_php80delta.php +++ b/resources/functionMap_php80delta.php @@ -43,8 +43,11 @@ 'date_time_set' => ['DateTime', 'object'=>'DateTime', 'hour'=>'int', 'minute'=>'int', 'second='=>'int', 'microseconds='=>'int'], 'date_timestamp_set' => ['DateTime', 'object'=>'DateTime', 'unixtimestamp'=>'int'], 'date_timezone_set' => ['DateTime', 'object'=>'DateTime', 'timezone'=>'DateTimeZone'], + 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'0|1|3|4', 'destination='=>'string', 'extra_headers='=>'string'], 'explode' => ['list', 'separator'=>'non-empty-string', 'str'=>'string', 'limit='=>'int'], 'fdiv' => ['float', 'dividend'=>'float', 'divisor'=>'float'], + 'filter_input' => ['mixed', 'type'=>'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'variable_name'=>'string', 'filter='=>'int', 'options='=>'array|int'], + 'filter_input_array' => ['array|false|null', 'type'=>'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'definition='=>'int|array', 'add_empty='=>'bool'], 'floor' => ['float', 'number'=>'float'], 'forward_static_call_array' => ['mixed', 'function'=>'callable', 'parameters'=>'array'], 'get_debug_type' => ['string', 'var'=>'mixed'], @@ -52,11 +55,11 @@ 'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int'], 'gmmktime' => ['int|false', 'hour'=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'], 'hash' => ['non-falsy-string', 'algo'=>'string', 'data'=>'string', 'raw_output='=>'bool'], - 'hash_hkdf' => ['non-falsy-string', 'algo'=>'string', 'key'=>'string', 'length='=>'int', 'info='=>'string', 'salt='=>'string'], + 'hash_hkdf' => ['non-falsy-string', 'algo'=>'non-falsy-string', 'key'=>'string', 'length='=>'0|positive-int', 'info='=>'string', 'salt='=>'string'], 'hash_hmac' => ['non-empty-string', 'algo'=>'string', 'data'=>'string', 'key'=>'string', 'raw_output='=>'bool'], - 'hash_pbkdf2' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'raw_output='=>'bool'], + 'hash_pbkdf2' => ['non-empty-string', 'algo'=>'non-falsy-string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'positive-int', 'length='=>'0|positive-int', 'raw_output='=>'bool'], 'imageaffine' => ['false|object', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], - 'imagecreate' => ['__benevolent', 'width'=>'int', 'height'=>'int'], + 'imagecreate' => ['__benevolent', 'width'=>'int<1, max>', 'height'=>'int<1, max>'], 'imagecreatefrombmp' => ['false|object', 'filename'=>'string'], 'imagecreatefromgd' => ['false|object', 'filename'=>'string'], 'imagecreatefromgd2' => ['false|object', 'filename'=>'string'], @@ -69,7 +72,7 @@ 'imagecreatefromwebp' => ['false|object', 'filename'=>'string'], 'imagecreatefromxbm' => ['false|object', 'filename'=>'string'], 'imagecreatefromxpm' => ['false|object', 'filename'=>'string'], - 'imagecreatetruecolor' => ['__benevolent', 'width'=>'int', 'height'=>'int'], + 'imagecreatetruecolor' => ['__benevolent', 'width'=>'int<1, max>', 'height'=>'int<1, max>'], 'imagecrop' => ['false|object', 'im'=>'resource', 'rect'=>'array'], 'imagecropauto' => ['false|object', 'im'=>'resource', 'mode'=>'int', 'threshold'=>'float', 'color'=>'int'], 'imagegetclip' => ['array', 'im'=>'resource'], @@ -80,6 +83,7 @@ 'imagescale' => ['false|object', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'], 'ldap_set_rebind_proc' => ['bool', 'ldap'=>'resource', 'callback'=>'?callable'], 'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string'], + 'mb_detect_order' => ['bool|list', 'encoding_list='=>'non-empty-list|non-falsy-string|null'], 'mb_encoding_aliases' => ['list', 'encoding'=>'string'], 'mb_str_split' => ['list', 'str'=>'string', 'split_length='=>'positive-int', 'encoding='=>'string'], 'mb_strlen' => ['0|positive-int', 'str'=>'string', 'encoding='=>'string'], diff --git a/resources/functionMap_php80delta_bleedingEdge.php b/resources/functionMap_php80delta_bleedingEdge.php index 82e9b720a8..92f41e9db0 100644 --- a/resources/functionMap_php80delta_bleedingEdge.php +++ b/resources/functionMap_php80delta_bleedingEdge.php @@ -2,16 +2,7 @@ return [ 'new' => [ - 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'0|1|3|4', 'destination='=>'string', 'extra_headers='=>'string'], - 'filter_input' => ['mixed', 'type'=>'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'variable_name'=>'string', 'filter='=>'int', 'options='=>'array|int'], - 'filter_input_array' => ['array|false|null', 'type'=>'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'definition='=>'int|array', 'add_empty='=>'bool'], - 'hash_hkdf' => ['non-falsy-string', 'algo'=>'non-falsy-string', 'key'=>'string', 'length='=>'0|positive-int', 'info='=>'string', 'salt='=>'string'], - 'hash_pbkdf2' => ['non-empty-string', 'algo'=>'non-falsy-string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'positive-int', 'length='=>'0|positive-int', 'raw_output='=>'bool'], - 'imagecreate' => ['__benevolent', 'width'=>'int<1, max>', 'height'=>'int<1, max>'], - 'imagecreatetruecolor' => ['__benevolent', 'width'=>'int<1, max>', 'height'=>'int<1, max>'], - 'mb_detect_order' => ['bool|list', 'encoding_list='=>'non-empty-list|non-falsy-string|null'], ], 'old' => [ - - ] + ], ]; From fd570f1f39eea7aa550dfb6ea6204678960e3861 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 14:39:04 +0200 Subject: [PATCH 156/508] Empty skipCheckGenericClasses parameter array --- conf/config.neon | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index 8e53e03343..a737795700 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -23,18 +23,7 @@ parameters: featureToggles: bleedingEdge: false disableRuntimeReflectionProvider: true - skipCheckGenericClasses: - - DatePeriod - - CallbackFilterIterator - - FilterIterator - - RecursiveCallbackFilterIterator - - AppendIterator - - NoRewindIterator - - LimitIterator - - InfiniteIterator - - CachingIterator - - RegexIterator - - ReflectionEnum + skipCheckGenericClasses: [] explicitMixedViaIsArray: false arrayFilter: false arrayUnpacking: false From 99c831c160c31762686af92b683334f07c577f12 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:20:52 +0200 Subject: [PATCH 157/508] [BE] Detect duplicate stub classes and functions --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 3 --- conf/parametersSchema.neon | 1 - src/PhpDoc/StubValidator.php | 14 ++++++-------- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index d84b7cf2e8..882c1decbd 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -51,7 +51,6 @@ Bleeding edge (TODO move to other sections) * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! -* Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) * Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! * Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) * Validate inline PHPDoc `@var` tag type against native type (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) @@ -128,6 +127,7 @@ Improvements 🔧 * Stricter ++/-- operator check ([#3255](https://github.com/phpstan/phpstan-src/pull/3255)), thanks @schlndh! * Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! * Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! +* Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 6c988343b3..bac0b4dedf 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -22,7 +22,6 @@ parameters: nullContextForVoidReturningFunctions: true unescapeStrings: true alwaysCheckTooWideReturnTypeFinalMethods: true - duplicateStubs: true logicalXor: true betterNoop: true alwaysTrueAlwaysReported: true diff --git a/conf/config.neon b/conf/config.neon index a737795700..e28fbc692a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -43,7 +43,6 @@ parameters: nullContextForVoidReturningFunctions: false unescapeStrings: false alwaysCheckTooWideReturnTypeFinalMethods: false - duplicateStubs: false logicalXor: false betterNoop: false alwaysTrueAlwaysReported: false @@ -426,8 +425,6 @@ services: - class: PHPStan\PhpDoc\StubValidator - arguments: - duplicateStubs: %featureToggles.duplicateStubs% - class: PHPStan\PhpDoc\SocketSelectStubFilesExtension diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index c5d8a0b821..90aca4d582 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -49,7 +49,6 @@ parametersSchema: nullContextForVoidReturningFunctions: bool() unescapeStrings: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() - duplicateStubs: bool() logicalXor: bool() betterNoop: bool() alwaysTrueAlwaysReported: bool() diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index e37624c68b..96922b4c09 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -95,7 +95,6 @@ final class StubValidator public function __construct( private DerivativeContainerFactory $derivativeContainerFactory, - private bool $duplicateStubs, ) { } @@ -188,6 +187,8 @@ private function getRuleRegistry(Container $container): RuleRegistry $mixinCheck = $container->getByType(MixinCheck::class); $methodTagCheck = new MethodTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true); $propertyTagCheck = new PropertyTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true); + $reflector = $container->getService('stubReflector'); + $relativePathHelper = $container->getService('simpleRelativePathHelper'); $rules = [ // level 0 @@ -247,14 +248,11 @@ private function getRuleRegistry(Container $container): RuleRegistry new MissingMethodReturnTypehintRule($missingTypehintCheck), new MissingPropertyTypehintRule($missingTypehintCheck), new MissingMethodSelfOutTypeRule($missingTypehintCheck), - ]; - if ($this->duplicateStubs) { - $reflector = $container->getService('stubReflector'); - $relativePathHelper = $container->getService('simpleRelativePathHelper'); - $rules[] = new DuplicateClassDeclarationRule($reflector, $relativePathHelper); - $rules[] = new DuplicateFunctionDeclarationRule($reflector, $relativePathHelper); - } + // duplicate stubs + new DuplicateClassDeclarationRule($reflector, $relativePathHelper), + new DuplicateFunctionDeclarationRule($reflector, $relativePathHelper), + ]; return new DirectRuleRegistry($rules); } From ad150281e163a86b33aff3e674c046efd4823972 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:25:09 +0200 Subject: [PATCH 158/508] [BE] LogicalXorConstantConditionRule --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level4.neon | 4 ++-- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 882c1decbd..d692b7a4c9 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -10,6 +10,7 @@ Major new features 🚀 * **Enhancements in Handling Parameters Passed by Reference** * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! +* LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * Added previously absent type checks (level 0) * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) @@ -69,7 +70,6 @@ Bleeding edge (TODO move to other sections) * Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) -* LogicalXorConstantConditionRule (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * NoopRule - report top-level `xor` because that's probably not what the user intended to do (https://github.com/phpstan/phpstan-src/commit/a1fffb3346e09f1e8e8d987d4282263295a55142), #10267 * Report unused results of `and` and `or` (https://github.com/phpstan/phpstan-src/commit/1d8fff637d70a9e9ed3f11dee5d61b9f796cbf1a) * Report unused result of ternary (https://github.com/phpstan/phpstan-src/commit/9664f7a9d2223c07e750f0dfc949c3accfa6b65e) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index bac0b4dedf..b872cc3b98 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -22,7 +22,6 @@ parameters: nullContextForVoidReturningFunctions: true unescapeStrings: true alwaysCheckTooWideReturnTypeFinalMethods: true - logicalXor: true betterNoop: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 327f98e113..f28b2e2f9a 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -26,8 +26,6 @@ conditionalTags: phpstan.collector: %featureToggles.notAnalysedTrait% PHPStan\Rules\Traits\NotAnalysedTraitRule: phpstan.rules.rule: %featureToggles.notAnalysedTrait% - PHPStan\Rules\Comparison\LogicalXorConstantConditionRule: - phpstan.rules.rule: %featureToggles.logicalXor% PHPStan\Rules\DeadCode\BetterNoopRule: phpstan.rules.rule: %featureToggles.betterNoop% PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule: @@ -199,6 +197,8 @@ services: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% + tags: + - phpstan.rules.rule - class: PHPStan\Rules\DeadCode\BetterNoopRule diff --git a/conf/config.neon b/conf/config.neon index e28fbc692a..079f1b457d 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -43,7 +43,6 @@ parameters: nullContextForVoidReturningFunctions: false unescapeStrings: false alwaysCheckTooWideReturnTypeFinalMethods: false - logicalXor: false betterNoop: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 90aca4d582..21e82bdaa0 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -49,7 +49,6 @@ parametersSchema: nullContextForVoidReturningFunctions: bool() unescapeStrings: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() - logicalXor: bool() betterNoop: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() From f2809dd5d487b33e20688e2184c06a238c019032 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:28:16 +0200 Subject: [PATCH 159/508] [BE] New better NoopRule --- changelog-2.0.md | 3 +-- conf/bleedingEdge.neon | 1 - conf/config.level4.neon | 6 +----- conf/config.neon | 2 -- conf/parametersSchema.neon | 1 - src/Rules/DeadCode/{BetterNoopRule.php => NoopRule.php} | 2 +- .../DeadCode/{BetterNoopRuleTest.php => NoopRuleTest.php} | 6 +++--- 7 files changed, 6 insertions(+), 15 deletions(-) rename src/Rules/DeadCode/{BetterNoopRule.php => NoopRule.php} (98%) rename tests/PHPStan/Rules/DeadCode/{BetterNoopRuleTest.php => NoopRuleTest.php} (95%) diff --git a/changelog-2.0.md b/changelog-2.0.md index d692b7a4c9..6941b58e5a 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -70,7 +70,6 @@ Bleeding edge (TODO move to other sections) * Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) -* NoopRule - report top-level `xor` because that's probably not what the user intended to do (https://github.com/phpstan/phpstan-src/commit/a1fffb3346e09f1e8e8d987d4282263295a55142), #10267 * Report unused results of `and` and `or` (https://github.com/phpstan/phpstan-src/commit/1d8fff637d70a9e9ed3f11dee5d61b9f796cbf1a) * Report unused result of ternary (https://github.com/phpstan/phpstan-src/commit/9664f7a9d2223c07e750f0dfc949c3accfa6b65e) * Report unused results of `&&` and `||` (https://github.com/phpstan/phpstan-src/commit/cf2c8bbd9ebd2ebe300dbd310e136ad603d7def3) @@ -83,7 +82,6 @@ Bleeding edge (TODO move to other sections) * [#3020](https://github.com/phpstan/phpstan-src/pull/3020), thanks @staabm! * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! -* BetterNoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 @@ -128,6 +126,7 @@ Improvements 🔧 * Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! * Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! * Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) +* NoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index b872cc3b98..5eb0bf1979 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -22,7 +22,6 @@ parameters: nullContextForVoidReturningFunctions: true unescapeStrings: true alwaysCheckTooWideReturnTypeFinalMethods: true - betterNoop: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true varTagType: true diff --git a/conf/config.level4.neon b/conf/config.level4.neon index f28b2e2f9a..cc3cdff418 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -3,6 +3,7 @@ includes: rules: - PHPStan\Rules\Arrays\DeadForeachRule + - PHPStan\Rules\DeadCode\NoopRule - PHPStan\Rules\DeadCode\UnreachableStatementRule - PHPStan\Rules\DeadCode\UnusedPrivateConstantRule - PHPStan\Rules\DeadCode\UnusedPrivateMethodRule @@ -26,8 +27,6 @@ conditionalTags: phpstan.collector: %featureToggles.notAnalysedTrait% PHPStan\Rules\Traits\NotAnalysedTraitRule: phpstan.rules.rule: %featureToggles.notAnalysedTrait% - PHPStan\Rules\DeadCode\BetterNoopRule: - phpstan.rules.rule: %featureToggles.betterNoop% PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule: phpstan.rules.rule: %featureToggles.pure% PHPStan\Rules\DeadCode\PossiblyPureNewCollector: @@ -200,9 +199,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\DeadCode\BetterNoopRule - - class: PHPStan\Rules\Comparison\MatchExpressionRule arguments: diff --git a/conf/config.neon b/conf/config.neon index 079f1b457d..cb5855c70e 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -43,14 +43,12 @@ parameters: nullContextForVoidReturningFunctions: false unescapeStrings: false alwaysCheckTooWideReturnTypeFinalMethods: false - betterNoop: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false varTagType: false closureDefaultParameterTypeRule: false instanceofType: false paramOutVariance: false - strictStaticMethodTemplateTypeVariance: false propertyVariance: false stricterFunctionMap: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 21e82bdaa0..be829608c9 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -49,7 +49,6 @@ parametersSchema: nullContextForVoidReturningFunctions: bool() unescapeStrings: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() - betterNoop: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() varTagType: bool() diff --git a/src/Rules/DeadCode/BetterNoopRule.php b/src/Rules/DeadCode/NoopRule.php similarity index 98% rename from src/Rules/DeadCode/BetterNoopRule.php rename to src/Rules/DeadCode/NoopRule.php index 2e246941b7..abc5200a71 100644 --- a/src/Rules/DeadCode/BetterNoopRule.php +++ b/src/Rules/DeadCode/NoopRule.php @@ -15,7 +15,7 @@ /** * @implements Rule */ -final class BetterNoopRule implements Rule +final class NoopRule implements Rule { public function __construct(private ExprPrinter $exprPrinter) diff --git a/tests/PHPStan/Rules/DeadCode/BetterNoopRuleTest.php b/tests/PHPStan/Rules/DeadCode/NoopRuleTest.php similarity index 95% rename from tests/PHPStan/Rules/DeadCode/BetterNoopRuleTest.php rename to tests/PHPStan/Rules/DeadCode/NoopRuleTest.php index a12768aa0f..2e082297d1 100644 --- a/tests/PHPStan/Rules/DeadCode/BetterNoopRuleTest.php +++ b/tests/PHPStan/Rules/DeadCode/NoopRuleTest.php @@ -8,14 +8,14 @@ use PHPStan\Testing\RuleTestCase; /** - * @extends RuleTestCase + * @extends RuleTestCase */ -class BetterNoopRuleTest extends RuleTestCase +class NoopRuleTest extends RuleTestCase { protected function getRule(): Rule { - return new BetterNoopRule(new ExprPrinter(new Printer())); + return new NoopRule(new ExprPrinter(new Printer())); } public function testRule(): void From 660cf2d19f032a5902badf861d051202ee36792f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:31:48 +0200 Subject: [PATCH 160/508] Remove unused feature toggle --- conf/bleedingEdge.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 3 files changed, 3 deletions(-) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 5eb0bf1979..6ee6d1fe29 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -30,7 +30,6 @@ parameters: paramOutVariance: true strictStaticMethodTemplateTypeVariance: true propertyVariance: true - zeroFiles: true projectServicesNotInAnalysedPaths: true callUserFunc: true magicConstantOutOfContext: true diff --git a/conf/config.neon b/conf/config.neon index cb5855c70e..ae1b954687 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -52,7 +52,6 @@ parameters: strictStaticMethodTemplateTypeVariance: false propertyVariance: false stricterFunctionMap: false - zeroFiles: false projectServicesNotInAnalysedPaths: false callUserFunc: false magicConstantOutOfContext: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index be829608c9..efeb421ebc 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -58,7 +58,6 @@ parametersSchema: strictStaticMethodTemplateTypeVariance: bool() propertyVariance: bool() stricterFunctionMap: bool() - zeroFiles: bool() projectServicesNotInAnalysedPaths: bool() callUserFunc: bool() magicConstantOutOfContext: bool() From e01399795162ec57f49adb416bbe41b592c99610 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:34:00 +0200 Subject: [PATCH 161/508] [BE] Check preg_quote delimiter sanity --- changelog-2.0.md | 3 +-- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 11 ++--------- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 3 insertions(+), 14 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 6941b58e5a..991f721fda 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -11,6 +11,7 @@ Major new features 🚀 * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 +* Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Added previously absent type checks (level 0) * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) @@ -87,10 +88,8 @@ Bleeding edge (TODO move to other sections) * Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 * Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 -* RegularExpressionPatternRule: validate preg_quote'd patterns ([#3270](https://github.com/phpstan/phpstan-src/pull/3270)), thanks @staabm! * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! -* Check preg_quote delimiter sanity ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Check array functions which require stringish values ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! Improvements 🔧 diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 6ee6d1fe29..0b6d0ab3e3 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -37,6 +37,5 @@ parameters: checkParameterCastableToStringFunctions: true uselessReturnValue: true printfArrayParameters: true - validatePregQuote: true tooWidePropertyType: true requireFileExists: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 1d5325aefa..a7cd743caf 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -28,8 +28,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.uselessReturnValue% PHPStan\Rules\Functions\PrintfArrayParametersRule: phpstan.rules.rule: %featureToggles.printfArrayParameters% - PHPStan\Rules\Regexp\RegularExpressionQuotingRule: - phpstan.rules.rule: %featureToggles.validatePregQuote% PHPStan\Rules\Keywords\RequireFileExistsRule: phpstan.rules.rule: %featureToggles.requireFileExists% @@ -114,6 +112,8 @@ rules: - PHPStan\Rules\Properties\PropertiesInInterfaceRule - PHPStan\Rules\Properties\PropertyAttributesRule - PHPStan\Rules\Properties\ReadOnlyPropertyRule + - PHPStan\Rules\Regexp\RegularExpressionPatternRule + - PHPStan\Rules\Regexp\RegularExpressionQuotingRule - PHPStan\Rules\Traits\ConflictingTraitConstantsRule - PHPStan\Rules\Traits\ConstantsInTraitsRule - PHPStan\Rules\Types\InvalidTypesInUnionRule @@ -279,11 +279,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Regexp\RegularExpressionPatternRule - tags: - - phpstan.rules.rule - - class: PHPStan\Reflection\ConstructorsHelper arguments: @@ -301,8 +296,6 @@ services: - class: PHPStan\Rules\Functions\PrintfArrayParametersRule - - - class: PHPStan\Rules\Regexp\RegularExpressionQuotingRule - class: PHPStan\Rules\Keywords\RequireFileExistsRule arguments: diff --git a/conf/config.neon b/conf/config.neon index ae1b954687..65ba96b61c 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -59,7 +59,6 @@ parameters: checkParameterCastableToStringFunctions: false uselessReturnValue: false printfArrayParameters: false - validatePregQuote: false requireFileExists: false narrowPregMatches: true tooWidePropertyType: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index efeb421ebc..9f85497e62 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -65,7 +65,6 @@ parametersSchema: checkParameterCastableToStringFunctions: bool() uselessReturnValue: bool() printfArrayParameters: bool() - validatePregQuote: bool() narrowPregMatches: bool() tooWidePropertyType: bool() requireFileExists: bool() From 622b11210e3365b651b8af21791f216f91b221e0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:39:17 +0200 Subject: [PATCH 162/508] Remove unused feature toggle --- conf/bleedingEdge.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 3 files changed, 3 deletions(-) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 0b6d0ab3e3..cffea53253 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -30,7 +30,6 @@ parameters: paramOutVariance: true strictStaticMethodTemplateTypeVariance: true propertyVariance: true - projectServicesNotInAnalysedPaths: true callUserFunc: true magicConstantOutOfContext: true pure: true diff --git a/conf/config.neon b/conf/config.neon index 65ba96b61c..967c875dc4 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -52,7 +52,6 @@ parameters: strictStaticMethodTemplateTypeVariance: false propertyVariance: false stricterFunctionMap: false - projectServicesNotInAnalysedPaths: false callUserFunc: false magicConstantOutOfContext: false pure: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 9f85497e62..b0b46521e6 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -58,7 +58,6 @@ parametersSchema: strictStaticMethodTemplateTypeVariance: bool() propertyVariance: bool() stricterFunctionMap: bool() - projectServicesNotInAnalysedPaths: bool() callUserFunc: bool() magicConstantOutOfContext: bool() pure: bool() From 5cd4572ef009f726aed761b7aad65b3138517753 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:42:33 +0200 Subject: [PATCH 163/508] [BCB] Removed NodeConnectingVisitor --- UPGRADING.md | 4 +++ changelog-2.0.md | 6 ++-- conf/bleedingEdge.neon | 2 -- conf/config.level0.neon | 5 +-- conf/config.neon | 7 ---- conf/parametersSchema.neon | 2 -- .../NodeConnectingVisitorAttributesRule.php | 22 ------------- tests/PHPStan/Parser/CachedParserTest.php | 25 +++++++++++++-- tests/PHPStan/Parser/data/test.php | 5 +-- ...odeConnectingVisitorAttributesRuleTest.php | 2 +- ...ttributesRuleWithVisitorRegisteredTest.php | 32 ------------------- .../nodeConnectingVisitorCompatibility.neon | 3 -- 12 files changed, 32 insertions(+), 83 deletions(-) delete mode 100644 tests/PHPStan/Rules/Api/NodeConnectingVisitorAttributesRuleWithVisitorRegisteredTest.php delete mode 100644 tests/PHPStan/Rules/Api/nodeConnectingVisitorCompatibility.neon diff --git a/UPGRADING.md b/UPGRADING.md index cb182fbd3d..18861737b0 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -148,6 +148,10 @@ If you want to change `$overwrite` or `$rootExpr` (previous parameters also used This method now longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable). +### Node attributes `parent`, `previous`, `next` are no longer available + +Learn more: https://phpstan.org/blog/preprocessing-ast-for-custom-rules + ### Removed config parameter `scopeClass` As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtension`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.ExpressionTypeResolverExtension.html) interface instead and register it as a service. diff --git a/changelog-2.0.md b/changelog-2.0.md index 991f721fda..c58e4ee853 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -7,6 +7,9 @@ Major new features 🚀 * **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! * Lists are arrays with sequential integer keys starting at 0 +* Lower memory consumption thanks to breaking up of reference cycles + * [Learn more »](https://phpstan.org/blog/preprocessing-ast-for-custom-rules) + * In testing the memory consumption was reduced by 50–70 %. * **Enhancements in Handling Parameters Passed by Reference** * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! @@ -35,9 +38,6 @@ Bleeding edge (TODO move to other sections) * Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! * Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! -* Lower memory consumption thanks to breaking up of reference cycles - * This is a BC break for rules that use `'parent'`, `'next'`, and `'previous'` node attributes. [Learn more »](https://phpstan.org/blog/preprocessing-ast-for-custom-rules) - * In testing the memory consumption was reduced by 50–70 %. * ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! * Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! * ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index cffea53253..fcc1ec9d55 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -8,8 +8,6 @@ parameters: arrayFilter: true arrayUnpacking: true arrayValues: true - nodeConnectingVisitorCompatibility: false - nodeConnectingVisitorRule: true strictUnnecessaryNullsafePropertyFetch: true looseComparison: true consistentConstructor: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index a7cd743caf..1f1aa09e62 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -2,8 +2,6 @@ parameters: customRulesetUsed: false conditionalTags: - PHPStan\Rules\Api\NodeConnectingVisitorAttributesRule: - phpstan.rules.rule: %featureToggles.nodeConnectingVisitorRule% PHPStan\Rules\Properties\MissingReadOnlyByPhpDocPropertyAssignRule: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyRule: @@ -40,6 +38,7 @@ rules: - PHPStan\Rules\Api\ApiStaticCallRule - PHPStan\Rules\Api\ApiTraitUseRule - PHPStan\Rules\Api\GetTemplateTypeRule + - PHPStan\Rules\Api\NodeConnectingVisitorAttributesRule - PHPStan\Rules\Api\PhpStanNamespaceIn3rdPartyPackageRule - PHPStan\Rules\Arrays\DuplicateKeysInLiteralArraysRule - PHPStan\Rules\Arrays\EmptyArrayItemRule @@ -132,8 +131,6 @@ services: deprecationRulesInstalled: %deprecationRulesInstalled% tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Api\NodeConnectingVisitorAttributesRule - class: PHPStan\Rules\Api\RuntimeReflectionFunctionRule - diff --git a/conf/config.neon b/conf/config.neon index 967c875dc4..8b60279ccc 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -28,8 +28,6 @@ parameters: arrayFilter: false arrayUnpacking: false arrayValues: false - nodeConnectingVisitorCompatibility: true - nodeConnectingVisitorRule: false illegalConstructorMethodCall: false strictUnnecessaryNullsafePropertyFetch: false looseComparison: false @@ -253,8 +251,6 @@ conditionalTags: phpstan.rules.rule: %exceptions.check.tooWideThrowType% PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule: phpstan.rules.rule: %exceptions.check.tooWideThrowType% - PhpParser\NodeVisitor\NodeConnectingVisitor: - phpstan.parser.richParserNodeVisitor: %featureToggles.nodeConnectingVisitorCompatibility% PHPStan\Parser\CurlSetOptArgVisitor: phpstan.parser.richParserNodeVisitor: %featureToggles.curlSetOptTypes% PHPStan\Parser\TypeTraverserInstanceofVisitor: @@ -349,9 +345,6 @@ services: tags: - phpstan.parser.richParserNodeVisitor - - - class: PhpParser\NodeVisitor\NodeConnectingVisitor - - class: PHPStan\Node\Printer\ExprPrinter diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index b0b46521e6..fc1d1ea225 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -34,8 +34,6 @@ parametersSchema: arrayFilter: bool(), arrayUnpacking: bool(), arrayValues: bool(), - nodeConnectingVisitorCompatibility: bool(), - nodeConnectingVisitorRule: bool(), illegalConstructorMethodCall: bool(), strictUnnecessaryNullsafePropertyFetch: bool(), looseComparison: bool(), diff --git a/src/Rules/Api/NodeConnectingVisitorAttributesRule.php b/src/Rules/Api/NodeConnectingVisitorAttributesRule.php index a1f27a33e2..7ad74631b9 100644 --- a/src/Rules/Api/NodeConnectingVisitorAttributesRule.php +++ b/src/Rules/Api/NodeConnectingVisitorAttributesRule.php @@ -4,16 +4,12 @@ use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; -use PhpParser\NodeVisitor\NodeConnectingVisitor; use PHPStan\Analyser\Scope; -use PHPStan\DependencyInjection\Container; -use PHPStan\Parser\RichParser; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ObjectType; use function array_keys; -use function get_class; use function in_array; use function sprintf; use function str_starts_with; @@ -24,10 +20,6 @@ final class NodeConnectingVisitorAttributesRule implements Rule { - public function __construct(private Container $container) - { - } - public function getNodeType(): string { return MethodCall::class; @@ -74,20 +66,6 @@ public function processNode(Node $node, Scope $scope): array return []; } - $isVisitorRegistered = false; - foreach ($this->container->getServicesByTag(RichParser::VISITOR_SERVICE_TAG) as $service) { - if (get_class($service) !== NodeConnectingVisitor::class) { - continue; - } - - $isVisitorRegistered = true; - break; - } - - if ($isVisitorRegistered) { - return []; - } - return [ RuleErrorBuilder::message(sprintf('Node attribute \'%s\' is no longer available.', $argType->getValue())) ->identifier('phpParser.nodeConnectingAttribute') diff --git a/tests/PHPStan/Parser/CachedParserTest.php b/tests/PHPStan/Parser/CachedParserTest.php index 13505dbce7..3b97a1b99a 100644 --- a/tests/PHPStan/Parser/CachedParserTest.php +++ b/tests/PHPStan/Parser/CachedParserTest.php @@ -90,15 +90,34 @@ public function testParseTheSameFileWithDifferentMethod(): void $contents = FileReader::read($path); $stmts = $parser->parseString($contents); $this->assertInstanceOf(Namespace_::class, $stmts[0]); - $this->assertNull($stmts[0]->stmts[0]->getAttribute('parent')); + $this->assertInstanceOf(Node\Stmt\Expression::class, $stmts[0]->stmts[0]); + $this->assertInstanceOf(Node\Expr\Assign::class, $stmts[0]->stmts[0]->expr); + $this->assertInstanceOf(Node\Expr\New_::class, $stmts[0]->stmts[0]->expr->expr); + $this->assertNull($stmts[0]->stmts[0]->expr->expr->class->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX)); $stmts = $parser->parseFile($path); $this->assertInstanceOf(Namespace_::class, $stmts[0]); - $this->assertInstanceOf(Namespace_::class, $stmts[0]->stmts[0]->getAttribute('parent')); + $this->assertInstanceOf(Node\Stmt\Expression::class, $stmts[0]->stmts[0]); + $this->assertInstanceOf(Node\Expr\Assign::class, $stmts[0]->stmts[0]->expr); + $this->assertInstanceOf(Node\Expr\New_::class, $stmts[0]->stmts[0]->expr->expr); + $this->assertSame(1, $stmts[0]->stmts[0]->expr->expr->class->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX)); + + $this->assertInstanceOf(Node\Stmt\Expression::class, $stmts[0]->stmts[1]); + $this->assertInstanceOf(Node\Expr\Assign::class, $stmts[0]->stmts[1]->expr); + $this->assertInstanceOf(Node\Expr\New_::class, $stmts[0]->stmts[1]->expr->expr); + $this->assertSame(2, $stmts[0]->stmts[1]->expr->expr->class->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX)); $stmts = $parser->parseString($contents); $this->assertInstanceOf(Namespace_::class, $stmts[0]); - $this->assertInstanceOf(Namespace_::class, $stmts[0]->stmts[0]->getAttribute('parent')); + $this->assertInstanceOf(Node\Stmt\Expression::class, $stmts[0]->stmts[0]); + $this->assertInstanceOf(Node\Expr\Assign::class, $stmts[0]->stmts[0]->expr); + $this->assertInstanceOf(Node\Expr\New_::class, $stmts[0]->stmts[0]->expr->expr); + $this->assertSame(1, $stmts[0]->stmts[0]->expr->expr->class->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX)); + + $this->assertInstanceOf(Node\Stmt\Expression::class, $stmts[0]->stmts[1]); + $this->assertInstanceOf(Node\Expr\Assign::class, $stmts[0]->stmts[1]->expr); + $this->assertInstanceOf(Node\Expr\New_::class, $stmts[0]->stmts[1]->expr->expr); + $this->assertSame(2, $stmts[0]->stmts[1]->expr->expr->class->getAttribute(AnonymousClassVisitor::ATTRIBUTE_LINE_INDEX)); } } diff --git a/tests/PHPStan/Parser/data/test.php b/tests/PHPStan/Parser/data/test.php index a6bee51214..b7ee628d37 100644 --- a/tests/PHPStan/Parser/data/test.php +++ b/tests/PHPStan/Parser/data/test.php @@ -2,7 +2,4 @@ namespace CachedParserBug; -class Foo -{ - -} +$a = new class () {}; $b = new class () {}; diff --git a/tests/PHPStan/Rules/Api/NodeConnectingVisitorAttributesRuleTest.php b/tests/PHPStan/Rules/Api/NodeConnectingVisitorAttributesRuleTest.php index 2e5388d2b1..c7fe99bc18 100644 --- a/tests/PHPStan/Rules/Api/NodeConnectingVisitorAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Api/NodeConnectingVisitorAttributesRuleTest.php @@ -13,7 +13,7 @@ class NodeConnectingVisitorAttributesRuleTest extends RuleTestCase protected function getRule(): Rule { - return new NodeConnectingVisitorAttributesRule(self::getContainer()); + return new NodeConnectingVisitorAttributesRule(); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Api/NodeConnectingVisitorAttributesRuleWithVisitorRegisteredTest.php b/tests/PHPStan/Rules/Api/NodeConnectingVisitorAttributesRuleWithVisitorRegisteredTest.php deleted file mode 100644 index 569d7747eb..0000000000 --- a/tests/PHPStan/Rules/Api/NodeConnectingVisitorAttributesRuleWithVisitorRegisteredTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ -class NodeConnectingVisitorAttributesRuleWithVisitorRegisteredTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new NodeConnectingVisitorAttributesRule(self::getContainer()); - } - - public function testRule(): void - { - $this->analyse([__DIR__ . '/data/node-connecting-visitor.php'], []); - } - - public static function getAdditionalConfigFiles(): array - { - return array_merge(parent::getAdditionalConfigFiles(), [ - __DIR__ . '/nodeConnectingVisitorCompatibility.neon', - ]); - } - -} diff --git a/tests/PHPStan/Rules/Api/nodeConnectingVisitorCompatibility.neon b/tests/PHPStan/Rules/Api/nodeConnectingVisitorCompatibility.neon deleted file mode 100644 index efb020baea..0000000000 --- a/tests/PHPStan/Rules/Api/nodeConnectingVisitorCompatibility.neon +++ /dev/null @@ -1,3 +0,0 @@ -conditionalTags: - PhpParser\NodeVisitor\NodeConnectingVisitor: - phpstan.parser.richParserNodeVisitor: true From 4def38de833fa776d97dadc7c98af3c08b4e8b50 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:54:20 +0200 Subject: [PATCH 164/508] [BE] Check that each trait is used and analysed at least once --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level4.neon | 14 +++++--------- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index c58e4ee853..594e85adb0 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -14,6 +14,7 @@ Major new features 🚀 * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 +* Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Added previously absent type checks (level 0) * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) @@ -44,7 +45,6 @@ Bleeding edge (TODO move to other sections) * Unresolvable parameters ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) -* Check that each trait is used and analysed at least once - level 4 (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check that PHPStan class in class constant fetch is covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) * Check code in custom PHPStan extensions for runtime reflection concepts like `is_a()` or `class_parents()` (https://github.com/phpstan/phpstan-src/commit/c4a662ac6c3ec63f063238880b243b5399c34fcc) * Check code in custom PHPStan extensions for runtime reflection concepts like `new ReflectionMethod()` (https://github.com/phpstan/phpstan-src/commit/536306611cbb5877b6565755cd07b87f9ccfdf08) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index fcc1ec9d55..82bb13d05f 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -14,7 +14,6 @@ parameters: checkUnresolvableParameterTypes: true readOnlyByPhpDoc: true runtimeReflectionRules: true - notAnalysedTrait: true curlSetOptTypes: true missingMagicSerializationRule: true nullContextForVoidReturningFunctions: true diff --git a/conf/config.level4.neon b/conf/config.level4.neon index cc3cdff418..27c09f7ab7 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -17,16 +17,11 @@ rules: - PHPStan\Rules\TooWideTypehints\TooWideFunctionReturnTypehintRule - PHPStan\Rules\TooWideTypehints\TooWideFunctionParameterOutTypeRule - PHPStan\Rules\TooWideTypehints\TooWideMethodParameterOutTypeRule + - PHPStan\Rules\Traits\NotAnalysedTraitRule conditionalTags: PHPStan\Rules\Comparison\ConstantLooseComparisonRule: phpstan.rules.rule: %featureToggles.looseComparison% - PHPStan\Rules\Traits\TraitDeclarationCollector: - phpstan.collector: %featureToggles.notAnalysedTrait% - PHPStan\Rules\Traits\TraitUseCollector: - phpstan.collector: %featureToggles.notAnalysedTrait% - PHPStan\Rules\Traits\NotAnalysedTraitRule: - phpstan.rules.rule: %featureToggles.notAnalysedTrait% PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule: phpstan.rules.rule: %featureToggles.pure% PHPStan\Rules\DeadCode\PossiblyPureNewCollector: @@ -299,12 +294,13 @@ services: - class: PHPStan\Rules\Traits\TraitDeclarationCollector + tags: + - phpstan.collector - class: PHPStan\Rules\Traits\TraitUseCollector - - - - class: PHPStan\Rules\Traits\NotAnalysedTraitRule + tags: + - phpstan.collector - class: PHPStan\Rules\Exceptions\CatchWithUnthrownExceptionRule diff --git a/conf/config.neon b/conf/config.neon index 8b60279ccc..966b903b3c 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -35,7 +35,6 @@ parameters: checkUnresolvableParameterTypes: false readOnlyByPhpDoc: false runtimeReflectionRules: false - notAnalysedTrait: false curlSetOptTypes: false missingMagicSerializationRule: false nullContextForVoidReturningFunctions: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index fc1d1ea225..55d94d52ff 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -41,7 +41,6 @@ parametersSchema: checkUnresolvableParameterTypes: bool() readOnlyByPhpDoc: bool() runtimeReflectionRules: bool() - notAnalysedTrait: bool() curlSetOptTypes: bool() missingMagicSerializationRule: bool() nullContextForVoidReturningFunctions: bool() From 6f6e25d2646dca2f93a44f87b314d37be902ccb5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:55:13 +0200 Subject: [PATCH 165/508] Remove unused feature toggle --- conf/bleedingEdge.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 3 files changed, 3 deletions(-) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 82bb13d05f..0e5c07251e 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -17,7 +17,6 @@ parameters: curlSetOptTypes: true missingMagicSerializationRule: true nullContextForVoidReturningFunctions: true - unescapeStrings: true alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true diff --git a/conf/config.neon b/conf/config.neon index 966b903b3c..3c26e4825f 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -38,7 +38,6 @@ parameters: curlSetOptTypes: false missingMagicSerializationRule: false nullContextForVoidReturningFunctions: false - unescapeStrings: false alwaysCheckTooWideReturnTypeFinalMethods: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 55d94d52ff..2a7bae6797 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -44,7 +44,6 @@ parametersSchema: curlSetOptTypes: bool() missingMagicSerializationRule: bool() nullContextForVoidReturningFunctions: bool() - unescapeStrings: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() From bc86dcc1f83d1967639c8b1f402d3fd55d9a0cbf Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 15:57:49 +0200 Subject: [PATCH 166/508] [BE] Improve impossible type checker for void-returning functions --- changelog-2.0.md | 1 + conf/bleedingEdge.neon | 1 - conf/config.neon | 3 --- conf/parametersSchema.neon | 1 - src/Rules/Comparison/ImpossibleCheckTypeHelper.php | 6 ------ .../TypeSpecifyingFunctionsDynamicReturnTypeExtension.php | 4 ++-- .../Comparison/BooleanAndConstantConditionRuleTest.php | 1 - .../Comparison/BooleanNotConstantConditionRuleTest.php | 1 - .../Rules/Comparison/BooleanOrConstantConditionRuleTest.php | 1 - .../Comparison/DoWhileLoopConstantConditionRuleTest.php | 1 - .../Rules/Comparison/ElseIfConstantConditionRuleTest.php | 1 - .../Rules/Comparison/IfConstantConditionRuleTest.php | 1 - .../Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php | 1 - .../ImpossibleCheckTypeGenericOverwriteRuleTest.php | 1 - .../ImpossibleCheckTypeMethodCallRuleEqualsTest.php | 1 - .../Comparison/ImpossibleCheckTypeMethodCallRuleTest.php | 1 - .../ImpossibleCheckTypeStaticMethodCallRuleTest.php | 1 - .../Comparison/LogicalXorConstantConditionRuleTest.php | 1 - tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php | 1 - .../Comparison/TernaryOperatorConstantConditionRuleTest.php | 1 - .../Rules/Comparison/UnreachableIfBranchesRuleTest.php | 1 - .../Comparison/UnreachableTernaryElseBranchRuleTest.php | 1 - .../Comparison/WhileLoopAlwaysFalseConditionRuleTest.php | 1 - .../Comparison/WhileLoopAlwaysTrueConditionRuleTest.php | 1 - 24 files changed, 3 insertions(+), 31 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 594e85adb0..51c219357f 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -126,6 +126,7 @@ Improvements 🔧 * Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! * Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) * NoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 +* Improve impossible type checker for void-returning functions ([#1857](https://github.com/phpstan/phpstan-src/pull/1857)), #8169, thanks @rvanvelzen! Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 0e5c07251e..c695c525d1 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -16,7 +16,6 @@ parameters: runtimeReflectionRules: true curlSetOptTypes: true missingMagicSerializationRule: true - nullContextForVoidReturningFunctions: true alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true diff --git a/conf/config.neon b/conf/config.neon index 3c26e4825f..c4892a4de7 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -37,7 +37,6 @@ parameters: runtimeReflectionRules: false curlSetOptTypes: false missingMagicSerializationRule: false - nullContextForVoidReturningFunctions: false alwaysCheckTooWideReturnTypeFinalMethods: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false @@ -895,7 +894,6 @@ services: arguments: universalObjectCratesClasses: %universalObjectCratesClasses% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - nullContextForVoidReturningFunctions: %featureToggles.nullContextForVoidReturningFunctions% - class: PHPStan\Rules\Exceptions\DefaultExceptionTypeResolver @@ -1792,7 +1790,6 @@ services: arguments: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% universalObjectCratesClasses: %universalObjectCratesClasses% - nullContextForVoidReturningFunctions: %featureToggles.nullContextForVoidReturningFunctions% tags: - phpstan.broker.dynamicFunctionReturnTypeExtension diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 2a7bae6797..ce34892968 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -43,7 +43,6 @@ parametersSchema: runtimeReflectionRules: bool() curlSetOptTypes: bool() missingMagicSerializationRule: bool() - nullContextForVoidReturningFunctions: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() diff --git a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php index 39a4da06bd..45574a089a 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php @@ -48,7 +48,6 @@ public function __construct( private TypeSpecifier $typeSpecifier, private array $universalObjectCratesClasses, private bool $treatPhpDocTypesAsCertain, - private bool $nullContextForVoidReturningFunctions, ) { } @@ -369,16 +368,11 @@ public function doNotTreatPhpDocTypesAsCertain(): self $this->typeSpecifier, $this->universalObjectCratesClasses, false, - $this->nullContextForVoidReturningFunctions, ); } private function determineContext(Scope $scope, Expr $node): TypeSpecifierContext { - if (!$this->nullContextForVoidReturningFunctions) { - return TypeSpecifierContext::createTruthy(); - } - if ($node instanceof Expr\CallLike && $node->isFirstClassCallable()) { return TypeSpecifierContext::createTruthy(); } diff --git a/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php b/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php index 1f715dad2c..a6ab212328 100644 --- a/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php +++ b/src/Type/Php/TypeSpecifyingFunctionsDynamicReturnTypeExtension.php @@ -25,7 +25,7 @@ final class TypeSpecifyingFunctionsDynamicReturnTypeExtension implements Dynamic /** * @param string[] $universalObjectCratesClasses */ - public function __construct(private ReflectionProvider $reflectionProvider, private bool $treatPhpDocTypesAsCertain, private array $universalObjectCratesClasses, private bool $nullContextForVoidReturningFunctions) + public function __construct(private ReflectionProvider $reflectionProvider, private bool $treatPhpDocTypesAsCertain, private array $universalObjectCratesClasses) { } @@ -68,7 +68,7 @@ public function getTypeFromFunctionCall( private function getHelper(): ImpossibleCheckTypeHelper { if ($this->helper === null) { - $this->helper = new ImpossibleCheckTypeHelper($this->reflectionProvider, $this->typeSpecifier, $this->universalObjectCratesClasses, $this->treatPhpDocTypesAsCertain, $this->nullContextForVoidReturningFunctions); + $this->helper = new ImpossibleCheckTypeHelper($this->reflectionProvider, $this->typeSpecifier, $this->universalObjectCratesClasses, $this->treatPhpDocTypesAsCertain); } return $this->helper; diff --git a/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php index e84e4956c7..1b66a5898e 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php index 980be0e207..5fb982f548 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php index b5d52ba9a0..4db5d7167a 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php @@ -25,7 +25,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php index 7d05804a46..4ddf9941e8 100644 --- a/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php index bf67146684..4bac3a314f 100644 --- a/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php @@ -25,7 +25,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php index 840839ac9b..80ee3c0763 100644 --- a/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php @@ -23,7 +23,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index 7a9e4e59af..bee9669510 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -31,7 +31,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [stdClass::class], $this->treatPhpDocTypesAsCertain, - true, ), $this->checkAlwaysTrueCheckTypeFunctionCall, $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php index 152cbaa4a4..47fb5d60f6 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php @@ -19,7 +19,6 @@ public function getRule(): Rule $this->getTypeSpecifier(), [], true, - true, ), true, true, diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php index 54564bf9ea..4d7eedcf84 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php @@ -19,7 +19,6 @@ public function getRule(): Rule $this->getTypeSpecifier(), [], true, - true, ), true, true, diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php index 5fb28b96ba..cfaf5fce01 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php @@ -24,7 +24,6 @@ public function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), true, $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php index b173c04eea..b3c7227ee1 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php @@ -23,7 +23,6 @@ public function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), true, $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php index 7e6c6015ca..4eab90f017 100644 --- a/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): TRule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php index b727ba76e2..4674b642a7 100644 --- a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php @@ -27,7 +27,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php index fa4a13a729..2169597e68 100644 --- a/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/UnreachableIfBranchesRuleTest.php b/tests/PHPStan/Rules/Comparison/UnreachableIfBranchesRuleTest.php index f31bbe5023..4459045cc0 100644 --- a/tests/PHPStan/Rules/Comparison/UnreachableIfBranchesRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/UnreachableIfBranchesRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php b/tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php index 00175cc6fc..bd3cc00a4f 100644 --- a/tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php index 349eb489ed..df5ce1d3c8 100644 --- a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php index 2be9972f15..83f53c071a 100644 --- a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php @@ -22,7 +22,6 @@ protected function getRule(): Rule $this->getTypeSpecifier(), [], $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, From 086a2707ab611d775b9bd25c22896c75f3ae0426 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:03:47 +0200 Subject: [PATCH 167/508] [BE] Check template type variance in `@param-out` --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 2 -- conf/parametersSchema.neon | 1 - src/Rules/Generics/VarianceCheck.php | 5 ----- tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php | 2 +- tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php | 2 +- tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php | 2 +- tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php | 2 +- 9 files changed, 5 insertions(+), 14 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 51c219357f..80784d2042 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -61,7 +61,6 @@ Bleeding edge (TODO move to other sections) * Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed * IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) -* Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 * Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) * Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! * Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! @@ -127,6 +126,7 @@ Improvements 🔧 * Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) * NoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 * Improve impossible type checker for void-returning functions ([#1857](https://github.com/phpstan/phpstan-src/pull/1857)), #8169, thanks @rvanvelzen! +* Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index c695c525d1..4d893731f5 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -22,7 +22,6 @@ parameters: varTagType: true closureDefaultParameterTypeRule: true instanceofType: true - paramOutVariance: true strictStaticMethodTemplateTypeVariance: true propertyVariance: true callUserFunc: true diff --git a/conf/config.neon b/conf/config.neon index c4892a4de7..e6ed12ba2f 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -43,7 +43,6 @@ parameters: varTagType: false closureDefaultParameterTypeRule: false instanceofType: false - paramOutVariance: false strictStaticMethodTemplateTypeVariance: false propertyVariance: false stricterFunctionMap: false @@ -967,7 +966,6 @@ services: - class: PHPStan\Rules\Generics\VarianceCheck arguments: - checkParamOutVariance: %featureToggles.paramOutVariance% strictStaticVariance: %featureToggles.strictStaticMethodTemplateTypeVariance% - diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index ce34892968..68102c39ab 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -49,7 +49,6 @@ parametersSchema: varTagType: bool() closureDefaultParameterTypeRule: bool() instanceofType: bool() - paramOutVariance: bool() strictStaticMethodTemplateTypeVariance: bool() propertyVariance: bool() stricterFunctionMap: bool() diff --git a/src/Rules/Generics/VarianceCheck.php b/src/Rules/Generics/VarianceCheck.php index ca13ca07a6..376a7109e6 100644 --- a/src/Rules/Generics/VarianceCheck.php +++ b/src/Rules/Generics/VarianceCheck.php @@ -14,7 +14,6 @@ final class VarianceCheck { public function __construct( - private bool $checkParamOutVariance, private bool $strictStaticVariance, ) { @@ -68,10 +67,6 @@ public function checkParametersAcceptor( $errors[] = $error; } - if (!$this->checkParamOutVariance) { - continue; - } - $paramOutType = $parameterReflection->getOutType(); if ($paramOutType === null) { continue; diff --git a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php index 867cff2e50..a7bd6c6c7a 100644 --- a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php @@ -18,7 +18,7 @@ protected function getRule(): Rule new GenericAncestorsCheck( $this->createReflectionProvider(), new GenericObjectTypeCheck(), - new VarianceCheck(true, true), + new VarianceCheck(true), new UnresolvableTypeHelper(), [], ), diff --git a/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php index 0978f6c7c5..af69ef5ea9 100644 --- a/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php @@ -19,7 +19,7 @@ protected function getRule(): Rule new GenericAncestorsCheck( $this->createReflectionProvider(), new GenericObjectTypeCheck(), - new VarianceCheck(true, true), + new VarianceCheck(true), new UnresolvableTypeHelper(), [], ), diff --git a/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php index 8d7a275278..c5c92bb097 100644 --- a/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php @@ -18,7 +18,7 @@ protected function getRule(): Rule new GenericAncestorsCheck( $this->createReflectionProvider(), new GenericObjectTypeCheck(), - new VarianceCheck(true, true), + new VarianceCheck(true), new UnresolvableTypeHelper(), [], ), diff --git a/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php b/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php index c62ce6fc24..7e1ee17d34 100644 --- a/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php @@ -20,7 +20,7 @@ protected function getRule(): Rule new GenericAncestorsCheck( $this->createReflectionProvider(), new GenericObjectTypeCheck(), - new VarianceCheck(true, true), + new VarianceCheck(true), new UnresolvableTypeHelper(), [], ), From 047c2d362e4f80be48747e4afe6cb84f7fdf7ae1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:05:20 +0200 Subject: [PATCH 168/508] [BE] Fix position variance of static method parameters --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 3 --- conf/parametersSchema.neon | 1 - src/Rules/Generics/VarianceCheck.php | 10 +--------- .../PHPStan/Rules/Generics/ClassAncestorsRuleTest.php | 2 +- tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php | 2 +- .../Rules/Generics/InterfaceAncestorsRuleTest.php | 2 +- tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php | 2 +- 9 files changed, 6 insertions(+), 19 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 80784d2042..58a26b37cf 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -62,7 +62,6 @@ Bleeding edge (TODO move to other sections) * Because "always true" is always reported, these are no longer needed * IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) * Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) -* Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! * Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) @@ -127,6 +126,7 @@ Improvements 🔧 * NoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 * Improve impossible type checker for void-returning functions ([#1857](https://github.com/phpstan/phpstan-src/pull/1857)), #8169, thanks @rvanvelzen! * Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 +* Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 4d893731f5..8ec2f5e19e 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -22,7 +22,6 @@ parameters: varTagType: true closureDefaultParameterTypeRule: true instanceofType: true - strictStaticMethodTemplateTypeVariance: true propertyVariance: true callUserFunc: true magicConstantOutOfContext: true diff --git a/conf/config.neon b/conf/config.neon index e6ed12ba2f..dcc8b5c61a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -43,7 +43,6 @@ parameters: varTagType: false closureDefaultParameterTypeRule: false instanceofType: false - strictStaticMethodTemplateTypeVariance: false propertyVariance: false stricterFunctionMap: false callUserFunc: false @@ -965,8 +964,6 @@ services: - class: PHPStan\Rules\Generics\VarianceCheck - arguments: - strictStaticVariance: %featureToggles.strictStaticMethodTemplateTypeVariance% - class: PHPStan\Rules\IssetCheck diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 68102c39ab..7b991aedb9 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -49,7 +49,6 @@ parametersSchema: varTagType: bool() closureDefaultParameterTypeRule: bool() instanceofType: bool() - strictStaticMethodTemplateTypeVariance: bool() propertyVariance: bool() stricterFunctionMap: bool() callUserFunc: bool() diff --git a/src/Rules/Generics/VarianceCheck.php b/src/Rules/Generics/VarianceCheck.php index 376a7109e6..95170eecb4 100644 --- a/src/Rules/Generics/VarianceCheck.php +++ b/src/Rules/Generics/VarianceCheck.php @@ -13,12 +13,6 @@ final class VarianceCheck { - public function __construct( - private bool $strictStaticVariance, - ) - { - } - /** * @param 'function'|'method' $identifier * @return list @@ -56,9 +50,7 @@ public function checkParametersAcceptor( } $covariant = TemplateTypeVariance::createCovariant(); - $parameterVariance = $isStatic && !$this->strictStaticVariance - ? TemplateTypeVariance::createStatic() - : TemplateTypeVariance::createContravariant(); + $parameterVariance = TemplateTypeVariance::createContravariant(); foreach ($parametersAcceptor->getParameters() as $parameterReflection) { $type = $parameterReflection->getType(); diff --git a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php index a7bd6c6c7a..b36d872851 100644 --- a/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php @@ -18,7 +18,7 @@ protected function getRule(): Rule new GenericAncestorsCheck( $this->createReflectionProvider(), new GenericObjectTypeCheck(), - new VarianceCheck(true), + new VarianceCheck(), new UnresolvableTypeHelper(), [], ), diff --git a/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php index af69ef5ea9..3bc3ac59e6 100644 --- a/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php @@ -19,7 +19,7 @@ protected function getRule(): Rule new GenericAncestorsCheck( $this->createReflectionProvider(), new GenericObjectTypeCheck(), - new VarianceCheck(true), + new VarianceCheck(), new UnresolvableTypeHelper(), [], ), diff --git a/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php b/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php index c5c92bb097..ee7fd32fd9 100644 --- a/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php @@ -18,7 +18,7 @@ protected function getRule(): Rule new GenericAncestorsCheck( $this->createReflectionProvider(), new GenericObjectTypeCheck(), - new VarianceCheck(true), + new VarianceCheck(), new UnresolvableTypeHelper(), [], ), diff --git a/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php b/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php index 7e1ee17d34..9eab4b213e 100644 --- a/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php +++ b/tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php @@ -20,7 +20,7 @@ protected function getRule(): Rule new GenericAncestorsCheck( $this->createReflectionProvider(), new GenericObjectTypeCheck(), - new VarianceCheck(true), + new VarianceCheck(), new UnresolvableTypeHelper(), [], ), From 80ad11ea4d97d939629b4aab7526652c9abe261f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:09:11 +0200 Subject: [PATCH 169/508] Upgrading note --- UPGRADING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 18861737b0..e6ccef2f83 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -32,6 +32,8 @@ Don't forget to update [3rd party PHPStan extensions](https://phpstan.org/user-g After changing your `composer.json`, run `composer update 'phpstan/*' -W`. +It's up to you whether you go through the new reported errors or if you just put them all to the [baseline](https://phpstan.org/user-guide/baseline) ;) Everyone who's on PHPStan 1.12 should be able to upgrade to PHPStan 2.0. + ### Removed option `checkMissingIterableValueType` It's strongly recommended to add the missing array typehints. From 27ab11b3320b8b75bfa73f0938b456fbec9263ff Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:10:07 +0200 Subject: [PATCH 170/508] [BE] Check code in custom PHPStan extensions for runtime reflection concepts --- changelog-2.0.md | 12 ++++++------ conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 20 ++++---------------- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 10 insertions(+), 25 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 58a26b37cf..7bd3f55652 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -33,6 +33,12 @@ Major new features 🚀 * Check missing types in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/892b319f25f04bc1b55c3d0063b607909612fe6d) * Check missing types in local type aliases (https://github.com/phpstan/phpstan-src/commit/ce7ffaf02d624a7fb9d38f8e5dffc9739f1233fc) * Check missing types in `@mixin` (https://github.com/phpstan/phpstan-src/commit/3175c81f26fd5bcb4a161b24e774921870ed2533) +* Check code in custom PHPStan extensions for runtime reflection concepts like `is_a()` or `class_parents()` (level 0) (https://github.com/phpstan/phpstan-src/commit/c4a662ac6c3ec63f063238880b243b5399c34fcc) +* Check code in custom PHPStan extensions for runtime reflection concepts like `new ReflectionMethod()` (level 0) (https://github.com/phpstan/phpstan-src/commit/536306611cbb5877b6565755cd07b87f9ccfdf08) +* ApiInstanceofRule (level 0) + * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) + * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) +* Check that PHPStan class in class constant fetch is covered by backward compatibility promise (level 0) (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) Bleeding edge (TODO move to other sections) ===================== @@ -45,12 +51,6 @@ Bleeding edge (TODO move to other sections) * Unresolvable parameters ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) -* Check that PHPStan class in class constant fetch is covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) -* Check code in custom PHPStan extensions for runtime reflection concepts like `is_a()` or `class_parents()` (https://github.com/phpstan/phpstan-src/commit/c4a662ac6c3ec63f063238880b243b5399c34fcc) -* Check code in custom PHPStan extensions for runtime reflection concepts like `new ReflectionMethod()` (https://github.com/phpstan/phpstan-src/commit/536306611cbb5877b6565755cd07b87f9ccfdf08) -* ApiInstanceofRule - * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) - * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! * Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 8ec2f5e19e..3356f15719 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -13,7 +13,6 @@ parameters: consistentConstructor: true checkUnresolvableParameterTypes: true readOnlyByPhpDoc: true - runtimeReflectionRules: true curlSetOptTypes: true missingMagicSerializationRule: true alwaysCheckTooWideReturnTypeFinalMethods: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 1f1aa09e62..be485cdbc3 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -10,14 +10,6 @@ conditionalTags: phpstan.rules.rule: %checkUninitializedProperties% PHPStan\Rules\Methods\ConsistentConstructorRule: phpstan.rules.rule: %featureToggles.consistentConstructor% - PHPStan\Rules\Api\ApiClassConstFetchRule: - phpstan.rules.rule: %featureToggles.runtimeReflectionRules% - PHPStan\Rules\Api\ApiInstanceofRule: - phpstan.rules.rule: %featureToggles.runtimeReflectionRules% - PHPStan\Rules\Api\RuntimeReflectionFunctionRule: - phpstan.rules.rule: %featureToggles.runtimeReflectionRules% - PHPStan\Rules\Api\RuntimeReflectionInstantiationRule: - phpstan.rules.rule: %featureToggles.runtimeReflectionRules% PHPStan\Rules\Methods\MissingMagicSerializationMethodsRule: phpstan.rules.rule: %featureToggles.missingMagicSerializationRule% PHPStan\Rules\Constants\MagicConstantContextRule: @@ -30,7 +22,9 @@ conditionalTags: phpstan.rules.rule: %featureToggles.requireFileExists% rules: + - PHPStan\Rules\Api\ApiInstanceofRule - PHPStan\Rules\Api\ApiInstantiationRule + - PHPStan\Rules\Api\ApiClassConstFetchRule - PHPStan\Rules\Api\ApiClassExtendsRule - PHPStan\Rules\Api\ApiClassImplementsRule - PHPStan\Rules\Api\ApiInterfaceExtendsRule @@ -40,6 +34,8 @@ rules: - PHPStan\Rules\Api\GetTemplateTypeRule - PHPStan\Rules\Api\NodeConnectingVisitorAttributesRule - PHPStan\Rules\Api\PhpStanNamespaceIn3rdPartyPackageRule + - PHPStan\Rules\Api\RuntimeReflectionInstantiationRule + - PHPStan\Rules\Api\RuntimeReflectionFunctionRule - PHPStan\Rules\Arrays\DuplicateKeysInLiteralArraysRule - PHPStan\Rules\Arrays\EmptyArrayItemRule - PHPStan\Rules\Arrays\OffsetAccessWithoutDimForReadingRule @@ -120,10 +116,6 @@ rules: - PHPStan\Rules\Whitespace\FileWhitespaceRule services: - - - class: PHPStan\Rules\Api\ApiClassConstFetchRule - - - class: PHPStan\Rules\Api\ApiInstanceofRule - class: PHPStan\Rules\Api\ApiInstanceofTypeRule arguments: @@ -131,10 +123,6 @@ services: deprecationRulesInstalled: %deprecationRulesInstalled% tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Api\RuntimeReflectionFunctionRule - - - class: PHPStan\Rules\Api\RuntimeReflectionInstantiationRule - class: PHPStan\Rules\Classes\ExistingClassInClassExtendsRule tags: diff --git a/conf/config.neon b/conf/config.neon index dcc8b5c61a..3de3cefcab 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -34,7 +34,6 @@ parameters: consistentConstructor: false checkUnresolvableParameterTypes: false readOnlyByPhpDoc: false - runtimeReflectionRules: false curlSetOptTypes: false missingMagicSerializationRule: false alwaysCheckTooWideReturnTypeFinalMethods: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 7b991aedb9..07fc7a4084 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -40,7 +40,6 @@ parametersSchema: consistentConstructor: bool() checkUnresolvableParameterTypes: bool() readOnlyByPhpDoc: bool() - runtimeReflectionRules: bool() curlSetOptTypes: bool() missingMagicSerializationRule: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() From 8bf527b3b374dd694ee7f07e6deb80da54b69368 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:16:30 +0200 Subject: [PATCH 171/508] [BE] Deprecate various `instanceof *Type` in favour of new methods on `Type` interface --- UPGRADING.md | 4 ++++ changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 8 +------- conf/config.neon | 8 +++++--- conf/parametersSchema.neon | 1 - src/Rules/Api/ApiInstanceofTypeRule.php | 6 ------ tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php | 2 +- 8 files changed, 12 insertions(+), 20 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index e6ccef2f83..9a0e770952 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -128,6 +128,10 @@ return [ ]; ``` +### Deprecate various `instanceof *Type` in favour of new methods on `Type` interface + +Learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) + ### Changed `TypeSpecifier::create()` and `SpecifiedTypes` constructor parameters [`PHPStan\Analyser\TypeSpecifier::create()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.TypeSpecifier.html#_create) now accepts (all parameters are required): diff --git a/changelog-2.0.md b/changelog-2.0.md index 7bd3f55652..f6897df85e 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -39,6 +39,7 @@ Major new features 🚀 * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) * Check that PHPStan class in class constant fetch is covered by backward compatibility promise (level 0) (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) +* Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) Bleeding edge (TODO move to other sections) ===================== @@ -61,7 +62,6 @@ Bleeding edge (TODO move to other sections) * Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed * IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) -* Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) * Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 3356f15719..7fbd8c23b3 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -20,7 +20,6 @@ parameters: disableUnreachableBranchesRules: true varTagType: true closureDefaultParameterTypeRule: true - instanceofType: true propertyVariance: true callUserFunc: true magicConstantOutOfContext: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index be485cdbc3..0e00bc5e92 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -23,6 +23,7 @@ conditionalTags: rules: - PHPStan\Rules\Api\ApiInstanceofRule + - PHPStan\Rules\Api\ApiInstanceofTypeRule - PHPStan\Rules\Api\ApiInstantiationRule - PHPStan\Rules\Api\ApiClassConstFetchRule - PHPStan\Rules\Api\ApiClassExtendsRule @@ -116,13 +117,6 @@ rules: - PHPStan\Rules\Whitespace\FileWhitespaceRule services: - - - class: PHPStan\Rules\Api\ApiInstanceofTypeRule - arguments: - enabled: %featureToggles.instanceofType% - deprecationRulesInstalled: %deprecationRulesInstalled% - tags: - - phpstan.rules.rule - class: PHPStan\Rules\Classes\ExistingClassInClassExtendsRule tags: diff --git a/conf/config.neon b/conf/config.neon index 3de3cefcab..66ea8a4a67 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -41,7 +41,6 @@ parameters: disableUnreachableBranchesRules: false varTagType: false closureDefaultParameterTypeRule: false - instanceofType: false propertyVariance: false stricterFunctionMap: false callUserFunc: false @@ -247,8 +246,6 @@ conditionalTags: phpstan.rules.rule: %exceptions.check.tooWideThrowType% PHPStan\Parser\CurlSetOptArgVisitor: phpstan.parser.richParserNodeVisitor: %featureToggles.curlSetOptTypes% - PHPStan\Parser\TypeTraverserInstanceofVisitor: - phpstan.parser.richParserNodeVisitor: %featureToggles.instanceofType% services: - @@ -339,6 +336,11 @@ services: tags: - phpstan.parser.richParserNodeVisitor + - + class: PHPStan\Parser\TypeTraverserInstanceofVisitor + tags: + - phpstan.parser.richParserNodeVisitor + - class: PHPStan\Node\Printer\ExprPrinter diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 07fc7a4084..a4373609b7 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -47,7 +47,6 @@ parametersSchema: disableUnreachableBranchesRules: bool() varTagType: bool() closureDefaultParameterTypeRule: bool() - instanceofType: bool() propertyVariance: bool() stricterFunctionMap: bool() callUserFunc: bool() diff --git a/src/Rules/Api/ApiInstanceofTypeRule.php b/src/Rules/Api/ApiInstanceofTypeRule.php index 1ae24aa0ca..c78d682e11 100644 --- a/src/Rules/Api/ApiInstanceofTypeRule.php +++ b/src/Rules/Api/ApiInstanceofTypeRule.php @@ -94,8 +94,6 @@ final class ApiInstanceofTypeRule implements Rule public function __construct( private ReflectionProvider $reflectionProvider, - private bool $enabled, - private bool $deprecationRulesInstalled, ) { } @@ -107,10 +105,6 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if (!$this->enabled && !$this->deprecationRulesInstalled) { - return []; - } - if (!$node->class instanceof Node\Name) { return []; } diff --git a/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php b/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php index 6be9f18d4b..e12f8aaf14 100644 --- a/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php +++ b/tests/PHPStan/Rules/Api/ApiInstanceofTypeRuleTest.php @@ -13,7 +13,7 @@ class ApiInstanceofTypeRuleTest extends RuleTestCase public function getRule(): Rule { - return new ApiInstanceofTypeRule($this->createReflectionProvider(), true, true); + return new ApiInstanceofTypeRule($this->createReflectionProvider()); } public function testRule(): void From c764f78868c630ebe3fd7ae3890a6acbbd7d9b20 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:22:26 +0200 Subject: [PATCH 172/508] [BE] Change `curl_setopt` function signature based on 2nd arg --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 5 ++--- conf/parametersSchema.neon | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index f6897df85e..7fee5b125c 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -54,7 +54,6 @@ Bleeding edge (TODO move to other sections) * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! -* Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! * Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) * Validate inline PHPDoc `@var` tag type against native type (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones @@ -154,6 +153,7 @@ Function signature fixes 🤖 * More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! * Update `Locale` signatures ([#2880](https://github.com/phpstan/phpstan-src/pull/2880)), thanks @devnix! * Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3!* Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! +* Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! Internals 🔍 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 7fbd8c23b3..5a4efe4678 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -13,7 +13,6 @@ parameters: consistentConstructor: true checkUnresolvableParameterTypes: true readOnlyByPhpDoc: true - curlSetOptTypes: true missingMagicSerializationRule: true alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true diff --git a/conf/config.neon b/conf/config.neon index 66ea8a4a67..637fc05249 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -34,7 +34,6 @@ parameters: consistentConstructor: false checkUnresolvableParameterTypes: false readOnlyByPhpDoc: false - curlSetOptTypes: false missingMagicSerializationRule: false alwaysCheckTooWideReturnTypeFinalMethods: false alwaysTrueAlwaysReported: false @@ -244,8 +243,6 @@ conditionalTags: phpstan.rules.rule: %exceptions.check.tooWideThrowType% PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule: phpstan.rules.rule: %exceptions.check.tooWideThrowType% - PHPStan\Parser\CurlSetOptArgVisitor: - phpstan.parser.richParserNodeVisitor: %featureToggles.curlSetOptTypes% services: - @@ -297,6 +294,8 @@ services: - class: PHPStan\Parser\CurlSetOptArgVisitor + tags: + - phpstan.parser.richParserNodeVisitor - class: PHPStan\Parser\TypeTraverserInstanceofVisitor diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index a4373609b7..074b8bd080 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -40,7 +40,6 @@ parametersSchema: consistentConstructor: bool() checkUnresolvableParameterTypes: bool() readOnlyByPhpDoc: bool() - curlSetOptTypes: bool() missingMagicSerializationRule: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() alwaysTrueAlwaysReported: bool() From 676cbaebe057db61be6656a7af1884cb80cf09a5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:23:50 +0200 Subject: [PATCH 173/508] [BE] Rule for `call_user_func()` --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level5.neon | 5 +---- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 7fee5b125c..24792df71a 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -16,6 +16,7 @@ Major new features 🚀 * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! +* Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Added previously absent type checks (level 0) * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) @@ -65,7 +66,6 @@ Bleeding edge (TODO move to other sections) * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) -* Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) * Report unused results of `and` and `or` (https://github.com/phpstan/phpstan-src/commit/1d8fff637d70a9e9ed3f11dee5d61b9f796cbf1a) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 5a4efe4678..3889cfac9e 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -20,7 +20,6 @@ parameters: varTagType: true closureDefaultParameterTypeRule: true propertyVariance: true - callUserFunc: true magicConstantOutOfContext: true pure: true checkParameterCastableToStringFunctions: true diff --git a/conf/config.level5.neon b/conf/config.level5.neon index cdc7638cde..2f2e4feaca 100644 --- a/conf/config.level5.neon +++ b/conf/config.level5.neon @@ -10,8 +10,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.arrayFilter% PHPStan\Rules\Functions\ArrayValuesRule: phpstan.rules.rule: %featureToggles.arrayValues% - PHPStan\Rules\Functions\CallUserFuncRule: - phpstan.rules.rule: %featureToggles.callUserFunc% PHPStan\Rules\Functions\ParameterCastableToStringRule: phpstan.rules.rule: %featureToggles.checkParameterCastableToStringFunctions% PHPStan\Rules\Functions\ImplodeParameterCastableToStringRule: @@ -21,6 +19,7 @@ conditionalTags: rules: - PHPStan\Rules\DateTimeInstantiationRule + - PHPStan\Rules\Functions\CallUserFuncRule services: - @@ -42,8 +41,6 @@ services: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% - - - class: PHPStan\Rules\Functions\CallUserFuncRule - class: PHPStan\Rules\Functions\ParameterCastableToStringRule - diff --git a/conf/config.neon b/conf/config.neon index 637fc05249..1d3f9c31aa 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -42,7 +42,6 @@ parameters: closureDefaultParameterTypeRule: false propertyVariance: false stricterFunctionMap: false - callUserFunc: false magicConstantOutOfContext: false pure: false checkParameterCastableToStringFunctions: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 074b8bd080..5a53e3e544 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -48,7 +48,6 @@ parametersSchema: closureDefaultParameterTypeRule: bool() propertyVariance: bool() stricterFunctionMap: bool() - callUserFunc: bool() magicConstantOutOfContext: bool() pure: bool() checkParameterCastableToStringFunctions: bool() From 0dc119c7bb5bacc944c2f242fea9696a91f761ea Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:24:11 +0200 Subject: [PATCH 174/508] Remove unused feature toggle --- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 2 files changed, 2 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index 1d3f9c31aa..5a0f69d1e7 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -48,7 +48,6 @@ parameters: uselessReturnValue: false printfArrayParameters: false requireFileExists: false - narrowPregMatches: true tooWidePropertyType: false fileExtensions: - php diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 5a53e3e544..ade1f92f34 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -53,7 +53,6 @@ parametersSchema: checkParameterCastableToStringFunctions: bool() uselessReturnValue: bool() printfArrayParameters: bool() - narrowPregMatches: bool() tooWidePropertyType: bool() requireFileExists: bool() ]) From 8270b37864cec90a00a3754a66429314bcedbf78 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:25:26 +0200 Subject: [PATCH 175/508] [BE] ArrayUnpackingRule --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level3.neon | 6 +----- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 24792df71a..2796a14ccf 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -17,6 +17,7 @@ Major new features 🚀 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! +* ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! * Added previously absent type checks (level 0) * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) @@ -47,7 +48,6 @@ Bleeding edge (TODO move to other sections) * Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! * Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! -* ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! * Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! * ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) * Unresolvable parameters ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 3889cfac9e..82b2a09848 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -6,7 +6,6 @@ parameters: explicitMixedViaIsArray: true arrayFilter: true - arrayUnpacking: true arrayValues: true strictUnnecessaryNullsafePropertyFetch: true looseComparison: true diff --git a/conf/config.level3.neon b/conf/config.level3.neon index dfbfc00454..089569684c 100644 --- a/conf/config.level3.neon +++ b/conf/config.level3.neon @@ -2,8 +2,6 @@ includes: - config.level2.neon conditionalTags: - PHPStan\Rules\Arrays\ArrayUnpackingRule: - phpstan.rules.rule: %featureToggles.arrayUnpacking% PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRefRule: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRule: @@ -11,6 +9,7 @@ conditionalTags: rules: - PHPStan\Rules\Arrays\ArrayDestructuringRule + - PHPStan\Rules\Arrays\ArrayUnpackingRule - PHPStan\Rules\Arrays\IterableInForeachRule - PHPStan\Rules\Arrays\OffsetAccessAssignmentRule - PHPStan\Rules\Arrays\OffsetAccessAssignOpRule @@ -85,9 +84,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Arrays\ArrayUnpackingRule - - class: PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRefRule diff --git a/conf/config.neon b/conf/config.neon index 5a0f69d1e7..b5f6c75be7 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -26,7 +26,6 @@ parameters: skipCheckGenericClasses: [] explicitMixedViaIsArray: false arrayFilter: false - arrayUnpacking: false arrayValues: false illegalConstructorMethodCall: false strictUnnecessaryNullsafePropertyFetch: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index ade1f92f34..f403ca849c 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -32,7 +32,6 @@ parametersSchema: skipCheckGenericClasses: listOf(string()), explicitMixedViaIsArray: bool(), arrayFilter: bool(), - arrayUnpacking: bool(), arrayValues: bool(), illegalConstructorMethodCall: bool(), strictUnnecessaryNullsafePropertyFetch: bool(), From 32564ee9c7c78cf6ce2788671a9b643baf6080cf Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:31:04 +0200 Subject: [PATCH 176/508] [BE] Check unresolvable parameters --- changelog-2.0.md | 4 ++-- conf/bleedingEdge.neon | 1 - conf/config.neon | 2 -- conf/parametersSchema.neon | 1 - src/Rules/FunctionCallParametersCheck.php | 12 ++++-------- src/Testing/TestCase.neon | 2 -- .../PHPStan/Analyser/Bug9307CallMethodsRuleTest.php | 2 +- .../Rules/Classes/ClassAttributesRuleTest.php | 1 - .../Classes/ClassConstantAttributesRuleTest.php | 1 - .../Classes/ForbiddenNameCheckExtensionRuleTest.php | 2 +- .../PHPStan/Rules/Classes/InstantiationRuleTest.php | 2 +- .../Rules/EnumCases/EnumCaseAttributesRuleTest.php | 1 - .../Functions/ArrowFunctionAttributesRuleTest.php | 1 - .../Rules/Functions/CallCallablesRuleTest.php | 1 - .../Functions/CallToFunctionParametersRuleTest.php | 2 +- .../PHPStan/Rules/Functions/CallUserFuncRuleTest.php | 2 +- .../Rules/Functions/ClosureAttributesRuleTest.php | 1 - .../Rules/Functions/FunctionAttributesRuleTest.php | 1 - .../Rules/Functions/ParamAttributesRuleTest.php | 1 - tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php | 2 +- .../Rules/Methods/CallStaticMethodsRuleTest.php | 1 - .../Rules/Methods/MethodAttributesRuleTest.php | 1 - .../Rules/Properties/PropertyAttributesRuleTest.php | 1 - 23 files changed, 12 insertions(+), 33 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 2796a14ccf..fe5a7ae058 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -18,6 +18,8 @@ Major new features 🚀 * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! +* Check unresolvable parameters (level 5) ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! +* Enforce `@no-named-arguments` (level 5) (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 * Added previously absent type checks (level 0) * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) @@ -50,7 +52,6 @@ Bleeding edge (TODO move to other sections) * Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! * Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! * ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) -* Unresolvable parameters ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! @@ -82,7 +83,6 @@ Bleeding edge (TODO move to other sections) * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! -* Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 * Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 82b2a09848..5b911974f4 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -10,7 +10,6 @@ parameters: strictUnnecessaryNullsafePropertyFetch: true looseComparison: true consistentConstructor: true - checkUnresolvableParameterTypes: true readOnlyByPhpDoc: true missingMagicSerializationRule: true alwaysCheckTooWideReturnTypeFinalMethods: true diff --git a/conf/config.neon b/conf/config.neon index b5f6c75be7..5d60538a42 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -31,7 +31,6 @@ parameters: strictUnnecessaryNullsafePropertyFetch: false looseComparison: false consistentConstructor: false - checkUnresolvableParameterTypes: false readOnlyByPhpDoc: false missingMagicSerializationRule: false alwaysCheckTooWideReturnTypeFinalMethods: false @@ -927,7 +926,6 @@ services: checkArgumentsPassedByReference: %checkArgumentsPassedByReference% checkExtraArguments: %checkExtraArguments% checkMissingTypehints: %checkMissingTypehints% - checkUnresolvableParameterTypes: %featureToggles.checkUnresolvableParameterTypes% - class: PHPStan\Rules\FunctionDefinitionCheck diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index f403ca849c..96adcd6578 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -37,7 +37,6 @@ parametersSchema: strictUnnecessaryNullsafePropertyFetch: bool(), looseComparison: bool(), consistentConstructor: bool() - checkUnresolvableParameterTypes: bool() readOnlyByPhpDoc: bool() missingMagicSerializationRule: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 412dd928ba..9f42773237 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -46,7 +46,6 @@ public function __construct( private bool $checkArgumentsPassedByReference, private bool $checkExtraArguments, private bool $checkMissingTypehints, - private bool $checkUnresolvableParameterTypes, ) { } @@ -290,7 +289,7 @@ public function check( } } - if (!$acceptsNamedArguments && $this->checkUnresolvableParameterTypes && isset($messages[14])) { + if (!$acceptsNamedArguments && isset($messages[14])) { if ($argumentName !== null) { $errors[] = RuleErrorBuilder::message(sprintf($messages[14], sprintf('named argument $%s', $argumentName))) ->identifier('argument.named') @@ -311,10 +310,7 @@ public function check( if ($this->checkArgumentTypes) { $parameterType = TypeUtils::resolveLateResolvableTypes($parameter->getType()); - if ( - !$parameter->passedByReference()->createsNewVariable() - || (!$isBuiltin && $this->checkUnresolvableParameterTypes) // bleeding edge only - ) { + if (!$parameter->passedByReference()->createsNewVariable() || !$isBuiltin) { $accepts = $this->ruleLevelHelper->acceptsWithReason($parameterType, $argumentValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { @@ -332,8 +328,8 @@ public function check( } } - if ($this->checkUnresolvableParameterTypes - && $originalParameter !== null + if ( + $originalParameter !== null && isset($messages[13]) && !$this->unresolvableTypeHelper->containsUnresolvableType($originalParameter->getType()) && $this->unresolvableTypeHelper->containsUnresolvableType($parameterType) diff --git a/src/Testing/TestCase.neon b/src/Testing/TestCase.neon index a5ed7689b6..c5ef275d1f 100644 --- a/src/Testing/TestCase.neon +++ b/src/Testing/TestCase.neon @@ -1,7 +1,5 @@ parameters: inferPrivatePropertyTypeFromConstructor: true - featureToggles: - checkUnresolvableParameterTypes: true services: - diff --git a/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php b/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php index c7b4f688a3..a49a650286 100644 --- a/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php +++ b/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php @@ -26,7 +26,7 @@ protected function getRule(): Rule $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false); return new CallMethodsRule( new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true), - new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion(PHP_VERSION_ID), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), + new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion(PHP_VERSION_ID), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), ); } diff --git a/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php b/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php index e261724d7d..aac5cbda3c 100644 --- a/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php @@ -38,7 +38,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), diff --git a/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php b/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php index 69fd7a2c2b..d5787f8344 100644 --- a/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php @@ -37,7 +37,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), diff --git a/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php b/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php index fa8b767c4b..4907d1d7ec 100644 --- a/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php @@ -26,7 +26,7 @@ protected function getRule(): Rule $reflectionProvider = $this->createReflectionProvider(); return new InstantiationRule( $reflectionProvider, - new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php index 4271153e36..657c47bd75 100644 --- a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php +++ b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php @@ -26,7 +26,7 @@ protected function getRule(): Rule $reflectionProvider = $this->createReflectionProvider(); return new InstantiationRule( $reflectionProvider, - new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php b/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php index bb81a1157e..52428ced2b 100644 --- a/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php +++ b/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php @@ -37,7 +37,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), diff --git a/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php index 44d564b8ff..af9266b7e5 100644 --- a/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php @@ -37,7 +37,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), diff --git a/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php b/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php index 97260fb244..31a92a4f92 100644 --- a/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php @@ -34,7 +34,6 @@ protected function getRule(): Rule true, true, true, - true, ), $ruleLevelHelper, true, diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index 22dfd46eb8..c150f1890e 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -26,7 +26,7 @@ protected function getRule(): Rule $broker = $this->createReflectionProvider(); return new CallToFunctionParametersRule( $broker, - new FunctionCallParametersCheck(new RuleLevelHelper($broker, true, false, true, $this->checkExplicitMixed, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($broker, true, false, true, $this->checkExplicitMixed, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), ); } diff --git a/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php b/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php index 4744b8f1ce..f4eb4c2c6e 100644 --- a/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php @@ -21,7 +21,7 @@ class CallUserFuncRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - return new CallUserFuncRule($reflectionProvider, new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true)); + return new CallUserFuncRule($reflectionProvider, new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php index 5827cc181c..dbab699a2b 100644 --- a/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php @@ -37,7 +37,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), diff --git a/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php index 5fe8fe58f8..6d028b1b96 100644 --- a/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php @@ -37,7 +37,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), diff --git a/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php index 3298bd5bb0..842d0513a1 100644 --- a/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php @@ -37,7 +37,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index 85f5aa6e8d..8eeba69aab 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -36,7 +36,7 @@ protected function getRule(): Rule $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, $this->checkNullables, $this->checkThisOnly, $this->checkUnionTypes, $this->checkExplicitMixed, $this->checkImplicitMixed, false); return new CallMethodsRule( new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true), - new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion($this->phpVersion), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true, true), + new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion($this->phpVersion), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), ); } diff --git a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php index f13767c4ed..56e260b8d2 100644 --- a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php @@ -54,7 +54,6 @@ protected function getRule(): Rule true, true, true, - true, ), ); } diff --git a/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php b/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php index 03d672afd0..ef5ca25aef 100644 --- a/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php @@ -39,7 +39,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), diff --git a/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php b/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php index 26f8969686..02b75d1007 100644 --- a/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php @@ -36,7 +36,6 @@ protected function getRule(): Rule true, true, true, - true, ), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, false), From 4e30a47a63665f35a783c623b715626eb266fc5f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 23 Sep 2024 16:33:54 +0200 Subject: [PATCH 177/508] Changelog update --- changelog-2.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index fe5a7ae058..a72024427b 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -56,7 +56,6 @@ Bleeding edge (TODO move to other sections) * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! -* Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) * Validate inline PHPDoc `@var` tag type against native type (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones * Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! @@ -126,6 +125,7 @@ Improvements 🔧 * Improve impossible type checker for void-returning functions ([#1857](https://github.com/phpstan/phpstan-src/pull/1857)), #8169, thanks @rvanvelzen! * Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 * Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! +* Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) Bugfixes 🐛 ===================== From 56bfb926774041523cc4a95f13a427fc5fe1e3fa Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 08:45:36 +0200 Subject: [PATCH 178/508] [BE] Validate `@var` tags --- changelog-2.0.md | 8 +-- conf/bleedingEdge.neon | 1 - conf/config.level2.neon | 12 +---- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - .../PhpDoc/WrongVariableNameInVarTagRule.php | 44 +++++++-------- .../WrongVariableNameInVarTagRuleTest.php | 54 +++++++++---------- 7 files changed, 51 insertions(+), 70 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index a72024427b..e40d87985a 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -7,10 +7,12 @@ Major new features 🚀 * **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! * Lists are arrays with sequential integer keys starting at 0 -* Lower memory consumption thanks to breaking up of reference cycles +* **Validate inline PHPDoc `@var` tag** type against native type (level 2) (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) + * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones +* **Lower memory consumption** thanks to breaking up of reference cycles * [Learn more »](https://phpstan.org/blog/preprocessing-ast-for-custom-rules) * In testing the memory consumption was reduced by 50–70 %. -* **Enhancements in Handling Parameters Passed by Reference** +* **Enhancements in handling parameters passed by reference** * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 @@ -56,8 +58,6 @@ Bleeding edge (TODO move to other sections) * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! -* Validate inline PHPDoc `@var` tag type against native type (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) - * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones * Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! * Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 5b911974f4..1fd98bf92a 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -15,7 +15,6 @@ parameters: alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true - varTagType: true closureDefaultParameterTypeRule: true propertyVariance: true magicConstantOutOfContext: true diff --git a/conf/config.level2.neon b/conf/config.level2.neon index 715f1089a8..5fd37f5fd4 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -52,6 +52,8 @@ rules: - PHPStan\Rules\PhpDoc\IncompatiblePropertyPhpDocTypeRule - PHPStan\Rules\PhpDoc\InvalidThrowsPhpDocValueRule - PHPStan\Rules\PhpDoc\IncompatibleParamImmediatelyInvokedCallableRule + - PHPStan\Rules\PhpDoc\VarTagChangedExpressionTypeRule + - PHPStan\Rules\PhpDoc\WrongVariableNameInVarTagRule - PHPStan\Rules\Properties\AccessPrivatePropertyThroughStaticRule - PHPStan\Rules\Classes\RequireImplementsRule - PHPStan\Rules\Classes\RequireExtendsRule @@ -68,8 +70,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% PHPStan\Rules\Methods\IllegalConstructorStaticCallRule: phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% - PHPStan\Rules\PhpDoc\VarTagChangedExpressionTypeRule: - phpstan.rules.rule: %featureToggles.varTagType% PHPStan\Rules\Generics\PropertyVarianceRule: phpstan.rules.rule: %featureToggles.propertyVariance% PHPStan\Rules\Pure\PureFunctionRule: @@ -125,14 +125,6 @@ services: class: PHPStan\Rules\PhpDoc\InvalidPHPStanDocTagRule tags: - phpstan.rules.rule - - - class: PHPStan\Rules\PhpDoc\VarTagChangedExpressionTypeRule - - - class: PHPStan\Rules\PhpDoc\WrongVariableNameInVarTagRule - arguments: - checkTypeAgainstNativeType: %featureToggles.varTagType% - tags: - - phpstan.rules.rule - class: PHPStan\Rules\Generics\PropertyVarianceRule arguments: diff --git a/conf/config.neon b/conf/config.neon index 5d60538a42..79392f5d1a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -36,7 +36,6 @@ parameters: alwaysCheckTooWideReturnTypeFinalMethods: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false - varTagType: false closureDefaultParameterTypeRule: false propertyVariance: false stricterFunctionMap: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 96adcd6578..0081f682df 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -42,7 +42,6 @@ parametersSchema: alwaysCheckTooWideReturnTypeFinalMethods: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() - varTagType: bool() closureDefaultParameterTypeRule: bool() propertyVariance: bool() stricterFunctionMap: bool() diff --git a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php index 87784c71d6..72e61ffdb6 100644 --- a/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php +++ b/src/Rules/PhpDoc/WrongVariableNameInVarTagRule.php @@ -37,7 +37,6 @@ final class WrongVariableNameInVarTagRule implements Rule public function __construct( private FileTypeMapper $fileTypeMapper, private VarTagTypeRuleHelper $varTagTypeRuleHelper, - private bool $checkTypeAgainstNativeType, ) { } @@ -138,11 +137,6 @@ private function processAssign(Scope $scope, Node\Expr $var, Node\Expr $expr, ar $errors = []; $hasMultipleMessage = false; $assignedVariables = $this->getAssignedVariables($var); - if ($this->checkTypeAgainstNativeType) { - foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $var, $expr, $varTags, $assignedVariables) as $error) { - $errors[] = $error; - } - } foreach (array_keys($varTags) as $key) { if (is_int($key)) { if (count($varTags) !== 1) { @@ -181,6 +175,12 @@ private function processAssign(Scope $scope, Node\Expr $var, Node\Expr $expr, ar } } + if (count($errors) === 0) { + foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $var, $expr, $varTags, $assignedVariables) as $error) { + $errors[] = $error; + } + } + return $errors; } @@ -251,19 +251,17 @@ private function processForeach(Scope $scope, Node\Expr $iterateeExpr, ?Node\Exp ))->identifier('varTag.differentVariable')->build(); } - if ($this->checkTypeAgainstNativeType) { - foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $iterateeExpr, $iterateeExpr, $varTags, $variableNames) as $error) { - $errors[] = $error; - } - if ($keyVar !== null) { - foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $keyVar, new GetIterableKeyTypeExpr($iterateeExpr), $varTags, $variableNames) as $error) { - $errors[] = $error; - } - } - foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $valueVar, new GetIterableValueTypeExpr($iterateeExpr), $varTags, $variableNames) as $error) { + foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $iterateeExpr, $iterateeExpr, $varTags, $variableNames) as $error) { + $errors[] = $error; + } + if ($keyVar !== null) { + foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $keyVar, new GetIterableKeyTypeExpr($iterateeExpr), $varTags, $variableNames) as $error) { $errors[] = $error; } } + foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $valueVar, new GetIterableValueTypeExpr($iterateeExpr), $varTags, $variableNames) as $error) { + $errors[] = $error; + } return $errors; } @@ -321,14 +319,12 @@ private function processStatic(Scope $scope, array $vars, array $varTags): array ))->identifier('varTag.differentVariable')->build(); } - if ($this->checkTypeAgainstNativeType) { - foreach ($vars as $var) { - if ($var->default === null) { - continue; - } - foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $var->var, $var->default, $varTags, $variableNames) as $error) { - $errors[] = $error; - } + foreach ($vars as $var) { + if ($var->default === null) { + continue; + } + foreach ($this->varTagTypeRuleHelper->checkVarType($scope, $var->var, $var->default, $varTags, $variableNames) as $error) { + $errors[] = $error; } } diff --git a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php index 6083de943d..155c0d6ea4 100644 --- a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php @@ -13,8 +13,6 @@ class WrongVariableNameInVarTagRuleTest extends RuleTestCase { - private bool $checkTypeAgainstNativeType = false; - private bool $checkTypeAgainstPhpDocType = false; private bool $strictWideningCheck = false; @@ -24,13 +22,20 @@ protected function getRule(): Rule return new WrongVariableNameInVarTagRule( self::getContainer()->getByType(FileTypeMapper::class), new VarTagTypeRuleHelper($this->checkTypeAgainstPhpDocType, $this->strictWideningCheck), - $this->checkTypeAgainstNativeType, ); } public function testRule(): void { $this->analyse([__DIR__ . '/data/wrong-variable-name-var.php'], [ + [ + 'PHPDoc tag @var with type int is not subtype of native type void.', + 11, + ], + [ + 'PHPDoc tag @var with type int is not subtype of native type void.', + 14, + ], [ 'Variable $foo in PHPDoc tag @var does not match assigned variable $test.', 17, @@ -71,6 +76,10 @@ public function testRule(): void 'Variable $foo in PHPDoc tag @var does not exist.', 109, ], + [ + 'PHPDoc tag @var with type int is not subtype of native type void.', + 120, + ], [ 'Multiple PHPDoc @var tags above single variable assignment are not supported.', 126, @@ -253,12 +262,9 @@ public function dataReportWrongType(): iterable ], ]; - yield [false, false, false, []]; - yield [true, false, false, $nativeCheckOnly]; - yield [true, false, true, $nativeCheckOnly]; - yield [false, true, false, []]; - yield [false, true, true, []]; - yield [true, true, false, [ + yield [false, false, $nativeCheckOnly]; + yield [false, true, $nativeCheckOnly]; + yield [true, false, [ [ 'PHPDoc tag @var with type string|null is not subtype of native type string.', 14, @@ -349,7 +355,7 @@ public function dataReportWrongType(): iterable 204, ], ]]; - yield [true, true, true, [ + yield [true, true, [ [ 'PHPDoc tag @var with type string|null is not subtype of native type string.', 14, @@ -469,29 +475,21 @@ public function dataReportWrongType(): iterable /** * @dataProvider dataPermutateCheckTypeAgainst */ - public function testEmptyArrayInitWithWiderPhpDoc(bool $checkTypeAgainstNativeType, bool $checkTypeAgainstPhpDocType): void + public function testEmptyArrayInitWithWiderPhpDoc(bool $checkTypeAgainstPhpDocType): void { - $this->checkTypeAgainstNativeType = $checkTypeAgainstNativeType; $this->checkTypeAgainstPhpDocType = $checkTypeAgainstPhpDocType; - - $errors = !$checkTypeAgainstNativeType - ? [] - : [ - [ - 'PHPDoc tag @var with type int is not subtype of native type array{}.', - 24, - ], - ]; - - $this->analyse([__DIR__ . '/data/var-above-empty-array-widening.php'], $errors); + $this->analyse([__DIR__ . '/data/var-above-empty-array-widening.php'], [ + [ + 'PHPDoc tag @var with type int is not subtype of native type array{}.', + 24, + ], + ]); } public function dataPermutateCheckTypeAgainst(): iterable { - yield [true, true]; - yield [false, true]; - yield [true, false]; - yield [false, false]; + yield [true]; + yield [false]; } /** @@ -499,13 +497,11 @@ public function dataPermutateCheckTypeAgainst(): iterable * @param list $expectedErrors */ public function testReportWrongType( - bool $checkTypeAgainstNativeType, bool $checkTypeAgainstPhpDocType, bool $strictWideningCheck, array $expectedErrors, ): void { - $this->checkTypeAgainstNativeType = $checkTypeAgainstNativeType; $this->checkTypeAgainstPhpDocType = $checkTypeAgainstPhpDocType; $this->strictWideningCheck = $strictWideningCheck; $this->analyse([__DIR__ . '/data/wrong-var-native-type.php'], $expectedErrors); From fe4a386f173c48cc409abdf2dfac8df4ae34b1e3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 08:58:47 +0200 Subject: [PATCH 179/508] Always report static property fetch in `isset()`, not just on PHP 8.2+ --- src/Analyser/MutatingScope.php | 2 +- .../AccessStaticPropertiesRuleTest.php | 170 +----------------- 2 files changed, 5 insertions(+), 167 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 62786fe77a..0e2ead8dde 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3855,7 +3855,7 @@ public function isInExpressionAssign(Expr $expr): bool public function setAllowedUndefinedExpression(Expr $expr): self { - if ($this->phpVersion->deprecatesDynamicProperties() && $expr instanceof Expr\StaticPropertyFetch) { + if ($expr instanceof Expr\StaticPropertyFetch) { return $this; } diff --git a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php index 822a048e1e..87861e276e 100644 --- a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php @@ -31,166 +31,6 @@ protected function getRule(): Rule public function testAccessStaticProperties(): void { - if (PHP_VERSION_ID >= 80200) { - $this->markTestSkipped('Test is not for PHP 8.2.'); - } - $this->analyse([__DIR__ . '/data/access-static-properties.php'], [ - [ - 'Access to an undefined static property FooAccessStaticProperties::$bar.', - 23, - ], - [ - 'Access to an undefined static property BarAccessStaticProperties::$bar.', - 24, - ], - [ - 'Access to an undefined static property FooAccessStaticProperties::$bar.', - 25, - ], - [ - 'Static access to instance property FooAccessStaticProperties::$loremIpsum.', - 26, - ], - [ - 'IpsumAccessStaticProperties::ipsum() accesses parent::$lorem but IpsumAccessStaticProperties does not extend any class.', - 42, - ], - [ - 'Access to protected property $foo of class FooAccessStaticProperties.', - 44, - ], - [ - 'Access to static property $test on an unknown class UnknownStaticProperties.', - 47, - 'Learn more at https://phpstan.org/user-guide/discovering-symbols', - ], - [ - 'Access to an undefined static property static(IpsumAccessStaticProperties)::$baz.', - 53, - ], - [ - 'Access to an undefined static property static(IpsumAccessStaticProperties)::$nonexistent.', - 55, - ], - [ - 'Access to an undefined static property static(IpsumAccessStaticProperties)::$emptyBaz.', - 63, - ], - [ - 'Access to an undefined static property static(IpsumAccessStaticProperties)::$emptyNonexistent.', - 65, - ], - [ - 'Access to an undefined static property static(IpsumAccessStaticProperties)::$anotherNonexistent.', - 71, - ], - [ - 'Access to an undefined static property static(IpsumAccessStaticProperties)::$anotherNonexistent.', - 72, - ], - [ - 'Access to an undefined static property static(IpsumAccessStaticProperties)::$anotherEmptyNonexistent.', - 75, - ], - [ - 'Access to an undefined static property static(IpsumAccessStaticProperties)::$anotherEmptyNonexistent.', - 78, - ], - [ - 'Accessing self::$staticFooProperty outside of class scope.', - 84, - ], - [ - 'Accessing static::$staticFooProperty outside of class scope.', - 85, - ], - [ - 'Accessing parent::$staticFooProperty outside of class scope.', - 86, - ], - [ - 'Access to protected property $foo of class FooAccessStaticProperties.', - 89, - ], - [ - 'Static access to instance property FooAccessStaticProperties::$loremIpsum.', - 90, - ], - [ - 'Access to an undefined static property FooAccessStaticProperties::$nonexistent.', - 94, - ], - [ - 'Access to static property $test on an unknown class NonexistentClass.', - 97, - 'Learn more at https://phpstan.org/user-guide/discovering-symbols', - ], - [ - 'Access to an undefined static property FooAccessStaticProperties&SomeInterface::$nonexistent.', - 108, - ], - [ - 'Cannot access static property $foo on int|string.', - 113, - ], - [ - 'Class FooAccessStaticProperties referenced with incorrect case: FOOAccessStaticPropertieS.', - 119, - ], - [ - 'Access to an undefined static property FooAccessStaticProperties::$unknownProperties.', - 119, - ], - [ - 'Class FooAccessStaticProperties referenced with incorrect case: FOOAccessStaticPropertieS.', - 120, - ], - [ - 'Static access to instance property FooAccessStaticProperties::$loremIpsum.', - 120, - ], - [ - 'Class FooAccessStaticProperties referenced with incorrect case: FOOAccessStaticPropertieS.', - 121, - ], - [ - 'Access to protected property $foo of class FooAccessStaticProperties.', - 121, - ], - [ - 'Class FooAccessStaticProperties referenced with incorrect case: FOOAccessStaticPropertieS.', - 122, - ], - [ - 'Access to an undefined static property ClassOrString|string::$unknownProperty.', - 141, - ], - [ - 'Static access to instance property ClassOrString::$instanceProperty.', - 152, - ], - [ - 'Access to static property $foo on an unknown class TraitWithStaticProperty.', - 209, - 'Learn more at https://phpstan.org/user-guide/discovering-symbols', - ], - [ - 'Static access to instance property AccessWithStatic::$bar.', - 223, - ], - [ - 'Access to an undefined static property static(AccessWithStatic)::$nonexistent.', - 224, - ], - ]); - } - - public function testAccessStaticPropertiesPhp82(): void - { - if (PHP_VERSION_ID < 80200) { - $this->markTestSkipped('Test requires PHP 8.2.'); - } - $this->analyse([__DIR__ . '/data/access-static-properties.php'], [ [ 'Access to an undefined static property FooAccessStaticProperties::$bar.', @@ -436,14 +276,12 @@ public function testBug5143(): void public function testBug6809(): void { - $errors = []; - if (PHP_VERSION_ID >= 80200) { - $errors[] = [ + $this->analyse([__DIR__ . '/data/bug-6809.php'], [ + [ 'Access to an undefined static property static(Bug6809\HelloWorld)::$coolClass.', 7, - ]; - } - $this->analyse([__DIR__ . '/data/bug-6809.php'], $errors); + ], + ]); } public function testBug8333(): void From 3e2feca2f2f1aef1a6b0070fcd16c697b49034de Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:16:24 +0200 Subject: [PATCH 180/508] Fix CS --- .../PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php index 87861e276e..acbfca290c 100644 --- a/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessStaticPropertiesRuleTest.php @@ -8,7 +8,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; -use const PHP_VERSION_ID; /** * @extends RuleTestCase From 8c10b7336f31be02b1c330b880dde76986950d35 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:20:47 +0200 Subject: [PATCH 181/508] [BE] Report unnecessary nullsafe property fetch with different message --- changelog-2.0.md | 1 + conf/bleedingEdge.neon | 1 - conf/config.neon | 2 - conf/parametersSchema.neon | 1 - src/Rules/IssetCheck.php | 5 --- .../PHPStan/Rules/Variables/EmptyRuleTest.php | 31 -------------- .../PHPStan/Rules/Variables/IssetRuleTest.php | 42 ++----------------- .../Rules/Variables/NullCoalesceRuleTest.php | 34 --------------- 8 files changed, 5 insertions(+), 112 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index e40d87985a..668dd218a3 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -126,6 +126,7 @@ Improvements 🔧 * Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 * Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! * Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) +* Report unnecessary nullsafe property fetch inside `??` / `isset` / `empty` with different message ([#1253](https://github.com/phpstan/phpstan-src/pull/1253)), thanks @rajyan! Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 1fd98bf92a..1154241b44 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -7,7 +7,6 @@ parameters: explicitMixedViaIsArray: true arrayFilter: true arrayValues: true - strictUnnecessaryNullsafePropertyFetch: true looseComparison: true consistentConstructor: true readOnlyByPhpDoc: true diff --git a/conf/config.neon b/conf/config.neon index 79392f5d1a..fef4f694c9 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -28,7 +28,6 @@ parameters: arrayFilter: false arrayValues: false illegalConstructorMethodCall: false - strictUnnecessaryNullsafePropertyFetch: false looseComparison: false consistentConstructor: false readOnlyByPhpDoc: false @@ -964,7 +963,6 @@ services: arguments: checkAdvancedIsset: %checkAdvancedIsset% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - strictUnnecessaryNullsafePropertyFetch: %featureToggles.strictUnnecessaryNullsafePropertyFetch% - class: PHPStan\Rules\Methods\MethodCallCheck diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 0081f682df..25cc07815b 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -34,7 +34,6 @@ parametersSchema: arrayFilter: bool(), arrayValues: bool(), illegalConstructorMethodCall: bool(), - strictUnnecessaryNullsafePropertyFetch: bool(), looseComparison: bool(), consistentConstructor: bool() readOnlyByPhpDoc: bool() diff --git a/src/Rules/IssetCheck.php b/src/Rules/IssetCheck.php index 1a07cb30c7..89433d32ca 100644 --- a/src/Rules/IssetCheck.php +++ b/src/Rules/IssetCheck.php @@ -25,7 +25,6 @@ public function __construct( private PropertyReflectionFinder $propertyReflectionFinder, private bool $checkAdvancedIsset, private bool $treatPhpDocTypesAsCertain, - private bool $strictUnnecessaryNullsafePropertyFetch, ) { } @@ -217,10 +216,6 @@ public function check(Expr $expr, Scope $scope, string $operatorDescription, str } if ($expr instanceof Expr\NullsafePropertyFetch) { - if (!$this->strictUnnecessaryNullsafePropertyFetch) { - return null; - } - if ($expr->name instanceof Node\Identifier) { return RuleErrorBuilder::message(sprintf('Using nullsafe property access "?->%s" %s is unnecessary. Use -> instead.', $expr->name->name, $operatorDescription)) ->identifier('nullsafe.neverNull') diff --git a/tests/PHPStan/Rules/Variables/EmptyRuleTest.php b/tests/PHPStan/Rules/Variables/EmptyRuleTest.php index 6fa229669f..150eb99d7e 100644 --- a/tests/PHPStan/Rules/Variables/EmptyRuleTest.php +++ b/tests/PHPStan/Rules/Variables/EmptyRuleTest.php @@ -17,8 +17,6 @@ class EmptyRuleTest extends RuleTestCase private bool $treatPhpDocTypesAsCertain; - private bool $strictUnnecessaryNullsafePropertyFetch; - protected function getRule(): Rule { return new EmptyRule(new IssetCheck( @@ -26,7 +24,6 @@ protected function getRule(): Rule new PropertyReflectionFinder(), true, $this->treatPhpDocTypesAsCertain, - $this->strictUnnecessaryNullsafePropertyFetch, )); } @@ -38,7 +35,6 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool public function testRule(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/empty-rule.php'], [ [ 'Offset \'nonexistent\' on array{2: bool, 3: false, 4: true}|array{bool, false, bool, false, true} in empty() does not exist.', @@ -78,7 +74,6 @@ public function testRule(): void public function testBug970(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-970.php'], [ [ 'Variable $ar in empty() is never defined.', @@ -90,7 +85,6 @@ public function testBug970(): void public function testBug6974(): void { $this->treatPhpDocTypesAsCertain = false; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-6974.php'], [ [ 'Variable $a in empty() always exists and is always falsy.', @@ -102,7 +96,6 @@ public function testBug6974(): void public function testBug6974TreatPhpDocTypesAsCertain(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-6974.php'], [ [ 'Variable $a in empty() always exists and is always falsy.', @@ -122,24 +115,6 @@ public function testBug7109(): void } $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; - - $this->analyse([__DIR__ . '/../Properties/data/bug-7109.php'], [ - [ - 'Expression in empty() is not falsy.', - 59, - ], - ]); - } - - public function testBug7109Strict(): void - { - if (PHP_VERSION_ID < 80000) { - $this->markTestSkipped('Test requires PHP 8.0.'); - } - - $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/../Properties/data/bug-7109.php'], [ [ @@ -176,7 +151,6 @@ public function testBug7109Strict(): void public function testBug7318(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/../Properties/data/bug-7318.php'], []); } @@ -184,7 +158,6 @@ public function testBug7318(): void public function testBug7424(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-7424.php'], []); } @@ -192,7 +165,6 @@ public function testBug7424(): void public function testBug7724(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-7724.php'], []); } @@ -200,7 +172,6 @@ public function testBug7724(): void public function testBug7199(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-7199.php'], []); } @@ -208,7 +179,6 @@ public function testBug7199(): void public function testBug9126(): void { $this->treatPhpDocTypesAsCertain = false; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-9126.php'], []); } @@ -225,7 +195,6 @@ public function dataBug9403(): iterable public function testBug9403(bool $treatPhpDocTypesAsCertain): void { $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-9403.php'], []); } diff --git a/tests/PHPStan/Rules/Variables/IssetRuleTest.php b/tests/PHPStan/Rules/Variables/IssetRuleTest.php index 2c22dfd35a..a3e1ed68a2 100644 --- a/tests/PHPStan/Rules/Variables/IssetRuleTest.php +++ b/tests/PHPStan/Rules/Variables/IssetRuleTest.php @@ -17,8 +17,6 @@ class IssetRuleTest extends RuleTestCase private bool $treatPhpDocTypesAsCertain; - private bool $strictUnnecessaryNullsafePropertyFetch; - protected function getRule(): Rule { return new IssetRule(new IssetCheck( @@ -26,7 +24,6 @@ protected function getRule(): Rule new PropertyReflectionFinder(), true, $this->treatPhpDocTypesAsCertain, - $this->strictUnnecessaryNullsafePropertyFetch, )); } @@ -38,7 +35,6 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool public function testRule(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/isset.php'], [ [ 'Property IssetRule\FooCoalesce::$string (string) in isset() is not nullable.', @@ -126,7 +122,6 @@ public function testRule(): void public function testRuleWithoutTreatPhpDocTypesAsCertain(): void { $this->treatPhpDocTypesAsCertain = false; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/isset.php'], [ [ 'Property IssetRule\FooCoalesce::$string (string) in isset() is not nullable.', @@ -206,7 +201,6 @@ public function testRuleWithoutTreatPhpDocTypesAsCertain(): void public function testNativePropertyTypes(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/isset-native-property-types.php'], [ /*[ // no way to achieve this with current PHP Reflection API @@ -225,14 +219,12 @@ public function testNativePropertyTypes(): void public function testBug4290(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-4290.php'], []); } public function testBug4671(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-4671.php'], [[ 'Offset numeric-string on array in isset() does not exist.', 13, @@ -242,7 +234,6 @@ public function testBug4671(): void public function testVariableCertaintyInIsset(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/variable-certainty-isset.php'], [ [ 'Variable $alwaysDefinedNotNullable in isset() always exists and is not nullable.', @@ -318,7 +309,6 @@ public function testVariableCertaintyInIsset(): void public function testIssetInGlobalScope(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/isset-global-scope.php'], [ [ 'Variable $alwaysDefinedNotNullable in isset() always exists and is not nullable.', @@ -330,35 +320,21 @@ public function testIssetInGlobalScope(): void public function testNullsafe(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; - $this->analyse([__DIR__ . '/data/isset-nullsafe.php'], []); - } - - public function testBug7109(): void - { - if (PHP_VERSION_ID < 80000) { - $this->markTestSkipped('Test requires PHP 8.0.'); - } - - $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; - - $this->analyse([__DIR__ . '/../Properties/data/bug-7109.php'], [ + $this->analyse([__DIR__ . '/data/isset-nullsafe.php'], [ [ - 'Expression in isset() is not nullable.', - 41, + 'Using nullsafe property access "?->bla" in isset() is unnecessary. Use -> instead.', + 10, ], ]); } - public function testBug7109Strict(): void + public function testBug7109(): void { if (PHP_VERSION_ID < 80000) { $this->markTestSkipped('Test requires PHP 8.0.'); } $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/../Properties/data/bug-7109.php'], [ [ @@ -387,7 +363,6 @@ public function testBug7109Strict(): void public function testBug7318(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/../Properties/data/bug-7318.php'], [ [ @@ -400,7 +375,6 @@ public function testBug7318(): void public function testBug6163(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-6163.php'], []); } @@ -408,7 +382,6 @@ public function testBug6163(): void public function testBug6997(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-6997.php'], []); } @@ -420,7 +393,6 @@ public function testBug7776(): void } $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-7776.php'], []); } @@ -428,7 +400,6 @@ public function testBug7776(): void public function testBug6008(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-6008.php'], []); } @@ -436,7 +407,6 @@ public function testBug6008(): void public function testBug7292(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-7292.php'], []); } @@ -444,7 +414,6 @@ public function testBug7292(): void public function testObjectShapes(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; // could be checked but current is not $this->analyse([__DIR__ . '/data/isset-object-shapes.php'], []); @@ -453,7 +422,6 @@ public function testObjectShapes(): void public function testBug10151(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-10151.php'], []); } @@ -461,7 +429,6 @@ public function testBug10151(): void public function testBug3985(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-3985.php'], [ [ @@ -478,7 +445,6 @@ public function testBug3985(): void public function testBug10064(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-10064.php'], []); } diff --git a/tests/PHPStan/Rules/Variables/NullCoalesceRuleTest.php b/tests/PHPStan/Rules/Variables/NullCoalesceRuleTest.php index 302858a4e5..2b32877d52 100644 --- a/tests/PHPStan/Rules/Variables/NullCoalesceRuleTest.php +++ b/tests/PHPStan/Rules/Variables/NullCoalesceRuleTest.php @@ -17,8 +17,6 @@ class NullCoalesceRuleTest extends RuleTestCase private bool $treatPhpDocTypesAsCertain; - private bool $strictUnnecessaryNullsafePropertyFetch; - protected function getRule(): Rule { return new NullCoalesceRule(new IssetCheck( @@ -26,7 +24,6 @@ protected function getRule(): Rule new PropertyReflectionFinder(), true, $this->treatPhpDocTypesAsCertain, - $this->strictUnnecessaryNullsafePropertyFetch, )); } @@ -38,7 +35,6 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool public function testCoalesceRule(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $errors = [ [ 'Property CoalesceRule\FooCoalesce::$string (string) on left side of ?? is not nullable.', @@ -145,7 +141,6 @@ public function testCoalesceRule(): void public function testCoalesceAssignRule(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/null-coalesce-assign.php'], [ [ 'Property CoalesceAssignRule\FooCoalesce::$string (string) on left side of ??= is not nullable.', @@ -209,14 +204,12 @@ public function testCoalesceAssignRule(): void public function testNullsafe(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/null-coalesce-nullsafe.php'], []); } public function testVariableCertaintyInNullCoalesce(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/variable-certainty-null.php'], [ [ 'Variable $scalar on left side of ?? always exists and is not nullable.', @@ -236,7 +229,6 @@ public function testVariableCertaintyInNullCoalesce(): void public function testVariableCertaintyInNullCoalesceAssign(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/variable-certainty-null-assign.php'], [ [ 'Variable $scalar on left side of ??= always exists and is not nullable.', @@ -256,7 +248,6 @@ public function testVariableCertaintyInNullCoalesceAssign(): void public function testNullCoalesceInGlobalScope(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/null-coalesce-global-scope.php'], [ [ 'Variable $bar on left side of ?? always exists and is not nullable.', @@ -268,7 +259,6 @@ public function testNullCoalesceInGlobalScope(): void public function testBug5933(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/data/bug-5933.php'], []); } @@ -279,24 +269,6 @@ public function testBug7109(): void } $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; - - $this->analyse([__DIR__ . '/../Properties/data/bug-7109.php'], [ - [ - 'Expression on left side of ?? is not nullable.', - 40, - ], - ]); - } - - public function testBug7109Strict(): void - { - if (PHP_VERSION_ID < 80000) { - $this->markTestSkipped('Test requires PHP 8.0.'); - } - - $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/../Properties/data/bug-7109.php'], [ [ @@ -325,7 +297,6 @@ public function testBug7109Strict(): void public function testBug7190(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = false; $this->analyse([__DIR__ . '/../Properties/data/bug-7190.php'], [ [ @@ -338,7 +309,6 @@ public function testBug7190(): void public function testBug7318(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/../Properties/data/bug-7318.php'], [ [ @@ -351,7 +321,6 @@ public function testBug7318(): void public function testBug7968(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-7968.php'], []); } @@ -359,7 +328,6 @@ public function testBug7968(): void public function testBug8084(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-8084.php'], []); } @@ -367,7 +335,6 @@ public function testBug8084(): void public function testBug10577(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-10577.php'], []); } @@ -375,7 +342,6 @@ public function testBug10577(): void public function testBug10610(): void { $this->treatPhpDocTypesAsCertain = true; - $this->strictUnnecessaryNullsafePropertyFetch = true; $this->analyse([__DIR__ . '/data/bug-10610.php'], []); } From f3b719024e3eb581d96562d1d1a6fdcb95dd790d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:35:37 +0200 Subject: [PATCH 182/508] [BE] Check array functions which require stringish values --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level5.neon | 16 +++------------- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 4 insertions(+), 17 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 668dd218a3..d9ad8796e9 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -19,6 +19,7 @@ Major new features 🚀 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! +* Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! * ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! * Check unresolvable parameters (level 5) ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! * Enforce `@no-named-arguments` (level 5) (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 @@ -86,7 +87,6 @@ Bleeding edge (TODO move to other sections) * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! -* Check array functions which require stringish values ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! Improvements 🔧 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 1154241b44..2a6accd9dc 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -18,7 +18,6 @@ parameters: propertyVariance: true magicConstantOutOfContext: true pure: true - checkParameterCastableToStringFunctions: true uselessReturnValue: true printfArrayParameters: true tooWidePropertyType: true diff --git a/conf/config.level5.neon b/conf/config.level5.neon index 2f2e4feaca..3fa1bb8e29 100644 --- a/conf/config.level5.neon +++ b/conf/config.level5.neon @@ -10,16 +10,13 @@ conditionalTags: phpstan.rules.rule: %featureToggles.arrayFilter% PHPStan\Rules\Functions\ArrayValuesRule: phpstan.rules.rule: %featureToggles.arrayValues% - PHPStan\Rules\Functions\ParameterCastableToStringRule: - phpstan.rules.rule: %featureToggles.checkParameterCastableToStringFunctions% - PHPStan\Rules\Functions\ImplodeParameterCastableToStringRule: - phpstan.rules.rule: %featureToggles.checkParameterCastableToStringFunctions% - PHPStan\Rules\Functions\SortParameterCastableToStringRule: - phpstan.rules.rule: %featureToggles.checkParameterCastableToStringFunctions% rules: - PHPStan\Rules\DateTimeInstantiationRule - PHPStan\Rules\Functions\CallUserFuncRule + - PHPStan\Rules\Functions\ParameterCastableToStringRule + - PHPStan\Rules\Functions\ImplodeParameterCastableToStringRule + - PHPStan\Rules\Functions\SortParameterCastableToStringRule services: - @@ -40,10 +37,3 @@ services: arguments: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% - - - - class: PHPStan\Rules\Functions\ParameterCastableToStringRule - - - class: PHPStan\Rules\Functions\ImplodeParameterCastableToStringRule - - - class: PHPStan\Rules\Functions\SortParameterCastableToStringRule diff --git a/conf/config.neon b/conf/config.neon index fef4f694c9..9038685e3a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -40,7 +40,6 @@ parameters: stricterFunctionMap: false magicConstantOutOfContext: false pure: false - checkParameterCastableToStringFunctions: false uselessReturnValue: false printfArrayParameters: false requireFileExists: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 25cc07815b..8a22e0fa82 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -46,7 +46,6 @@ parametersSchema: stricterFunctionMap: bool() magicConstantOutOfContext: bool() pure: bool() - checkParameterCastableToStringFunctions: bool() uselessReturnValue: bool() printfArrayParameters: bool() tooWidePropertyType: bool() From 6ce1743ae8feb1cf941f5e3ecc2d03aeede05f68 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:40:29 +0200 Subject: [PATCH 183/508] [BE] IncompatibleDefaultParameterTypeRule for closures --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level2.neon | 10 ++-------- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 3 insertions(+), 12 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index d9ad8796e9..d98795d5f5 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -23,6 +23,7 @@ Major new features 🚀 * ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! * Check unresolvable parameters (level 5) ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! * Enforce `@no-named-arguments` (level 5) (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 +* IncompatibleDefaultParameterTypeRule for closures (level 2) (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) * Added previously absent type checks (level 0) * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) @@ -62,7 +63,6 @@ Bleeding edge (TODO move to other sections) * Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! * Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed -* IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) * Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 2a6accd9dc..0ad75d4718 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -14,7 +14,6 @@ parameters: alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true - closureDefaultParameterTypeRule: true propertyVariance: true magicConstantOutOfContext: true pure: true diff --git a/conf/config.level2.neon b/conf/config.level2.neon index 5fd37f5fd4..7863272da9 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -23,6 +23,8 @@ rules: - PHPStan\Rules\Comparison\UsageOfVoidMatchExpressionRule - PHPStan\Rules\Constants\ValueAssignedToClassConstantRule - PHPStan\Rules\Functions\IncompatibleDefaultParameterTypeRule + - PHPStan\Rules\Functions\IncompatibleArrowFunctionDefaultParameterTypeRule + - PHPStan\Rules\Functions\IncompatibleClosureDefaultParameterTypeRule - PHPStan\Rules\Generics\ClassAncestorsRule - PHPStan\Rules\Generics\ClassTemplateTypeRule - PHPStan\Rules\Generics\EnumAncestorsRule @@ -62,10 +64,6 @@ rules: - PHPStan\Rules\PhpDoc\RequireExtendsDefinitionTraitRule conditionalTags: - PHPStan\Rules\Functions\IncompatibleArrowFunctionDefaultParameterTypeRule: - phpstan.rules.rule: %featureToggles.closureDefaultParameterTypeRule% - PHPStan\Rules\Functions\IncompatibleClosureDefaultParameterTypeRule: - phpstan.rules.rule: %featureToggles.closureDefaultParameterTypeRule% PHPStan\Rules\Methods\IllegalConstructorMethodCallRule: phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% PHPStan\Rules\Methods\IllegalConstructorStaticCallRule: @@ -95,10 +93,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Functions\IncompatibleArrowFunctionDefaultParameterTypeRule - - - class: PHPStan\Rules\Functions\IncompatibleClosureDefaultParameterTypeRule - class: PHPStan\Rules\Functions\CallCallablesRule arguments: diff --git a/conf/config.neon b/conf/config.neon index 9038685e3a..76b8e8e814 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -35,7 +35,6 @@ parameters: alwaysCheckTooWideReturnTypeFinalMethods: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false - closureDefaultParameterTypeRule: false propertyVariance: false stricterFunctionMap: false magicConstantOutOfContext: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 8a22e0fa82..a9f23039ef 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -41,7 +41,6 @@ parametersSchema: alwaysCheckTooWideReturnTypeFinalMethods: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() - closureDefaultParameterTypeRule: bool() propertyVariance: bool() stricterFunctionMap: bool() magicConstantOutOfContext: bool() From 8cf4281a70dbaeb048db580d8b78ba7258adbad3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:43:48 +0200 Subject: [PATCH 184/508] [BE] Rule about `@phpstan-consistent-constructor` --- changelog-2.0.md | 1 + conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 5 +---- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 2 insertions(+), 7 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index d98795d5f5..53269961ab 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -41,6 +41,7 @@ Major new features 🚀 * Check missing types in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/892b319f25f04bc1b55c3d0063b607909612fe6d) * Check missing types in local type aliases (https://github.com/phpstan/phpstan-src/commit/ce7ffaf02d624a7fb9d38f8e5dffc9739f1233fc) * Check missing types in `@mixin` (https://github.com/phpstan/phpstan-src/commit/3175c81f26fd5bcb4a161b24e774921870ed2533) +* Rule about `@phpstan-consistent-constructor` (level 0) ([#1296](https://github.com/phpstan/phpstan-src/pull/1296)), thanks @canvural! * Check code in custom PHPStan extensions for runtime reflection concepts like `is_a()` or `class_parents()` (level 0) (https://github.com/phpstan/phpstan-src/commit/c4a662ac6c3ec63f063238880b243b5399c34fcc) * Check code in custom PHPStan extensions for runtime reflection concepts like `new ReflectionMethod()` (level 0) (https://github.com/phpstan/phpstan-src/commit/536306611cbb5877b6565755cd07b87f9ccfdf08) * ApiInstanceofRule (level 0) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 0ad75d4718..35f6a99226 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -8,7 +8,6 @@ parameters: arrayFilter: true arrayValues: true looseComparison: true - consistentConstructor: true readOnlyByPhpDoc: true missingMagicSerializationRule: true alwaysCheckTooWideReturnTypeFinalMethods: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 0e00bc5e92..711beeff40 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -8,8 +8,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\UninitializedPropertyRule: phpstan.rules.rule: %checkUninitializedProperties% - PHPStan\Rules\Methods\ConsistentConstructorRule: - phpstan.rules.rule: %featureToggles.consistentConstructor% PHPStan\Rules\Methods\MissingMagicSerializationMethodsRule: phpstan.rules.rule: %featureToggles.missingMagicSerializationRule% PHPStan\Rules\Constants\MagicConstantContextRule: @@ -90,6 +88,7 @@ rules: - PHPStan\Rules\Methods\AbstractPrivateMethodRule - PHPStan\Rules\Methods\CallMethodsRule - PHPStan\Rules\Methods\CallStaticMethodsRule + - PHPStan\Rules\Methods\ConsistentConstructorRule - PHPStan\Rules\Methods\ConstructorReturnTypeRule - PHPStan\Rules\Methods\ExistingClassesInTypehintsRule - PHPStan\Rules\Methods\FinalPrivateMethodRule @@ -158,8 +157,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Methods\ConsistentConstructorRule - class: PHPStan\Rules\Missing\MissingReturnRule diff --git a/conf/config.neon b/conf/config.neon index 76b8e8e814..a6871cf0b0 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -29,7 +29,6 @@ parameters: arrayValues: false illegalConstructorMethodCall: false looseComparison: false - consistentConstructor: false readOnlyByPhpDoc: false missingMagicSerializationRule: false alwaysCheckTooWideReturnTypeFinalMethods: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index a9f23039ef..5a960314b5 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -35,7 +35,6 @@ parametersSchema: arrayValues: bool(), illegalConstructorMethodCall: bool(), looseComparison: bool(), - consistentConstructor: bool() readOnlyByPhpDoc: bool() missingMagicSerializationRule: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() From 293fbca1e3a47bd347ab7c6960335c104b7b56b1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:45:38 +0200 Subject: [PATCH 185/508] [BE] Check too wide private property type --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level4.neon | 7 +------ conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 2 insertions(+), 10 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 53269961ab..a1e03d841a 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -15,6 +15,7 @@ Major new features 🚀 * **Enhancements in handling parameters passed by reference** * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! +* Check too wide private property type (level 4) (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! @@ -84,7 +85,6 @@ Bleeding edge (TODO move to other sections) * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! -* Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 35f6a99226..ab60f6996a 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -18,5 +18,4 @@ parameters: pure: true uselessReturnValue: true printfArrayParameters: true - tooWidePropertyType: true requireFileExists: true diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 27c09f7ab7..21621869e5 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -17,6 +17,7 @@ rules: - PHPStan\Rules\TooWideTypehints\TooWideFunctionReturnTypehintRule - PHPStan\Rules\TooWideTypehints\TooWideFunctionParameterOutTypeRule - PHPStan\Rules\TooWideTypehints\TooWideMethodParameterOutTypeRule + - PHPStan\Rules\TooWideTypehints\TooWidePropertyTypeRule - PHPStan\Rules\Traits\NotAnalysedTraitRule conditionalTags: @@ -44,8 +45,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.pure% PHPStan\Rules\DeadCode\PossiblyPureStaticCallCollector: phpstan.collector: %featureToggles.pure% - PHPStan\Rules\TooWideTypehints\TooWidePropertyTypeRule: - phpstan.rules.rule: %featureToggles.tooWidePropertyType% parameters: checkAdvancedIsset: true @@ -309,7 +308,3 @@ services: reportUncheckedExceptionDeadCatch: %exceptions.reportUncheckedExceptionDeadCatch% tags: - phpstan.rules.rule - - - - - class: PHPStan\Rules\TooWideTypehints\TooWidePropertyTypeRule diff --git a/conf/config.neon b/conf/config.neon index a6871cf0b0..096d92c518 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -41,7 +41,6 @@ parameters: uselessReturnValue: false printfArrayParameters: false requireFileExists: false - tooWidePropertyType: false fileExtensions: - php checkAdvancedIsset: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 5a960314b5..be8d4959b9 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -46,7 +46,6 @@ parametersSchema: pure: bool() uselessReturnValue: bool() printfArrayParameters: bool() - tooWidePropertyType: bool() requireFileExists: bool() ]) fileExtensions: listOf(string()) From b593dde0278d9862447f9b254d3e3e4f679ab0e0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:47:32 +0200 Subject: [PATCH 186/508] [BE] Check variance of template types in properties --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level2.neon | 4 ++-- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index a1e03d841a..19be2cdc9c 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -21,6 +21,7 @@ Major new features 🚀 * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! +* Check variance of template types in properties (level 2) ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! * ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! * Check unresolvable parameters (level 5) ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! * Enforce `@no-named-arguments` (level 5) (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 @@ -65,7 +66,6 @@ Bleeding edge (TODO move to other sections) * Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! * Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed -* Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index ab60f6996a..37de1e3e7e 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -13,7 +13,6 @@ parameters: alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true - propertyVariance: true magicConstantOutOfContext: true pure: true uselessReturnValue: true diff --git a/conf/config.level2.neon b/conf/config.level2.neon index 7863272da9..f75e01dfde 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -68,8 +68,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% PHPStan\Rules\Methods\IllegalConstructorStaticCallRule: phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% - PHPStan\Rules\Generics\PropertyVarianceRule: - phpstan.rules.rule: %featureToggles.propertyVariance% PHPStan\Rules\Pure\PureFunctionRule: phpstan.rules.rule: %featureToggles.pure% PHPStan\Rules\Pure\PureMethodRule: @@ -123,6 +121,8 @@ services: class: PHPStan\Rules\Generics\PropertyVarianceRule arguments: readOnlyByPhpDoc: %featureToggles.readOnlyByPhpDoc% + tags: + - phpstan.rules.rule - class: PHPStan\Rules\Pure\PureFunctionRule diff --git a/conf/config.neon b/conf/config.neon index 096d92c518..7738f1ffa6 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -34,7 +34,6 @@ parameters: alwaysCheckTooWideReturnTypeFinalMethods: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false - propertyVariance: false stricterFunctionMap: false magicConstantOutOfContext: false pure: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index be8d4959b9..e4f663d442 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -40,7 +40,6 @@ parametersSchema: alwaysCheckTooWideReturnTypeFinalMethods: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() - propertyVariance: bool() stricterFunctionMap: bool() magicConstantOutOfContext: bool() pure: bool() From 879590db6046d747e62692061449f81f9a13b04e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:48:59 +0200 Subject: [PATCH 187/508] [BE] MagicConstantContextRule --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 6 +----- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 19be2cdc9c..76dd765878 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -19,6 +19,7 @@ Major new features 🚀 * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! +* MagicConstantContextRule (level 0) ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! * Check variance of template types in properties (level 2) ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! @@ -69,7 +70,6 @@ Bleeding edge (TODO move to other sections) * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) -* MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) * Report unused results of `and` and `or` (https://github.com/phpstan/phpstan-src/commit/1d8fff637d70a9e9ed3f11dee5d61b9f796cbf1a) * Report unused result of ternary (https://github.com/phpstan/phpstan-src/commit/9664f7a9d2223c07e750f0dfc949c3accfa6b65e) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 37de1e3e7e..32fb150921 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -13,7 +13,6 @@ parameters: alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true - magicConstantOutOfContext: true pure: true uselessReturnValue: true printfArrayParameters: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 711beeff40..d9fdeea93c 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -10,8 +10,6 @@ conditionalTags: phpstan.rules.rule: %checkUninitializedProperties% PHPStan\Rules\Methods\MissingMagicSerializationMethodsRule: phpstan.rules.rule: %featureToggles.missingMagicSerializationRule% - PHPStan\Rules\Constants\MagicConstantContextRule: - phpstan.rules.rule: %featureToggles.magicConstantOutOfContext% PHPStan\Rules\Functions\UselessFunctionReturnValueRule: phpstan.rules.rule: %featureToggles.uselessReturnValue% PHPStan\Rules\Functions\PrintfArrayParametersRule: @@ -61,6 +59,7 @@ rules: - PHPStan\Rules\Classes\TraitAttributeClassRule - PHPStan\Rules\Constants\DynamicClassConstantFetchRule - PHPStan\Rules\Constants\FinalConstantRule + - PHPStan\Rules\Constants\MagicConstantContextRule - PHPStan\Rules\Constants\NativeTypedClassConstantRule - PHPStan\Rules\EnumCases\EnumCaseAttributesRule - PHPStan\Rules\Exceptions\NoncapturingCatchRule @@ -263,9 +262,6 @@ services: - class: PHPStan\Rules\Methods\MissingMagicSerializationMethodsRule - - - class: PHPStan\Rules\Constants\MagicConstantContextRule - - class: PHPStan\Rules\Functions\UselessFunctionReturnValueRule diff --git a/conf/config.neon b/conf/config.neon index 7738f1ffa6..bc7e8a3aa0 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -35,7 +35,6 @@ parameters: alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false stricterFunctionMap: false - magicConstantOutOfContext: false pure: false uselessReturnValue: false printfArrayParameters: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index e4f663d442..0582652892 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -41,7 +41,6 @@ parametersSchema: alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() stricterFunctionMap: bool() - magicConstantOutOfContext: bool() pure: bool() uselessReturnValue: bool() printfArrayParameters: bool() From d419f43b38f9ab045e0bf5ca5cc4967be4b28259 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:51:29 +0200 Subject: [PATCH 188/508] [BE] MissingMagicSerializationMethodsRule --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 6 +----- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 76dd765878..49420a6753 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -20,6 +20,7 @@ Major new features 🚀 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * MagicConstantContextRule (level 0) ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! +* MissingMagicSerializationMethodsRule (level 0) ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! * Check variance of template types in properties (level 2) ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! @@ -63,7 +64,6 @@ Bleeding edge (TODO move to other sections) * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! -* MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! * Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! * Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 32fb150921..ae30dc43d3 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -9,7 +9,6 @@ parameters: arrayValues: true looseComparison: true readOnlyByPhpDoc: true - missingMagicSerializationRule: true alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index d9fdeea93c..731f86cb11 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -8,8 +8,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\UninitializedPropertyRule: phpstan.rules.rule: %checkUninitializedProperties% - PHPStan\Rules\Methods\MissingMagicSerializationMethodsRule: - phpstan.rules.rule: %featureToggles.missingMagicSerializationRule% PHPStan\Rules\Functions\UselessFunctionReturnValueRule: phpstan.rules.rule: %featureToggles.uselessReturnValue% PHPStan\Rules\Functions\PrintfArrayParametersRule: @@ -93,6 +91,7 @@ rules: - PHPStan\Rules\Methods\FinalPrivateMethodRule - PHPStan\Rules\Methods\MethodCallableRule - PHPStan\Rules\Methods\MethodVisibilityInInterfaceRule + - PHPStan\Rules\Methods\MissingMagicSerializationMethodsRule - PHPStan\Rules\Methods\MissingMethodImplementationRule - PHPStan\Rules\Methods\MethodAttributesRule - PHPStan\Rules\Methods\StaticMethodCallableRule @@ -259,9 +258,6 @@ services: arguments: additionalConstructors: %additionalConstructors% - - - class: PHPStan\Rules\Methods\MissingMagicSerializationMethodsRule - - class: PHPStan\Rules\Functions\UselessFunctionReturnValueRule diff --git a/conf/config.neon b/conf/config.neon index bc7e8a3aa0..02795237fc 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -30,7 +30,6 @@ parameters: illegalConstructorMethodCall: false looseComparison: false readOnlyByPhpDoc: false - missingMagicSerializationRule: false alwaysCheckTooWideReturnTypeFinalMethods: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 0582652892..1d2af1cb84 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -36,7 +36,6 @@ parametersSchema: illegalConstructorMethodCall: bool(), looseComparison: bool(), readOnlyByPhpDoc: bool() - missingMagicSerializationRule: bool() alwaysCheckTooWideReturnTypeFinalMethods: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() From 6703fce6c32d4e8f6917819d1eaa4066ae41999c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 09:53:59 +0200 Subject: [PATCH 189/508] [BE] Report useless return values of function calls like `var_export` without `$return=true` --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 5 +---- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 49420a6753..6eab345888 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -21,6 +21,7 @@ Major new features 🚀 * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * MagicConstantContextRule (level 0) ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * MissingMagicSerializationMethodsRule (level 0) ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! +* Report useless return values of function calls like `var_export` without `$return=true` (level 0) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! * Check variance of template types in properties (level 2) ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! @@ -86,7 +87,6 @@ Bleeding edge (TODO move to other sections) * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 -* Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! Improvements 🔧 diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index ae30dc43d3..1c68c2c5ab 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -13,6 +13,5 @@ parameters: alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true pure: true - uselessReturnValue: true printfArrayParameters: true requireFileExists: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 731f86cb11..691f468809 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -8,8 +8,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\UninitializedPropertyRule: phpstan.rules.rule: %checkUninitializedProperties% - PHPStan\Rules\Functions\UselessFunctionReturnValueRule: - phpstan.rules.rule: %featureToggles.uselessReturnValue% PHPStan\Rules\Functions\PrintfArrayParametersRule: phpstan.rules.rule: %featureToggles.printfArrayParameters% PHPStan\Rules\Keywords\RequireFileExistsRule: @@ -77,6 +75,7 @@ rules: - PHPStan\Rules\Functions\PrintfParametersRule - PHPStan\Rules\Functions\RedefinedParametersRule - PHPStan\Rules\Functions\ReturnNullsafeByRefRule + - PHPStan\Rules\Functions\UselessFunctionReturnValueRule - PHPStan\Rules\Ignore\IgnoreParseErrorRule - PHPStan\Rules\Functions\VariadicParametersDeclarationRule - PHPStan\Rules\Keywords\ContinueBreakInLoopRule @@ -258,8 +257,6 @@ services: arguments: additionalConstructors: %additionalConstructors% - - - class: PHPStan\Rules\Functions\UselessFunctionReturnValueRule - class: PHPStan\Rules\Functions\PrintfArrayParametersRule diff --git a/conf/config.neon b/conf/config.neon index 02795237fc..6466d2dfd2 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -35,7 +35,6 @@ parameters: disableUnreachableBranchesRules: false stricterFunctionMap: false pure: false - uselessReturnValue: false printfArrayParameters: false requireFileExists: false fileExtensions: diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 1d2af1cb84..3135bb2353 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -41,7 +41,6 @@ parametersSchema: disableUnreachableBranchesRules: bool() stricterFunctionMap: bool() pure: bool() - uselessReturnValue: bool() printfArrayParameters: bool() requireFileExists: bool() ]) From 36dde49f709688359d6f9a77be25a6ec76c4fce4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 13:39:33 +0200 Subject: [PATCH 190/508] [BE] Check vprintf/vsprintf arguments against placeholder count --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 7 +------ conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 2 insertions(+), 10 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 6eab345888..100086e449 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -21,6 +21,7 @@ Major new features 🚀 * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * MagicConstantContextRule (level 0) ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * MissingMagicSerializationMethodsRule (level 0) ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! +* Check vprintf/vsprintf arguments against placeholder count (level 0) ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! * Report useless return values of function calls like `var_export` without `$return=true` (level 0) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! @@ -87,7 +88,6 @@ Bleeding edge (TODO move to other sections) * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 -* Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! Improvements 🔧 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 1c68c2c5ab..eb63f79d85 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -13,5 +13,4 @@ parameters: alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true pure: true - printfArrayParameters: true requireFileExists: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 691f468809..d62a5e4ce9 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -8,8 +8,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\UninitializedPropertyRule: phpstan.rules.rule: %checkUninitializedProperties% - PHPStan\Rules\Functions\PrintfArrayParametersRule: - phpstan.rules.rule: %featureToggles.printfArrayParameters% PHPStan\Rules\Keywords\RequireFileExistsRule: phpstan.rules.rule: %featureToggles.requireFileExists% @@ -72,6 +70,7 @@ rules: - PHPStan\Rules\Functions\InnerFunctionRule - PHPStan\Rules\Functions\InvalidLexicalVariablesInClosureUseRule - PHPStan\Rules\Functions\ParamAttributesRule + - PHPStan\Rules\Functions\PrintfArrayParametersRule - PHPStan\Rules\Functions\PrintfParametersRule - PHPStan\Rules\Functions\RedefinedParametersRule - PHPStan\Rules\Functions\ReturnNullsafeByRefRule @@ -257,10 +256,6 @@ services: arguments: additionalConstructors: %additionalConstructors% - - - - class: PHPStan\Rules\Functions\PrintfArrayParametersRule - - class: PHPStan\Rules\Keywords\RequireFileExistsRule arguments: diff --git a/conf/config.neon b/conf/config.neon index 6466d2dfd2..48adf0b874 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -35,7 +35,6 @@ parameters: disableUnreachableBranchesRules: false stricterFunctionMap: false pure: false - printfArrayParameters: false requireFileExists: false fileExtensions: - php diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 3135bb2353..12d68d952e 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -41,7 +41,6 @@ parametersSchema: disableUnreachableBranchesRules: bool() stricterFunctionMap: bool() pure: bool() - printfArrayParameters: bool() requireFileExists: bool() ]) fileExtensions: listOf(string()) From 81aaff9a79a43d44438014e427c0e9af84b964c1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:02:59 +0200 Subject: [PATCH 191/508] [BE] Specify explicit mixed array type via `is_array` --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 3 --- conf/parametersSchema.neon | 1 - src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php | 6 +----- 5 files changed, 2 insertions(+), 11 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 100086e449..c269678b38 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -60,7 +60,6 @@ Bleeding edge (TODO move to other sections) ===================== * Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! -* Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! * Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! * ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! @@ -128,6 +127,7 @@ Improvements 🔧 * Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! * Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) * Report unnecessary nullsafe property fetch inside `??` / `isset` / `empty` with different message ([#1253](https://github.com/phpstan/phpstan-src/pull/1253)), thanks @rajyan! +* Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index eb63f79d85..90ed6da046 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -4,7 +4,6 @@ parameters: skipCheckGenericClasses!: [] stricterFunctionMap: true - explicitMixedViaIsArray: true arrayFilter: true arrayValues: true looseComparison: true diff --git a/conf/config.neon b/conf/config.neon index 48adf0b874..b50daa7879 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -24,7 +24,6 @@ parameters: bleedingEdge: false disableRuntimeReflectionProvider: true skipCheckGenericClasses: [] - explicitMixedViaIsArray: false arrayFilter: false arrayValues: false illegalConstructorMethodCall: false @@ -1722,8 +1721,6 @@ services: class: PHPStan\Type\Php\IsArrayFunctionTypeSpecifyingExtension tags: - phpstan.typeSpecifier.functionTypeSpecifyingExtension - arguments: - explicitMixed: %featureToggles.explicitMixedViaIsArray% - class: PHPStan\Type\Php\IsCallableFunctionTypeSpecifyingExtension diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 12d68d952e..a6278e72e2 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -30,7 +30,6 @@ parametersSchema: bleedingEdge: bool(), disableRuntimeReflectionProvider: bool(), skipCheckGenericClasses: listOf(string()), - explicitMixedViaIsArray: bool(), arrayFilter: bool(), arrayValues: bool(), illegalConstructorMethodCall: bool(), diff --git a/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php b/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php index 5f6c0d710e..e31033185e 100644 --- a/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/IsArrayFunctionTypeSpecifyingExtension.php @@ -20,10 +20,6 @@ final class IsArrayFunctionTypeSpecifyingExtension implements FunctionTypeSpecif private TypeSpecifier $typeSpecifier; - public function __construct(private bool $explicitMixed) - { - } - public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context): bool { return strtolower($functionReflection->getName()) === 'is_array' @@ -39,7 +35,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n throw new ShouldNotHappenException(); } - return $this->typeSpecifier->create($node->getArgs()[0]->value, new ArrayType(new MixedType($this->explicitMixed), new MixedType($this->explicitMixed)), $context, $scope); + return $this->typeSpecifier->create($node->getArgs()[0]->value, new ArrayType(new MixedType(true), new MixedType(true)), $context, $scope); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void From 7d74a638011774d9e59aa1f9472c39c00182365c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:07:00 +0200 Subject: [PATCH 192/508] [BE] TooWideMethodReturnTypehintRule - always report for final methods --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level4.neon | 1 - conf/config.neon | 1 - conf/parametersSchema.neon | 1 - .../TooWideMethodReturnTypehintRule.php | 20 +++--- .../TooWideMethodReturnTypehintRuleTest.php | 63 +------------------ 7 files changed, 10 insertions(+), 79 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index c269678b38..d5b46b03d5 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -71,7 +71,6 @@ Bleeding edge (TODO move to other sections) * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) -* TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) * Report unused results of `and` and `or` (https://github.com/phpstan/phpstan-src/commit/1d8fff637d70a9e9ed3f11dee5d61b9f796cbf1a) * Report unused result of ternary (https://github.com/phpstan/phpstan-src/commit/9664f7a9d2223c07e750f0dfc949c3accfa6b65e) * Report unused results of `&&` and `||` (https://github.com/phpstan/phpstan-src/commit/cf2c8bbd9ebd2ebe300dbd310e136ad603d7def3) @@ -128,6 +127,7 @@ Improvements 🔧 * Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) * Report unnecessary nullsafe property fetch inside `??` / `isset` / `empty` with different message ([#1253](https://github.com/phpstan/phpstan-src/pull/1253)), thanks @rajyan! * Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! +* TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) Bugfixes 🐛 ===================== diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 90ed6da046..18fc70d92d 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -8,7 +8,6 @@ parameters: arrayValues: true looseComparison: true readOnlyByPhpDoc: true - alwaysCheckTooWideReturnTypeFinalMethods: true alwaysTrueAlwaysReported: true disableUnreachableBranchesRules: true pure: true diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 21621869e5..36cc5448cb 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -282,7 +282,6 @@ services: class: PHPStan\Rules\TooWideTypehints\TooWideMethodReturnTypehintRule arguments: checkProtectedAndPublicMethods: %checkTooWideReturnTypesInProtectedAndPublicMethods% - alwaysCheckFinal: %featureToggles.alwaysCheckTooWideReturnTypeFinalMethods% tags: - phpstan.rules.rule diff --git a/conf/config.neon b/conf/config.neon index b50daa7879..339b64e24a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -29,7 +29,6 @@ parameters: illegalConstructorMethodCall: false looseComparison: false readOnlyByPhpDoc: false - alwaysCheckTooWideReturnTypeFinalMethods: false alwaysTrueAlwaysReported: false disableUnreachableBranchesRules: false stricterFunctionMap: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index a6278e72e2..c9027f11fd 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -35,7 +35,6 @@ parametersSchema: illegalConstructorMethodCall: bool(), looseComparison: bool(), readOnlyByPhpDoc: bool() - alwaysCheckTooWideReturnTypeFinalMethods: bool() alwaysTrueAlwaysReported: bool() disableUnreachableBranchesRules: bool() stricterFunctionMap: bool() diff --git a/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php b/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php index 0c74e65a02..58cf807050 100644 --- a/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php +++ b/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php @@ -22,7 +22,7 @@ final class TooWideMethodReturnTypehintRule implements Rule { - public function __construct(private bool $checkProtectedAndPublicMethods, private bool $alwaysCheckFinal) + public function __construct(private bool $checkProtectedAndPublicMethods) { } @@ -39,20 +39,14 @@ public function processNode(Node $node, Scope $scope): array $method = $node->getMethodReflection(); $isFirstDeclaration = $method->getPrototype()->getDeclaringClass() === $method->getDeclaringClass(); if (!$method->isPrivate()) { - if ($this->alwaysCheckFinal) { - if (!$method->getDeclaringClass()->isFinal() && !$method->isFinal()->yes()) { - if (!$this->checkProtectedAndPublicMethods) { - return []; - } + if (!$method->getDeclaringClass()->isFinal() && !$method->isFinal()->yes()) { + if (!$this->checkProtectedAndPublicMethods) { + return []; + } - if ($isFirstDeclaration) { - return []; - } + if ($isFirstDeclaration) { + return []; } - } elseif (!$this->checkProtectedAndPublicMethods) { - return []; - } elseif ($isFirstDeclaration && !$method->getDeclaringClass()->isFinal() && !$method->isFinal()->yes()) { - return []; } } diff --git a/tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php b/tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php index 9e9588d219..019e7bf59f 100644 --- a/tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php +++ b/tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php @@ -14,11 +14,9 @@ class TooWideMethodReturnTypehintRuleTest extends RuleTestCase private bool $checkProtectedAndPublicMethods = true; - private bool $alwaysCheckFinal = false; - protected function getRule(): Rule { - return new TooWideMethodReturnTypehintRule($this->checkProtectedAndPublicMethods, $this->alwaysCheckFinal); + return new TooWideMethodReturnTypehintRule($this->checkProtectedAndPublicMethods); } public function testPrivate(): void @@ -113,26 +111,6 @@ public function testBug6175(): void public function dataAlwaysCheckFinal(): iterable { yield [ - false, - false, - [ - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\Foo::test() never returns null so it can be removed from the return type.', - 8, - ], - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\FinalFoo::test() never returns null so it can be removed from the return type.', - 28, - ], - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\FooFinalMethods::test() never returns null so it can be removed from the return type.', - 48, - ], - ], - ]; - - yield [ - true, false, [ [ @@ -167,42 +145,6 @@ public function dataAlwaysCheckFinal(): iterable ]; yield [ - false, - true, - [ - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\Foo::test() never returns null so it can be removed from the return type.', - 8, - ], - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\FinalFoo::test() never returns null so it can be removed from the return type.', - 28, - ], - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\FinalFoo::test2() never returns null so it can be removed from the return type.', - 33, - ], - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\FinalFoo::test3() never returns null so it can be removed from the return type.', - 38, - ], - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\FooFinalMethods::test() never returns null so it can be removed from the return type.', - 48, - ], - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\FooFinalMethods::test2() never returns null so it can be removed from the return type.', - 53, - ], - [ - 'Method MethodTooWideReturnAlwaysCheckFinal\FooFinalMethods::test3() never returns null so it can be removed from the return type.', - 58, - ], - ], - ]; - - yield [ - true, true, [ [ @@ -241,10 +183,9 @@ public function dataAlwaysCheckFinal(): iterable * @dataProvider dataAlwaysCheckFinal * @param list $expectedErrors */ - public function testAlwaysCheckFinal(bool $checkProtectedAndPublicMethods, bool $alwaysCheckFinal, array $expectedErrors): void + public function testAlwaysCheckFinal(bool $checkProtectedAndPublicMethods, array $expectedErrors): void { $this->checkProtectedAndPublicMethods = $checkProtectedAndPublicMethods; - $this->alwaysCheckFinal = $alwaysCheckFinal; $this->analyse([__DIR__ . '/data/method-too-wide-return-always-check-final.php'], $expectedErrors); } From cc7ff8b217021402dcbe817f7002b29a48722811 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:13:36 +0200 Subject: [PATCH 193/508] [BE] Remove rules about unreachable branches --- changelog-2.0.md | 4 +- conf/bleedingEdge.neon | 1 - conf/config.level4.neon | 19 --- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - phpstan-baseline.neon | 10 -- src/Rules/Comparison/MatchExpressionRule.php | 7 - .../Comparison/UnreachableIfBranchesRule.php | 84 ----------- .../UnreachableTernaryElseBranchRule.php | 70 --------- .../Comparison/MatchExpressionRuleTest.php | 108 +------------- .../UnreachableIfBranchesRuleTest.php | 139 ------------------ .../UnreachableTernaryElseBranchRuleTest.php | 111 -------------- .../Rules/Comparison/data/bug-7686.php | 25 ---- 13 files changed, 5 insertions(+), 575 deletions(-) delete mode 100644 src/Rules/Comparison/UnreachableIfBranchesRule.php delete mode 100644 src/Rules/Comparison/UnreachableTernaryElseBranchRule.php delete mode 100644 tests/PHPStan/Rules/Comparison/UnreachableIfBranchesRuleTest.php delete mode 100644 tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php delete mode 100644 tests/PHPStan/Rules/Comparison/data/bug-7686.php diff --git a/changelog-2.0.md b/changelog-2.0.md index d5b46b03d5..8f14a5e937 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -16,6 +16,8 @@ Major new features 🚀 * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! * Check too wide private property type (level 4) (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) +* Remove "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule + * Because "always true" is always reported, these are no longer needed * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! @@ -66,8 +68,6 @@ Bleeding edge (TODO move to other sections) * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! -* Disable "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule - * Because "always true" is always reported, these are no longer needed * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 18fc70d92d..7e102ef694 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -9,6 +9,5 @@ parameters: looseComparison: true readOnlyByPhpDoc: true alwaysTrueAlwaysReported: true - disableUnreachableBranchesRules: true pure: true requireFileExists: true diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 36cc5448cb..52ff204352 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -197,7 +197,6 @@ services: class: PHPStan\Rules\Comparison\MatchExpressionRule arguments: checkAlwaysTrueStrictComparison: %checkAlwaysTrueStrictComparison% - disableUnreachable: %featureToggles.disableUnreachableBranchesRules% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% tags: @@ -237,24 +236,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Comparison\UnreachableIfBranchesRule - arguments: - treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - disable: %featureToggles.disableUnreachableBranchesRules% - treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% - tags: - - phpstan.rules.rule - - - - class: PHPStan\Rules\Comparison\UnreachableTernaryElseBranchRule - arguments: - treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - disable: %featureToggles.disableUnreachableBranchesRules% - treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% - tags: - - phpstan.rules.rule - - class: PHPStan\Rules\Comparison\WhileLoopAlwaysFalseConditionRule arguments: diff --git a/conf/config.neon b/conf/config.neon index 339b64e24a..01a3bf1206 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -30,7 +30,6 @@ parameters: looseComparison: false readOnlyByPhpDoc: false alwaysTrueAlwaysReported: false - disableUnreachableBranchesRules: false stricterFunctionMap: false pure: false requireFileExists: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index c9027f11fd..dcf4230ff9 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -36,7 +36,6 @@ parametersSchema: looseComparison: bool(), readOnlyByPhpDoc: bool() alwaysTrueAlwaysReported: bool() - disableUnreachableBranchesRules: bool() stricterFunctionMap: bool() pure: bool() requireFileExists: bool() diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index edb70aafe7..287fdbae03 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -491,16 +491,6 @@ parameters: count: 2 path: src/Rules/Comparison/TernaryOperatorConstantConditionRule.php - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" - count: 1 - path: src/Rules/Comparison/UnreachableIfBranchesRule.php - - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" - count: 1 - path: src/Rules/Comparison/UnreachableTernaryElseBranchRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 1 diff --git a/src/Rules/Comparison/MatchExpressionRule.php b/src/Rules/Comparison/MatchExpressionRule.php index 81cfb1f471..d204ca9c64 100644 --- a/src/Rules/Comparison/MatchExpressionRule.php +++ b/src/Rules/Comparison/MatchExpressionRule.php @@ -28,7 +28,6 @@ final class MatchExpressionRule implements Rule public function __construct( private ConstantConditionRuleHelper $constantConditionRuleHelper, private bool $checkAlwaysTrueStrictComparison, - private bool $disableUnreachable, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertain, ) @@ -54,12 +53,6 @@ public function processNode(Node $node, Scope $scope): array $nextArmIsDeadForNativeType || ($nextArmIsDeadForType && $this->treatPhpDocTypesAsCertain) ) { - if (!$this->disableUnreachable) { - $errors[] = RuleErrorBuilder::message('Match arm is unreachable because previous comparison is always true.') - ->identifier('match.unreachable') - ->line($arm->getLine()) - ->build(); - } continue; } $armConditions = $arm->getConditions(); diff --git a/src/Rules/Comparison/UnreachableIfBranchesRule.php b/src/Rules/Comparison/UnreachableIfBranchesRule.php deleted file mode 100644 index 5d6b001e88..0000000000 --- a/src/Rules/Comparison/UnreachableIfBranchesRule.php +++ /dev/null @@ -1,84 +0,0 @@ - - */ -final class UnreachableIfBranchesRule implements Rule -{ - - public function __construct( - private ConstantConditionRuleHelper $helper, - private bool $treatPhpDocTypesAsCertain, - private bool $disable, - private bool $treatPhpDocTypesAsCertainTip, - ) - { - } - - public function getNodeType(): string - { - return Node\Stmt\If_::class; - } - - public function processNode(Node $node, Scope $scope): array - { - if ($this->disable) { - return []; - } - - $errors = []; - $condition = $node->cond; - $conditionType = $this->treatPhpDocTypesAsCertain ? $scope->getType($condition) : $scope->getNativeType($condition); - $conditionBooleanType = $conditionType->toBoolean(); - $nextBranchIsDead = $conditionBooleanType->isTrue()->yes() && $this->helper->shouldSkip($scope, $node->cond) && !$this->helper->shouldReportAlwaysTrueByDefault($node->cond); - - $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use ($scope, &$condition): RuleErrorBuilder { - if (!$this->treatPhpDocTypesAsCertain) { - return $ruleErrorBuilder; - } - - $booleanNativeType = $scope->getNativeType($condition)->toBoolean(); - if ($booleanNativeType instanceof ConstantBooleanType) { - return $ruleErrorBuilder; - } - if (!$this->treatPhpDocTypesAsCertainTip) { - return $ruleErrorBuilder; - } - - return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); - }; - - foreach ($node->elseifs as $elseif) { - if ($nextBranchIsDead) { - $errors[] = $addTip(RuleErrorBuilder::message('Elseif branch is unreachable because previous condition is always true.')) - ->identifier('elseif.unreachable') - ->line($elseif->getStartLine()) - ->build(); - continue; - } - - $condition = $elseif->cond; - $conditionType = $this->treatPhpDocTypesAsCertain ? $scope->getType($condition) : $scope->getNativeType($condition); - $conditionBooleanType = $conditionType->toBoolean(); - $nextBranchIsDead = $conditionBooleanType->isTrue()->yes() && $this->helper->shouldSkip($scope, $elseif->cond) && !$this->helper->shouldReportAlwaysTrueByDefault($elseif->cond); - } - - if ($node->else !== null && $nextBranchIsDead) { - $errors[] = $addTip(RuleErrorBuilder::message('Else branch is unreachable because previous condition is always true.')) - ->identifier('else.unreachable') - ->line($node->else->getStartLine()) - ->build(); - } - - return $errors; - } - -} diff --git a/src/Rules/Comparison/UnreachableTernaryElseBranchRule.php b/src/Rules/Comparison/UnreachableTernaryElseBranchRule.php deleted file mode 100644 index 63ea467ce4..0000000000 --- a/src/Rules/Comparison/UnreachableTernaryElseBranchRule.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ -final class UnreachableTernaryElseBranchRule implements Rule -{ - - public function __construct( - private ConstantConditionRuleHelper $helper, - private bool $treatPhpDocTypesAsCertain, - private bool $disable, - private bool $treatPhpDocTypesAsCertainTip, - ) - { - } - - public function getNodeType(): string - { - return Node\Expr\Ternary::class; - } - - public function processNode(Node $node, Scope $scope): array - { - if ($this->disable) { - return []; - } - - $conditionType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->cond) : $scope->getNativeType($node->cond); - $conditionBooleanType = $conditionType->toBoolean(); - if ( - $conditionBooleanType->isTrue()->yes() - && $this->helper->shouldSkip($scope, $node->cond) - && !$this->helper->shouldReportAlwaysTrueByDefault($node->cond) - ) { - $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use ($scope, $node): RuleErrorBuilder { - if (!$this->treatPhpDocTypesAsCertain) { - return $ruleErrorBuilder; - } - - $booleanNativeType = $scope->getNativeType($node->cond); - if ($booleanNativeType instanceof ConstantBooleanType) { - return $ruleErrorBuilder; - } - if (!$this->treatPhpDocTypesAsCertainTip) { - return $ruleErrorBuilder; - } - - return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); - }; - return [ - $addTip(RuleErrorBuilder::message('Else branch is unreachable because ternary operator condition is always true.')) - ->identifier('ternary.elseUnreachable') - ->line($node->else->getStartLine()) - ->build(), - ]; - } - - return []; - } - -} diff --git a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php index 4674b642a7..8d9cf3443e 100644 --- a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php @@ -16,8 +16,6 @@ class MatchExpressionRuleTest extends RuleTestCase private bool $reportAlwaysTrueInLastCondition = false; - private bool $disableUnreachable = false; - protected function getRule(): Rule { return new MatchExpressionRule( @@ -32,7 +30,6 @@ protected function getRule(): Rule true, ), true, - $this->disableUnreachable, $this->reportAlwaysTrueInLastCondition, $this->treatPhpDocTypesAsCertain, ); @@ -60,41 +57,21 @@ public function testRule(): void 28, $tipText, ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 29, - ], [ 'Match arm comparison between 3 and 3 is always true.', 35, $tipText, ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 36, - ], [ 'Match arm comparison between 1 and 1 is always true.', 40, $tipText, ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 41, - ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 42, - ], [ 'Match arm comparison between 1 and 1 is always true.', 46, $tipText, ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 47, - ], [ 'Match expression does not handle remaining value: 3', 50, @@ -169,10 +146,6 @@ public function testEnums(): void 76, 'Remove remaining cases below this one and this error will disappear too.', ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 77, - ], [ 'Match arm comparison between MatchEnums\Foo and MatchEnums\Foo::ONE is always false.', 85, @@ -291,19 +264,11 @@ public function testBug8240(): void 13, 'Remove remaining cases below this one and this error will disappear too.', ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 14, - ], [ 'Match arm comparison between Bug8240\Foo2::BAZ and Bug8240\Foo2::BAZ is always true.', 28, 'Remove remaining cases below this one and this error will disappear too.', ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 29, - ], ]); } @@ -320,41 +285,21 @@ public function testLastArmAlwaysTrue(): void 22, $tipText, ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 23, - ], [ 'Match arm comparison between $this(LastMatchArmAlwaysTrue\Foo)&LastMatchArmAlwaysTrue\Foo::TWO and LastMatchArmAlwaysTrue\Foo::TWO is always true.', 31, $tipText, ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 32, - ], [ 'Match arm comparison between $this(LastMatchArmAlwaysTrue\Foo)&LastMatchArmAlwaysTrue\Foo::TWO and LastMatchArmAlwaysTrue\Foo::TWO is always true.', 40, $tipText, ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 41, - ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 42, - ], [ 'Match arm comparison between $this(LastMatchArmAlwaysTrue\Bar)&LastMatchArmAlwaysTrue\Bar::ONE and LastMatchArmAlwaysTrue\Bar::ONE is always true.', 62, $tipText, ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 63, - ], [ 'Match arm comparison between 1 and 0 is always false.', 70, @@ -368,53 +313,7 @@ public function testLastArmAlwaysTrue(): void public function dataReportAlwaysTrueInLastCondition(): iterable { - yield [false, false, [ - [ - 'Match arm comparison between $this(MatchAlwaysTrueLastArm\Foo)&MatchAlwaysTrueLastArm\Foo::BAR and MatchAlwaysTrueLastArm\Foo::BAR is always true.', - 23, - 'Remove remaining cases below this one and this error will disappear too.', - ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 24, - ], - [ - 'Match arm comparison between $this(MatchAlwaysTrueLastArm\Foo)&MatchAlwaysTrueLastArm\Foo::BAR and MatchAlwaysTrueLastArm\Foo::BAR is always true.', - 49, - 'Remove remaining cases below this one and this error will disappear too.', - ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 50, - ], - ]]; - yield [true, false, [ - [ - 'Match arm comparison between $this(MatchAlwaysTrueLastArm\Foo)&MatchAlwaysTrueLastArm\Foo::BAR and MatchAlwaysTrueLastArm\Foo::BAR is always true.', - 15, - ], - [ - 'Match arm comparison between $this(MatchAlwaysTrueLastArm\Foo)&MatchAlwaysTrueLastArm\Foo::BAR and MatchAlwaysTrueLastArm\Foo::BAR is always true.', - 23, - ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 24, - ], - [ - 'Match arm comparison between $this(MatchAlwaysTrueLastArm\Foo)&MatchAlwaysTrueLastArm\Foo::BAR and MatchAlwaysTrueLastArm\Foo::BAR is always true.', - 45, - ], - [ - 'Match arm comparison between $this(MatchAlwaysTrueLastArm\Foo)&MatchAlwaysTrueLastArm\Foo::BAR and MatchAlwaysTrueLastArm\Foo::BAR is always true.', - 49, - ], - [ - 'Match arm is unreachable because previous comparison is always true.', - 50, - ], - ]]; - yield [false, true, [ + yield [false, [ [ 'Match arm comparison between $this(MatchAlwaysTrueLastArm\Foo)&MatchAlwaysTrueLastArm\Foo::BAR and MatchAlwaysTrueLastArm\Foo::BAR is always true.', 23, @@ -426,7 +325,7 @@ public function dataReportAlwaysTrueInLastCondition(): iterable 'Remove remaining cases below this one and this error will disappear too.', ], ]]; - yield [true, true, [ + yield [true, [ [ 'Match arm comparison between $this(MatchAlwaysTrueLastArm\Foo)&MatchAlwaysTrueLastArm\Foo::BAR and MatchAlwaysTrueLastArm\Foo::BAR is always true.', 15, @@ -450,14 +349,13 @@ public function dataReportAlwaysTrueInLastCondition(): iterable * @dataProvider dataReportAlwaysTrueInLastCondition * @param list $expectedErrors */ - public function testReportAlwaysTrueInLastCondition(bool $reportAlwaysTrueInLastCondition, bool $disableUnreachable, array $expectedErrors): void + public function testReportAlwaysTrueInLastCondition(bool $reportAlwaysTrueInLastCondition, array $expectedErrors): void { if (PHP_VERSION_ID < 80100) { $this->markTestSkipped('Test requires PHP 8.1.'); } $this->treatPhpDocTypesAsCertain = true; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; - $this->disableUnreachable = $disableUnreachable; $this->analyse([__DIR__ . '/data/match-always-true-last-arm.php'], $expectedErrors); } diff --git a/tests/PHPStan/Rules/Comparison/UnreachableIfBranchesRuleTest.php b/tests/PHPStan/Rules/Comparison/UnreachableIfBranchesRuleTest.php deleted file mode 100644 index 4459045cc0..0000000000 --- a/tests/PHPStan/Rules/Comparison/UnreachableIfBranchesRuleTest.php +++ /dev/null @@ -1,139 +0,0 @@ - - */ -class UnreachableIfBranchesRuleTest extends RuleTestCase -{ - - private bool $treatPhpDocTypesAsCertain; - - protected function getRule(): Rule - { - return new UnreachableIfBranchesRule( - new ConstantConditionRuleHelper( - new ImpossibleCheckTypeHelper( - $this->createReflectionProvider(), - $this->getTypeSpecifier(), - [], - $this->treatPhpDocTypesAsCertain, - ), - $this->treatPhpDocTypesAsCertain, - true, - ), - $this->treatPhpDocTypesAsCertain, - false, - true, - ); - } - - protected function shouldTreatPhpDocTypesAsCertain(): bool - { - return $this->treatPhpDocTypesAsCertain; - } - - public function testRule(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->analyse([__DIR__ . '/data/unreachable-if-branches.php'], [ - [ - 'Else branch is unreachable because previous condition is always true.', - 15, - ], - [ - 'Elseif branch is unreachable because previous condition is always true.', - 25, - ], - [ - 'Else branch is unreachable because previous condition is always true.', - 27, - ], - [ - 'Elseif branch is unreachable because previous condition is always true.', - 39, - ], - [ - 'Else branch is unreachable because previous condition is always true.', - 41, - ], - ]); - } - - public function testDoNotReportPhpDoc(): void - { - $this->treatPhpDocTypesAsCertain = false; - $this->analyse([__DIR__ . '/data/unreachable-if-branches-not-phpdoc.php'], [ - [ - 'Elseif branch is unreachable because previous condition is always true.', - 18, - ], - [ - 'Else branch is unreachable because previous condition is always true.', - 28, - ], - [ - 'Elseif branch is unreachable because previous condition is always true.', - 38, - ], - ]); - } - - public function testReportPhpDoc(): void - { - $this->treatPhpDocTypesAsCertain = true; - $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->analyse([__DIR__ . '/data/unreachable-if-branches-not-phpdoc.php'], [ - [ - 'Elseif branch is unreachable because previous condition is always true.', - 18, - ], - [ - 'Else branch is unreachable because previous condition is always true.', - 28, - ], - [ - 'Elseif branch is unreachable because previous condition is always true.', - 38, - ], - [ - 'Elseif branch is unreachable because previous condition is always true.', - 44, - $tipText, - ], - [ - 'Else branch is unreachable because previous condition is always true.', - 54, - //$tipText, - ], - [ - 'Elseif branch is unreachable because previous condition is always true.', - 64, - //$tipText, - ], - ]); - } - - public function testBug8076(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->analyse([__DIR__ . '/data/bug-8076.php'], []); - } - - public function testBug8562(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->analyse([__DIR__ . '/data/bug-8562.php'], []); - } - - public function testBug7491(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->analyse([__DIR__ . '/data/bug-7491.php'], []); - } - -} diff --git a/tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php b/tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php deleted file mode 100644 index bd3cc00a4f..0000000000 --- a/tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php +++ /dev/null @@ -1,111 +0,0 @@ - - */ -class UnreachableTernaryElseBranchRuleTest extends RuleTestCase -{ - - private bool $treatPhpDocTypesAsCertain; - - protected function getRule(): Rule - { - return new UnreachableTernaryElseBranchRule( - new ConstantConditionRuleHelper( - new ImpossibleCheckTypeHelper( - $this->createReflectionProvider(), - $this->getTypeSpecifier(), - [], - $this->treatPhpDocTypesAsCertain, - ), - $this->treatPhpDocTypesAsCertain, - true, - ), - $this->treatPhpDocTypesAsCertain, - false, - true, - ); - } - - protected function shouldTreatPhpDocTypesAsCertain(): bool - { - return $this->treatPhpDocTypesAsCertain; - } - - public function testRule(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->analyse([__DIR__ . '/data/unreachable-ternary-else-branch.php'], [ - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 6, - ], - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 9, - ], - ]); - } - - public function testDoNotReportPhpDoc(): void - { - $this->treatPhpDocTypesAsCertain = false; - $this->analyse([__DIR__ . '/data/unreachable-ternary-else-branch-not-phpdoc.php'], [ - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 16, - ], - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 17, - ], - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 20, - ], - ]); - } - - public function testReportPhpDoc(): void - { - $this->treatPhpDocTypesAsCertain = true; - $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->analyse([__DIR__ . '/data/unreachable-ternary-else-branch-not-phpdoc.php'], [ - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 16, - ], - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 17, - ], - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 19, - $tipText, - ], - [ - 'Else branch is unreachable because ternary operator condition is always true.', - 20, - ], - ]); - } - - public function testBug3019(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-3019.php'], []); - } - - public function testBug7686(): void - { - $this->treatPhpDocTypesAsCertain = true; - $this->analyse([__DIR__ . '/data/bug-7686.php'], []); - } - -} diff --git a/tests/PHPStan/Rules/Comparison/data/bug-7686.php b/tests/PHPStan/Rules/Comparison/data/bug-7686.php deleted file mode 100644 index be05325779..0000000000 --- a/tests/PHPStan/Rules/Comparison/data/bug-7686.php +++ /dev/null @@ -1,25 +0,0 @@ - $input - * @return array<'return'|int, string> - */ - public static function test(array $input): array - { - $output = []; - foreach($input as $match) { - if (array_key_exists($match['name'], $output) == false) { - $output[$match['name']] = ''; - } - if (($match['type'] === '') || (in_array($match['type'], explode('|', $output[$match['name']]), true) === true)) { - continue; - } - $output[$match['name']] = ($output[$match['name']] === '' ? $match['type'] : $output[$match['name']] . '|' . $match['type']); - } - return $output; - } -} From 335c16f1abb5d26d81f2e24ab078807bbe37f2b9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:19:26 +0200 Subject: [PATCH 194/508] [BE] Always report always true conditions, except for last elseif and match arm --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.neon | 9 ++++----- conf/parametersSchema.neon | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 8f14a5e937..cc93b6af1b 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -16,6 +16,7 @@ Major new features 🚀 * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! * Check too wide private property type (level 4) (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) +* Always report always true conditions, except for last elseif and match arm (https://github.com/phpstan/phpstan-src/commit/565fb0f6da9cdc58e8686598015561a848693972) * Remove "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 @@ -67,7 +68,6 @@ Bleeding edge (TODO move to other sections) * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! -* Always report always true conditions, except for last elseif and match arm ([#2105](https://github.com/phpstan/phpstan-src/pull/2105)), thanks @staabm! * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 7e102ef694..578124828b 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -8,6 +8,5 @@ parameters: arrayValues: true looseComparison: true readOnlyByPhpDoc: true - alwaysTrueAlwaysReported: true pure: true requireFileExists: true diff --git a/conf/config.neon b/conf/config.neon index 01a3bf1206..ac3f1d096c 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -29,17 +29,16 @@ parameters: illegalConstructorMethodCall: false looseComparison: false readOnlyByPhpDoc: false - alwaysTrueAlwaysReported: false stricterFunctionMap: false pure: false requireFileExists: false fileExtensions: - php checkAdvancedIsset: false - checkAlwaysTrueCheckTypeFunctionCall: %featureToggles.alwaysTrueAlwaysReported% - checkAlwaysTrueInstanceof: %featureToggles.alwaysTrueAlwaysReported% - checkAlwaysTrueStrictComparison: %featureToggles.alwaysTrueAlwaysReported% - checkAlwaysTrueLooseComparison: %featureToggles.alwaysTrueAlwaysReported% + checkAlwaysTrueCheckTypeFunctionCall: true + checkAlwaysTrueInstanceof: true + checkAlwaysTrueStrictComparison: true + checkAlwaysTrueLooseComparison: true reportAlwaysTrueInLastCondition: false checkClassCaseSensitivity: false checkExplicitMixed: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index dcf4230ff9..97ac234f8d 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -35,7 +35,6 @@ parametersSchema: illegalConstructorMethodCall: bool(), looseComparison: bool(), readOnlyByPhpDoc: bool() - alwaysTrueAlwaysReported: bool() stricterFunctionMap: bool() pure: bool() requireFileExists: bool() From 59fd06a03d2104d577c845c73ecb91cc3202aa04 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:34:02 +0200 Subject: [PATCH 195/508] Update phpstan-strict-rules --- composer.lock | 8 ++++---- issue-bot/composer.lock | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index 4acec2e4a1..997e53f86f 100644 --- a/composer.lock +++ b/composer.lock @@ -4831,12 +4831,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "1062d489f1d10e79df42d73fa5352a27741d65f1" + "reference": "ad53bd9f911e7831e8e02cd3e54faf1d44910c33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/1062d489f1d10e79df42d73fa5352a27741d65f1", - "reference": "1062d489f1d10e79df42d73fa5352a27741d65f1", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/ad53bd9f911e7831e8e02cd3e54faf1d44910c33", + "reference": "ad53bd9f911e7831e8e02cd3e54faf1d44910c33", "shasum": "" }, "require": { @@ -4872,7 +4872,7 @@ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-09-13T12:49:46+00:00" + "time": "2024-09-24T12:25:28+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/issue-bot/composer.lock b/issue-bot/composer.lock index 8dca547099..7479e1b1b1 100644 --- a/issue-bot/composer.lock +++ b/issue-bot/composer.lock @@ -1407,12 +1407,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "946cf18b3e9f64c41d2f62903f8148b3f0b3be41" + "reference": "b1165b76fe8d451783d63ac99e3e31377353a90a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/946cf18b3e9f64c41d2f62903f8148b3f0b3be41", - "reference": "946cf18b3e9f64c41d2f62903f8148b3f0b3be41", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b1165b76fe8d451783d63ac99e3e31377353a90a", + "reference": "b1165b76fe8d451783d63ac99e3e31377353a90a", "shasum": "" }, "require": { @@ -1458,7 +1458,7 @@ "type": "github" } ], - "time": "2024-09-06T18:47:21+00:00" + "time": "2024-09-24T12:23:49+00:00" }, { "name": "phpstan/phpstan-strict-rules", @@ -1466,12 +1466,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "5eec39fc6ef36015e6de08949c8e9ae9d64560a3" + "reference": "ad53bd9f911e7831e8e02cd3e54faf1d44910c33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/5eec39fc6ef36015e6de08949c8e9ae9d64560a3", - "reference": "5eec39fc6ef36015e6de08949c8e9ae9d64560a3", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/ad53bd9f911e7831e8e02cd3e54faf1d44910c33", + "reference": "ad53bd9f911e7831e8e02cd3e54faf1d44910c33", "shasum": "" }, "require": { @@ -1507,7 +1507,7 @@ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-09-06T18:44:39+00:00" + "time": "2024-09-24T12:25:28+00:00" }, { "name": "psr/cache", From d22c481ef224d5c11e8d23c4d5f84ed9ac8aac9c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:26:46 +0200 Subject: [PATCH 196/508] Remove `checkAlwaysTrue*` options --- UPGRADING.md | 9 ++++ conf/config.level4.neon | 7 --- conf/config.neon | 4 -- conf/parametersSchema.neon | 4 -- .../Classes/ImpossibleInstanceOfRule.php | 35 ++++++------ .../ConstantLooseComparisonRule.php | 35 ++++++------ .../ImpossibleCheckTypeFunctionCallRule.php | 33 ++++++------ .../ImpossibleCheckTypeMethodCallRule.php | 37 ++++++------- ...mpossibleCheckTypeStaticMethodCallRule.php | 37 ++++++------- src/Rules/Comparison/MatchExpressionRule.php | 36 ++++++------- .../StrictComparisonOfDifferentTypesRule.php | 53 +++++++++---------- .../Classes/ImpossibleInstanceOfRuleTest.php | 1 - .../ConstantLooseComparisonRuleTest.php | 1 - ...mpossibleCheckTypeFunctionCallRuleTest.php | 1 - ...sibleCheckTypeGenericOverwriteRuleTest.php | 1 - ...sibleCheckTypeMethodCallRuleEqualsTest.php | 1 - .../ImpossibleCheckTypeMethodCallRuleTest.php | 1 - ...sibleCheckTypeStaticMethodCallRuleTest.php | 1 - .../Comparison/MatchExpressionRuleTest.php | 1 - ...rictComparisonOfDifferentTypesRuleTest.php | 1 - 20 files changed, 132 insertions(+), 167 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 9a0e770952..658f366c00 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -60,6 +60,15 @@ parameters: identifier: missingType.generics ``` +### Removed `checkAlwaysTrue*` options + +These options have been removed because PHPStan now always behaves as if these were set to `true`: + +* `checkAlwaysTrueCheckTypeFunctionCall` +* `checkAlwaysTrueInstanceof` +* `checkAlwaysTrueStrictComparison` +* `checkAlwaysTrueLooseComparison` + ### Removed option `excludes_analyse` It has been replaced with [`excludePaths`](https://phpstan.org/user-guide/ignoring-errors#excluding-whole-files). diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 52ff204352..ed64b65aec 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -53,7 +53,6 @@ services: - class: PHPStan\Rules\Classes\ImpossibleInstanceOfRule arguments: - checkAlwaysTrueInstanceof: %checkAlwaysTrueInstanceof% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% @@ -157,7 +156,6 @@ services: - class: PHPStan\Rules\Comparison\ImpossibleCheckTypeFunctionCallRule arguments: - checkAlwaysTrueCheckTypeFunctionCall: %checkAlwaysTrueCheckTypeFunctionCall% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% @@ -167,7 +165,6 @@ services: - class: PHPStan\Rules\Comparison\ImpossibleCheckTypeMethodCallRule arguments: - checkAlwaysTrueCheckTypeFunctionCall: %checkAlwaysTrueCheckTypeFunctionCall% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% @@ -177,7 +174,6 @@ services: - class: PHPStan\Rules\Comparison\ImpossibleCheckTypeStaticMethodCallRule arguments: - checkAlwaysTrueCheckTypeFunctionCall: %checkAlwaysTrueCheckTypeFunctionCall% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% @@ -196,7 +192,6 @@ services: - class: PHPStan\Rules\Comparison\MatchExpressionRule arguments: - checkAlwaysTrueStrictComparison: %checkAlwaysTrueStrictComparison% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% tags: @@ -213,7 +208,6 @@ services: - class: PHPStan\Rules\Comparison\StrictComparisonOfDifferentTypesRule arguments: - checkAlwaysTrueStrictComparison: %checkAlwaysTrueStrictComparison% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% @@ -223,7 +217,6 @@ services: - class: PHPStan\Rules\Comparison\ConstantLooseComparisonRule arguments: - checkAlwaysTrueLooseComparison: %checkAlwaysTrueLooseComparison% treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% diff --git a/conf/config.neon b/conf/config.neon index ac3f1d096c..a6be092dc4 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -35,10 +35,6 @@ parameters: fileExtensions: - php checkAdvancedIsset: false - checkAlwaysTrueCheckTypeFunctionCall: true - checkAlwaysTrueInstanceof: true - checkAlwaysTrueStrictComparison: true - checkAlwaysTrueLooseComparison: true reportAlwaysTrueInLastCondition: false checkClassCaseSensitivity: false checkExplicitMixed: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 97ac234f8d..d5a31f5b0e 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -41,10 +41,6 @@ parametersSchema: ]) fileExtensions: listOf(string()) checkAdvancedIsset: bool() - checkAlwaysTrueCheckTypeFunctionCall: bool() - checkAlwaysTrueInstanceof: bool() - checkAlwaysTrueStrictComparison: bool() - checkAlwaysTrueLooseComparison: bool() reportAlwaysTrueInLastCondition: bool() checkClassCaseSensitivity: bool() checkExplicitMixed: bool() diff --git a/src/Rules/Classes/ImpossibleInstanceOfRule.php b/src/Rules/Classes/ImpossibleInstanceOfRule.php index b6d9c84ee3..a4b3cfe70c 100644 --- a/src/Rules/Classes/ImpossibleInstanceOfRule.php +++ b/src/Rules/Classes/ImpossibleInstanceOfRule.php @@ -22,7 +22,6 @@ final class ImpossibleInstanceOfRule implements Rule { public function __construct( - private bool $checkAlwaysTrueInstanceof, private bool $treatPhpDocTypesAsCertain, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertainTip, @@ -89,28 +88,26 @@ public function processNode(Node $node, Scope $scope): array $classType->describe(VerbosityLevel::getRecommendedLevelByType($classType)), )))->identifier('instanceof.alwaysFalse')->build(), ]; - } elseif ($this->checkAlwaysTrueInstanceof) { - $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); - if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { - return []; - } - - $exprType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->expr) : $scope->getNativeType($node->expr); - $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( - 'Instanceof between %s and %s will always evaluate to true.', - $exprType->describe(VerbosityLevel::typeOnly()), - $classType->describe(VerbosityLevel::getRecommendedLevelByType($classType)), - ))); - if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { - $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); - } + } - $errorBuilder->identifier('instanceof.alwaysTrue'); + $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); + if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { + return []; + } - return [$errorBuilder->build()]; + $exprType = $this->treatPhpDocTypesAsCertain ? $scope->getType($node->expr) : $scope->getNativeType($node->expr); + $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( + 'Instanceof between %s and %s will always evaluate to true.', + $exprType->describe(VerbosityLevel::typeOnly()), + $classType->describe(VerbosityLevel::getRecommendedLevelByType($classType)), + ))); + if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { + $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } - return []; + $errorBuilder->identifier('instanceof.alwaysTrue'); + + return [$errorBuilder->build()]; } } diff --git a/src/Rules/Comparison/ConstantLooseComparisonRule.php b/src/Rules/Comparison/ConstantLooseComparisonRule.php index d6fa6c6aac..09961335e7 100644 --- a/src/Rules/Comparison/ConstantLooseComparisonRule.php +++ b/src/Rules/Comparison/ConstantLooseComparisonRule.php @@ -18,7 +18,6 @@ final class ConstantLooseComparisonRule implements Rule { public function __construct( - private bool $checkAlwaysTrueLooseComparison, private bool $treatPhpDocTypesAsCertain, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertainTip, @@ -67,28 +66,26 @@ public function processNode(Node $node, Scope $scope): array $scope->getType($node->right)->describe(VerbosityLevel::value()), )))->identifier(sprintf('%s.alwaysFalse', $node instanceof Node\Expr\BinaryOp\Equal ? 'equal' : 'notEqual'))->build(), ]; - } elseif ($this->checkAlwaysTrueLooseComparison) { - $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); - if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { - return []; - } - - $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( - 'Loose comparison using %s between %s and %s will always evaluate to true.', - $node->getOperatorSigil(), - $scope->getType($node->left)->describe(VerbosityLevel::value()), - $scope->getType($node->right)->describe(VerbosityLevel::value()), - ))); - if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { - $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); - } + } - $errorBuilder->identifier(sprintf('%s.alwaysTrue', $node instanceof Node\Expr\BinaryOp\Equal ? 'equal' : 'notEqual')); + $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); + if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { + return []; + } - return [$errorBuilder->build()]; + $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( + 'Loose comparison using %s between %s and %s will always evaluate to true.', + $node->getOperatorSigil(), + $scope->getType($node->left)->describe(VerbosityLevel::value()), + $scope->getType($node->right)->describe(VerbosityLevel::value()), + ))); + if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { + $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } - return []; + $errorBuilder->identifier(sprintf('%s.alwaysTrue', $node instanceof Node\Expr\BinaryOp\Equal ? 'equal' : 'notEqual')); + + return [$errorBuilder->build()]; } } diff --git a/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php b/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php index 9033aa3865..690307e6fc 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php @@ -18,7 +18,6 @@ final class ImpossibleCheckTypeFunctionCallRule implements Rule public function __construct( private ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, - private bool $checkAlwaysTrueCheckTypeFunctionCall, private bool $treatPhpDocTypesAsCertain, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertainTip, @@ -70,27 +69,25 @@ public function processNode(Node $node, Scope $scope): array $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), )))->identifier('function.impossibleType')->build(), ]; - } elseif ($this->checkAlwaysTrueCheckTypeFunctionCall) { - $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); - if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { - return []; - } - - $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( - 'Call to function %s()%s will always evaluate to true.', - $functionName, - $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), - ))); - if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { - $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); - } + } - $errorBuilder->identifier('function.alreadyNarrowedType'); + $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); + if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { + return []; + } - return [$errorBuilder->build()]; + $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( + 'Call to function %s()%s will always evaluate to true.', + $functionName, + $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), + ))); + if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { + $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } - return []; + $errorBuilder->identifier('function.alreadyNarrowedType'); + + return [$errorBuilder->build()]; } } diff --git a/src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.php b/src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.php index 7bbcecefd7..4b79d98acb 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.php @@ -20,7 +20,6 @@ final class ImpossibleCheckTypeMethodCallRule implements Rule public function __construct( private ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, - private bool $checkAlwaysTrueCheckTypeFunctionCall, private bool $treatPhpDocTypesAsCertain, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertainTip, @@ -70,29 +69,27 @@ public function processNode(Node $node, Scope $scope): array $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), )))->identifier('method.impossibleType')->build(), ]; - } elseif ($this->checkAlwaysTrueCheckTypeFunctionCall) { - $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); - if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { - return []; - } - - $method = $this->getMethod($node->var, $node->name->name, $scope); - $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( - 'Call to method %s::%s()%s will always evaluate to true.', - $method->getDeclaringClass()->getDisplayName(), - $method->getName(), - $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), - ))); - if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { - $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); - } + } - $errorBuilder->identifier('method.alreadyNarrowedType'); + $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); + if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { + return []; + } - return [$errorBuilder->build()]; + $method = $this->getMethod($node->var, $node->name->name, $scope); + $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( + 'Call to method %s::%s()%s will always evaluate to true.', + $method->getDeclaringClass()->getDisplayName(), + $method->getName(), + $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), + ))); + if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { + $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } - return []; + $errorBuilder->identifier('method.alreadyNarrowedType'); + + return [$errorBuilder->build()]; } private function getMethod( diff --git a/src/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRule.php b/src/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRule.php index df4504cb0e..e4b3721538 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRule.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRule.php @@ -20,7 +20,6 @@ final class ImpossibleCheckTypeStaticMethodCallRule implements Rule public function __construct( private ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, - private bool $checkAlwaysTrueCheckTypeFunctionCall, private bool $treatPhpDocTypesAsCertain, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertainTip, @@ -71,29 +70,27 @@ public function processNode(Node $node, Scope $scope): array $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), )))->identifier('staticMethod.impossibleType')->build(), ]; - } elseif ($this->checkAlwaysTrueCheckTypeFunctionCall) { - $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); - if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { - return []; - } - - $method = $this->getMethod($node->class, $node->name->name, $scope); - $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( - 'Call to static method %s::%s()%s will always evaluate to true.', - $method->getDeclaringClass()->getDisplayName(), - $method->getName(), - $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), - ))); - if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { - $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); - } + } - $errorBuilder->identifier('staticMethod.alreadyNarrowedType'); + $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); + if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { + return []; + } - return [$errorBuilder->build()]; + $method = $this->getMethod($node->class, $node->name->name, $scope); + $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( + 'Call to static method %s::%s()%s will always evaluate to true.', + $method->getDeclaringClass()->getDisplayName(), + $method->getName(), + $this->impossibleCheckTypeHelper->getArgumentsDescription($scope, $node->getArgs()), + ))); + if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { + $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } - return []; + $errorBuilder->identifier('staticMethod.alreadyNarrowedType'); + + return [$errorBuilder->build()]; } /** diff --git a/src/Rules/Comparison/MatchExpressionRule.php b/src/Rules/Comparison/MatchExpressionRule.php index d204ca9c64..6edef9747b 100644 --- a/src/Rules/Comparison/MatchExpressionRule.php +++ b/src/Rules/Comparison/MatchExpressionRule.php @@ -27,7 +27,6 @@ final class MatchExpressionRule implements Rule public function __construct( private ConstantConditionRuleHelper $constantConditionRuleHelper, - private bool $checkAlwaysTrueStrictComparison, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertain, ) @@ -98,25 +97,24 @@ public function processNode(Node $node, Scope $scope): array $armConditionScope->getType($matchCondition)->describe(VerbosityLevel::value()), $armConditionScope->getType($armCondition->getCondition())->describe(VerbosityLevel::value()), ))->line($armLine)->identifier('match.alwaysFalse')->build(); - } else { - if ($this->checkAlwaysTrueStrictComparison) { - if ($i === $armsCount - 1 && !$this->reportAlwaysTrueInLastCondition) { - continue; - } - $errorBuilder = RuleErrorBuilder::message(sprintf( - 'Match arm comparison between %s and %s is always true.', - $armConditionScope->getType($matchCondition)->describe(VerbosityLevel::value()), - $armConditionScope->getType($armCondition->getCondition())->describe(VerbosityLevel::value()), - ))->line($armLine); - if ($i !== $armsCount - 1 && !$this->reportAlwaysTrueInLastCondition) { - $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); - } - - $errorBuilder->identifier('match.alwaysTrue'); - - $errors[] = $errorBuilder->build(); - } + continue; + } + + if ($i === $armsCount - 1 && !$this->reportAlwaysTrueInLastCondition) { + continue; + } + $errorBuilder = RuleErrorBuilder::message(sprintf( + 'Match arm comparison between %s and %s is always true.', + $armConditionScope->getType($matchCondition)->describe(VerbosityLevel::value()), + $armConditionScope->getType($armCondition->getCondition())->describe(VerbosityLevel::value()), + ))->line($armLine); + if ($i !== $armsCount - 1 && !$this->reportAlwaysTrueInLastCondition) { + $errorBuilder->tip('Remove remaining cases below this one and this error will disappear too.'); } + + $errorBuilder->identifier('match.alwaysTrue'); + + $errors[] = $errorBuilder->build(); } } diff --git a/src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php b/src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php index f4ea23258b..637ba4c50b 100644 --- a/src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php +++ b/src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php @@ -18,7 +18,6 @@ final class StrictComparisonOfDifferentTypesRule implements Rule { public function __construct( - private bool $checkAlwaysTrueStrictComparison, private bool $treatPhpDocTypesAsCertain, private bool $reportAlwaysTrueInLastCondition, private bool $treatPhpDocTypesAsCertainTip, @@ -70,38 +69,36 @@ public function processNode(Node $node, Scope $scope): array $rightType->describe(VerbosityLevel::value()), )))->identifier(sprintf('%s.alwaysFalse', $node instanceof Node\Expr\BinaryOp\Identical ? 'identical' : 'notIdentical'))->build(), ]; - } elseif ($this->checkAlwaysTrueStrictComparison) { - $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); - if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { - return []; - } - - $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( - 'Strict comparison using %s between %s and %s will always evaluate to true.', - $node->getOperatorSigil(), - $leftType->describe(VerbosityLevel::value()), - $rightType->describe(VerbosityLevel::value()), - ))); - if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { - $errorBuilder->addTip('Remove remaining cases below this one and this error will disappear too.'); - } + } - if ( - $leftType->isEnum()->yes() - && $rightType->isEnum()->yes() - && $node->getAttribute(LastConditionVisitor::ATTRIBUTE_IS_MATCH_NAME, false) !== true - ) { - $errorBuilder->addTip('Use match expression instead. PHPStan will report unhandled enum cases.'); - } + $isLast = $node->getAttribute(LastConditionVisitor::ATTRIBUTE_NAME); + if ($isLast === true && !$this->reportAlwaysTrueInLastCondition) { + return []; + } - $errorBuilder->identifier(sprintf('%s.alwaysTrue', $node instanceof Node\Expr\BinaryOp\Identical ? 'identical' : 'notIdentical')); + $errorBuilder = $addTip(RuleErrorBuilder::message(sprintf( + 'Strict comparison using %s between %s and %s will always evaluate to true.', + $node->getOperatorSigil(), + $leftType->describe(VerbosityLevel::value()), + $rightType->describe(VerbosityLevel::value()), + ))); + if ($isLast === false && !$this->reportAlwaysTrueInLastCondition) { + $errorBuilder->addTip('Remove remaining cases below this one and this error will disappear too.'); + } - return [ - $errorBuilder->build(), - ]; + if ( + $leftType->isEnum()->yes() + && $rightType->isEnum()->yes() + && $node->getAttribute(LastConditionVisitor::ATTRIBUTE_IS_MATCH_NAME, false) !== true + ) { + $errorBuilder->addTip('Use match expression instead. PHPStan will report unhandled enum cases.'); } - return []; + $errorBuilder->identifier(sprintf('%s.alwaysTrue', $node instanceof Node\Expr\BinaryOp\Identical ? 'identical' : 'notIdentical')); + + return [ + $errorBuilder->build(), + ]; } } diff --git a/tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php b/tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php index fde28cab1a..f8228f04f6 100644 --- a/tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule $this->checkAlwaysTrueInstanceOf, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, - true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ConstantLooseComparisonRuleTest.php b/tests/PHPStan/Rules/Comparison/ConstantLooseComparisonRuleTest.php index 213b9df52d..cbd60c68ed 100644 --- a/tests/PHPStan/Rules/Comparison/ConstantLooseComparisonRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ConstantLooseComparisonRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule $this->checkAlwaysTrueStrictComparison, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, - true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index bee9669510..95839c42cc 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -35,7 +35,6 @@ protected function getRule(): Rule $this->checkAlwaysTrueCheckTypeFunctionCall, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, - true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php index 47fb5d60f6..03de668ca6 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php @@ -23,7 +23,6 @@ public function getRule(): Rule true, true, false, - true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php index 4d7eedcf84..736e912ab7 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php @@ -23,7 +23,6 @@ public function getRule(): Rule true, true, false, - true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php index cfaf5fce01..2741c67864 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php @@ -28,7 +28,6 @@ public function getRule(): Rule true, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, - true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php index b3c7227ee1..3133e3aa96 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php @@ -27,7 +27,6 @@ public function getRule(): Rule true, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, - true, ); } diff --git a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php index 8d9cf3443e..072475e3e7 100644 --- a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php @@ -29,7 +29,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, true, ), - true, $this->reportAlwaysTrueInLastCondition, $this->treatPhpDocTypesAsCertain, ); diff --git a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php index 4d184029d7..f30f842ca2 100644 --- a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php @@ -25,7 +25,6 @@ protected function getRule(): Rule $this->checkAlwaysTrueStrictComparison, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, - true, ); } From db61867f112a07feedd72687d7f4684303b3a8c3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:42:03 +0200 Subject: [PATCH 197/508] [BE] ConstantLooseComparisonRule --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level4.neon | 4 ++-- conf/config.neon | 2 -- conf/parametersSchema.neon | 1 - src/Rules/Comparison/ConstantConditionRuleHelper.php | 7 ++----- 6 files changed, 5 insertions(+), 12 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index cc93b6af1b..274dae47b3 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -27,6 +27,7 @@ Major new features 🚀 * Check vprintf/vsprintf arguments against placeholder count (level 0) ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! * Report useless return values of function calls like `var_export` without `$return=true` (level 0) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! +* ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! * Check variance of template types in properties (level 2) ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! * ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! @@ -64,7 +65,6 @@ Bleeding edge (TODO move to other sections) * Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! * Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! -* ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 578124828b..54bad4da40 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -6,7 +6,6 @@ parameters: arrayFilter: true arrayValues: true - looseComparison: true readOnlyByPhpDoc: true pure: true requireFileExists: true diff --git a/conf/config.level4.neon b/conf/config.level4.neon index ed64b65aec..714843e781 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -21,8 +21,6 @@ rules: - PHPStan\Rules\Traits\NotAnalysedTraitRule conditionalTags: - PHPStan\Rules\Comparison\ConstantLooseComparisonRule: - phpstan.rules.rule: %featureToggles.looseComparison% PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule: phpstan.rules.rule: %featureToggles.pure% PHPStan\Rules\DeadCode\PossiblyPureNewCollector: @@ -220,6 +218,8 @@ services: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% reportAlwaysTrueInLastCondition: %reportAlwaysTrueInLastCondition% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% + tags: + - phpstan.rules.rule - class: PHPStan\Rules\Comparison\TernaryOperatorConstantConditionRule diff --git a/conf/config.neon b/conf/config.neon index a6be092dc4..c9fd627837 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -27,7 +27,6 @@ parameters: arrayFilter: false arrayValues: false illegalConstructorMethodCall: false - looseComparison: false readOnlyByPhpDoc: false stricterFunctionMap: false pure: false @@ -862,7 +861,6 @@ services: class: PHPStan\Rules\Comparison\ConstantConditionRuleHelper arguments: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - looseComparisonRuleEnabled: %featureToggles.looseComparison% - class: PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index d5a31f5b0e..68ebb600e3 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -33,7 +33,6 @@ parametersSchema: arrayFilter: bool(), arrayValues: bool(), illegalConstructorMethodCall: bool(), - looseComparison: bool(), readOnlyByPhpDoc: bool() stricterFunctionMap: bool() pure: bool() diff --git a/src/Rules/Comparison/ConstantConditionRuleHelper.php b/src/Rules/Comparison/ConstantConditionRuleHelper.php index 9271ef2782..dc3167a38d 100644 --- a/src/Rules/Comparison/ConstantConditionRuleHelper.php +++ b/src/Rules/Comparison/ConstantConditionRuleHelper.php @@ -14,7 +14,6 @@ final class ConstantConditionRuleHelper public function __construct( private ImpossibleCheckTypeHelper $impossibleCheckTypeHelper, private bool $treatPhpDocTypesAsCertain, - private bool $looseComparisonRuleEnabled, ) { } @@ -32,10 +31,8 @@ public function shouldReportAlwaysTrueByDefault(Expr $expr): bool public function shouldSkip(Scope $scope, Expr $expr): bool { if ( - $this->looseComparisonRuleEnabled - && ($expr instanceof Expr\BinaryOp\Equal - || $expr instanceof Expr\BinaryOp\NotEqual - ) + $expr instanceof Expr\BinaryOp\Equal + || $expr instanceof Expr\BinaryOp\NotEqual ) { return true; } From eb0504c45191f8ffbde497394e6ceecc01686213 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:43:10 +0200 Subject: [PATCH 198/508] [BCB] Remove unused `disableRuntimeReflectionProvider` feature toggle --- UPGRADING.md | 2 +- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 658f366c00..2ac65c3d17 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -98,7 +98,7 @@ Appending `(?)` in `ignoreErrors` is not supported. * Removed unused config parameter `cache.nodesByFileCountMax` * Removed unused config parameter `memoryLimitFile` - +* Removed unused feature toggle `disableRuntimeReflectionProvider` ## Upgrading guide for extension developers diff --git a/conf/config.neon b/conf/config.neon index c9fd627837..f901eb6dfe 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -22,7 +22,6 @@ parameters: tooWideThrowType: false featureToggles: bleedingEdge: false - disableRuntimeReflectionProvider: true skipCheckGenericClasses: [] arrayFilter: false arrayValues: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 68ebb600e3..9871903109 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -28,7 +28,6 @@ parametersSchema: ]) featureToggles: structure([ bleedingEdge: bool(), - disableRuntimeReflectionProvider: bool(), skipCheckGenericClasses: listOf(string()), arrayFilter: bool(), arrayValues: bool(), From 7cfc02e0e137d633fa8e2d86f1244cddbd6bf37d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 14:56:05 +0200 Subject: [PATCH 199/508] Other attempt at removing `checkAlwaysTrue*` from tests --- .../Classes/ImpossibleInstanceOfRuleTest.php | 120 +--------- .../BooleanAndConstantConditionRuleTest.php | 1 - .../BooleanNotConstantConditionRuleTest.php | 1 - .../BooleanOrConstantConditionRuleTest.php | 1 - .../ConstantLooseComparisonRuleTest.php | 33 +-- .../DoWhileLoopConstantConditionRuleTest.php | 1 - .../ElseIfConstantConditionRuleTest.php | 1 - .../IfConstantConditionRuleTest.php | 1 - ...mpossibleCheckTypeFunctionCallRuleTest.php | 163 +------------ ...sibleCheckTypeGenericOverwriteRuleTest.php | 2 +- ...sibleCheckTypeMethodCallRuleEqualsTest.php | 2 +- .../ImpossibleCheckTypeMethodCallRuleTest.php | 2 +- ...sibleCheckTypeStaticMethodCallRuleTest.php | 2 +- .../LogicalXorConstantConditionRuleTest.php | 1 - .../Comparison/MatchExpressionRuleTest.php | 1 - ...rictComparisonOfDifferentTypesRuleTest.php | 214 +----------------- ...rnaryOperatorConstantConditionRuleTest.php | 1 - .../WhileLoopAlwaysFalseConditionRuleTest.php | 1 - .../WhileLoopAlwaysTrueConditionRuleTest.php | 1 - 19 files changed, 12 insertions(+), 537 deletions(-) diff --git a/tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php b/tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php index f8228f04f6..a7c21443f1 100644 --- a/tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php @@ -12,8 +12,6 @@ class ImpossibleInstanceOfRuleTest extends RuleTestCase { - private bool $checkAlwaysTrueInstanceOf; - private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition = false; @@ -21,9 +19,9 @@ class ImpossibleInstanceOfRuleTest extends RuleTestCase protected function getRule(): Rule { return new ImpossibleInstanceOfRule( - $this->checkAlwaysTrueInstanceOf, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, + true, ); } @@ -34,7 +32,6 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool public function testInstanceof(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; $this->analyse( @@ -195,107 +192,8 @@ public function testInstanceof(): void ); } - public function testInstanceofWithoutAlwaysTrue(): void - { - $this->checkAlwaysTrueInstanceOf = false; - $this->treatPhpDocTypesAsCertain = true; - - $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->analyse( - [__DIR__ . '/data/impossible-instanceof.php'], - [ - [ - 'Instanceof between ImpossibleInstanceOf\Dolor and ImpossibleInstanceOf\Lorem will always evaluate to false.', - 71, - ], - [ - 'Instanceof between string and ImpossibleInstanceOf\Foo will always evaluate to false.', - 94, - ], - [ - 'Instanceof between string and \'str\' will always evaluate to false.', - 98, - ], - [ - 'Instanceof between ImpossibleInstanceOf\Test|null and ImpossibleInstanceOf\Lorem will always evaluate to false.', - 119, - ], - [ - 'Instanceof between ImpossibleInstanceOf\Test|null and ImpossibleInstanceOf\Lorem will always evaluate to false.', - 137, - ], - [ - 'Instanceof between ImpossibleInstanceOf\Test|null and ImpossibleInstanceOf\Lorem will always evaluate to false.', - 155, - ], - [ - 'Instanceof between callable and ImpossibleInstanceOf\FinalClassWithoutInvoke will always evaluate to false.', - 204, - ], - [ - 'Instanceof between *NEVER* and ImpossibleInstanceOf\Lorem will always evaluate to false.', - 228, - ], - [ - 'Instanceof between *NEVER* and ImpossibleInstanceOf\Foo will always evaluate to false.', - 234, - ], - [ - 'Instanceof between *NEVER* and ImpossibleInstanceOf\Bar will always evaluate to false.', - 240, - //$tipText, - ], - [ - 'Instanceof between object and Exception will always evaluate to false.', - 303, - ], - [ - 'Instanceof between object and InvalidArgumentException will always evaluate to false.', - 307, - ], - [ - 'Instanceof between ImpossibleInstanceOf\Bar and ImpossibleInstanceOf\BarChild will always evaluate to false.', - 318, - ], - [ - 'Instanceof between ImpossibleInstanceOf\Bar and ImpossibleInstanceOf\BarGrandChild will always evaluate to false.', - 322, - ], - /*[ - 'Instanceof between mixed and int results in an error.', - 353, - ], - [ - 'Instanceof between mixed and ImpossibleInstanceOf\InvalidTypeTest|int results in an error.', - 362, - ],*/ - [ - 'Instanceof between T of Exception and Error will always evaluate to false.', - 404, - $tipText, - ], - [ - 'Instanceof between class-string and DateTimeInterface will always evaluate to false.', - 418, - $tipText, - ], - [ - 'Instanceof between class-string and class-string will always evaluate to false.', - 419, - $tipText, - ], - [ - 'Instanceof between class-string and \'DateTimeInterface\' will always evaluate to false.', - 432, - $tipText, - ], - ], - ); - } - public function testDoNotReportTypesFromPhpDocs(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/impossible-instanceof-not-phpdoc.php'], [ [ @@ -319,7 +217,6 @@ public function testDoNotReportTypesFromPhpDocs(): void public function testReportTypesFromPhpDocs(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/impossible-instanceof-not-phpdoc.php'], [ [ @@ -353,21 +250,18 @@ public function testReportTypesFromPhpDocs(): void public function testBug3096(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-3096.php'], []); } public function testBug6213(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-6213.php'], []); } public function testBug5333(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/bug-5333.php'], []); } @@ -378,7 +272,6 @@ public function testBug8042(): void $this->markTestSkipped('This test needs PHP 8.0'); } - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-8042.php'], [ [ @@ -400,14 +293,12 @@ public function testBug7721(): void $this->markTestSkipped('This test needs PHP 8.1'); } - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-7721.php'], []); } public function testUnreachableIfBranches(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../Comparison/data/unreachable-if-branches.php'], [ [ @@ -432,7 +323,6 @@ public function testUnreachableIfBranches(): void public function testIfBranchesDoNotReportPhpDoc(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/../Comparison/data/unreachable-if-branches-not-phpdoc.php'], [ [ @@ -454,7 +344,6 @@ public function testIfBranchesDoNotReportPhpDoc(): void public function testIfBranchesReportPhpDoc(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; $this->analyse([__DIR__ . '/../Comparison/data/unreachable-if-branches-not-phpdoc.php'], [ @@ -492,7 +381,6 @@ public function testIfBranchesReportPhpDoc(): void public function testUnreachableTernaryElse(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../Comparison/data/unreachable-ternary-else-branch.php'], [ [ @@ -508,7 +396,6 @@ public function testUnreachableTernaryElse(): void public function testTernaryElseDoNotReportPhpDoc(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/../Comparison/data/unreachable-ternary-else-branch-not-phpdoc.php'], [ [ @@ -528,7 +415,6 @@ public function testTernaryElseDoNotReportPhpDoc(): void public function testTernaryElseReportPhpDoc(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; $this->analyse([__DIR__ . '/../Comparison/data/unreachable-ternary-else-branch-not-phpdoc.php'], [ @@ -554,7 +440,6 @@ public function testTernaryElseReportPhpDoc(): void public function testBug4689(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/bug-4689.php'], []); } @@ -590,7 +475,6 @@ public function dataReportAlwaysTrueInLastCondition(): iterable */ public function testReportAlwaysTrueInLastCondition(bool $reportAlwaysTrueInLastCondition, array $expectedErrors): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->analyse([__DIR__ . '/data/impossible-instanceof-report-always-true-last-condition.php'], $expectedErrors); @@ -602,7 +486,6 @@ public function testBug10201(): void $this->markTestSkipped('This test needs PHP 8.1'); } - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-10201.php'], [ [ @@ -614,7 +497,6 @@ public function testBug10201(): void public function testBug3632(): void { - $this->checkAlwaysTrueInstanceOf = true; $this->treatPhpDocTypesAsCertain = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; diff --git a/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php index 1b66a5898e..566c651fd4 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php @@ -26,7 +26,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, diff --git a/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php index 5fb982f548..ce5d1615f4 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php @@ -26,7 +26,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, diff --git a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php index 4db5d7167a..ca46233349 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php @@ -27,7 +27,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, diff --git a/tests/PHPStan/Rules/Comparison/ConstantLooseComparisonRuleTest.php b/tests/PHPStan/Rules/Comparison/ConstantLooseComparisonRuleTest.php index cbd60c68ed..e0bbf466ab 100644 --- a/tests/PHPStan/Rules/Comparison/ConstantLooseComparisonRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ConstantLooseComparisonRuleTest.php @@ -12,8 +12,6 @@ class ConstantLooseComparisonRuleTest extends RuleTestCase { - private bool $checkAlwaysTrueStrictComparison; - private bool $treatPhpDocTypesAsCertain = true; private bool $reportAlwaysTrueInLastCondition = false; @@ -21,39 +19,14 @@ class ConstantLooseComparisonRuleTest extends RuleTestCase protected function getRule(): Rule { return new ConstantLooseComparisonRule( - $this->checkAlwaysTrueStrictComparison, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, + true, ); } public function testRule(): void { - $this->checkAlwaysTrueStrictComparison = false; - $this->analyse([__DIR__ . '/data/loose-comparison.php'], [ - [ - "Loose comparison using == between 0 and '1' will always evaluate to false.", - 20, - ], - [ - "Loose comparison using == between 0 and '1' will always evaluate to false.", - 27, - ], - [ - "Loose comparison using == between 0 and '1' will always evaluate to false.", - 33, - ], - [ - 'Loose comparison using != between 3 and 3 will always evaluate to false.', - 48, - 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', - ], - ]); - } - - public function testRuleAlwaysTrue(): void - { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/loose-comparison.php'], [ [ "Loose comparison using == between 0 and '0' will always evaluate to true.", @@ -90,7 +63,6 @@ public function testBug8485(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8485.php'], [ [ 'Loose comparison using == between Bug8485\E::c and Bug8485\E::c will always evaluate to true.', @@ -142,7 +114,6 @@ public function dataReportAlwaysTrueInLastCondition(): iterable */ public function testReportAlwaysTrueInLastCondition(bool $reportAlwaysTrueInLastCondition, array $expectedErrors): void { - $this->checkAlwaysTrueStrictComparison = true; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->analyse([__DIR__ . '/data/loose-comparison-report-always-true-last-condition.php'], $expectedErrors); } @@ -165,14 +136,12 @@ public function dataTreatPhpDocTypesAsCertain(): iterable */ public function testTreatPhpDocTypesAsCertain(bool $treatPhpDocTypesAsCertain, array $expectedErrors): void { - $this->checkAlwaysTrueStrictComparison = true; $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; $this->analyse([__DIR__ . '/data/loose-comparison-treat-phpdoc-types.php'], $expectedErrors); } public function testBug11694(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-11694.php'], [ [ 'Loose comparison using == between 3 and int<10, 20> will always evaluate to false.', diff --git a/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php index 4ddf9941e8..38f3237a45 100644 --- a/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/DoWhileLoopConstantConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php index 4bac3a314f..e734b8ea1f 100644 --- a/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php @@ -27,7 +27,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, diff --git a/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php index 80ee3c0763..1f03a122bd 100644 --- a/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/IfConstantConditionRuleTest.php @@ -25,7 +25,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index 95839c42cc..5480eb394c 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -17,8 +17,6 @@ class ImpossibleCheckTypeFunctionCallRuleTest extends RuleTestCase { - private bool $checkAlwaysTrueCheckTypeFunctionCall; - private bool $treatPhpDocTypesAsCertain; private bool $reportAlwaysTrueInLastCondition = false; @@ -32,9 +30,9 @@ protected function getRule(): Rule [stdClass::class], $this->treatPhpDocTypesAsCertain, ), - $this->checkAlwaysTrueCheckTypeFunctionCall, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, + true, ); } @@ -49,7 +47,6 @@ public function testImpossibleCheckTypeFunctionCall(): void self::markTestSkipped('Test requires PHP 8.0.'); } - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse( [__DIR__ . '/data/check-type-function-call.php'], @@ -270,121 +267,12 @@ public function testImpossibleCheckTypeFunctionCall(): void public function testBug7898(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-7898.php'], []); } - public function testImpossibleCheckTypeFunctionCallWithoutAlwaysTrue(): void - { - if (PHP_VERSION_ID < 80000) { - self::markTestSkipped('Test requires PHP 8.0.'); - } - - $this->checkAlwaysTrueCheckTypeFunctionCall = false; - $this->treatPhpDocTypesAsCertain = true; - $this->analyse( - [__DIR__ . '/data/check-type-function-call.php'], - [ - [ - 'Call to function is_int() with string will always evaluate to false.', - 31, - ], - [ - 'Call to function is_callable() with array will always evaluate to false.', - 44, - 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', - ], - [ - 'Call to function assert() with false will always evaluate to false.', - 48, - ], - [ - 'Call to function is_callable() with \'nonexistentFunction\' will always evaluate to false.', - 87, - ], - [ - 'Call to function is_numeric() with \'blabla\' will always evaluate to false.', - 105, - ], - [ - 'Call to function method_exists() with $this(CheckTypeFunctionCall\FinalClassWithMethodExists) and \'doBar\' will always evaluate to false.', - 194, - ], - [ - 'Call to function in_array() with arguments int, array{\'foo\', \'bar\'} and true will always evaluate to false.', - 236, - ], - [ - 'Call to function in_array() with arguments \'bar\'|\'foo\', array{\'baz\', \'lorem\'} and true will always evaluate to false.', - 245, - ], - [ - 'Call to function in_array() with arguments \'bar\', array{}|array{\'foo\'} and true will always evaluate to false.', - 321, - ], - [ - 'Call to function in_array() with arguments \'baz\', array{0: \'bar\', 1?: \'foo\'} and true will always evaluate to false.', - 337, - ], - [ - 'Call to function in_array() with arguments \'foo\', array{} and true will always evaluate to false.', - 344, - ], - [ - 'Call to function array_key_exists() with \'c\' and array{a: 1, b?: 2} will always evaluate to false.', - 367, - ], - [ - 'Call to function is_string() with mixed will always evaluate to false.', - 561, - ], - [ - 'Call to function is_callable() with mixed will always evaluate to false.', - 572, - ], - [ - 'Call to function method_exists() with \'UndefinedClass\' and string will always evaluate to false.', - 595, - ], - [ - 'Call to function method_exists() with \'UndefinedClass\' and \'test\' will always evaluate to false.', - 598, - ], - [ - 'Call to function method_exists() with $this(CheckTypeFunctionCall\MethodExistsWithTrait) and \'unknown\' will always evaluate to false.', - 631, - ], - [ - 'Call to function method_exists() with \'CheckTypeFunctionCall\\\\MethodExistsWithTrait\' and \'unknown\' will always evaluate to false.', - 640, - 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', - ], - [ - 'Call to function method_exists() with \'CheckTypeFunctionCall\\\\MethodExistsWithTrait\' and \'unknown\' will always evaluate to false.', - 649, - ], - [ - 'Call to function assert() with false will always evaluate to false.', - 694, - 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', - ], - [ - 'Call to function is_numeric() with \'blabla\' will always evaluate to false.', - 694, - ], - [ - 'Call to function in_array() with arguments 1, array and true will always evaluate to false.', - 927, - 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.', - ], - ], - ); - } - public function testDoNotReportTypesFromPhpDocs(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/check-type-function-call-not-phpdoc.php'], [ [ @@ -396,7 +284,6 @@ public function testDoNotReportTypesFromPhpDocs(): void public function testReportTypesFromPhpDocs(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/check-type-function-call-not-phpdoc.php'], [ [ @@ -423,42 +310,36 @@ public function testReportTypesFromPhpDocs(): void public function testBug2550(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-2550.php'], []); } public function testBug3994(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-3994.php'], []); } public function testBug1613(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-1613.php'], []); } public function testBug2714(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-2714.php'], []); } public function testBug4657(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/bug-4657.php'], []); } public function testBug4999(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/bug-4999.php'], []); } @@ -469,7 +350,6 @@ public function testArrayIsList(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/array-is-list.php'], [ [ @@ -490,14 +370,12 @@ public function testArrayIsList(): void public function testBug3766(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-3766.php'], []); } public function testBug6305(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-6305.php'], [ [ @@ -513,21 +391,18 @@ public function testBug6305(): void public function testBug6698(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-6698.php'], []); } public function testBug5369(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-5369.php'], []); } public function testBugInArrayDateFormat(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/in-array-date-format.php'], [ [ @@ -554,63 +429,54 @@ public function testBugInArrayDateFormat(): void public function testBug5496(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-5496.php'], []); } public function testBug3892(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-3892.php'], []); } public function testBug3314(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-3314.php'], []); } public function testBug2870(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-2870.php'], []); } public function testBug5354(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-5354.php'], []); } public function testSlevomatCsInArrayBug(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/slevomat-cs-in-array.php'], []); } public function testNonEmptySpecifiedString(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/non-empty-string-impossible-type.php'], []); } public function testBug2755(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-2755.php'], []); } public function testBug7079(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-7079.php'], []); } @@ -621,7 +487,6 @@ public function testConditionalTypesInference(): void self::markTestSkipped('Test requires PHP 8.0.'); } - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/conditional-types-inference.php'], [ [ @@ -649,7 +514,6 @@ public function testConditionalTypesInference(): void public function testBug6697(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-6697.php'], []); } @@ -660,56 +524,48 @@ public function testBug6443(): void self::markTestSkipped('Test requires PHP 8.0.'); } - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-6443.php'], []); } public function testBug7684(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = false; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-7684.php'], []); } public function testBug7224(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-7224.php'], []); } public function testBug4708(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-4708.php'], []); } public function testBug3821(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-3821.php'], []); } public function testBug6599(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-6599.php'], []); } public function testBug7914(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-7914.php'], []); } public function testDocblockAssertEquality(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/docblock-assert-equality.php'], [ [ @@ -721,63 +577,54 @@ public function testDocblockAssertEquality(): void public function testBug8076(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-8076.php'], []); } public function testBug8562(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-8562.php'], []); } public function testBug6938(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/bug-6938.php'], []); } public function testBug8727(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-8727.php'], []); } public function testBug8474(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-8474.php'], []); } public function testBug5695(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/bug-5695.php'], []); } public function testBug8752(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-8752.php'], []); } public function testDiscussion9134(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/discussion-9134.php'], []); } public function testImpossibleMethodExistOnGenericClassString(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; @@ -838,7 +685,6 @@ public function dataReportAlwaysTrueInLastCondition(): iterable */ public function testReportAlwaysTrueInLastCondition(bool $reportAlwaysTrueInLastCondition, array $expectedErrors): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->analyse([__DIR__ . '/data/impossible-function-report-always-true-last-condition.php'], $expectedErrors); @@ -846,7 +692,6 @@ public function testReportAlwaysTrueInLastCondition(bool $reportAlwaysTrueInLast public function testObjectShapes(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/property-exists-object-shapes.php'], [ [ @@ -1023,7 +868,6 @@ public function testLooseComparisonAgainstEnums(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $issues = array_map( static function (array $i): array { @@ -1040,7 +884,6 @@ static function (array $i): array { public function testNonStrictInArray(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-9662.php'], []); } @@ -1053,7 +896,6 @@ public function testNonStrictInArrayEnums(): void $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-9662-enums.php'], [ [ @@ -1083,7 +925,6 @@ public function testLooseComparisonAgainstEnumsNoPhpdoc(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = false; $issues = self::getLooseComparisonAgainsEnumsIssues(); $issues = array_values(array_filter($issues, static fn (array $i) => count($i) === 2)); @@ -1094,7 +935,6 @@ public function testBug10502(): void { $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/bug-10502.php'], [ [ @@ -1111,7 +951,6 @@ public function testBug10502(): void public function testAlwaysTruePregMatch(): void { - $this->checkAlwaysTrueCheckTypeFunctionCall = true; $this->treatPhpDocTypesAsCertain = true; $this->analyse([__DIR__ . '/data/always-true-preg-match.php'], []); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php index 03de668ca6..67245ebaba 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeGenericOverwriteRuleTest.php @@ -21,8 +21,8 @@ public function getRule(): Rule true, ), true, - true, false, + true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php index 736e912ab7..b81646c023 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleEqualsTest.php @@ -21,8 +21,8 @@ public function getRule(): Rule true, ), true, - true, false, + true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php index 2741c67864..eceaff15f9 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeMethodCallRuleTest.php @@ -25,9 +25,9 @@ public function getRule(): Rule [], $this->treatPhpDocTypesAsCertain, ), - true, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, + true, ); } diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php index 3133e3aa96..1cdbc1a7ad 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php @@ -24,9 +24,9 @@ public function getRule(): Rule [], $this->treatPhpDocTypesAsCertain, ), - true, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, + true, ); } diff --git a/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php index 4eab90f017..c191856047 100644 --- a/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/LogicalXorConstantConditionRuleTest.php @@ -26,7 +26,6 @@ protected function getRule(): TRule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, diff --git a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php index 072475e3e7..365b9dff9c 100644 --- a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php @@ -27,7 +27,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->reportAlwaysTrueInLastCondition, $this->treatPhpDocTypesAsCertain, diff --git a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php index f30f842ca2..0d9fb746aa 100644 --- a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php @@ -13,8 +13,6 @@ class StrictComparisonOfDifferentTypesRuleTest extends RuleTestCase { - private bool $checkAlwaysTrueStrictComparison; - private bool $reportAlwaysTrueInLastCondition = false; private bool $treatPhpDocTypesAsCertain = true; @@ -22,9 +20,9 @@ class StrictComparisonOfDifferentTypesRuleTest extends RuleTestCase protected function getRule(): Rule { return new StrictComparisonOfDifferentTypesRule( - $this->checkAlwaysTrueStrictComparison, $this->treatPhpDocTypesAsCertain, $this->reportAlwaysTrueInLastCondition, + true, ); } @@ -35,7 +33,6 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool public function testStrictComparison(): void { - $this->checkAlwaysTrueStrictComparison = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; $this->analyse( [__DIR__ . '/data/strict-comparison.php'], @@ -273,162 +270,8 @@ public function testStrictComparison(): void ); } - public function testStrictComparisonWithoutAlwaysTrue(): void - { - $this->checkAlwaysTrueStrictComparison = false; - $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->analyse( - [__DIR__ . '/data/strict-comparison.php'], - [ - [ - 'Strict comparison using === between 1 and \'1\' will always evaluate to false.', - 11, - ], - [ - 'Strict comparison using === between 1 and null will always evaluate to false.', - 14, - ], - [ - 'Strict comparison using === between StrictComparison\Bar and 1 will always evaluate to false.', - 15, - ], - [ - 'Strict comparison using === between 1 and array|bool|StrictComparison\Collection will always evaluate to false.', - 19, - $tipText, - ], - [ - 'Strict comparison using === between true and false will always evaluate to false.', - 30, - ], - [ - 'Strict comparison using === between false and true will always evaluate to false.', - 31, - ], - [ - 'Strict comparison using === between 1.0 and 1 will always evaluate to false.', - 46, - ], - [ - 'Strict comparison using === between 1 and 1.0 will always evaluate to false.', - 47, - ], - [ - 'Strict comparison using === between string and null will always evaluate to false.', - 69, - ], - [ - 'Strict comparison using === between 1|2|3 and null will always evaluate to false.', - 98, - ], - [ - 'Strict comparison using === between non-empty-array and null will always evaluate to false.', - 140, - ], - [ - 'Strict comparison using === between non-empty-array and null will always evaluate to false.', - 164, - ], - [ - 'Strict comparison using === between 1 and 2 will always evaluate to false.', - 284, - ], - [ - 'Strict comparison using === between array{X: 1} and array{X: 2} will always evaluate to false.', - 292, - ], - [ - 'Strict comparison using === between array{X: 1, Y: 2} and array{X: 2, Y: 1} will always evaluate to false.', - 300, - ], - [ - 'Strict comparison using === between array{X: 1, Y: 2} and array{Y: 2, X: 1} will always evaluate to false.', - 308, - ], - [ - 'Strict comparison using === between \'/\'|\'\\\\\' and \'//\' will always evaluate to false.', - 320, - ], - [ - 'Strict comparison using === between int<1, max> and \'string\' will always evaluate to false.', - 335, - ], - [ - 'Strict comparison using === between int<0, max> and \'string\' will always evaluate to false.', - 343, - ], - [ - 'Strict comparison using === between int<0, max> and \'string\' will always evaluate to false.', - 360, - ], - [ - 'Strict comparison using === between int<1, max> and \'string\' will always evaluate to false.', - 368, - ], - [ - 'Strict comparison using === between float and \'string\' will always evaluate to false.', - 386, - ], - [ - 'Strict comparison using === between float and \'string\' will always evaluate to false.', - 394, - ], - [ - 'Strict comparison using !== between null and null will always evaluate to false.', - 408, - ], - [ - 'Strict comparison using === between (int|int<2, max>|string) and 1.0 will always evaluate to false.', - 464, - ], - [ - 'Strict comparison using === between (int|int<2, max>|string) and stdClass will always evaluate to false.', - 466, - ], - [ - 'Strict comparison using === between int<0, 1> and 100 will always evaluate to false.', - 622, - $tipText, - ], - [ - 'Strict comparison using === between 100 and \'foo\' will always evaluate to false.', - 624, - ], - [ - 'Strict comparison using === between int<10, max> and \'foo\' will always evaluate to false.', - 635, - ], - [ - 'Strict comparison using === between string|null and 1 will always evaluate to false.', - 685, - ], - [ - 'Strict comparison using === between string|null and 1 will always evaluate to false.', - 695, - ], - [ - 'Strict comparison using === between string|null and 1 will always evaluate to false.', - 705, - ], - [ - 'Strict comparison using === between mixed and \'foo\' will always evaluate to false.', - 808, - ], - [ - 'Strict comparison using === between NAN and NAN will always evaluate to false.', - 980, - ], - [ - 'Strict comparison using !== between INF and INF will always evaluate to false.', - 982, - ], - ], - ); - } - public function testStrictComparisonPhp71(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/strict-comparison-71.php'], [ [ 'Strict comparison using === between null and null will always evaluate to true.', @@ -439,7 +282,6 @@ public function testStrictComparisonPhp71(): void public function testStrictComparisonPropertyNativeTypesPhp74(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/strict-comparison-property-native-types.php'], [ [ 'Strict comparison using === between string and null will always evaluate to false.', @@ -462,13 +304,11 @@ public function testStrictComparisonPropertyNativeTypesPhp74(): void public function testBug2835(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-2835.php'], []); } public function testBug1860(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-1860.php'], [ [ 'Strict comparison using === between string and null will always evaluate to false.', @@ -483,31 +323,26 @@ public function testBug1860(): void public function testBug3544(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-3544.php'], []); } public function testBug2675(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-2675.php'], []); } public function testBug2220(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-2220.php'], []); } public function testBug1707(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-1707.php'], []); } public function testBug3357(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-3357.php'], []); } @@ -516,7 +351,6 @@ public function testBug4848(): void if (PHP_INT_SIZE !== 8) { $this->markTestSkipped('Test requires 64-bit platform.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-4848.php'], [ [ 'Strict comparison using === between \'18446744073709551615\' and \'9223372036854775807\' will always evaluate to false.', @@ -527,25 +361,21 @@ public function testBug4848(): void public function testBug4793(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-4793.php'], []); } public function testBug5062(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-5062.php'], []); } public function testBug3366(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-3366.php'], []); } public function testBug5362(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-5362.php'], [ [ 'Strict comparison using === between 0 and 1|2 will always evaluate to false.', @@ -556,8 +386,6 @@ public function testBug5362(): void public function testBug6939(): void { - $this->checkAlwaysTrueStrictComparison = true; - if (PHP_VERSION_ID < 80000) { $this->analyse([__DIR__ . '/data/bug-6939.php'], []); return; @@ -573,13 +401,11 @@ public function testBug6939(): void public function testBug7166(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-7166.php'], []); } public function testBug7555(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-7555.php'], [ [ 'Strict comparison using === between 2 and 2 will always evaluate to true.', @@ -591,30 +417,30 @@ public function testBug7555(): void public function testBug7257(): void { - $this->checkAlwaysTrueStrictComparison = false; $this->analyse([__DIR__ . '/data/bug-7257.php'], []); } public function testBug5474(): void { - $this->checkAlwaysTrueStrictComparison = false; $this->analyse([__DIR__ . '/data/bug-5474.php'], [ [ 'Strict comparison using !== between array{test: 1} and array{test: 1} will always evaluate to false.', 25, ], + [ + 'Strict comparison using !== between array{test: 1} and array{test: 5} will always evaluate to true.', + 29, + ], ]); } public function testBug7684(): void { - $this->checkAlwaysTrueStrictComparison = false; $this->analyse([__DIR__ . '/data/bug-7684.php'], []); } public function testBug6181(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-6181.php'], []); } @@ -622,7 +448,6 @@ public function testBug2851b(): void { $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-2851b.php'], [ [ 'Strict comparison using === between 0 and 0 will always evaluate to true.', @@ -634,7 +459,6 @@ public function testBug2851b(): void public function testBug8158(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8158.php'], []); } @@ -644,7 +468,6 @@ public function testBug8485(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8485.php'], [ [ 'Strict comparison using === between Bug8485\E::c and Bug8485\E::c will always evaluate to true.', @@ -682,19 +505,16 @@ public function testBug8485(): void public function testBug8516(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8516.php'], []); } public function testPhpUnitIntegration(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/phpunit-integration.php'], []); } public function testBug8586(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8586.php'], []); } @@ -704,13 +524,11 @@ public function testBug4242(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-4242.php'], []); } public function testBug3633(): void { - $this->checkAlwaysTrueStrictComparison = true; $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; $this->analyse([__DIR__ . '/data/bug-3633.php'], [ [ @@ -781,7 +599,6 @@ public function testBug3633(): void public function testLastConditionAlwaysTrue(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/strict-comparison-last-condition-always-true.php'], [ [ 'Strict comparison using === between \'bar\' and \'bar\' will always evaluate to true.', @@ -793,13 +610,11 @@ public function testLastConditionAlwaysTrue(): void public function testBug3019(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-3019.php'], []); } public function testBug7578(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/bug-7578.php'], []); } @@ -810,14 +625,12 @@ public function testBug6260(): void $this->markTestSkipped('Test requires PHP 8.0.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->treatPhpDocTypesAsCertain = false; $this->analyse([__DIR__ . '/data/bug-6260.php'], []); } public function testBug8736(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8736.php'], []); } @@ -895,20 +708,17 @@ public function testLastMatchArm(bool $reportAlwaysTrueInLastCondition, array $e $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->reportAlwaysTrueInLastCondition = $reportAlwaysTrueInLastCondition; $this->analyse([__DIR__ . '/data/strict-comparison-last-match-arm.php'], $expectedErrors); } public function testBug8776Part1(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8776-1.php'], []); } public function testBug8776Part2(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-8776-2.php'], []); } @@ -929,13 +739,11 @@ public function testBug5978(): void $expectedErrors = []; } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-5978.php'], $expectedErrors); } public function testBug9104(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-9104.php'], [ [ 'Strict comparison using === between int<1, max> and 0 will always evaluate to false.', @@ -951,7 +759,6 @@ public function testEnumTips(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/strict-comparison-enum-tips.php'], [ [ 'Strict comparison using === between StrictComparisonEnumTips\SomeEnum::Two and StrictComparisonEnumTips\SomeEnum::Two will always evaluate to true.', @@ -967,7 +774,6 @@ public function testBug9142(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-9142.php'], [ [ 'Strict comparison using === between $this(Bug9142\MyEnum) and Bug9142\MyEnum::Three will always evaluate to false.', @@ -986,7 +792,6 @@ public function testBug4061(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-4061.php'], []); } @@ -996,7 +801,6 @@ public function testBug9723(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-9723.php'], []); } @@ -1006,25 +810,21 @@ public function testBug9723b(): void $this->markTestSkipped('Test requires PHP 8.1.'); } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-9723b.php'], []); } public function testBug8366(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-8366.php'], []); } public function testBug3300(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/../../Analyser/data/bug-3300.php'], []); } public function testBug11035(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-11035.php'], [ [ "Strict comparison using === between '0' and non-falsy-string will always evaluate to false.", @@ -1036,25 +836,21 @@ public function testBug11035(): void public function testBug9804(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-9804.php'], []); } public function testBug11161(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-11161.php'], []); } public function testBug10697(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-10697.php'], []); } public function testBug10493(): void { - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/bug-10493.php'], []); } diff --git a/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php index 2169597e68..e1e7474e17 100644 --- a/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php index df5ce1d3c8..4d65f02d2b 100644 --- a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysFalseConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, diff --git a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php index 83f53c071a..4a377f1855 100644 --- a/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/WhileLoopAlwaysTrueConditionRuleTest.php @@ -24,7 +24,6 @@ protected function getRule(): Rule $this->treatPhpDocTypesAsCertain, ), $this->treatPhpDocTypesAsCertain, - true, ), $this->treatPhpDocTypesAsCertain, true, From a2a2905d76bde5a12cad9f69297bc2670b71ecfa Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 16:11:41 +0200 Subject: [PATCH 200/508] Issue bot - let all comments about PHPStan 2.0 through --- issue-bot/src/Console/EvaluateCommand.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index 0f8d05a8d8..f18941039b 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,10 +158,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { - if (count($toPost) > 20) { - $output->writeln('Too many comments to post, something is probably wrong.'); - return 1; - } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From b02b79fa02c634a8c34e5a14f7686ed3b74fb74b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 15:06:23 +0200 Subject: [PATCH 201/508] Revert "Issue bot - let all comments about PHPStan 2.0 through" This reverts commit a2a2905d76bde5a12cad9f69297bc2670b71ecfa. --- issue-bot/src/Console/EvaluateCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index f18941039b..0f8d05a8d8 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,6 +158,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { + if (count($toPost) > 20) { + $output->writeln('Too many comments to post, something is probably wrong.'); + return 1; + } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From 29ddf4248932f88a7a97aa05213125b0e23e1db1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 15:08:07 +0200 Subject: [PATCH 202/508] [BE] Check if required file exists --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 4 ++-- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 274dae47b3..bd23ea35b3 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -27,6 +27,7 @@ Major new features 🚀 * Check vprintf/vsprintf arguments against placeholder count (level 0) ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! * Report useless return values of function calls like `var_export` without `$return=true` (level 0) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! +* Check if required file exists (level 0) ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! * Check variance of template types in properties (level 2) ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! @@ -84,7 +85,6 @@ Bleeding edge (TODO move to other sections) * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) -* Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 Improvements 🔧 diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 54bad4da40..fa60d6e22a 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -8,4 +8,3 @@ parameters: arrayValues: true readOnlyByPhpDoc: true pure: true - requireFileExists: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index d62a5e4ce9..13147b6c45 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -8,8 +8,6 @@ conditionalTags: phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\UninitializedPropertyRule: phpstan.rules.rule: %checkUninitializedProperties% - PHPStan\Rules\Keywords\RequireFileExistsRule: - phpstan.rules.rule: %featureToggles.requireFileExists% rules: - PHPStan\Rules\Api\ApiInstanceofRule @@ -260,3 +258,5 @@ services: class: PHPStan\Rules\Keywords\RequireFileExistsRule arguments: currentWorkingDirectory: %currentWorkingDirectory% + tags: + - phpstan.rules.rule diff --git a/conf/config.neon b/conf/config.neon index f901eb6dfe..e8bad648c4 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -29,7 +29,6 @@ parameters: readOnlyByPhpDoc: false stricterFunctionMap: false pure: false - requireFileExists: false fileExtensions: - php checkAdvancedIsset: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 9871903109..31e5cad0e0 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -35,7 +35,6 @@ parametersSchema: readOnlyByPhpDoc: bool() stricterFunctionMap: bool() pure: bool() - requireFileExists: bool() ]) fileExtensions: listOf(string()) checkAdvancedIsset: bool() From e47eee311dbff0f4f8931b13f7d14f5822835602 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 15:10:22 +0200 Subject: [PATCH 203/508] [BE] Report useless `array_filter()` calls --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level5.neon | 4 ++-- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index bd23ea35b3..6da15f7259 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -27,6 +27,7 @@ Major new features 🚀 * Check vprintf/vsprintf arguments against placeholder count (level 0) ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! * Report useless return values of function calls like `var_export` without `$return=true` (level 0) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! +* Report useless `array_filter()` calls (level 5) ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! * Check if required file exists (level 0) ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! @@ -64,7 +65,6 @@ Major new features 🚀 Bleeding edge (TODO move to other sections) ===================== -* Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! * Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index fa60d6e22a..555389c6e6 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -4,7 +4,6 @@ parameters: skipCheckGenericClasses!: [] stricterFunctionMap: true - arrayFilter: true arrayValues: true readOnlyByPhpDoc: true pure: true diff --git a/conf/config.level5.neon b/conf/config.level5.neon index 3fa1bb8e29..a8aa14b986 100644 --- a/conf/config.level5.neon +++ b/conf/config.level5.neon @@ -6,8 +6,6 @@ parameters: checkArgumentsPassedByReference: true conditionalTags: - PHPStan\Rules\Functions\ArrayFilterRule: - phpstan.rules.rule: %featureToggles.arrayFilter% PHPStan\Rules\Functions\ArrayValuesRule: phpstan.rules.rule: %featureToggles.arrayValues% @@ -31,6 +29,8 @@ services: arguments: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% + tags: + - phpstan.rules.rule - class: PHPStan\Rules\Functions\ArrayValuesRule diff --git a/conf/config.neon b/conf/config.neon index e8bad648c4..5104a7e040 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -23,7 +23,6 @@ parameters: featureToggles: bleedingEdge: false skipCheckGenericClasses: [] - arrayFilter: false arrayValues: false illegalConstructorMethodCall: false readOnlyByPhpDoc: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 31e5cad0e0..351862a0cd 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -29,7 +29,6 @@ parametersSchema: featureToggles: structure([ bleedingEdge: bool(), skipCheckGenericClasses: listOf(string()), - arrayFilter: bool(), arrayValues: bool(), illegalConstructorMethodCall: bool(), readOnlyByPhpDoc: bool() From 439950412f287cf78270bd32cf34912712d4b2e5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 15:11:56 +0200 Subject: [PATCH 204/508] [BE] Report useless `array_values()` calls --- changelog-2.0.md | 2 +- conf/bleedingEdge.neon | 1 - conf/config.level5.neon | 6 ++---- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 6da15f7259..803b7d8f42 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -28,6 +28,7 @@ Major new features 🚀 * Report useless return values of function calls like `var_export` without `$return=true` (level 0) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Report useless `array_filter()` calls (level 5) ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! +* Report useless `array_values()` calls (level 5) ([#2917](https://github.com/phpstan/phpstan-src/pull/2917)), thanks @kamil-zacek! * Check if required file exists (level 0) ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! * ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) * Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! @@ -76,7 +77,6 @@ Bleeding edge (TODO move to other sections) * Report unused result of ternary (https://github.com/phpstan/phpstan-src/commit/9664f7a9d2223c07e750f0dfc949c3accfa6b65e) * Report unused results of `&&` and `||` (https://github.com/phpstan/phpstan-src/commit/cf2c8bbd9ebd2ebe300dbd310e136ad603d7def3) * Add option `reportAnyTypeWideningInVarTag` ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! -* `array_values` rule (report when a `list` type is always passed in) ([#2917](https://github.com/phpstan/phpstan-src/pull/2917)), thanks @kamil-zacek! * Fix checking generic `mixed` type based on config ([#2885](https://github.com/phpstan/phpstan-src/pull/2885)), thanks @schlndh! * Checking truthiness of `@phpstan-pure` above functions and methods * Check `new`/function call/method call/static method call on a separate line without any side effects even without `@phpstan-pure` PHPDoc tag on the declaration side diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 555389c6e6..694eba9796 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -4,6 +4,5 @@ parameters: skipCheckGenericClasses!: [] stricterFunctionMap: true - arrayValues: true readOnlyByPhpDoc: true pure: true diff --git a/conf/config.level5.neon b/conf/config.level5.neon index a8aa14b986..0cbccea5d6 100644 --- a/conf/config.level5.neon +++ b/conf/config.level5.neon @@ -5,10 +5,6 @@ parameters: checkFunctionArgumentTypes: true checkArgumentsPassedByReference: true -conditionalTags: - PHPStan\Rules\Functions\ArrayValuesRule: - phpstan.rules.rule: %featureToggles.arrayValues% - rules: - PHPStan\Rules\DateTimeInstantiationRule - PHPStan\Rules\Functions\CallUserFuncRule @@ -37,3 +33,5 @@ services: arguments: treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% + tags: + - phpstan.rules.rule diff --git a/conf/config.neon b/conf/config.neon index 5104a7e040..aa8fcc3a63 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -23,7 +23,6 @@ parameters: featureToggles: bleedingEdge: false skipCheckGenericClasses: [] - arrayValues: false illegalConstructorMethodCall: false readOnlyByPhpDoc: false stricterFunctionMap: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 351862a0cd..652bda42b0 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -29,7 +29,6 @@ parametersSchema: featureToggles: structure([ bleedingEdge: bool(), skipCheckGenericClasses: listOf(string()), - arrayValues: bool(), illegalConstructorMethodCall: bool(), readOnlyByPhpDoc: bool() stricterFunctionMap: bool() From 375879379aa709eebc4b14eb6349e97d854a3de6 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 17:09:55 +0200 Subject: [PATCH 205/508] [BE] Support `@readonly` property and `@immutable` class PHPDoc --- changelog-2.0.md | 4 ++-- conf/bleedingEdge.neon | 1 - conf/config.level0.neon | 12 ++---------- conf/config.level2.neon | 7 +------ conf/config.level3.neon | 14 ++------------ conf/config.neon | 1 - conf/parametersSchema.neon | 1 - src/Rules/Generics/PropertyVarianceRule.php | 3 +-- .../Rules/Generics/PropertyVarianceRuleTest.php | 1 - 9 files changed, 8 insertions(+), 36 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 803b7d8f42..29e9d612b4 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -36,6 +36,8 @@ Major new features 🚀 * ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! * Check unresolvable parameters (level 5) ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! * Enforce `@no-named-arguments` (level 5) (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 +* Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! +* Add `@readonly` rule that disallows default values (level 0) ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * IncompatibleDefaultParameterTypeRule for closures (level 2) (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) * Added previously absent type checks (level 0) * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) @@ -67,9 +69,7 @@ Bleeding edge (TODO move to other sections) ===================== * Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! -* Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) -* Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 694eba9796..89a624594a 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -4,5 +4,4 @@ parameters: skipCheckGenericClasses!: [] stricterFunctionMap: true - readOnlyByPhpDoc: true pure: true diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 13147b6c45..6dd5e4c7ca 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -2,10 +2,6 @@ parameters: customRulesetUsed: false conditionalTags: - PHPStan\Rules\Properties\MissingReadOnlyByPhpDocPropertyAssignRule: - phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% - PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyRule: - phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% PHPStan\Rules\Properties\UninitializedPropertyRule: phpstan.rules.rule: %checkUninitializedProperties% @@ -98,9 +94,11 @@ rules: - PHPStan\Rules\Properties\AccessStaticPropertiesInAssignRule - PHPStan\Rules\Properties\InvalidCallablePropertyTypeRule - PHPStan\Rules\Properties\MissingReadOnlyPropertyAssignRule + - PHPStan\Rules\Properties\MissingReadOnlyByPhpDocPropertyAssignRule - PHPStan\Rules\Properties\PropertiesInInterfaceRule - PHPStan\Rules\Properties\PropertyAttributesRule - PHPStan\Rules\Properties\ReadOnlyPropertyRule + - PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyRule - PHPStan\Rules\Regexp\RegularExpressionPatternRule - PHPStan\Rules\Regexp\RegularExpressionQuotingRule - PHPStan\Rules\Traits\ConflictingTraitConstantsRule @@ -203,9 +201,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Properties\MissingReadOnlyByPhpDocPropertyAssignRule - - class: PHPStan\Rules\Properties\OverridingPropertyRule arguments: @@ -214,9 +209,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyRule - - class: PHPStan\Rules\Properties\UninitializedPropertyRule diff --git a/conf/config.level2.neon b/conf/config.level2.neon index f75e01dfde..b9fbf7d023 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -37,6 +37,7 @@ rules: - PHPStan\Rules\Generics\MethodTagTemplateTypeRule - PHPStan\Rules\Generics\MethodTagTemplateTypeTraitRule - PHPStan\Rules\Generics\MethodSignatureVarianceRule + - PHPStan\Rules\Generics\PropertyVarianceRule - PHPStan\Rules\Generics\TraitTemplateTypeRule - PHPStan\Rules\Generics\UsedTraitsRule - PHPStan\Rules\Methods\CallPrivateMethodThroughStaticRule @@ -117,12 +118,6 @@ services: class: PHPStan\Rules\PhpDoc\InvalidPHPStanDocTagRule tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Generics\PropertyVarianceRule - arguments: - readOnlyByPhpDoc: %featureToggles.readOnlyByPhpDoc% - tags: - - phpstan.rules.rule - class: PHPStan\Rules\Pure\PureFunctionRule diff --git a/conf/config.level3.neon b/conf/config.level3.neon index 089569684c..250d545f15 100644 --- a/conf/config.level3.neon +++ b/conf/config.level3.neon @@ -1,12 +1,6 @@ includes: - config.level2.neon -conditionalTags: - PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRefRule: - phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% - PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRule: - phpstan.rules.rule: %featureToggles.readOnlyByPhpDoc% - rules: - PHPStan\Rules\Arrays\ArrayDestructuringRule - PHPStan\Rules\Arrays\ArrayUnpackingRule @@ -23,7 +17,9 @@ rules: - PHPStan\Rules\Methods\ReturnTypeRule - PHPStan\Rules\Properties\DefaultValueTypesAssignedToPropertiesRule - PHPStan\Rules\Properties\ReadOnlyPropertyAssignRule + - PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRule - PHPStan\Rules\Properties\ReadOnlyPropertyAssignRefRule + - PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRefRule - PHPStan\Rules\Properties\TypesAssignedToPropertiesRule - PHPStan\Rules\Variables\ParameterOutAssignedTypeRule - PHPStan\Rules\Variables\ParameterOutExecutionEndTypeRule @@ -83,9 +79,3 @@ services: reportMaybes: %reportMaybes% tags: - phpstan.rules.rule - - - - class: PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRefRule - - - - class: PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyAssignRule diff --git a/conf/config.neon b/conf/config.neon index aa8fcc3a63..5f0d9fd1ef 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -24,7 +24,6 @@ parameters: bleedingEdge: false skipCheckGenericClasses: [] illegalConstructorMethodCall: false - readOnlyByPhpDoc: false stricterFunctionMap: false pure: false fileExtensions: diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 652bda42b0..51133df707 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -30,7 +30,6 @@ parametersSchema: bleedingEdge: bool(), skipCheckGenericClasses: listOf(string()), illegalConstructorMethodCall: bool(), - readOnlyByPhpDoc: bool() stricterFunctionMap: bool() pure: bool() ]) diff --git a/src/Rules/Generics/PropertyVarianceRule.php b/src/Rules/Generics/PropertyVarianceRule.php index 4ddff55f11..f222bd9945 100644 --- a/src/Rules/Generics/PropertyVarianceRule.php +++ b/src/Rules/Generics/PropertyVarianceRule.php @@ -18,7 +18,6 @@ final class PropertyVarianceRule implements Rule public function __construct( private VarianceCheck $varianceCheck, - private bool $readOnlyByPhpDoc, ) { } @@ -42,7 +41,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - $variance = $node->isReadOnly() || ($this->readOnlyByPhpDoc && $node->isReadOnlyByPhpDoc()) + $variance = $node->isReadOnly() || $node->isReadOnlyByPhpDoc() ? TemplateTypeVariance::createCovariant() : TemplateTypeVariance::createInvariant(); diff --git a/tests/PHPStan/Rules/Generics/PropertyVarianceRuleTest.php b/tests/PHPStan/Rules/Generics/PropertyVarianceRuleTest.php index 97870f3572..0708ec3095 100644 --- a/tests/PHPStan/Rules/Generics/PropertyVarianceRuleTest.php +++ b/tests/PHPStan/Rules/Generics/PropertyVarianceRuleTest.php @@ -16,7 +16,6 @@ protected function getRule(): Rule { return new PropertyVarianceRule( self::getContainer()->getByType(VarianceCheck::class), - true, ); } From ba93e96748062dc931e1b4aa069980a04787544b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 17:13:55 +0200 Subject: [PATCH 206/508] [BE] Check `@phpstan-pure` --- changelog-2.0.md | 12 ++-- conf/bleedingEdge.neon | 2 - conf/config.level2.neon | 11 +--- conf/config.level4.neon | 62 ++++++------------- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - ...tructorStatementWithoutSideEffectsRule.php | 17 ++--- ...torStatementWithoutSideEffectsRuleTest.php | 2 +- 8 files changed, 34 insertions(+), 74 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 29e9d612b4..34f9d49201 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -19,6 +19,12 @@ Major new features 🚀 * Always report always true conditions, except for last elseif and match arm (https://github.com/phpstan/phpstan-src/commit/565fb0f6da9cdc58e8686598015561a848693972) * Remove "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed +* Checking truthiness of `@phpstan-pure` above functions and methods +* Check `new`/function call/method call/static method call on a separate line without any side effects even without `@phpstan-pure` PHPDoc tag on the declaration side + * https://github.com/phpstan/phpstan-src/commit/281a87d1ab61809076ecfa6dfc2cc86e3babe235 + * [#3020](https://github.com/phpstan/phpstan-src/pull/3020), thanks @staabm! + * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! + * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) * Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! @@ -78,12 +84,6 @@ Bleeding edge (TODO move to other sections) * Report unused results of `&&` and `||` (https://github.com/phpstan/phpstan-src/commit/cf2c8bbd9ebd2ebe300dbd310e136ad603d7def3) * Add option `reportAnyTypeWideningInVarTag` ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! * Fix checking generic `mixed` type based on config ([#2885](https://github.com/phpstan/phpstan-src/pull/2885)), thanks @schlndh! -* Checking truthiness of `@phpstan-pure` above functions and methods -* Check `new`/function call/method call/static method call on a separate line without any side effects even without `@phpstan-pure` PHPDoc tag on the declaration side - * https://github.com/phpstan/phpstan-src/commit/281a87d1ab61809076ecfa6dfc2cc86e3babe235 - * [#3020](https://github.com/phpstan/phpstan-src/pull/3020), thanks @staabm! - * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! - * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) * Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 89a624594a..8e06b22fda 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -3,5 +3,3 @@ parameters: bleedingEdge: true skipCheckGenericClasses!: [] stricterFunctionMap: true - - pure: true diff --git a/conf/config.level2.neon b/conf/config.level2.neon index b9fbf7d023..b3507a4a46 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -63,16 +63,14 @@ rules: - PHPStan\Rules\PhpDoc\RequireImplementsDefinitionClassRule - PHPStan\Rules\PhpDoc\RequireExtendsDefinitionClassRule - PHPStan\Rules\PhpDoc\RequireExtendsDefinitionTraitRule + - PHPStan\Rules\Pure\PureFunctionRule + - PHPStan\Rules\Pure\PureMethodRule conditionalTags: PHPStan\Rules\Methods\IllegalConstructorMethodCallRule: phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% PHPStan\Rules\Methods\IllegalConstructorStaticCallRule: phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% - PHPStan\Rules\Pure\PureFunctionRule: - phpstan.rules.rule: %featureToggles.pure% - PHPStan\Rules\Pure\PureMethodRule: - phpstan.rules.rule: %featureToggles.pure% services: - @@ -118,8 +116,3 @@ services: class: PHPStan\Rules\PhpDoc\InvalidPHPStanDocTagRule tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Pure\PureFunctionRule - - - - class: PHPStan\Rules\Pure\PureMethodRule diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 714843e781..5636417046 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -3,12 +3,17 @@ includes: rules: - PHPStan\Rules\Arrays\DeadForeachRule + - PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule + - PHPStan\Rules\DeadCode\CallToFunctionStatementWithoutImpurePointsRule + - PHPStan\Rules\DeadCode\CallToMethodStatementWithoutImpurePointsRule + - PHPStan\Rules\DeadCode\CallToStaticMethodStatementWithoutImpurePointsRule - PHPStan\Rules\DeadCode\NoopRule - PHPStan\Rules\DeadCode\UnreachableStatementRule - PHPStan\Rules\DeadCode\UnusedPrivateConstantRule - PHPStan\Rules\DeadCode\UnusedPrivateMethodRule - PHPStan\Rules\Exceptions\OverwrittenExitPointByFinallyRule - PHPStan\Rules\Functions\CallToFunctionStatementWithoutSideEffectsRule + - PHPStan\Rules\Methods\CallToConstructorStatementWithoutSideEffectsRule - PHPStan\Rules\Methods\CallToMethodStatementWithoutSideEffectsRule - PHPStan\Rules\Methods\CallToStaticMethodStatementWithoutSideEffectsRule - PHPStan\Rules\Methods\NullsafeMethodCallRule @@ -20,30 +25,6 @@ rules: - PHPStan\Rules\TooWideTypehints\TooWidePropertyTypeRule - PHPStan\Rules\Traits\NotAnalysedTraitRule -conditionalTags: - PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule: - phpstan.rules.rule: %featureToggles.pure% - PHPStan\Rules\DeadCode\PossiblyPureNewCollector: - phpstan.collector: %featureToggles.pure% - PHPStan\Rules\DeadCode\ConstructorWithoutImpurePointsCollector: - phpstan.collector: %featureToggles.pure% - PHPStan\Rules\DeadCode\CallToFunctionStatementWithoutImpurePointsRule: - phpstan.rules.rule: %featureToggles.pure% - PHPStan\Rules\DeadCode\PossiblyPureFuncCallCollector: - phpstan.collector: %featureToggles.pure% - PHPStan\Rules\DeadCode\FunctionWithoutImpurePointsCollector: - phpstan.collector: %featureToggles.pure% - PHPStan\Rules\DeadCode\CallToMethodStatementWithoutImpurePointsRule: - phpstan.rules.rule: %featureToggles.pure% - PHPStan\Rules\DeadCode\PossiblyPureMethodCallCollector: - phpstan.collector: %featureToggles.pure% - PHPStan\Rules\DeadCode\MethodWithoutImpurePointsCollector: - phpstan.collector: %featureToggles.pure% - PHPStan\Rules\DeadCode\CallToStaticMethodStatementWithoutImpurePointsRule: - phpstan.rules.rule: %featureToggles.pure% - PHPStan\Rules\DeadCode\PossiblyPureStaticCallCollector: - phpstan.collector: %featureToggles.pure% - parameters: checkAdvancedIsset: true @@ -84,38 +65,40 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\DeadCode\CallToConstructorStatementWithoutImpurePointsRule - - class: PHPStan\Rules\DeadCode\ConstructorWithoutImpurePointsCollector + tags: + - phpstan.collector - class: PHPStan\Rules\DeadCode\PossiblyPureNewCollector - - - - class: PHPStan\Rules\DeadCode\CallToFunctionStatementWithoutImpurePointsRule + tags: + - phpstan.collector - class: PHPStan\Rules\DeadCode\FunctionWithoutImpurePointsCollector + tags: + - phpstan.collector - class: PHPStan\Rules\DeadCode\PossiblyPureFuncCallCollector - - - - class: PHPStan\Rules\DeadCode\CallToMethodStatementWithoutImpurePointsRule + tags: + - phpstan.collector - class: PHPStan\Rules\DeadCode\MethodWithoutImpurePointsCollector + tags: + - phpstan.collector - class: PHPStan\Rules\DeadCode\PossiblyPureMethodCallCollector - - - - class: PHPStan\Rules\DeadCode\CallToStaticMethodStatementWithoutImpurePointsRule + tags: + - phpstan.collector - class: PHPStan\Rules\DeadCode\PossiblyPureStaticCallCollector + tags: + - phpstan.collector - class: PHPStan\Rules\DeadCode\UnusedPrivatePropertyRule @@ -245,13 +228,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Methods\CallToConstructorStatementWithoutSideEffectsRule - arguments: - reportNoConstructor: %featureToggles.pure% - tags: - - phpstan.rules.rule - - class: PHPStan\Rules\TooWideTypehints\TooWideMethodReturnTypehintRule arguments: diff --git a/conf/config.neon b/conf/config.neon index 5f0d9fd1ef..9deb65b892 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -25,7 +25,6 @@ parameters: skipCheckGenericClasses: [] illegalConstructorMethodCall: false stricterFunctionMap: false - pure: false fileExtensions: - php checkAdvancedIsset: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 51133df707..cbdba229a4 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -31,7 +31,6 @@ parametersSchema: skipCheckGenericClasses: listOf(string()), illegalConstructorMethodCall: bool(), stricterFunctionMap: bool() - pure: bool() ]) fileExtensions: listOf(string()) checkAdvancedIsset: bool() diff --git a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php index c50d21d878..f214edf960 100644 --- a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php @@ -19,7 +19,6 @@ final class CallToConstructorStatementWithoutSideEffectsRule implements Rule public function __construct( private ReflectionProvider $reflectionProvider, - private bool $reportNoConstructor, ) { } @@ -47,16 +46,12 @@ public function processNode(Node $node, Scope $scope): array $classReflection = $this->reflectionProvider->getClass($className); if (!$classReflection->hasConstructor()) { - if ($this->reportNoConstructor) { - return [ - RuleErrorBuilder::message(sprintf( - 'Call to new %s() on a separate line has no effect.', - $classReflection->getDisplayName(), - ))->identifier('new.resultUnused')->build(), - ]; - } - - return []; + return [ + RuleErrorBuilder::message(sprintf( + 'Call to new %s() on a separate line has no effect.', + $classReflection->getDisplayName(), + ))->identifier('new.resultUnused')->build(), + ]; } $constructor = $classReflection->getConstructor(); diff --git a/tests/PHPStan/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRuleTest.php b/tests/PHPStan/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRuleTest.php index 29e99526e2..c7c0e8f89a 100644 --- a/tests/PHPStan/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRuleTest.php @@ -13,7 +13,7 @@ class CallToConstructorStatementWithoutSideEffectsRuleTest extends RuleTestCase protected function getRule(): Rule { - return new CallToConstructorStatementWithoutSideEffectsRule($this->createReflectionProvider(), true); + return new CallToConstructorStatementWithoutSideEffectsRule($this->createReflectionProvider()); } public function testRule(): void From 2d623e494593277098db40a7a279e56f37bfdab4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 16:11:41 +0200 Subject: [PATCH 207/508] Issue bot - let all comments about `@phpstan-pure` through --- issue-bot/src/Console/EvaluateCommand.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index 0f8d05a8d8..f18941039b 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,10 +158,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { - if (count($toPost) > 20) { - $output->writeln('Too many comments to post, something is probably wrong.'); - return 1; - } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From a09cae7abbc25ec283f0279b1ab6484758f3ca15 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 17:23:00 +0200 Subject: [PATCH 208/508] Upgrading note --- UPGRADING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 2ac65c3d17..640d57af1f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -12,6 +12,8 @@ PHPStan now requires PHP 7.4 or newer to run. The best way do get ready for upgrade to PHPStan 2.0 is to update to the **latest PHPStan 1.12 release** and enable [**Bleeding Edge**](https://phpstan.org/blog/what-is-bleeding-edge). This will enable the new rules and behaviours that 2.0 turns on for all users. +Also make sure to install and enable [`phpstan/phpstan-deprecation-rules`](https://github.com/phpstan/phpstan-deprecation-rules). + Once you get to a green build with no deprecations showed on latest PHPStan 1.12.x with Bleeding Edge enabled, you can update all your related PHPStan dependencies to 2.0 in `composer.json`: ```json From 4393881c4a28f9d7118fdf2dfd6ab02533f71959 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 17:34:00 +0200 Subject: [PATCH 209/508] Update phpstan-strict-rules --- composer.lock | 8 ++++---- issue-bot/composer.lock | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index 997e53f86f..96460dab5a 100644 --- a/composer.lock +++ b/composer.lock @@ -4831,12 +4831,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "ad53bd9f911e7831e8e02cd3e54faf1d44910c33" + "reference": "63956f7896780551ed1ab29e75a6a645d8a0919c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/ad53bd9f911e7831e8e02cd3e54faf1d44910c33", - "reference": "ad53bd9f911e7831e8e02cd3e54faf1d44910c33", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/63956f7896780551ed1ab29e75a6a645d8a0919c", + "reference": "63956f7896780551ed1ab29e75a6a645d8a0919c", "shasum": "" }, "require": { @@ -4872,7 +4872,7 @@ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-09-24T12:25:28+00:00" + "time": "2024-09-24T15:32:27+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/issue-bot/composer.lock b/issue-bot/composer.lock index 7479e1b1b1..bea3c5e356 100644 --- a/issue-bot/composer.lock +++ b/issue-bot/composer.lock @@ -1466,12 +1466,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "ad53bd9f911e7831e8e02cd3e54faf1d44910c33" + "reference": "63956f7896780551ed1ab29e75a6a645d8a0919c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/ad53bd9f911e7831e8e02cd3e54faf1d44910c33", - "reference": "ad53bd9f911e7831e8e02cd3e54faf1d44910c33", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/63956f7896780551ed1ab29e75a6a645d8a0919c", + "reference": "63956f7896780551ed1ab29e75a6a645d8a0919c", "shasum": "" }, "require": { @@ -1507,7 +1507,7 @@ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-09-24T12:25:28+00:00" + "time": "2024-09-24T15:32:27+00:00" }, { "name": "psr/cache", From 8db7e92521bc944f75a9e850708066c2d425e729 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 17:33:29 +0200 Subject: [PATCH 210/508] Moved illegalConstructorMethodCall rules from phpstan to phpstan-strict-rules --- conf/config.level2.neon | 10 -- conf/config.neon | 1 - conf/parametersSchema.neon | 1 - .../IllegalConstructorMethodCallRule.php | 34 ------ .../IllegalConstructorStaticCallRule.php | 92 ---------------- .../IllegalConstructorMethodCallRuleTest.php | 37 ------- .../IllegalConstructorStaticCallRuleTest.php | 59 ---------- tests/PHPStan/Rules/Methods/data/bug-9577.php | 40 ------- .../illegal-constructor-call-rule-test.php | 103 ------------------ 9 files changed, 377 deletions(-) delete mode 100644 src/Rules/Methods/IllegalConstructorMethodCallRule.php delete mode 100644 src/Rules/Methods/IllegalConstructorStaticCallRule.php delete mode 100644 tests/PHPStan/Rules/Methods/IllegalConstructorMethodCallRuleTest.php delete mode 100644 tests/PHPStan/Rules/Methods/IllegalConstructorStaticCallRuleTest.php delete mode 100644 tests/PHPStan/Rules/Methods/data/bug-9577.php delete mode 100644 tests/PHPStan/Rules/Methods/data/illegal-constructor-call-rule-test.php diff --git a/conf/config.level2.neon b/conf/config.level2.neon index b3507a4a46..2d547cb94e 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -66,12 +66,6 @@ rules: - PHPStan\Rules\Pure\PureFunctionRule - PHPStan\Rules\Pure\PureMethodRule -conditionalTags: - PHPStan\Rules\Methods\IllegalConstructorMethodCallRule: - phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% - PHPStan\Rules\Methods\IllegalConstructorStaticCallRule: - phpstan.rules.rule: %featureToggles.illegalConstructorMethodCall% - services: - class: PHPStan\Rules\Classes\MixinRule @@ -97,10 +91,6 @@ services: tags: - phpstan.rules.rule - - - class: PHPStan\Rules\Methods\IllegalConstructorMethodCallRule - - - class: PHPStan\Rules\Methods\IllegalConstructorStaticCallRule - class: PHPStan\Rules\PhpDoc\InvalidPhpDocTagValueRule tags: diff --git a/conf/config.neon b/conf/config.neon index 9deb65b892..46424fd414 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -23,7 +23,6 @@ parameters: featureToggles: bleedingEdge: false skipCheckGenericClasses: [] - illegalConstructorMethodCall: false stricterFunctionMap: false fileExtensions: - php diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index cbdba229a4..7307fc8571 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -29,7 +29,6 @@ parametersSchema: featureToggles: structure([ bleedingEdge: bool(), skipCheckGenericClasses: listOf(string()), - illegalConstructorMethodCall: bool(), stricterFunctionMap: bool() ]) fileExtensions: listOf(string()) diff --git a/src/Rules/Methods/IllegalConstructorMethodCallRule.php b/src/Rules/Methods/IllegalConstructorMethodCallRule.php deleted file mode 100644 index 1dba6ed6d2..0000000000 --- a/src/Rules/Methods/IllegalConstructorMethodCallRule.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ -final class IllegalConstructorMethodCallRule implements Rule -{ - - public function getNodeType(): string - { - return Node\Expr\MethodCall::class; - } - - public function processNode(Node $node, Scope $scope): array - { - if (!$node->name instanceof Node\Identifier || $node->name->toLowerString() !== '__construct') { - return []; - } - - return [ - RuleErrorBuilder::message('Call to __construct() on an existing object is not allowed.') - ->identifier('constructor.call') - ->build(), - ]; - } - -} diff --git a/src/Rules/Methods/IllegalConstructorStaticCallRule.php b/src/Rules/Methods/IllegalConstructorStaticCallRule.php deleted file mode 100644 index fa747d6a2b..0000000000 --- a/src/Rules/Methods/IllegalConstructorStaticCallRule.php +++ /dev/null @@ -1,92 +0,0 @@ - - */ -final class IllegalConstructorStaticCallRule implements Rule -{ - - public function getNodeType(): string - { - return Node\Expr\StaticCall::class; - } - - public function processNode(Node $node, Scope $scope): array - { - if (!$node->name instanceof Node\Identifier || $node->name->toLowerString() !== '__construct') { - return []; - } - - if ($this->isCollectCallingConstructor($node, $scope)) { - return []; - } - - return [ - RuleErrorBuilder::message('Static call to __construct() is only allowed on a parent class in the constructor.') - ->identifier('constructor.call') - ->build(), - ]; - } - - private function isCollectCallingConstructor(Node\Expr\StaticCall $node, Scope $scope): bool - { - // __construct should be called from inside constructor - if ($scope->getFunction() === null) { - return false; - } - - if ($scope->getFunction()->getName() !== '__construct') { - if (!$this->isInRenamedTraitConstructor($scope)) { - return false; - } - } - - if (!$scope->isInClass()) { - return false; - } - - if (!$node->class instanceof Node\Name) { - return false; - } - - $parentClasses = array_map(static fn (string $name) => strtolower($name), $scope->getClassReflection()->getParentClassesNames()); - - return in_array(strtolower($scope->resolveName($node->class)), $parentClasses, true); - } - - private function isInRenamedTraitConstructor(Scope $scope): bool - { - if (!$scope->isInClass()) { - return false; - } - - if (!$scope->isInTrait()) { - return false; - } - - if ($scope->getFunction() === null) { - return false; - } - - $traitAliases = $scope->getClassReflection()->getNativeReflection()->getTraitAliases(); - $functionName = $scope->getFunction()->getName(); - if (!array_key_exists($functionName, $traitAliases)) { - return false; - } - - return $traitAliases[$functionName] === sprintf('%s::%s', $scope->getTraitReflection()->getName(), '__construct'); - } - -} diff --git a/tests/PHPStan/Rules/Methods/IllegalConstructorMethodCallRuleTest.php b/tests/PHPStan/Rules/Methods/IllegalConstructorMethodCallRuleTest.php deleted file mode 100644 index 8b0f957e85..0000000000 --- a/tests/PHPStan/Rules/Methods/IllegalConstructorMethodCallRuleTest.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -class IllegalConstructorMethodCallRuleTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new IllegalConstructorMethodCallRule(); - } - - public function testMethods(): void - { - $this->analyse([__DIR__ . '/data/illegal-constructor-call-rule-test.php'], [ - [ - 'Call to __construct() on an existing object is not allowed.', - 13, - ], - [ - 'Call to __construct() on an existing object is not allowed.', - 18, - ], - [ - 'Call to __construct() on an existing object is not allowed.', - 60, - ], - ]); - } - -} diff --git a/tests/PHPStan/Rules/Methods/IllegalConstructorStaticCallRuleTest.php b/tests/PHPStan/Rules/Methods/IllegalConstructorStaticCallRuleTest.php deleted file mode 100644 index 065a5785bf..0000000000 --- a/tests/PHPStan/Rules/Methods/IllegalConstructorStaticCallRuleTest.php +++ /dev/null @@ -1,59 +0,0 @@ - - */ -class IllegalConstructorStaticCallRuleTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new IllegalConstructorStaticCallRule(); - } - - public function testMethods(): void - { - $this->analyse([__DIR__ . '/data/illegal-constructor-call-rule-test.php'], [ - [ - 'Static call to __construct() is only allowed on a parent class in the constructor.', - 31, - ], - [ - 'Static call to __construct() is only allowed on a parent class in the constructor.', - 43, - ], - [ - 'Static call to __construct() is only allowed on a parent class in the constructor.', - 44, - ], - [ - 'Static call to __construct() is only allowed on a parent class in the constructor.', - 49, - ], - [ - 'Static call to __construct() is only allowed on a parent class in the constructor.', - 50, - ], - [ - 'Static call to __construct() is only allowed on a parent class in the constructor.', - 100, - ], - ]); - } - - public function testBug9577(): void - { - if (PHP_VERSION_ID < 80100) { - $this->markTestSkipped('Test requires PHP 8.1.'); - } - - $this->analyse([__DIR__ . '/data/bug-9577.php'], []); - } - -} diff --git a/tests/PHPStan/Rules/Methods/data/bug-9577.php b/tests/PHPStan/Rules/Methods/data/bug-9577.php deleted file mode 100644 index 2214d45b33..0000000000 --- a/tests/PHPStan/Rules/Methods/data/bug-9577.php +++ /dev/null @@ -1,40 +0,0 @@ -= 8.1 - -namespace Bug9577IllegalConstructorStaticCall; - -trait StringableMessageTrait -{ - public function __construct( - private readonly \Stringable $StringableMessage, - int $code = 0, - ?\Throwable $previous = null, - ) { - parent::__construct((string) $StringableMessage, $code, $previous); - } - - public function getStringableMessage(): \Stringable - { - return $this->StringableMessage; - } -} - -class SpecializedException extends \RuntimeException -{ - use StringableMessageTrait { - StringableMessageTrait::__construct as __traitConstruct; - } - - public function __construct( - private readonly object $aService, - \Stringable $StringableMessage, - int $code = 0, - ?\Throwable $previous = null, - ) { - $this->__traitConstruct($StringableMessage, $code, $previous); - } - - public function getService(): object - { - return $this->aService; - } -} diff --git a/tests/PHPStan/Rules/Methods/data/illegal-constructor-call-rule-test.php b/tests/PHPStan/Rules/Methods/data/illegal-constructor-call-rule-test.php deleted file mode 100644 index f5198a5089..0000000000 --- a/tests/PHPStan/Rules/Methods/data/illegal-constructor-call-rule-test.php +++ /dev/null @@ -1,103 +0,0 @@ - 1) { - return; - } - $this->__construct($datetime, $timezone); - } - - public function mutate(string $datetime = "now", ?\DateTimeZone $timezone = null): void - { - $this->__construct($datetime, $timezone); - } -} - -class ExtendedDateTimeWithParentCall extends \DateTimeImmutable -{ - public function __construct(string $datetime = "now", ?\DateTimeZone $timezone = null) - { - parent::__construct($datetime, $timezone); - } - - public function mutate(string $datetime = "now", ?\DateTimeZone $timezone = null): void - { - parent::__construct($datetime, $timezone); - } -} - -class ExtendedDateTimeWithSelfCall extends \DateTimeImmutable -{ - public function __construct(string $datetime = "now", ?\DateTimeZone $timezone = null) - { - // Avoid infinite loop - if (count(debug_backtrace()) > 1) { - return; - } - self::__construct($datetime, $timezone); - ExtendedDateTimeWithSelfCall::__construct($datetime, $timezone); - } - - public function mutate(string $datetime = "now", ?\DateTimeZone $timezone = null): void - { - self::__construct($datetime, $timezone); - ExtendedDateTimeWithSelfCall::__construct($datetime, $timezone); - } -} - -class Foo -{ - - public function doFoo() - { - $extendedDateTime = new ExtendedDateTimeWithMethodCall('2022/04/12'); - $extendedDateTime->__construct('2022/04/13'); - } - -} - -abstract class Presenter -{ - - public function __construct() - { - - } - -} - -abstract class BasePresenter extends Presenter -{ - - public function __construct() - { - Presenter::__construct(); - } - -} - -class CatPresenter extends BasePresenter -{ - - public function __construct() - { - Presenter::__construct(); - } - -} - -class DogPresenter extends BasePresenter -{ - - public function __construct() - { - CatPresenter::__construct(); - } - -} From 694bc09b94914887de6ad29f2be5269edffc788d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 17:44:05 +0200 Subject: [PATCH 211/508] Revert "Issue bot - let all comments about `@phpstan-pure` through" This reverts commit 2d623e494593277098db40a7a279e56f37bfdab4. --- issue-bot/src/Console/EvaluateCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index f18941039b..0f8d05a8d8 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,6 +158,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { + if (count($toPost) > 20) { + $output->writeln('Too many comments to post, something is probably wrong.'); + return 1; + } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From 51de9032c6e98bff2d6eb0e5b7295720ec0276b9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 17:58:40 +0200 Subject: [PATCH 212/508] Cover AccessoryArrayListType constructor with BC promise --- src/Type/Accessory/AccessoryArrayListType.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index a413c9bae1..64131446d9 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -39,6 +39,7 @@ class AccessoryArrayListType implements CompoundType, AccessoryType use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; + /** @api */ public function __construct() { } From f046ebcbc643bef7ede64b0134478b63229d405c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 18:10:49 +0200 Subject: [PATCH 213/508] Update PHPStan extensions --- composer.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index 96460dab5a..c17a33a1e1 100644 --- a/composer.lock +++ b/composer.lock @@ -4718,12 +4718,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-nette.git", - "reference": "93a4f025a4d11ffcf9523617cb3c620c5373fe56" + "reference": "c903386c4e3d1d25a57f66458476bfb6347f1c66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-nette/zipball/93a4f025a4d11ffcf9523617cb3c620c5373fe56", - "reference": "93a4f025a4d11ffcf9523617cb3c620c5373fe56", + "url": "https://api.github.com/repos/phpstan/phpstan-nette/zipball/c903386c4e3d1d25a57f66458476bfb6347f1c66", + "reference": "c903386c4e3d1d25a57f66458476bfb6347f1c66", "shasum": "" }, "require": { @@ -4771,7 +4771,7 @@ "issues": "https://github.com/phpstan/phpstan-nette/issues", "source": "https://github.com/phpstan/phpstan-nette/tree/2.0.x" }, - "time": "2024-09-04T21:08:28+00:00" + "time": "2024-09-24T16:09:34+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -4779,12 +4779,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "4d861e0843cd1f8eccacfac14e24a8629280a887" + "reference": "09e2d3b470bdda02824c626735153dfd962e3f29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/4d861e0843cd1f8eccacfac14e24a8629280a887", - "reference": "4d861e0843cd1f8eccacfac14e24a8629280a887", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/09e2d3b470bdda02824c626735153dfd962e3f29", + "reference": "09e2d3b470bdda02824c626735153dfd962e3f29", "shasum": "" }, "require": { @@ -4823,7 +4823,7 @@ "issues": "https://github.com/phpstan/phpstan-phpunit/issues", "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.x" }, - "time": "2024-09-13T12:47:01+00:00" + "time": "2024-09-24T16:07:03+00:00" }, { "name": "phpstan/phpstan-strict-rules", From 74b8e9c963398ae5ced9c26ac5702bd7f84ca92a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 18:13:34 +0200 Subject: [PATCH 214/508] Update changelog --- changelog-2.0.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 34f9d49201..7469ed558c 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -74,8 +74,6 @@ Major new features 🚀 Bleeding edge (TODO move to other sections) ===================== -* Rules for checking direct calls to `__construct()` (level 2) ([#1208](https://github.com/phpstan/phpstan-src/pull/1208)), #7022, thanks @muno92! -* Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) @@ -128,6 +126,7 @@ Improvements 🔧 * Report unnecessary nullsafe property fetch inside `??` / `isset` / `empty` with different message ([#1253](https://github.com/phpstan/phpstan-src/pull/1253)), thanks @rajyan! * Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) +* Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) Bugfixes 🐛 ===================== From ae6403f117d7318721fe6a89eb8cec24994e9ed9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 20:18:45 +0200 Subject: [PATCH 215/508] Fix build --- tests/PHPStan/Levels/data/stubs-functions-4.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/PHPStan/Levels/data/stubs-functions-4.json diff --git a/tests/PHPStan/Levels/data/stubs-functions-4.json b/tests/PHPStan/Levels/data/stubs-functions-4.json new file mode 100644 index 0000000000..dd57bdf13f --- /dev/null +++ b/tests/PHPStan/Levels/data/stubs-functions-4.json @@ -0,0 +1,12 @@ +[ + { + "message": "Call to function StubsIntegrationTest\\foo() on a separate line has no effect.", + "line": 11, + "ignorable": true + }, + { + "message": "Call to function StubsIntegrationTest\\foo() on a separate line has no effect.", + "line": 13, + "ignorable": true + } +] \ No newline at end of file From 20baec2efeffff1c1c65c60f8c62315ba3712967 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 20:19:06 +0200 Subject: [PATCH 216/508] Missing types should always be reported on level 6, not sooner --- conf/config.neon | 1 + src/Rules/Generics/GenericAncestorsCheck.php | 39 ++++++++++--------- .../PhpDoc/InvalidPhpDocVarTagTypeRule.php | 22 +++++------ .../PHPStan/Levels/LevelsIntegrationTest.php | 1 + tests/PHPStan/Levels/data/missingTypes-6.json | 7 ++++ tests/PHPStan/Levels/data/missingTypes.php | 16 ++++++++ .../Rules/Generics/ClassAncestorsRuleTest.php | 1 + .../Rules/Generics/EnumAncestorsRuleTest.php | 1 + .../Generics/InterfaceAncestorsRuleTest.php | 1 + .../Rules/Generics/UsedTraitsRuleTest.php | 1 + 10 files changed, 61 insertions(+), 29 deletions(-) create mode 100644 tests/PHPStan/Levels/data/missingTypes-6.json create mode 100644 tests/PHPStan/Levels/data/missingTypes.php diff --git a/conf/config.neon b/conf/config.neon index 46424fd414..05aab74b88 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -917,6 +917,7 @@ services: class: PHPStan\Rules\Generics\GenericAncestorsCheck arguments: skipCheckGenericClasses: %featureToggles.skipCheckGenericClasses% + checkMissingTypehints: %checkMissingTypehints% - class: PHPStan\Rules\Generics\GenericObjectTypeCheck diff --git a/src/Rules/Generics/GenericAncestorsCheck.php b/src/Rules/Generics/GenericAncestorsCheck.php index 8dc3830cad..1cedcda8be 100644 --- a/src/Rules/Generics/GenericAncestorsCheck.php +++ b/src/Rules/Generics/GenericAncestorsCheck.php @@ -34,6 +34,7 @@ public function __construct( private VarianceCheck $varianceCheck, private UnresolvableTypeHelper $unresolvableTypeHelper, private array $skipCheckGenericClasses, + private bool $checkMissingTypehints, ) { } @@ -151,26 +152,28 @@ public function check( } } - foreach (array_keys($unusedNames) as $unusedName) { - if (!$this->reflectionProvider->hasClass($unusedName)) { - continue; - } + if ($this->checkMissingTypehints) { + foreach (array_keys($unusedNames) as $unusedName) { + if (!$this->reflectionProvider->hasClass($unusedName)) { + continue; + } - $unusedNameClassReflection = $this->reflectionProvider->getClass($unusedName); - if (in_array($unusedNameClassReflection->getName(), $this->skipCheckGenericClasses, true)) { - continue; - } - if (!$unusedNameClassReflection->isGeneric()) { - continue; - } + $unusedNameClassReflection = $this->reflectionProvider->getClass($unusedName); + if (in_array($unusedNameClassReflection->getName(), $this->skipCheckGenericClasses, true)) { + continue; + } + if (!$unusedNameClassReflection->isGeneric()) { + continue; + } - $messages[] = RuleErrorBuilder::message(sprintf( - $genericClassInNonGenericObjectType, - $unusedName, - implode(', ', array_keys($unusedNameClassReflection->getTemplateTypeMap()->getTypes())), - )) - ->identifier('missingType.generics') - ->build(); + $messages[] = RuleErrorBuilder::message(sprintf( + $genericClassInNonGenericObjectType, + $unusedName, + implode(', ', array_keys($unusedNameClassReflection->getTemplateTypeMap()->getTypes())), + )) + ->identifier('missingType.generics') + ->build(); + } } return $messages; diff --git a/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php b/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php index 81b4296100..204da1481a 100644 --- a/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php +++ b/src/Rules/PhpDoc/InvalidPhpDocVarTagTypeRule.php @@ -97,6 +97,17 @@ public function processNode(Node $node, Scope $scope): array ->identifier('missingType.iterableValue') ->build(); } + + foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($varTagType) as [$innerName, $genericTypeNames]) { + $errors[] = RuleErrorBuilder::message(sprintf( + '%s contains generic %s but does not specify its types: %s', + $identifier, + $innerName, + implode(', ', $genericTypeNames), + )) + ->identifier('missingType.generics') + ->build(); + } } $escapedIdentifier = SprintfHelper::escapeFormatString($identifier); @@ -110,17 +121,6 @@ public function processNode(Node $node, Scope $scope): array sprintf('Call-site variance of %%s in generic type %%s in %s is redundant, template type %%s of %%s %%s has the same variance.', $escapedIdentifier), )); - foreach ($this->missingTypehintCheck->getNonGenericObjectTypesWithGenericClass($varTagType) as [$innerName, $genericTypeNames]) { - $errors[] = RuleErrorBuilder::message(sprintf( - '%s contains generic %s but does not specify its types: %s', - $identifier, - $innerName, - implode(', ', $genericTypeNames), - )) - ->identifier('missingType.generics') - ->build(); - } - $referencedClasses = $varTagType->getReferencedClasses(); foreach ($referencedClasses as $referencedClass) { if ($this->reflectionProvider->hasClass($referencedClass)) { diff --git a/tests/PHPStan/Levels/LevelsIntegrationTest.php b/tests/PHPStan/Levels/LevelsIntegrationTest.php index 45f5d7634e..ee86187c8c 100644 --- a/tests/PHPStan/Levels/LevelsIntegrationTest.php +++ b/tests/PHPStan/Levels/LevelsIntegrationTest.php @@ -41,6 +41,7 @@ public function dataTopics(): array ['coalesce'], ['arrayDestructuring'], ['listType'], + ['missingTypes'], ]; if (PHP_VERSION_ID >= 80300) { $topics[] = ['constantAccesses83']; diff --git a/tests/PHPStan/Levels/data/missingTypes-6.json b/tests/PHPStan/Levels/data/missingTypes-6.json new file mode 100644 index 0000000000..66b17f1111 --- /dev/null +++ b/tests/PHPStan/Levels/data/missingTypes-6.json @@ -0,0 +1,7 @@ +[ + { + "message": "Class MissingTypesLevels\\Foo extends generic class MissingTypesLevels\\Generic but does not specify its types: T", + "line": 13, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/missingTypes.php b/tests/PHPStan/Levels/data/missingTypes.php new file mode 100644 index 0000000000..ed3d9bd3bf --- /dev/null +++ b/tests/PHPStan/Levels/data/missingTypes.php @@ -0,0 +1,16 @@ + Date: Tue, 24 Sep 2024 20:33:40 +0200 Subject: [PATCH 217/508] Remove deprecated EmptyArrayItemRule --- conf/config.level0.neon | 1 - src/Rules/Arrays/EmptyArrayItemRule.php | 42 ------------------- .../Rules/Arrays/EmptyArrayItemRuleTest.php | 29 ------------- .../Rules/Arrays/data/empty-array-item.php | 7 ---- 4 files changed, 79 deletions(-) delete mode 100644 src/Rules/Arrays/EmptyArrayItemRule.php delete mode 100644 tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php delete mode 100644 tests/PHPStan/Rules/Arrays/data/empty-array-item.php diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 6dd5e4c7ca..d8b1b775cc 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -22,7 +22,6 @@ rules: - PHPStan\Rules\Api\RuntimeReflectionInstantiationRule - PHPStan\Rules\Api\RuntimeReflectionFunctionRule - PHPStan\Rules\Arrays\DuplicateKeysInLiteralArraysRule - - PHPStan\Rules\Arrays\EmptyArrayItemRule - PHPStan\Rules\Arrays\OffsetAccessWithoutDimForReadingRule - PHPStan\Rules\Cast\UnsetCastRule - PHPStan\Rules\Classes\AllowedSubTypesRule diff --git a/src/Rules/Arrays/EmptyArrayItemRule.php b/src/Rules/Arrays/EmptyArrayItemRule.php deleted file mode 100644 index dfe2a48d4b..0000000000 --- a/src/Rules/Arrays/EmptyArrayItemRule.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ -final class EmptyArrayItemRule implements Rule -{ - - public function getNodeType(): string - { - return LiteralArrayNode::class; - } - - public function processNode(Node $node, Scope $scope): array - { - foreach ($node->getItemNodes() as $itemNode) { - $item = $itemNode->getArrayItem(); - if ($item !== null) { - continue; - } - - return [ - RuleErrorBuilder::message('Literal array contains empty item.') - ->nonIgnorable() - ->identifier('array.emptyItem') - ->build(), - ]; - } - - return []; - } - -} diff --git a/tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php b/tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php deleted file mode 100644 index df14e33493..0000000000 --- a/tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -class EmptyArrayItemRuleTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new EmptyArrayItemRule(); - } - - public function testRule(): void - { - $this->analyse([__DIR__ . '/data/empty-array-item.php'], [ - [ - 'Cannot use empty array elements in arrays on line 5', - 5, - ], - ]); - } - -} diff --git a/tests/PHPStan/Rules/Arrays/data/empty-array-item.php b/tests/PHPStan/Rules/Arrays/data/empty-array-item.php deleted file mode 100644 index 4a08a799a8..0000000000 --- a/tests/PHPStan/Rules/Arrays/data/empty-array-item.php +++ /dev/null @@ -1,7 +0,0 @@ - Date: Tue, 24 Sep 2024 20:38:10 +0200 Subject: [PATCH 218/508] Update changelog --- changelog-2.0.md | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 7469ed558c..d9fe72d6c9 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -9,6 +9,7 @@ Major new features 🚀 * Lists are arrays with sequential integer keys starting at 0 * **Validate inline PHPDoc `@var` tag** type against native type (level 2) (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones + * Use config option `reportAnyTypeWideningInVarTag: true` for stricter behaviour ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! * **Lower memory consumption** thanks to breaking up of reference cycles * [Learn more »](https://phpstan.org/blog/preprocessing-ast-for-custom-rules) * In testing the memory consumption was reduced by 50–70 %. @@ -70,20 +71,8 @@ Major new features 🚀 * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) * Check that PHPStan class in class constant fetch is covered by backward compatibility promise (level 0) (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) * Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) - -Bleeding edge (TODO move to other sections) -===================== - * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 -* Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) -* InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) -* Report unused results of `and` and `or` (https://github.com/phpstan/phpstan-src/commit/1d8fff637d70a9e9ed3f11dee5d61b9f796cbf1a) -* Report unused result of ternary (https://github.com/phpstan/phpstan-src/commit/9664f7a9d2223c07e750f0dfc949c3accfa6b65e) -* Report unused results of `&&` and `||` (https://github.com/phpstan/phpstan-src/commit/cf2c8bbd9ebd2ebe300dbd310e136ad603d7def3) -* Add option `reportAnyTypeWideningInVarTag` ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! -* Fix checking generic `mixed` type based on config ([#2885](https://github.com/phpstan/phpstan-src/pull/2885)), thanks @schlndh! -* CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) -* Check `@param-immediately-invoked-callable` and `@param-later-invoked-callable` (https://github.com/phpstan/phpstan-src/commit/580a6add422f4e34191df9e7a77ba1655e914bda), #10932 + Improvements 🔧 ===================== @@ -127,11 +116,17 @@ Improvements 🔧 * Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! * TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) * Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) +* Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) +* InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) +* CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) + Bugfixes 🐛 ===================== * Fix invariance composition ([#2054](https://github.com/phpstan/phpstan-src/pull/2054)), thanks @jiripudil! +* Fix checking generic `mixed` type based on config ([#2885](https://github.com/phpstan/phpstan-src/pull/2885)), thanks @schlndh! + Function signature fixes 🤖 ======================= From 673a090f145784c08ca6136b46f78c0872d9ddf6 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 20:39:25 +0200 Subject: [PATCH 219/508] Fix typo --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index 640d57af1f..a6b527bc54 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -118,7 +118,7 @@ Now, `throw $e;` is represented as a `Stmt\Expression` that contains an `Expr\Th See [UPGRADING](https://github.com/phpstan/phpdoc-parser/blob/2.0.x/UPGRADING.md) guide for phpstan/phpdoc-parser. ### Returning plain strings as errors no longer supported, use RuleErrorBuilder - * + Identifiers are also required in custom rules. Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) From 6cefca5ca5f88bc02f82845de9b700ad52ec37f5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 24 Sep 2024 20:51:05 +0200 Subject: [PATCH 220/508] Fix build --- phpstan-baseline.neon | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 287fdbae03..dbc99984e0 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1749,22 +1749,6 @@ parameters: count: 1 path: tests/PHPStan/Rules/Arrays/AppendedArrayKeyTypeRuleTest.php - - - message: """ - #^Instantiation of deprecated class PHPStan\\\\Rules\\\\Arrays\\\\EmptyArrayItemRule\\: - Since PHP\\-Parser 5\\.0 this is a parse error\\.$# - """ - count: 1 - path: tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php - - - - message: """ - #^Return type of method PHPStan\\\\Rules\\\\Arrays\\\\EmptyArrayItemRuleTest\\:\\:getRule\\(\\) has typehint with deprecated class PHPStan\\\\Rules\\\\Arrays\\\\EmptyArrayItemRule\\: - Since PHP\\-Parser 5\\.0 this is a parse error\\.$# - """ - count: 1 - path: tests/PHPStan/Rules/Arrays/EmptyArrayItemRuleTest.php - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" count: 1 From a4773235aa4a6b0ed4b9c703539ff4f8af3583d6 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 25 Sep 2024 10:44:19 +0200 Subject: [PATCH 221/508] Fix error message on level < 7 --- phpstan-baseline.neon | 5 ---- src/Rules/RuleLevelHelper.php | 27 ++++++++++++------- .../Properties/AccessPropertiesRuleTest.php | 5 ++++ .../Properties/data/access-properties.php | 17 ++++++++++++ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index dbc99984e0..9131efff54 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -601,11 +601,6 @@ parameters: count: 1 path: src/Rules/RuleLevelHelper.php - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" - count: 1 - path: src/Rules/RuleLevelHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 1 diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php index 9869c16c62..1fe931aca5 100644 --- a/src/Rules/RuleLevelHelper.php +++ b/src/Rules/RuleLevelHelper.php @@ -14,7 +14,6 @@ use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; use PHPStan\Type\NullType; -use PHPStan\Type\ObjectWithoutClassType; use PHPStan\Type\StrictMixedType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -241,7 +240,7 @@ private function findTypeToCheckImplementation( return new FoundTypeResult(new ErrorType(), [], $errors, null); } - if (!$this->checkUnionTypes && $type instanceof ObjectWithoutClassType) { + if (!$this->checkUnionTypes && $type->isObject()->yes() && count($type->getObjectClassNames()) === 0) { return new FoundTypeResult(new ErrorType(), [], [], null); } @@ -286,17 +285,25 @@ private function findTypeToCheckImplementation( if ($type instanceof IntersectionType) { $newTypes = []; + $changed = false; foreach ($type->getTypes() as $innerType) { - $newTypes[] = $this->findTypeToCheckImplementation( - $scope, - $var, - $innerType, - $unknownClassErrorPattern, - $unionTypeCriteriaCallback, - )->getType(); + if ($innerType instanceof TemplateMixedType) { + $changed = true; + $newTypes[] = $this->findTypeToCheckImplementation( + $scope, + $var, + $innerType->toStrictMixedType(), + $unknownClassErrorPattern, + $unionTypeCriteriaCallback, + )->getType(); + continue; + } + $newTypes[] = $innerType; } - return new FoundTypeResult(TypeCombinator::intersect(...$newTypes), $directClassNames, [], null); + if ($changed) { + return new FoundTypeResult(TypeCombinator::intersect(...$newTypes), $directClassNames, [], null); + } } $tip = null; diff --git a/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php index 7e5d97a44b..164aefaafe 100644 --- a/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php @@ -169,6 +169,11 @@ public function testAccessProperties(): void 'Cannot access property $selfOrNull on TestAccessProperties\RevertNonNullabilityForIsset|null.', 407, ], + [ + 'Access to an undefined property object::$baz.', + 438, + $tipText, + ], ], ); } diff --git a/tests/PHPStan/Rules/Properties/data/access-properties.php b/tests/PHPStan/Rules/Properties/data/access-properties.php index f83bc6ef85..f755c42eac 100644 --- a/tests/PHPStan/Rules/Properties/data/access-properties.php +++ b/tests/PHPStan/Rules/Properties/data/access-properties.php @@ -423,3 +423,20 @@ function mustNotReport(?\stdClass $nullable): bool } } + +class OnObjectAfterIsset +{ + + /** + * @param mixed $m + */ + public function doFoo($m): void + { + if (isset($m->foo) && isset($m->bar)) { + echo $m->foo; + echo $m->bar; + echo $m->baz; + } + } + +} From c3cad7d4814ed4fe3bd35e521988ee4ab6b782a7 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 25 Sep 2024 12:55:31 +0200 Subject: [PATCH 222/508] Regression test Closes https://github.com/phpstan/phpstan/issues/5297 --- .../Levels/data/propertyAccesses-7.json | 5 ++++ .../Levels/data/propertyAccesses-9.json | 7 +++++ .../PHPStan/Levels/data/propertyAccesses.php | 28 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 tests/PHPStan/Levels/data/propertyAccesses-9.json diff --git a/tests/PHPStan/Levels/data/propertyAccesses-7.json b/tests/PHPStan/Levels/data/propertyAccesses-7.json index aa6291fdfe..b6df87becb 100644 --- a/tests/PHPStan/Levels/data/propertyAccesses-7.json +++ b/tests/PHPStan/Levels/data/propertyAccesses-7.json @@ -38,5 +38,10 @@ "message": "Access to an undefined property Levels\\PropertyAccesses\\Bar|Levels\\PropertyAccesses\\Foo::$bar.", "line": 170, "ignorable": true + }, + { + "message": "Access to an undefined property object::$baz.", + "line": 200, + "ignorable": true } ] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/propertyAccesses-9.json b/tests/PHPStan/Levels/data/propertyAccesses-9.json new file mode 100644 index 0000000000..c7c6ae5a96 --- /dev/null +++ b/tests/PHPStan/Levels/data/propertyAccesses-9.json @@ -0,0 +1,7 @@ +[ + { + "message": "Cannot access property $foo on mixed.", + "line": 197, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/propertyAccesses.php b/tests/PHPStan/Levels/data/propertyAccesses.php index 72c9d4bcda..1c006ab6dc 100644 --- a/tests/PHPStan/Levels/data/propertyAccesses.php +++ b/tests/PHPStan/Levels/data/propertyAccesses.php @@ -174,3 +174,31 @@ public function doBaz() } } + +class ObjectWithIsset +{ + + public function doFoo(): void + { + $test = new \stdClass; + + if (isset($test->foo)) { + echo $test->foo; + echo $test->bar; + echo $test->baz; + } + } + + /** + * @param mixed $test + */ + public function doBar($test): void + { + if (isset($test->foo) && isset($test->bar)) { + echo $test->foo; + echo $test->bar; + echo $test->baz; + } + } + +} From ac91552a25ce83ef6de63b9f59296d4c5ee568a9 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Wed, 25 Sep 2024 17:50:35 +0200 Subject: [PATCH 223/508] Add PhpVersion parameter to various Type methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Mirtes --- UPGRADING.md | 2 ++ src/Analyser/MutatingScope.php | 8 ++--- src/Analyser/TypeSpecifier.php | 10 +++--- src/Analyser/TypeSpecifierFactory.php | 2 ++ .../InitializerExprTypeResolver.php | 8 ++--- .../Functions/RandomIntParametersRule.php | 9 +++-- src/Type/CompoundType.php | 5 +-- src/Type/Constant/ConstantBooleanType.php | 8 ++--- src/Type/Constant/ConstantStringType.php | 9 ++--- src/Type/Enum/EnumCaseObjectType.php | 5 +-- src/Type/IntegerRangeType.php | 34 +++++++++--------- src/Type/IntersectionType.php | 32 ++++++++--------- src/Type/NullType.php | 16 ++++----- .../ConstantNumericComparisonTypeTrait.php | 9 ++--- src/Type/Traits/ConstantScalarTypeTrait.php | 8 ++--- src/Type/Traits/LateResolvableTypeTrait.php | 36 +++++++++---------- .../UndecidedComparisonCompoundTypeTrait.php | 5 +-- .../Traits/UndecidedComparisonTypeTrait.php | 13 +++---- src/Type/Type.php | 12 +++---- src/Type/UnionType.php | 32 ++++++++--------- .../Rules/Api/ApiClassImplementsRuleTest.php | 12 +++---- .../data/class-implements-out-of-phpstan.php | 13 +++---- .../Functions/RandomIntParametersRuleTest.php | 3 +- 23 files changed, 155 insertions(+), 136 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index a6b527bc54..14b029acc9 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -178,3 +178,5 @@ As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtensio * Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required * Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required * ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) +* `Type::getSmallerType()`, `Type::getSmallerOrEqualType()`, `Type::getGreaterType()`, `Type::getGreaterOrEqualType()`, `Type::isSmallerThan()`, `Type::isSmallerThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. +* `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 0e2ead8dde..2c9ef02f75 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -747,19 +747,19 @@ private function resolveType(string $exprString, Expr $node): Type } if ($node instanceof Expr\BinaryOp\Smaller) { - return $this->getType($node->left)->isSmallerThan($this->getType($node->right))->toBooleanType(); + return $this->getType($node->left)->isSmallerThan($this->getType($node->right), $this->phpVersion)->toBooleanType(); } if ($node instanceof Expr\BinaryOp\SmallerOrEqual) { - return $this->getType($node->left)->isSmallerThanOrEqual($this->getType($node->right))->toBooleanType(); + return $this->getType($node->left)->isSmallerThanOrEqual($this->getType($node->right), $this->phpVersion)->toBooleanType(); } if ($node instanceof Expr\BinaryOp\Greater) { - return $this->getType($node->right)->isSmallerThan($this->getType($node->left))->toBooleanType(); + return $this->getType($node->right)->isSmallerThan($this->getType($node->left), $this->phpVersion)->toBooleanType(); } if ($node instanceof Expr\BinaryOp\GreaterOrEqual) { - return $this->getType($node->right)->isSmallerThanOrEqual($this->getType($node->left))->toBooleanType(); + return $this->getType($node->right)->isSmallerThanOrEqual($this->getType($node->left), $this->phpVersion)->toBooleanType(); } if ($node instanceof Expr\BinaryOp\Equal) { diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 8c40e83826..9484fc52a7 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -22,6 +22,7 @@ use PHPStan\Node\Expr\AlwaysRememberedExpr; use PHPStan\Node\IssetExpr; use PHPStan\Node\Printer\ExprPrinter; +use PHPStan\Php\PhpVersion; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ParametersAcceptorSelector; @@ -100,6 +101,7 @@ final class TypeSpecifier public function __construct( private ExprPrinter $exprPrinter, private ReflectionProvider $reflectionProvider, + private PhpVersion $phpVersion, private array $functionTypeSpecifyingExtensions, private array $methodTypeSpecifyingExtensions, private array $staticMethodTypeSpecifyingExtensions, @@ -406,7 +408,7 @@ public function specifyTypesInCondition( $result = $result->unionWith( $this->create( $expr->left, - $orEqual ? $rightType->getSmallerOrEqualType() : $rightType->getSmallerType(), + $orEqual ? $rightType->getSmallerOrEqualType($this->phpVersion) : $rightType->getSmallerType($this->phpVersion), TypeSpecifierContext::createTruthy(), $scope, )->setRootExpr($expr), @@ -416,7 +418,7 @@ public function specifyTypesInCondition( $result = $result->unionWith( $this->create( $expr->right, - $orEqual ? $leftType->getGreaterOrEqualType() : $leftType->getGreaterType(), + $orEqual ? $leftType->getGreaterOrEqualType($this->phpVersion) : $leftType->getGreaterType($this->phpVersion), TypeSpecifierContext::createTruthy(), $scope, )->setRootExpr($expr), @@ -427,7 +429,7 @@ public function specifyTypesInCondition( $result = $result->unionWith( $this->create( $expr->left, - $orEqual ? $rightType->getGreaterType() : $rightType->getGreaterOrEqualType(), + $orEqual ? $rightType->getGreaterType($this->phpVersion) : $rightType->getGreaterOrEqualType($this->phpVersion), TypeSpecifierContext::createTruthy(), $scope, )->setRootExpr($expr), @@ -437,7 +439,7 @@ public function specifyTypesInCondition( $result = $result->unionWith( $this->create( $expr->right, - $orEqual ? $leftType->getSmallerType() : $leftType->getSmallerOrEqualType(), + $orEqual ? $leftType->getSmallerType($this->phpVersion) : $leftType->getSmallerOrEqualType($this->phpVersion), TypeSpecifierContext::createTruthy(), $scope, )->setRootExpr($expr), diff --git a/src/Analyser/TypeSpecifierFactory.php b/src/Analyser/TypeSpecifierFactory.php index 60219c3b6d..83315b6e0c 100644 --- a/src/Analyser/TypeSpecifierFactory.php +++ b/src/Analyser/TypeSpecifierFactory.php @@ -5,6 +5,7 @@ use PHPStan\Broker\BrokerFactory; use PHPStan\DependencyInjection\Container; use PHPStan\Node\Printer\ExprPrinter; +use PHPStan\Php\PhpVersion; use PHPStan\Reflection\ReflectionProvider; use function array_merge; @@ -24,6 +25,7 @@ public function create(): TypeSpecifier $typeSpecifier = new TypeSpecifier( $this->container->getByType(ExprPrinter::class), $this->container->getByType(ReflectionProvider::class), + $this->container->getByType(PhpVersion::class), $this->container->getServicesByTag(self::FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG), $this->container->getServicesByTag(self::METHOD_TYPE_SPECIFYING_EXTENSION_TAG), $this->container->getServicesByTag(self::STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG), diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index b4beb587bf..fdb3344d69 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -316,19 +316,19 @@ public function getType(Expr $expr, InitializerExprContext $context): Type } if ($expr instanceof Expr\BinaryOp\Smaller) { - return $this->getType($expr->left, $context)->isSmallerThan($this->getType($expr->right, $context))->toBooleanType(); + return $this->getType($expr->left, $context)->isSmallerThan($this->getType($expr->right, $context), $this->phpVersion)->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\SmallerOrEqual) { - return $this->getType($expr->left, $context)->isSmallerThanOrEqual($this->getType($expr->right, $context))->toBooleanType(); + return $this->getType($expr->left, $context)->isSmallerThanOrEqual($this->getType($expr->right, $context), $this->phpVersion)->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\Greater) { - return $this->getType($expr->right, $context)->isSmallerThan($this->getType($expr->left, $context))->toBooleanType(); + return $this->getType($expr->right, $context)->isSmallerThan($this->getType($expr->left, $context), $this->phpVersion)->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\GreaterOrEqual) { - return $this->getType($expr->right, $context)->isSmallerThanOrEqual($this->getType($expr->left, $context))->toBooleanType(); + return $this->getType($expr->right, $context)->isSmallerThanOrEqual($this->getType($expr->left, $context), $this->phpVersion)->toBooleanType(); } if ($expr instanceof Expr\BinaryOp\LogicalXor) { diff --git a/src/Rules/Functions/RandomIntParametersRule.php b/src/Rules/Functions/RandomIntParametersRule.php index ecca6e7d09..e35c21a3ed 100644 --- a/src/Rules/Functions/RandomIntParametersRule.php +++ b/src/Rules/Functions/RandomIntParametersRule.php @@ -5,6 +5,7 @@ use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; +use PHPStan\Php\PhpVersion; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -21,7 +22,11 @@ final class RandomIntParametersRule implements Rule { - public function __construct(private ReflectionProvider $reflectionProvider, private bool $reportMaybes) + public function __construct( + private ReflectionProvider $reflectionProvider, + private PhpVersion $phpVersion, + private bool $reportMaybes, + ) { } @@ -55,7 +60,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - $isSmaller = $maxType->isSmallerThan($minType); + $isSmaller = $maxType->isSmallerThan($minType, $this->phpVersion); if ($isSmaller->yes() || $isSmaller->maybe() && $this->reportMaybes) { $message = 'Parameter #1 $min (%s) of function random_int expects lower number than parameter #2 $max (%s).'; diff --git a/src/Type/CompoundType.php b/src/Type/CompoundType.php index ea9b2f4660..775a4eb50f 100644 --- a/src/Type/CompoundType.php +++ b/src/Type/CompoundType.php @@ -2,6 +2,7 @@ namespace PHPStan\Type; +use PHPStan\Php\PhpVersion; use PHPStan\TrinaryLogic; /** @api */ @@ -14,8 +15,8 @@ public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLog public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult; - public function isGreaterThan(Type $otherType): TrinaryLogic; + public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic; - public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic; + public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic; } diff --git a/src/Type/Constant/ConstantBooleanType.php b/src/Type/Constant/ConstantBooleanType.php index db5328d0d2..cbebe5b48b 100644 --- a/src/Type/Constant/ConstantBooleanType.php +++ b/src/Type/Constant/ConstantBooleanType.php @@ -40,7 +40,7 @@ public function describe(VerbosityLevel $level): string return $this->value ? 'true' : 'false'; } - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { if ($this->value) { return StaticTypeFactory::falsey(); @@ -48,7 +48,7 @@ public function getSmallerType(): Type return new NeverType(); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { if ($this->value) { return new MixedType(); @@ -56,7 +56,7 @@ public function getSmallerOrEqualType(): Type return StaticTypeFactory::falsey(); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { if ($this->value) { return new NeverType(); @@ -64,7 +64,7 @@ public function getGreaterType(): Type return StaticTypeFactory::truthy(); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { if ($this->value) { return StaticTypeFactory::truthy(); diff --git a/src/Type/Constant/ConstantStringType.php b/src/Type/Constant/ConstantStringType.php index 39b259ee37..09ddd2741e 100644 --- a/src/Type/Constant/ConstantStringType.php +++ b/src/Type/Constant/ConstantStringType.php @@ -6,6 +6,7 @@ use Nette\Utils\Strings; use PhpParser\Node\Name; use PHPStan\Analyser\OutOfClassScope; +use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode; use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; @@ -461,7 +462,7 @@ public function generalize(GeneralizePrecision $precision): Type return new StringType(); } - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { $subtractedTypes = [ new ConstantBooleanType(true), @@ -480,7 +481,7 @@ public function getSmallerType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { $subtractedTypes = [ IntegerRangeType::createAllGreaterThan((float) $this->value), @@ -493,7 +494,7 @@ public function getSmallerOrEqualType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { $subtractedTypes = [ new ConstantBooleanType(false), @@ -507,7 +508,7 @@ public function getGreaterType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { $subtractedTypes = [ IntegerRangeType::createAllSmallerThan((float) $this->value), diff --git a/src/Type/Enum/EnumCaseObjectType.php b/src/Type/Enum/EnumCaseObjectType.php index 42d8f4afc2..e0bc8c3340 100644 --- a/src/Type/Enum/EnumCaseObjectType.php +++ b/src/Type/Enum/EnumCaseObjectType.php @@ -2,6 +2,7 @@ namespace PHPStan\Type\Enum; +use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode; use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; @@ -179,12 +180,12 @@ public function generalize(GeneralizePrecision $precision): Type return new parent($this->getClassName(), null, $this->getClassReflection()); } - public function isSmallerThan(Type $otherType): TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return TrinaryLogic::createNo(); } - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/IntegerRangeType.php b/src/Type/IntegerRangeType.php index 534be0ebbb..d5680a59ac 100644 --- a/src/Type/IntegerRangeType.php +++ b/src/Type/IntegerRangeType.php @@ -308,75 +308,75 @@ public function generalize(GeneralizePrecision $precision): Type return new IntegerType(); } - public function isSmallerThan(Type $otherType): TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createYes(); } else { - $minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThan($otherType); + $minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThan($otherType, $phpVersion); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createNo(); } else { - $maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThan($otherType); + $maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThan($otherType, $phpVersion); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createYes(); } else { - $minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThanOrEqual($otherType); + $minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThanOrEqual($otherType, $phpVersion); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createNo(); } else { - $maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThanOrEqual($otherType); + $maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThanOrEqual($otherType, $phpVersion); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } - public function isGreaterThan(Type $otherType): TrinaryLogic + public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createNo(); } else { - $minIsSmaller = $otherType->isSmallerThan((new ConstantIntegerType($this->min))); + $minIsSmaller = $otherType->isSmallerThan((new ConstantIntegerType($this->min)), $phpVersion); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createYes(); } else { - $maxIsSmaller = $otherType->isSmallerThan((new ConstantIntegerType($this->max))); + $maxIsSmaller = $otherType->isSmallerThan((new ConstantIntegerType($this->max)), $phpVersion); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } - public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic + public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($this->min === null) { $minIsSmaller = TrinaryLogic::createNo(); } else { - $minIsSmaller = $otherType->isSmallerThanOrEqual((new ConstantIntegerType($this->min))); + $minIsSmaller = $otherType->isSmallerThanOrEqual((new ConstantIntegerType($this->min)), $phpVersion); } if ($this->max === null) { $maxIsSmaller = TrinaryLogic::createYes(); } else { - $maxIsSmaller = $otherType->isSmallerThanOrEqual((new ConstantIntegerType($this->max))); + $maxIsSmaller = $otherType->isSmallerThanOrEqual((new ConstantIntegerType($this->max)), $phpVersion); } return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller); } - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { $subtractedTypes = [ new ConstantBooleanType(true), @@ -389,7 +389,7 @@ public function getSmallerType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { $subtractedTypes = []; @@ -400,7 +400,7 @@ public function getSmallerOrEqualType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { $subtractedTypes = [ new NullType(), @@ -418,7 +418,7 @@ public function getGreaterType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { $subtractedTypes = []; @@ -692,7 +692,7 @@ public function toPhpDocNode(): TypeNode public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { - if ($this->isSmallerThan($type)->yes() || $this->isGreaterThan($type)->yes()) { + if ($this->isSmallerThan($type, $phpVersion)->yes() || $this->isGreaterThan($type, $phpVersion)->yes()) { return new ConstantBooleanType(false); } diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index 8bf38bddda..13704c9a5d 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -802,14 +802,14 @@ public function isCloneable(): TrinaryLogic return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isCloneable()); } - public function isSmallerThan(Type $otherType): TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isSmallerThan($otherType)); + return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isSmallerThan($otherType, $phpVersion)); } - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isSmallerThanOrEqual($otherType)); + return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isSmallerThanOrEqual($otherType, $phpVersion)); } public function isNull(): TrinaryLogic @@ -876,34 +876,34 @@ public function isInteger(): TrinaryLogic return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isInteger()); } - public function isGreaterThan(Type $otherType): TrinaryLogic + public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->intersectResults(static fn (Type $type): TrinaryLogic => $otherType->isSmallerThan($type)); + return $this->intersectResults(static fn (Type $type): TrinaryLogic => $otherType->isSmallerThan($type, $phpVersion)); } - public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic + public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->intersectResults(static fn (Type $type): TrinaryLogic => $otherType->isSmallerThanOrEqual($type)); + return $this->intersectResults(static fn (Type $type): TrinaryLogic => $otherType->isSmallerThanOrEqual($type, $phpVersion)); } - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { - return $this->intersectTypes(static fn (Type $type): Type => $type->getSmallerType()); + return $this->intersectTypes(static fn (Type $type): Type => $type->getSmallerType($phpVersion)); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { - return $this->intersectTypes(static fn (Type $type): Type => $type->getSmallerOrEqualType()); + return $this->intersectTypes(static fn (Type $type): Type => $type->getSmallerOrEqualType($phpVersion)); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { - return $this->intersectTypes(static fn (Type $type): Type => $type->getGreaterType()); + return $this->intersectTypes(static fn (Type $type): Type => $type->getGreaterType($phpVersion)); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { - return $this->intersectTypes(static fn (Type $type): Type => $type->getGreaterOrEqualType()); + return $this->intersectTypes(static fn (Type $type): Type => $type->getGreaterOrEqualType($phpVersion)); } public function toBoolean(): BooleanType diff --git a/src/Type/NullType.php b/src/Type/NullType.php index a59f86e868..01870ed2da 100644 --- a/src/Type/NullType.php +++ b/src/Type/NullType.php @@ -108,27 +108,27 @@ public function equals(Type $type): bool return $type instanceof self; } - public function isSmallerThan(Type $otherType): TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($otherType instanceof ConstantScalarType) { return TrinaryLogic::createFromBoolean(null < $otherType->getValue()); } if ($otherType instanceof CompoundType) { - return $otherType->isGreaterThan($this); + return $otherType->isGreaterThan($this, $phpVersion); } return TrinaryLogic::createMaybe(); } - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($otherType instanceof ConstantScalarType) { return TrinaryLogic::createFromBoolean(null <= $otherType->getValue()); } if ($otherType instanceof CompoundType) { - return $otherType->isGreaterThanOrEqual($this); + return $otherType->isGreaterThanOrEqual($this, $phpVersion); } return TrinaryLogic::createMaybe(); @@ -338,12 +338,12 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType return new BooleanType(); } - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { return new NeverType(); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { // All falsey types except '0' return new UnionType([ @@ -356,7 +356,7 @@ public function getSmallerOrEqualType(): Type ]); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { // All truthy types, but also '0' return new MixedType(false, new UnionType([ @@ -369,7 +369,7 @@ public function getGreaterType(): Type ])); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { return new MixedType(); } diff --git a/src/Type/Traits/ConstantNumericComparisonTypeTrait.php b/src/Type/Traits/ConstantNumericComparisonTypeTrait.php index 2b3b4a45c5..c6efe96950 100644 --- a/src/Type/Traits/ConstantNumericComparisonTypeTrait.php +++ b/src/Type/Traits/ConstantNumericComparisonTypeTrait.php @@ -2,6 +2,7 @@ namespace PHPStan\Type\Traits; +use PHPStan\Php\PhpVersion; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantFloatType; use PHPStan\Type\IntegerRangeType; @@ -13,7 +14,7 @@ trait ConstantNumericComparisonTypeTrait { - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { $subtractedTypes = [ new ConstantBooleanType(true), @@ -29,7 +30,7 @@ public function getSmallerType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { $subtractedTypes = [ IntegerRangeType::createAllGreaterThan($this->value), @@ -43,7 +44,7 @@ public function getSmallerOrEqualType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { $subtractedTypes = [ new NullType(), @@ -59,7 +60,7 @@ public function getGreaterType(): Type return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes)); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { $subtractedTypes = [ IntegerRangeType::createAllSmallerThan($this->value), diff --git a/src/Type/Traits/ConstantScalarTypeTrait.php b/src/Type/Traits/ConstantScalarTypeTrait.php index 527d10b68a..7452cd3c83 100644 --- a/src/Type/Traits/ConstantScalarTypeTrait.php +++ b/src/Type/Traits/ConstantScalarTypeTrait.php @@ -78,27 +78,27 @@ public function equals(Type $type): bool return $type instanceof self && $this->value === $type->value; } - public function isSmallerThan(Type $otherType): TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($otherType instanceof ConstantScalarType) { return TrinaryLogic::createFromBoolean($this->value < $otherType->getValue()); } if ($otherType instanceof CompoundType) { - return $otherType->isGreaterThan($this); + return $otherType->isGreaterThan($this, $phpVersion); } return TrinaryLogic::createMaybe(); } - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { if ($otherType instanceof ConstantScalarType) { return TrinaryLogic::createFromBoolean($this->value <= $otherType->getValue()); } if ($otherType instanceof CompoundType) { - return $otherType->isGreaterThanOrEqual($this); + return $otherType->isGreaterThanOrEqual($this, $phpVersion); } return TrinaryLogic::createMaybe(); diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index bff88f730e..ff3d015f36 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -367,14 +367,14 @@ public function toArrayKey(): Type return $this->resolve()->toArrayKey(); } - public function isSmallerThan(Type $otherType): TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->resolve()->isSmallerThan($otherType); + return $this->resolve()->isSmallerThan($otherType, $phpVersion); } - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->resolve()->isSmallerThanOrEqual($otherType); + return $this->resolve()->isSmallerThanOrEqual($otherType, $phpVersion); } public function isNull(): TrinaryLogic @@ -482,24 +482,24 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType return new BooleanType(); } - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { - return $this->resolve()->getSmallerType(); + return $this->resolve()->getSmallerType($phpVersion); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { - return $this->resolve()->getSmallerOrEqualType(); + return $this->resolve()->getSmallerOrEqualType($phpVersion); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { - return $this->resolve()->getGreaterType(); + return $this->resolve()->getGreaterType($phpVersion); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { - return $this->resolve()->getGreaterOrEqualType(); + return $this->resolve()->getGreaterOrEqualType($phpVersion); } public function inferTemplateTypes(Type $receivedType): TemplateTypeMap @@ -539,26 +539,26 @@ public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): return $acceptingType->acceptsWithReason($result, $strictTypes); } - public function isGreaterThan(Type $otherType): TrinaryLogic + public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { $result = $this->resolve(); if ($result instanceof CompoundType) { - return $result->isGreaterThan($otherType); + return $result->isGreaterThan($otherType, $phpVersion); } - return $otherType->isSmallerThan($result); + return $otherType->isSmallerThan($result, $phpVersion); } - public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic + public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { $result = $this->resolve(); if ($result instanceof CompoundType) { - return $result->isGreaterThanOrEqual($otherType); + return $result->isGreaterThanOrEqual($otherType, $phpVersion); } - return $otherType->isSmallerThanOrEqual($result); + return $otherType->isSmallerThanOrEqual($result, $phpVersion); } public function exponentiate(Type $exponent): Type diff --git a/src/Type/Traits/UndecidedComparisonCompoundTypeTrait.php b/src/Type/Traits/UndecidedComparisonCompoundTypeTrait.php index e40b72fad4..6adf571d54 100644 --- a/src/Type/Traits/UndecidedComparisonCompoundTypeTrait.php +++ b/src/Type/Traits/UndecidedComparisonCompoundTypeTrait.php @@ -2,6 +2,7 @@ namespace PHPStan\Type\Traits; +use PHPStan\Php\PhpVersion; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; @@ -10,12 +11,12 @@ trait UndecidedComparisonCompoundTypeTrait use UndecidedComparisonTypeTrait; - public function isGreaterThan(Type $otherType): TrinaryLogic + public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return TrinaryLogic::createMaybe(); } - public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic + public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return TrinaryLogic::createMaybe(); } diff --git a/src/Type/Traits/UndecidedComparisonTypeTrait.php b/src/Type/Traits/UndecidedComparisonTypeTrait.php index e5c6d2c891..6761274cf1 100644 --- a/src/Type/Traits/UndecidedComparisonTypeTrait.php +++ b/src/Type/Traits/UndecidedComparisonTypeTrait.php @@ -2,6 +2,7 @@ namespace PHPStan\Type\Traits; +use PHPStan\Php\PhpVersion; use PHPStan\TrinaryLogic; use PHPStan\Type\MixedType; use PHPStan\Type\Type; @@ -9,32 +10,32 @@ trait UndecidedComparisonTypeTrait { - public function isSmallerThan(Type $otherType): TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return TrinaryLogic::createMaybe(); } - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { return TrinaryLogic::createMaybe(); } - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { return new MixedType(); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { return new MixedType(); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { return new MixedType(); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { return new MixedType(); } diff --git a/src/Type/Type.php b/src/Type/Type.php index 727e2f8a31..47446d0dad 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -215,9 +215,9 @@ public function toArray(): Type; public function toArrayKey(): Type; - public function isSmallerThan(Type $otherType): TrinaryLogic; + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic; - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic; + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic; /** * Is Type of a known constant value? Includes literal strings, integers, floats, true, false, null, and array shapes. @@ -269,13 +269,13 @@ public function isScalar(): TrinaryLogic; public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType; - public function getSmallerType(): Type; + public function getSmallerType(PhpVersion $phpVersion): Type; - public function getSmallerOrEqualType(): Type; + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type; - public function getGreaterType(): Type; + public function getGreaterType(PhpVersion $phpVersion): Type; - public function getGreaterOrEqualType(): Type; + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type; /** * Returns actual template type for a given object. diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index af4ede1b40..839bad3817 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -783,14 +783,14 @@ public function isCloneable(): TrinaryLogic return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->isCloneable()); } - public function isSmallerThan(Type $otherType): TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $type->isSmallerThan($otherType)); + return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $type->isSmallerThan($otherType, $phpVersion)); } - public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $type->isSmallerThanOrEqual($otherType)); + return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $type->isSmallerThanOrEqual($otherType, $phpVersion)); } public function isNull(): TrinaryLogic @@ -843,34 +843,34 @@ public function isInteger(): TrinaryLogic return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $type->isInteger()); } - public function getSmallerType(): Type + public function getSmallerType(PhpVersion $phpVersion): Type { - return $this->unionTypes(static fn (Type $type): Type => $type->getSmallerType()); + return $this->unionTypes(static fn (Type $type): Type => $type->getSmallerType($phpVersion)); } - public function getSmallerOrEqualType(): Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): Type { - return $this->unionTypes(static fn (Type $type): Type => $type->getSmallerOrEqualType()); + return $this->unionTypes(static fn (Type $type): Type => $type->getSmallerOrEqualType($phpVersion)); } - public function getGreaterType(): Type + public function getGreaterType(PhpVersion $phpVersion): Type { - return $this->unionTypes(static fn (Type $type): Type => $type->getGreaterType()); + return $this->unionTypes(static fn (Type $type): Type => $type->getGreaterType($phpVersion)); } - public function getGreaterOrEqualType(): Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): Type { - return $this->unionTypes(static fn (Type $type): Type => $type->getGreaterOrEqualType()); + return $this->unionTypes(static fn (Type $type): Type => $type->getGreaterOrEqualType($phpVersion)); } - public function isGreaterThan(Type $otherType): TrinaryLogic + public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $otherType->isSmallerThan($type)); + return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $otherType->isSmallerThan($type, $phpVersion)); } - public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic + public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic { - return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $otherType->isSmallerThanOrEqual($type)); + return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $otherType->isSmallerThanOrEqual($type, $phpVersion)); } public function toBoolean(): BooleanType diff --git a/tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php b/tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php index a6a68a9b5e..f2b13d25c2 100644 --- a/tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php +++ b/tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php @@ -32,32 +32,32 @@ public function testRuleOutOfPhpStan(): void $this->analyse([__DIR__ . '/data/class-implements-out-of-phpstan.php'], [ [ 'Implementing PHPStan\DependencyInjection\Type\DynamicThrowTypeExtensionProvider is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 19, + 20, $tip, ], [ 'Implementing PHPStan\Type\Type is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 53, + 54, $tip, ], [ 'Implementing PHPStan\Reflection\ReflectionProvider is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 338, + 339, $tip, ], [ 'Implementing PHPStan\Analyser\Scope is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 343, + 344, $tip, ], [ 'Implementing PHPStan\Reflection\FunctionReflection is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 348, + 349, $tip, ], [ 'Implementing PHPStan\Reflection\ExtendedMethodReflection is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 352, + 353, $tip, ], ]); diff --git a/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php b/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php index c7b42d7e6e..c5211fd650 100644 --- a/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php +++ b/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php @@ -5,6 +5,7 @@ use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; use PHPStan\DependencyInjection\Type\DynamicThrowTypeExtensionProvider; +use PHPStan\Php\PhpVersion; use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\FunctionReflection; @@ -247,12 +248,12 @@ public function toArrayKey(): \PHPStan\Type\Type // TODO: Implement toArrayKey() method. } - public function isSmallerThan(Type $otherType): \PHPStan\TrinaryLogic + public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): \PHPStan\TrinaryLogic { // TODO: Implement isSmallerThan() method. } - public function isSmallerThanOrEqual(Type $otherType): \PHPStan\TrinaryLogic + public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): \PHPStan\TrinaryLogic { // TODO: Implement isSmallerThanOrEqual() method. } @@ -277,22 +278,22 @@ public function isLiteralString(): \PHPStan\TrinaryLogic // TODO: Implement isLiteralString() method. } - public function getSmallerType(): \PHPStan\Type\Type + public function getSmallerType(PhpVersion $phpVersion): \PHPStan\Type\Type { // TODO: Implement getSmallerType() method. } - public function getSmallerOrEqualType(): \PHPStan\Type\Type + public function getSmallerOrEqualType(PhpVersion $phpVersion): \PHPStan\Type\Type { // TODO: Implement getSmallerOrEqualType() method. } - public function getGreaterType(): \PHPStan\Type\Type + public function getGreaterType(PhpVersion $phpVersion): \PHPStan\Type\Type { // TODO: Implement getGreaterType() method. } - public function getGreaterOrEqualType(): \PHPStan\Type\Type + public function getGreaterOrEqualType(PhpVersion $phpVersion): \PHPStan\Type\Type { // TODO: Implement getGreaterOrEqualType() method. } diff --git a/tests/PHPStan/Rules/Functions/RandomIntParametersRuleTest.php b/tests/PHPStan/Rules/Functions/RandomIntParametersRuleTest.php index 4b9ab4e23c..40c0526e25 100644 --- a/tests/PHPStan/Rules/Functions/RandomIntParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/RandomIntParametersRuleTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Rules\Functions; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; use const PHP_INT_SIZE; @@ -14,7 +15,7 @@ class RandomIntParametersRuleTest extends RuleTestCase protected function getRule(): Rule { - return new RandomIntParametersRule($this->createReflectionProvider(), true); + return new RandomIntParametersRule($this->createReflectionProvider(), new PhpVersion(80000), true); } public function testFile(): void From 1b9c1e6666caccf2bc15437fdd0c67e1b9f3fa17 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 13:50:07 +0200 Subject: [PATCH 224/508] Note about removing `ParametersAcceptorSelector::selectSingle()` --- UPGRADING.md | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 14b029acc9..d28c6aed08 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -123,13 +123,13 @@ Identifiers are also required in custom rules. Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) -Before: +**Before**: ```php return ['My error']; ``` -After: +**After**: ```php return [ @@ -143,6 +143,47 @@ return [ Learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) +### Removed deprecated `ParametersAcceptorSelector::selectSingle()` + +Use [`ParametersAcceptorSelector::selectFromArgs()`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ParametersAcceptorSelector.html#_selectFromArgs) instead. It should be used in most places where `selectSingle()` was previously used, like dynamic return type extensions. + +**Before**: + +```php +$defaultReturnType = ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); +``` + +**After**: + +```php +$defaultReturnType = ParametersAcceptorSelector::selectFromArgs( + $scope, + $functionCall->getArgs(), + $functionReflection->getVariants() +)->getReturnType(); +``` + +If you're analysing function or method body itself and you're using one of the following methods, ask for `getParameters()` and `getReturnType()` directly on the reflection object: + +* [InClassMethodNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InClassMethodNode.html) +* [InFunctionNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InFunctionNode.html) +* [FunctionReturnStatementsNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.FunctionReturnStatementsNode.html) +* [MethodReturnStatementsNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.MethodReturnStatementsNode.html) +* [Scope::getFunction()](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.Scope.html#_getFunction) + +**Before**: + +```php +$function = $node->getFunctionReflection(); +$returnType = ParametersAcceptorSelector::selectSingle($function->getVariants())->getReturnType(); +``` + +**After**: + +``` +$returnType = $node->getFunctionReflection()->getReturnType(); +``` + ### Changed `TypeSpecifier::create()` and `SpecifiedTypes` constructor parameters [`PHPStan\Analyser\TypeSpecifier::create()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.TypeSpecifier.html#_create) now accepts (all parameters are required): From 4cbe3f62a39df393c3618a49bc0a1347ebc0f648 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 13:58:48 +0200 Subject: [PATCH 225/508] Fix build --- src/Analyser/DirectInternalScopeFactory.php | 4 ++-- src/Analyser/InternalScopeFactory.php | 4 ++-- src/Analyser/LazyInternalScopeFactory.php | 3 ++- .../Comparison/StrictComparisonOfDifferentTypesRuleTest.php | 1 - 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Analyser/DirectInternalScopeFactory.php b/src/Analyser/DirectInternalScopeFactory.php index a696c24777..6b66961f4f 100644 --- a/src/Analyser/DirectInternalScopeFactory.php +++ b/src/Analyser/DirectInternalScopeFactory.php @@ -7,12 +7,12 @@ use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Parser\Parser; use PHPStan\Php\PhpVersion; -use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\ParametersAcceptor; +use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Properties\PropertyReflectionFinder; @@ -46,7 +46,7 @@ public function __construct( public function create( ScopeContext $context, bool $declareStrictTypes = false, - FunctionReflection|ExtendedMethodReflection|null $function = null, + PhpFunctionFromParserNodeReflection|null $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], diff --git a/src/Analyser/InternalScopeFactory.php b/src/Analyser/InternalScopeFactory.php index 83c943f917..6d8608ec18 100644 --- a/src/Analyser/InternalScopeFactory.php +++ b/src/Analyser/InternalScopeFactory.php @@ -2,11 +2,11 @@ namespace PHPStan\Analyser; -use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\ParametersAcceptor; +use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; interface InternalScopeFactory { @@ -23,7 +23,7 @@ interface InternalScopeFactory public function create( ScopeContext $context, bool $declareStrictTypes = false, - FunctionReflection|ExtendedMethodReflection|null $function = null, + PhpFunctionFromParserNodeReflection|null $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], diff --git a/src/Analyser/LazyInternalScopeFactory.php b/src/Analyser/LazyInternalScopeFactory.php index 073bc6baef..c2b2069ac5 100644 --- a/src/Analyser/LazyInternalScopeFactory.php +++ b/src/Analyser/LazyInternalScopeFactory.php @@ -13,6 +13,7 @@ use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\ParametersAcceptor; +use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Properties\PropertyReflectionFinder; @@ -36,7 +37,7 @@ public function __construct( public function create( ScopeContext $context, bool $declareStrictTypes = false, - FunctionReflection|ExtendedMethodReflection|null $function = null, + PhpFunctionFromParserNodeReflection|null $function = null, ?string $namespace = null, array $expressionTypes = [], array $nativeExpressionTypes = [], diff --git a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php index 7012690dd9..9572fa7580 100644 --- a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php @@ -893,7 +893,6 @@ public function testLowercaseString(): void ]; } - $this->checkAlwaysTrueStrictComparison = true; $this->analyse([__DIR__ . '/data/lowercase-string.php'], $errors); } From e880a75c0038d42ce7000ba14014c14e75b14706 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 14:15:12 +0200 Subject: [PATCH 226/508] Update phpstan-deprecation-rules --- composer.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.lock b/composer.lock index f131aa7efb..b72f00167d 100644 --- a/composer.lock +++ b/composer.lock @@ -4670,12 +4670,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "89572d5481ec1e121ac1567f689fe49a25d6cef6" + "reference": "392bbe7be54b00fbe945fede6a8ef543216f3b9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/89572d5481ec1e121ac1567f689fe49a25d6cef6", - "reference": "89572d5481ec1e121ac1567f689fe49a25d6cef6", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/392bbe7be54b00fbe945fede6a8ef543216f3b9c", + "reference": "392bbe7be54b00fbe945fede6a8ef543216f3b9c", "shasum": "" }, "require": { @@ -4710,7 +4710,7 @@ "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.x" }, - "time": "2024-09-11T15:52:56+00:00" + "time": "2024-09-26T12:14:06+00:00" }, { "name": "phpstan/phpstan-nette", From 7f6913705b5b5091c59f59702b2fa1609ee60af7 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 13:54:30 +0200 Subject: [PATCH 227/508] Remove `ParametersAcceptorSelector::selectSingle()` --- src/Reflection/ParametersAcceptorSelector.php | 24 --------- .../data/TestDynamicReturnTypeExtensions.php | 54 +++++++++++++++---- tests/PHPStan/Reflection/UnionTypesTest.php | 4 +- .../Api/data/static-call-out-of-phpstan.php | 2 +- 4 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index 619ee2aa81..f9f66c7531 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -60,30 +60,6 @@ class ParametersAcceptorSelector { - /** - * @deprecated See https://github.com/phpstan/phpstan-src/blob/2.0.x/UPGRADING.md#removed-deprecated-parametersacceptorselectorselectsingle - * - * @template T of ParametersAcceptor - * @param T[] $parametersAcceptors - * @return T - */ - public static function selectSingle( - array $parametersAcceptors, - ): ParametersAcceptor - { - $count = count($parametersAcceptors); - if ($count === 0) { - throw new ShouldNotHappenException( - 'getVariants() must return at least one variant.', - ); - } - if ($count !== 1) { - throw new ShouldNotHappenException('Multiple variants - use selectFromArgs() instead.'); - } - - return $parametersAcceptors[0]; - } - /** * @param Node\Arg[] $args * @param ParametersAcceptor[] $parametersAcceptors diff --git a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php index 446e478cd0..dd72c4525e 100644 --- a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php +++ b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php @@ -41,16 +41,28 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method { $args = $methodCall->args; if (count($args) === 0) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } $arg = $args[0]->value; if (!($arg instanceof \PhpParser\Node\Expr\ClassConstFetch)) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } if (!($arg->class instanceof \PhpParser\Node\Name)) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } return new ObjectType((string) $arg->class); @@ -75,12 +87,20 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method { $args = $methodCall->args; if (count($args) === 0) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } $argType = $scope->getType($args[0]->value); if (!$argType instanceof ConstantStringType) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } return new ObjectType($argType->getValue()); @@ -105,16 +125,28 @@ public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, { $args = $methodCall->args; if (count($args) === 0) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } $arg = $args[0]->value; if (!($arg instanceof \PhpParser\Node\Expr\ClassConstFetch)) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } if (!($arg->class instanceof \PhpParser\Node\Name)) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } return new ObjectType((string) $arg->class); @@ -215,7 +247,11 @@ public function isMethodSupported(MethodReflection $methodReflection): bool public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $methodCall->getArgs(), + $methodReflection->getVariants(), + )->getReturnType(); } } diff --git a/tests/PHPStan/Reflection/UnionTypesTest.php b/tests/PHPStan/Reflection/UnionTypesTest.php index d8977504d2..79fb96b28a 100644 --- a/tests/PHPStan/Reflection/UnionTypesTest.php +++ b/tests/PHPStan/Reflection/UnionTypesTest.php @@ -22,7 +22,7 @@ public function testUnionTypes(): void $this->assertSame('bool|int', $propertyType->describe(VerbosityLevel::precise())); $method = $class->getNativeMethod('doFoo'); - $methodVariant = ParametersAcceptorSelector::selectSingle($method->getVariants()); + $methodVariant = $method->getOnlyVariant(); $methodReturnType = $methodVariant->getReturnType(); $this->assertInstanceOf(UnionType::class, $methodReturnType); $this->assertSame('NativeUnionTypes\\Bar|NativeUnionTypes\\Foo', $methodReturnType->describe(VerbosityLevel::precise())); @@ -32,7 +32,7 @@ public function testUnionTypes(): void $this->assertSame('bool|int', $methodParameterType->describe(VerbosityLevel::precise())); $function = $reflectionProvider->getFunction(new Name('NativeUnionTypes\doFoo'), null); - $functionVariant = ParametersAcceptorSelector::selectSingle($function->getVariants()); + $functionVariant = $function->getOnlyVariant(); $functionReturnType = $functionVariant->getReturnType(); $this->assertInstanceOf(UnionType::class, $functionReturnType); $this->assertSame('NativeUnionTypes\\Bar|NativeUnionTypes\\Foo', $functionReturnType->describe(VerbosityLevel::precise())); diff --git a/tests/PHPStan/Rules/Api/data/static-call-out-of-phpstan.php b/tests/PHPStan/Rules/Api/data/static-call-out-of-phpstan.php index ec450207c7..f0f5bdd9ab 100644 --- a/tests/PHPStan/Rules/Api/data/static-call-out-of-phpstan.php +++ b/tests/PHPStan/Rules/Api/data/static-call-out-of-phpstan.php @@ -19,7 +19,7 @@ public function doFoo(): void public function doBar(FunctionReflection $f): void { - ParametersAcceptorSelector::selectSingle($f->getVariants()); // @api above class + ParametersAcceptorSelector::selectFromArgs($f->getVariants()); // @api above class ScopeContext::create(__DIR__ . '/test.php'); // @api above method } From 6b66eb07e38e50c1a44f05c51076d46bd2d1c769 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 14:22:47 +0200 Subject: [PATCH 228/508] Fix CS --- src/Analyser/LazyInternalScopeFactory.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Analyser/LazyInternalScopeFactory.php b/src/Analyser/LazyInternalScopeFactory.php index c2b2069ac5..32cfc6f843 100644 --- a/src/Analyser/LazyInternalScopeFactory.php +++ b/src/Analyser/LazyInternalScopeFactory.php @@ -7,7 +7,6 @@ use PHPStan\DependencyInjection\Type\ExpressionTypeResolverExtensionRegistryProvider; use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Php\PhpVersion; -use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\MethodReflection; From f7380291c2b5ae2d78bac86e227b886c3e9e7381 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 14:35:48 +0200 Subject: [PATCH 229/508] Removed no longer valid test --- ...icReturnTypeExtensionTypeInferenceTest.php | 1 - ...ic-method-return-getsingle-conditional.php | 20 ------------------- 2 files changed, 21 deletions(-) delete mode 100644 tests/PHPStan/Analyser/data/dynamic-method-return-getsingle-conditional.php diff --git a/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php b/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php index c76ca0ebca..7e5fad5dda 100644 --- a/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php +++ b/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php @@ -14,7 +14,6 @@ public function dataAsserts(): iterable if (PHP_VERSION_ID >= 80000) { yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-types-named-args.php'); - yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-getsingle-conditional.php'); } yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-compound-types.php'); diff --git a/tests/PHPStan/Analyser/data/dynamic-method-return-getsingle-conditional.php b/tests/PHPStan/Analyser/data/dynamic-method-return-getsingle-conditional.php deleted file mode 100644 index 270658e7ef..0000000000 --- a/tests/PHPStan/Analyser/data/dynamic-method-return-getsingle-conditional.php +++ /dev/null @@ -1,20 +0,0 @@ -get(0)); - assertType('bool', $this->get(1)); - assertType('bool', $this->get(2)); - } -} From 5651bec661582b2d62de1b4ae9d5f27e69e3c524 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:16:29 +0200 Subject: [PATCH 230/508] Move ContainerDynamicReturnTypeExtension to build/PHPStan --- .../PHPStan/Build}/ContainerDynamicReturnTypeExtension.php | 2 +- build/phpstan.neon | 2 +- phpstan-baseline.neon | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename {src/Internal => build/PHPStan/Build}/ContainerDynamicReturnTypeExtension.php (98%) diff --git a/src/Internal/ContainerDynamicReturnTypeExtension.php b/build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php similarity index 98% rename from src/Internal/ContainerDynamicReturnTypeExtension.php rename to build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php index 0fc017e67f..8e43bd2d47 100644 --- a/src/Internal/ContainerDynamicReturnTypeExtension.php +++ b/build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php @@ -1,6 +1,6 @@ Date: Thu, 26 Sep 2024 20:18:22 +0200 Subject: [PATCH 231/508] Classes that were previously `@final` were made `final` --- UPGRADING.md | 1 + src/Analyser/Error.php | 3 +-- src/Analyser/ImpurePoint.php | 3 +-- src/Analyser/InternalError.php | 3 +-- src/Analyser/NameScope.php | 3 +-- src/Analyser/ScopeFactory.php | 3 +-- src/Analyser/StatementExitPoint.php | 3 +-- src/Analyser/StatementResult.php | 3 +-- src/Analyser/ThrowPoint.php | 3 +-- src/Analyser/TypeSpecifierContext.php | 3 +-- src/Broker/Broker.php | 3 +-- src/Collectors/CollectedData.php | 3 +-- src/Command/AnalysisResult.php | 3 +-- src/Command/ErrorFormatter/CiDetectedErrorFormatter.php | 3 +-- src/DependencyInjection/ContainerFactory.php | 3 +-- src/Node/BooleanAndNode.php | 3 +-- src/Node/BooleanOrNode.php | 3 +-- src/Node/BreaklessWhileLoopNode.php | 3 +-- src/Node/CatchWithUnthrownExceptionNode.php | 3 +-- src/Node/ClassConstantsNode.php | 3 +-- src/Node/ClassMethod.php | 3 +-- src/Node/ClassMethodsNode.php | 3 +-- src/Node/ClassPropertiesNode.php | 3 +-- src/Node/ClassPropertyNode.php | 3 +-- src/Node/ClosureReturnStatementsNode.php | 3 +-- src/Node/CollectedDataNode.php | 3 +-- src/Node/Constant/ClassConstantFetch.php | 3 +-- src/Node/ExecutionEndNode.php | 3 +-- src/Node/FileNode.php | 3 +-- src/Node/FinallyExitPointsNode.php | 3 +-- src/Node/FunctionCallableNode.php | 3 +-- src/Node/FunctionReturnStatementsNode.php | 3 +-- src/Node/InArrowFunctionNode.php | 3 +-- src/Node/InClassMethodNode.php | 3 +-- src/Node/InClassNode.php | 3 +-- src/Node/InClosureNode.php | 3 +-- src/Node/InFunctionNode.php | 3 +-- src/Node/InTraitNode.php | 3 +-- src/Node/InstantiationCallableNode.php | 3 +-- src/Node/InvalidateExprNode.php | 3 +-- src/Node/LiteralArrayItem.php | 3 +-- src/Node/LiteralArrayNode.php | 3 +-- src/Node/MatchExpressionArm.php | 3 +-- src/Node/MatchExpressionArmBody.php | 3 +-- src/Node/MatchExpressionArmCondition.php | 3 +-- src/Node/MatchExpressionNode.php | 3 +-- src/Node/Method/MethodCall.php | 3 +-- src/Node/MethodCallableNode.php | 3 +-- src/Node/MethodReturnStatementsNode.php | 3 +-- src/Node/Printer/ExprPrinter.php | 3 +-- src/Node/Property/PropertyRead.php | 3 +-- src/Node/Property/PropertyWrite.php | 3 +-- src/Node/ReturnStatement.php | 3 +-- src/Node/StaticMethodCallableNode.php | 3 +-- src/Node/UnreachableStatementNode.php | 3 +-- src/Php/PhpVersion.php | 3 +-- src/PhpDoc/ResolvedPhpDocBlock.php | 3 +-- src/PhpDoc/Tag/DeprecatedTag.php | 3 +-- src/PhpDoc/Tag/ExtendsTag.php | 3 +-- src/PhpDoc/Tag/ImplementsTag.php | 3 +-- src/PhpDoc/Tag/MethodTag.php | 3 +-- src/PhpDoc/Tag/MethodTagParameter.php | 3 +-- src/PhpDoc/Tag/MixinTag.php | 3 +-- src/PhpDoc/Tag/ParamClosureThisTag.php | 1 - src/PhpDoc/Tag/ParamOutTag.php | 3 +-- src/PhpDoc/Tag/ParamTag.php | 3 +-- src/PhpDoc/Tag/PropertyTag.php | 3 +-- src/PhpDoc/Tag/RequireExtendsTag.php | 3 +-- src/PhpDoc/Tag/RequireImplementsTag.php | 3 +-- src/PhpDoc/Tag/ReturnTag.php | 3 +-- src/PhpDoc/Tag/SelfOutTypeTag.php | 3 +-- src/PhpDoc/Tag/TemplateTag.php | 3 +-- src/PhpDoc/Tag/ThrowsTag.php | 3 +-- src/PhpDoc/Tag/TypeAliasTag.php | 3 +-- src/PhpDoc/Tag/UsesTag.php | 3 +-- src/PhpDoc/Tag/VarTag.php | 3 +-- src/Reflection/Assertions.php | 3 +-- src/Reflection/ClassConstantReflection.php | 3 +-- src/Reflection/ClassReflection.php | 3 +-- src/Reflection/EnumCaseReflection.php | 3 +-- src/Reflection/InitializerExprContext.php | 3 +-- src/Reflection/ParametersAcceptorSelector.php | 3 +-- src/Reflection/PassedByReference.php | 3 +-- src/Reflection/Php/PhpMethodFromParserNodeReflection.php | 3 +-- src/Reflection/Php/PhpMethodReflection.php | 3 +-- src/Reflection/Php/PhpPropertyReflection.php | 3 +-- src/Reflection/TrivialParametersAcceptor.php | 3 +-- src/Rules/DirectRegistry.php | 5 +---- src/Rules/Exceptions/DefaultExceptionTypeResolver.php | 3 +-- src/Rules/FoundTypeResult.php | 3 +-- src/Rules/RuleErrorBuilder.php | 3 +-- src/TrinaryLogic.php | 3 +-- src/Type/AcceptsResult.php | 3 +-- src/Type/ClosureTypeFactory.php | 3 +-- src/Type/Constant/ConstantArrayTypeAndMethod.php | 3 +-- src/Type/Constant/ConstantArrayTypeBuilder.php | 3 +-- src/Type/ConstantTypeHelper.php | 3 +-- src/Type/Generic/TemplateTypeMap.php | 3 +-- src/Type/Generic/TemplateTypeVariance.php | 3 +-- src/Type/Generic/TemplateTypeVarianceMap.php | 3 +-- src/Type/GenericTypeVariableResolver.php | 3 +-- src/Type/TypeCombinator.php | 3 +-- src/Type/TypeUtils.php | 3 +-- 103 files changed, 102 insertions(+), 205 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index d28c6aed08..6dc6ec47e3 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -216,6 +216,7 @@ As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtensio ### Minor backward compatibility breaks +* Classes that were previously `@final` were made `final` * Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required * Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required * ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) diff --git a/src/Analyser/Error.php b/src/Analyser/Error.php index d92f983a3e..1ad85c60be 100644 --- a/src/Analyser/Error.php +++ b/src/Analyser/Error.php @@ -14,9 +14,8 @@ /** * @api - * @final */ -class Error implements JsonSerializable +final class Error implements JsonSerializable { public const PATTERN_IDENTIFIER = '[a-zA-Z0-9](?:[a-zA-Z0-9\\.]*[a-zA-Z0-9])?'; diff --git a/src/Analyser/ImpurePoint.php b/src/Analyser/ImpurePoint.php index d4dc6fe133..20335325a7 100644 --- a/src/Analyser/ImpurePoint.php +++ b/src/Analyser/ImpurePoint.php @@ -8,9 +8,8 @@ /** * @phpstan-type ImpurePointIdentifier = 'echo'|'die'|'exit'|'propertyAssign'|'propertyAssignByRef'|'propertyUnset'|'methodCall'|'new'|'functionCall'|'include'|'require'|'print'|'eval'|'superglobal'|'yield'|'yieldFrom'|'static'|'global'|'betweenPhpTags' * @api - * @final */ -class ImpurePoint +final class ImpurePoint { /** diff --git a/src/Analyser/InternalError.php b/src/Analyser/InternalError.php index d778e89462..371b64cdc3 100644 --- a/src/Analyser/InternalError.php +++ b/src/Analyser/InternalError.php @@ -10,10 +10,9 @@ /** * @api - * @final * @phpstan-type Trace = list */ -class InternalError implements JsonSerializable +final class InternalError implements JsonSerializable { public const STACK_TRACE_METADATA_KEY = 'stackTrace'; diff --git a/src/Analyser/NameScope.php b/src/Analyser/NameScope.php index fbc602329e..f7f54f0a6a 100644 --- a/src/Analyser/NameScope.php +++ b/src/Analyser/NameScope.php @@ -18,9 +18,8 @@ /** * @api - * @final */ -class NameScope +final class NameScope { private TemplateTypeMap $templateTypeMap; diff --git a/src/Analyser/ScopeFactory.php b/src/Analyser/ScopeFactory.php index ae35c9d74c..ade6e1d894 100644 --- a/src/Analyser/ScopeFactory.php +++ b/src/Analyser/ScopeFactory.php @@ -4,9 +4,8 @@ /** * @api - * @final */ -class ScopeFactory +final class ScopeFactory { public function __construct(private InternalScopeFactory $internalScopeFactory) diff --git a/src/Analyser/StatementExitPoint.php b/src/Analyser/StatementExitPoint.php index 14c8d24824..5c4916373e 100644 --- a/src/Analyser/StatementExitPoint.php +++ b/src/Analyser/StatementExitPoint.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class StatementExitPoint +final class StatementExitPoint { public function __construct(private Stmt $statement, private MutatingScope $scope) diff --git a/src/Analyser/StatementResult.php b/src/Analyser/StatementResult.php index 985777317e..71f0ddc740 100644 --- a/src/Analyser/StatementResult.php +++ b/src/Analyser/StatementResult.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class StatementResult +final class StatementResult { /** diff --git a/src/Analyser/ThrowPoint.php b/src/Analyser/ThrowPoint.php index 1de4b937f9..873c11e425 100644 --- a/src/Analyser/ThrowPoint.php +++ b/src/Analyser/ThrowPoint.php @@ -10,9 +10,8 @@ /** * @api - * @final */ -class ThrowPoint +final class ThrowPoint { /** diff --git a/src/Analyser/TypeSpecifierContext.php b/src/Analyser/TypeSpecifierContext.php index 3cd0ead0f9..fe09aa861c 100644 --- a/src/Analyser/TypeSpecifierContext.php +++ b/src/Analyser/TypeSpecifierContext.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class TypeSpecifierContext +final class TypeSpecifierContext { public const CONTEXT_TRUE = 0b0001; diff --git a/src/Broker/Broker.php b/src/Broker/Broker.php index 8db42d1f45..080d3accc8 100644 --- a/src/Broker/Broker.php +++ b/src/Broker/Broker.php @@ -13,9 +13,8 @@ /** * @api - * @final */ -class Broker implements ReflectionProvider +final class Broker implements ReflectionProvider { private static ?Broker $instance = null; diff --git a/src/Collectors/CollectedData.php b/src/Collectors/CollectedData.php index e6817382b6..1ae0078880 100644 --- a/src/Collectors/CollectedData.php +++ b/src/Collectors/CollectedData.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class CollectedData implements JsonSerializable +final class CollectedData implements JsonSerializable { /** diff --git a/src/Command/AnalysisResult.php b/src/Command/AnalysisResult.php index 6ddf536bc1..4b090e8a35 100644 --- a/src/Command/AnalysisResult.php +++ b/src/Command/AnalysisResult.php @@ -11,9 +11,8 @@ /** * @api - * @final */ -class AnalysisResult +final class AnalysisResult { /** @var list sorted by their file name, line number and message */ diff --git a/src/Command/ErrorFormatter/CiDetectedErrorFormatter.php b/src/Command/ErrorFormatter/CiDetectedErrorFormatter.php index a6c66bbafb..38d0a67439 100644 --- a/src/Command/ErrorFormatter/CiDetectedErrorFormatter.php +++ b/src/Command/ErrorFormatter/CiDetectedErrorFormatter.php @@ -9,9 +9,8 @@ /** * @api - * @final */ -class CiDetectedErrorFormatter implements ErrorFormatter +final class CiDetectedErrorFormatter implements ErrorFormatter { public function __construct( diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index 2a491725bb..4ab01e56c9 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -55,9 +55,8 @@ /** * @api - * @final */ -class ContainerFactory +final class ContainerFactory { private FileHelper $fileHelper; diff --git a/src/Node/BooleanAndNode.php b/src/Node/BooleanAndNode.php index 6d508713e7..361177c705 100644 --- a/src/Node/BooleanAndNode.php +++ b/src/Node/BooleanAndNode.php @@ -9,9 +9,8 @@ /** * @api - * @final */ -class BooleanAndNode extends Expr implements VirtualNode +final class BooleanAndNode extends Expr implements VirtualNode { public function __construct(private BooleanAnd|LogicalAnd $originalNode, private Scope $rightScope) diff --git a/src/Node/BooleanOrNode.php b/src/Node/BooleanOrNode.php index ca327164ee..c2ca5d14be 100644 --- a/src/Node/BooleanOrNode.php +++ b/src/Node/BooleanOrNode.php @@ -9,9 +9,8 @@ /** * @api - * @final */ -class BooleanOrNode extends Expr implements VirtualNode +final class BooleanOrNode extends Expr implements VirtualNode { public function __construct(private BooleanOr|LogicalOr $originalNode, private Scope $rightScope) diff --git a/src/Node/BreaklessWhileLoopNode.php b/src/Node/BreaklessWhileLoopNode.php index 3d3ff248a2..f7df71bf19 100644 --- a/src/Node/BreaklessWhileLoopNode.php +++ b/src/Node/BreaklessWhileLoopNode.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class BreaklessWhileLoopNode extends NodeAbstract implements VirtualNode +final class BreaklessWhileLoopNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/CatchWithUnthrownExceptionNode.php b/src/Node/CatchWithUnthrownExceptionNode.php index d1872895dd..9f06bf2009 100644 --- a/src/Node/CatchWithUnthrownExceptionNode.php +++ b/src/Node/CatchWithUnthrownExceptionNode.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class CatchWithUnthrownExceptionNode extends NodeAbstract implements VirtualNode +final class CatchWithUnthrownExceptionNode extends NodeAbstract implements VirtualNode { public function __construct(private Catch_ $originalNode, private Type $caughtType, private Type $originalCaughtType) diff --git a/src/Node/ClassConstantsNode.php b/src/Node/ClassConstantsNode.php index 0b12946d8c..4da543a2d7 100644 --- a/src/Node/ClassConstantsNode.php +++ b/src/Node/ClassConstantsNode.php @@ -10,9 +10,8 @@ /** * @api - * @final */ -class ClassConstantsNode extends NodeAbstract implements VirtualNode +final class ClassConstantsNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/ClassMethod.php b/src/Node/ClassMethod.php index e3f2cef221..3a30a402d6 100644 --- a/src/Node/ClassMethod.php +++ b/src/Node/ClassMethod.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class ClassMethod extends PhpParserClassMethod +final class ClassMethod extends PhpParserClassMethod { public function __construct( diff --git a/src/Node/ClassMethodsNode.php b/src/Node/ClassMethodsNode.php index 3a8a2df77d..4c46fd9253 100644 --- a/src/Node/ClassMethodsNode.php +++ b/src/Node/ClassMethodsNode.php @@ -9,9 +9,8 @@ /** * @api - * @final */ -class ClassMethodsNode extends NodeAbstract implements VirtualNode +final class ClassMethodsNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/ClassPropertiesNode.php b/src/Node/ClassPropertiesNode.php index df8f0f993a..c22ec65c29 100644 --- a/src/Node/ClassPropertiesNode.php +++ b/src/Node/ClassPropertiesNode.php @@ -30,9 +30,8 @@ /** * @api - * @final */ -class ClassPropertiesNode extends NodeAbstract implements VirtualNode +final class ClassPropertiesNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/ClassPropertyNode.php b/src/Node/ClassPropertyNode.php index f0ad86ff8c..571f8b34ed 100644 --- a/src/Node/ClassPropertyNode.php +++ b/src/Node/ClassPropertyNode.php @@ -13,9 +13,8 @@ /** * @api - * @final */ -class ClassPropertyNode extends NodeAbstract implements VirtualNode +final class ClassPropertyNode extends NodeAbstract implements VirtualNode { public function __construct( diff --git a/src/Node/ClosureReturnStatementsNode.php b/src/Node/ClosureReturnStatementsNode.php index 7231c02e5f..920b61750b 100644 --- a/src/Node/ClosureReturnStatementsNode.php +++ b/src/Node/ClosureReturnStatementsNode.php @@ -13,9 +13,8 @@ /** * @api - * @final */ -class ClosureReturnStatementsNode extends NodeAbstract implements ReturnStatementsNode +final class ClosureReturnStatementsNode extends NodeAbstract implements ReturnStatementsNode { private Node\Expr\Closure $closureExpr; diff --git a/src/Node/CollectedDataNode.php b/src/Node/CollectedDataNode.php index 7588947625..8c0f52dc3b 100644 --- a/src/Node/CollectedDataNode.php +++ b/src/Node/CollectedDataNode.php @@ -10,9 +10,8 @@ /** * @api - * @final */ -class CollectedDataNode extends NodeAbstract implements VirtualNode +final class CollectedDataNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/Constant/ClassConstantFetch.php b/src/Node/Constant/ClassConstantFetch.php index 8f23935dd1..bda533900b 100644 --- a/src/Node/Constant/ClassConstantFetch.php +++ b/src/Node/Constant/ClassConstantFetch.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class ClassConstantFetch +final class ClassConstantFetch { public function __construct(private ClassConstFetch $node, private Scope $scope) diff --git a/src/Node/ExecutionEndNode.php b/src/Node/ExecutionEndNode.php index e9cf081b13..5e0ddf13da 100644 --- a/src/Node/ExecutionEndNode.php +++ b/src/Node/ExecutionEndNode.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class ExecutionEndNode extends NodeAbstract implements VirtualNode +final class ExecutionEndNode extends NodeAbstract implements VirtualNode { public function __construct( diff --git a/src/Node/FileNode.php b/src/Node/FileNode.php index 355a4b9559..286168fb6a 100644 --- a/src/Node/FileNode.php +++ b/src/Node/FileNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class FileNode extends NodeAbstract implements VirtualNode +final class FileNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/FinallyExitPointsNode.php b/src/Node/FinallyExitPointsNode.php index 32c2adb50c..fed8d4888d 100644 --- a/src/Node/FinallyExitPointsNode.php +++ b/src/Node/FinallyExitPointsNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class FinallyExitPointsNode extends NodeAbstract implements VirtualNode +final class FinallyExitPointsNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/FunctionCallableNode.php b/src/Node/FunctionCallableNode.php index 00e9e24fba..9cd2cfc8c8 100644 --- a/src/Node/FunctionCallableNode.php +++ b/src/Node/FunctionCallableNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class FunctionCallableNode extends Expr implements VirtualNode +final class FunctionCallableNode extends Expr implements VirtualNode { public function __construct(private Name|Expr $name, private Expr\FuncCall $originalNode) diff --git a/src/Node/FunctionReturnStatementsNode.php b/src/Node/FunctionReturnStatementsNode.php index 4ab53d25c3..14582f309b 100644 --- a/src/Node/FunctionReturnStatementsNode.php +++ b/src/Node/FunctionReturnStatementsNode.php @@ -14,9 +14,8 @@ /** * @api - * @final */ -class FunctionReturnStatementsNode extends NodeAbstract implements ReturnStatementsNode +final class FunctionReturnStatementsNode extends NodeAbstract implements ReturnStatementsNode { /** diff --git a/src/Node/InArrowFunctionNode.php b/src/Node/InArrowFunctionNode.php index fb60b2b404..20acb7c36f 100644 --- a/src/Node/InArrowFunctionNode.php +++ b/src/Node/InArrowFunctionNode.php @@ -9,9 +9,8 @@ /** * @api - * @final */ -class InArrowFunctionNode extends NodeAbstract implements VirtualNode +final class InArrowFunctionNode extends NodeAbstract implements VirtualNode { private Node\Expr\ArrowFunction $originalNode; diff --git a/src/Node/InClassMethodNode.php b/src/Node/InClassMethodNode.php index f74db8e890..52b50c17fd 100644 --- a/src/Node/InClassMethodNode.php +++ b/src/Node/InClassMethodNode.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class InClassMethodNode extends Node\Stmt implements VirtualNode +final class InClassMethodNode extends Node\Stmt implements VirtualNode { public function __construct( diff --git a/src/Node/InClassNode.php b/src/Node/InClassNode.php index 1be1b7fab2..84a4ecab83 100644 --- a/src/Node/InClassNode.php +++ b/src/Node/InClassNode.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class InClassNode extends Node\Stmt implements VirtualNode +final class InClassNode extends Node\Stmt implements VirtualNode { public function __construct(private ClassLike $originalNode, private ClassReflection $classReflection) diff --git a/src/Node/InClosureNode.php b/src/Node/InClosureNode.php index 21def5dbef..3e95aea867 100644 --- a/src/Node/InClosureNode.php +++ b/src/Node/InClosureNode.php @@ -9,9 +9,8 @@ /** * @api - * @final */ -class InClosureNode extends NodeAbstract implements VirtualNode +final class InClosureNode extends NodeAbstract implements VirtualNode { private Node\Expr\Closure $originalNode; diff --git a/src/Node/InFunctionNode.php b/src/Node/InFunctionNode.php index 550c00e41b..ce90bb7f38 100644 --- a/src/Node/InFunctionNode.php +++ b/src/Node/InFunctionNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class InFunctionNode extends Node\Stmt implements VirtualNode +final class InFunctionNode extends Node\Stmt implements VirtualNode { public function __construct( diff --git a/src/Node/InTraitNode.php b/src/Node/InTraitNode.php index 2a3a810fb5..b7834e713f 100644 --- a/src/Node/InTraitNode.php +++ b/src/Node/InTraitNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class InTraitNode extends Node\Stmt implements VirtualNode +final class InTraitNode extends Node\Stmt implements VirtualNode { public function __construct(private Node\Stmt\Trait_ $originalNode, private ClassReflection $traitReflection, private ClassReflection $implementingClassReflection) diff --git a/src/Node/InstantiationCallableNode.php b/src/Node/InstantiationCallableNode.php index 289fb6fe5f..98d838b1be 100644 --- a/src/Node/InstantiationCallableNode.php +++ b/src/Node/InstantiationCallableNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class InstantiationCallableNode extends Expr implements VirtualNode +final class InstantiationCallableNode extends Expr implements VirtualNode { public function __construct(private Name|Expr $class, private Expr\New_ $originalNode) diff --git a/src/Node/InvalidateExprNode.php b/src/Node/InvalidateExprNode.php index a59799f0aa..5fb5ba27de 100644 --- a/src/Node/InvalidateExprNode.php +++ b/src/Node/InvalidateExprNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class InvalidateExprNode extends NodeAbstract implements VirtualNode +final class InvalidateExprNode extends NodeAbstract implements VirtualNode { public function __construct(private Expr $expr) diff --git a/src/Node/LiteralArrayItem.php b/src/Node/LiteralArrayItem.php index 1ba0c04ef5..4d9699121b 100644 --- a/src/Node/LiteralArrayItem.php +++ b/src/Node/LiteralArrayItem.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class LiteralArrayItem +final class LiteralArrayItem { public function __construct(private Scope $scope, private ?ArrayItem $arrayItem) diff --git a/src/Node/LiteralArrayNode.php b/src/Node/LiteralArrayNode.php index e0bd824fad..9c8a693ff6 100644 --- a/src/Node/LiteralArrayNode.php +++ b/src/Node/LiteralArrayNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class LiteralArrayNode extends NodeAbstract implements VirtualNode +final class LiteralArrayNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/MatchExpressionArm.php b/src/Node/MatchExpressionArm.php index 427ed83cae..bad6265698 100644 --- a/src/Node/MatchExpressionArm.php +++ b/src/Node/MatchExpressionArm.php @@ -4,9 +4,8 @@ /** * @api - * @final */ -class MatchExpressionArm +final class MatchExpressionArm { /** diff --git a/src/Node/MatchExpressionArmBody.php b/src/Node/MatchExpressionArmBody.php index 628f0f777c..dbb6f3f917 100644 --- a/src/Node/MatchExpressionArmBody.php +++ b/src/Node/MatchExpressionArmBody.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class MatchExpressionArmBody +final class MatchExpressionArmBody { public function __construct(private Scope $scope, private Expr $body) diff --git a/src/Node/MatchExpressionArmCondition.php b/src/Node/MatchExpressionArmCondition.php index 4b3bc54720..95a291cce3 100644 --- a/src/Node/MatchExpressionArmCondition.php +++ b/src/Node/MatchExpressionArmCondition.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class MatchExpressionArmCondition +final class MatchExpressionArmCondition { public function __construct(private Expr $condition, private Scope $scope, private int $line) diff --git a/src/Node/MatchExpressionNode.php b/src/Node/MatchExpressionNode.php index 0dd31d9b2b..fb7f360642 100644 --- a/src/Node/MatchExpressionNode.php +++ b/src/Node/MatchExpressionNode.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class MatchExpressionNode extends NodeAbstract implements VirtualNode +final class MatchExpressionNode extends NodeAbstract implements VirtualNode { /** diff --git a/src/Node/Method/MethodCall.php b/src/Node/Method/MethodCall.php index c88997a3f9..d3726915a9 100644 --- a/src/Node/Method/MethodCall.php +++ b/src/Node/Method/MethodCall.php @@ -9,9 +9,8 @@ /** * @api - * @final */ -class MethodCall +final class MethodCall { public function __construct( diff --git a/src/Node/MethodCallableNode.php b/src/Node/MethodCallableNode.php index 7e7f1240dd..b1e52bf1e6 100644 --- a/src/Node/MethodCallableNode.php +++ b/src/Node/MethodCallableNode.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class MethodCallableNode extends Expr implements VirtualNode +final class MethodCallableNode extends Expr implements VirtualNode { public function __construct( diff --git a/src/Node/MethodReturnStatementsNode.php b/src/Node/MethodReturnStatementsNode.php index 96218713d3..2444df30b5 100644 --- a/src/Node/MethodReturnStatementsNode.php +++ b/src/Node/MethodReturnStatementsNode.php @@ -15,9 +15,8 @@ /** * @api - * @final */ -class MethodReturnStatementsNode extends NodeAbstract implements ReturnStatementsNode +final class MethodReturnStatementsNode extends NodeAbstract implements ReturnStatementsNode { private ClassMethod $classMethod; diff --git a/src/Node/Printer/ExprPrinter.php b/src/Node/Printer/ExprPrinter.php index 6df730ddfc..32505ef568 100644 --- a/src/Node/Printer/ExprPrinter.php +++ b/src/Node/Printer/ExprPrinter.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class ExprPrinter +final class ExprPrinter { public function __construct(private Printer $printer) diff --git a/src/Node/Property/PropertyRead.php b/src/Node/Property/PropertyRead.php index 1c24537453..86c220b77f 100644 --- a/src/Node/Property/PropertyRead.php +++ b/src/Node/Property/PropertyRead.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class PropertyRead +final class PropertyRead { public function __construct( diff --git a/src/Node/Property/PropertyWrite.php b/src/Node/Property/PropertyWrite.php index fec7a1c4f0..df39b83d0b 100644 --- a/src/Node/Property/PropertyWrite.php +++ b/src/Node/Property/PropertyWrite.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class PropertyWrite +final class PropertyWrite { public function __construct(private PropertyFetch|StaticPropertyFetch $fetch, private Scope $scope, private bool $promotedPropertyWrite) diff --git a/src/Node/ReturnStatement.php b/src/Node/ReturnStatement.php index 7a5da6f203..153faf1534 100644 --- a/src/Node/ReturnStatement.php +++ b/src/Node/ReturnStatement.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class ReturnStatement +final class ReturnStatement { private Node\Stmt\Return_ $returnNode; diff --git a/src/Node/StaticMethodCallableNode.php b/src/Node/StaticMethodCallableNode.php index 19e823234b..407a5cfa4c 100644 --- a/src/Node/StaticMethodCallableNode.php +++ b/src/Node/StaticMethodCallableNode.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class StaticMethodCallableNode extends Expr implements VirtualNode +final class StaticMethodCallableNode extends Expr implements VirtualNode { public function __construct( diff --git a/src/Node/UnreachableStatementNode.php b/src/Node/UnreachableStatementNode.php index 7c3cfb163c..e0c8cb0af9 100644 --- a/src/Node/UnreachableStatementNode.php +++ b/src/Node/UnreachableStatementNode.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class UnreachableStatementNode extends Stmt implements VirtualNode +final class UnreachableStatementNode extends Stmt implements VirtualNode { public function __construct(private Stmt $originalStatement) diff --git a/src/Php/PhpVersion.php b/src/Php/PhpVersion.php index b275c464eb..fcd6871c39 100644 --- a/src/Php/PhpVersion.php +++ b/src/Php/PhpVersion.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class PhpVersion +final class PhpVersion { public const SOURCE_RUNTIME = 1; diff --git a/src/PhpDoc/ResolvedPhpDocBlock.php b/src/PhpDoc/ResolvedPhpDocBlock.php index ed45d60e48..6cd991341b 100644 --- a/src/PhpDoc/ResolvedPhpDocBlock.php +++ b/src/PhpDoc/ResolvedPhpDocBlock.php @@ -42,9 +42,8 @@ /** * @api - * @final */ -class ResolvedPhpDocBlock +final class ResolvedPhpDocBlock { public const EMPTY_DOC_STRING = '/** */'; diff --git a/src/PhpDoc/Tag/DeprecatedTag.php b/src/PhpDoc/Tag/DeprecatedTag.php index e7bf3c553f..9bc036e1d8 100644 --- a/src/PhpDoc/Tag/DeprecatedTag.php +++ b/src/PhpDoc/Tag/DeprecatedTag.php @@ -4,9 +4,8 @@ /** * @api - * @final */ -class DeprecatedTag +final class DeprecatedTag { public function __construct(private ?string $message) diff --git a/src/PhpDoc/Tag/ExtendsTag.php b/src/PhpDoc/Tag/ExtendsTag.php index e8a48922b4..72cb97f7cf 100644 --- a/src/PhpDoc/Tag/ExtendsTag.php +++ b/src/PhpDoc/Tag/ExtendsTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class ExtendsTag +final class ExtendsTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/ImplementsTag.php b/src/PhpDoc/Tag/ImplementsTag.php index bc82888d3f..556959b68d 100644 --- a/src/PhpDoc/Tag/ImplementsTag.php +++ b/src/PhpDoc/Tag/ImplementsTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class ImplementsTag +final class ImplementsTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/MethodTag.php b/src/PhpDoc/Tag/MethodTag.php index 85018267b1..43bda4cf97 100644 --- a/src/PhpDoc/Tag/MethodTag.php +++ b/src/PhpDoc/Tag/MethodTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class MethodTag +final class MethodTag { /** diff --git a/src/PhpDoc/Tag/MethodTagParameter.php b/src/PhpDoc/Tag/MethodTagParameter.php index 21f4377ce6..3e4c817bf8 100644 --- a/src/PhpDoc/Tag/MethodTagParameter.php +++ b/src/PhpDoc/Tag/MethodTagParameter.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class MethodTagParameter +final class MethodTagParameter { public function __construct( diff --git a/src/PhpDoc/Tag/MixinTag.php b/src/PhpDoc/Tag/MixinTag.php index 5df36d74bd..c115c2cacb 100644 --- a/src/PhpDoc/Tag/MixinTag.php +++ b/src/PhpDoc/Tag/MixinTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class MixinTag +final class MixinTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/ParamClosureThisTag.php b/src/PhpDoc/Tag/ParamClosureThisTag.php index ae601dabc2..eba2903f21 100644 --- a/src/PhpDoc/Tag/ParamClosureThisTag.php +++ b/src/PhpDoc/Tag/ParamClosureThisTag.php @@ -6,7 +6,6 @@ /** * @api - * @final */ final class ParamClosureThisTag implements TypedTag { diff --git a/src/PhpDoc/Tag/ParamOutTag.php b/src/PhpDoc/Tag/ParamOutTag.php index 8bc982f292..50d289fc87 100644 --- a/src/PhpDoc/Tag/ParamOutTag.php +++ b/src/PhpDoc/Tag/ParamOutTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class ParamOutTag implements TypedTag +final class ParamOutTag implements TypedTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/ParamTag.php b/src/PhpDoc/Tag/ParamTag.php index f21038c4e1..50a3e98cc8 100644 --- a/src/PhpDoc/Tag/ParamTag.php +++ b/src/PhpDoc/Tag/ParamTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class ParamTag implements TypedTag +final class ParamTag implements TypedTag { public function __construct( diff --git a/src/PhpDoc/Tag/PropertyTag.php b/src/PhpDoc/Tag/PropertyTag.php index a46bb9cdbf..372e8b3cb9 100644 --- a/src/PhpDoc/Tag/PropertyTag.php +++ b/src/PhpDoc/Tag/PropertyTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class PropertyTag +final class PropertyTag { public function __construct( diff --git a/src/PhpDoc/Tag/RequireExtendsTag.php b/src/PhpDoc/Tag/RequireExtendsTag.php index 60861f7615..97bf685468 100644 --- a/src/PhpDoc/Tag/RequireExtendsTag.php +++ b/src/PhpDoc/Tag/RequireExtendsTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class RequireExtendsTag +final class RequireExtendsTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/RequireImplementsTag.php b/src/PhpDoc/Tag/RequireImplementsTag.php index 12702bce71..aafd560260 100644 --- a/src/PhpDoc/Tag/RequireImplementsTag.php +++ b/src/PhpDoc/Tag/RequireImplementsTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class RequireImplementsTag +final class RequireImplementsTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/ReturnTag.php b/src/PhpDoc/Tag/ReturnTag.php index ef5b130293..c2354fa3b1 100644 --- a/src/PhpDoc/Tag/ReturnTag.php +++ b/src/PhpDoc/Tag/ReturnTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class ReturnTag implements TypedTag +final class ReturnTag implements TypedTag { public function __construct(private Type $type, private bool $isExplicit) diff --git a/src/PhpDoc/Tag/SelfOutTypeTag.php b/src/PhpDoc/Tag/SelfOutTypeTag.php index 1e1dacc2fa..63d275cc4c 100644 --- a/src/PhpDoc/Tag/SelfOutTypeTag.php +++ b/src/PhpDoc/Tag/SelfOutTypeTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class SelfOutTypeTag implements TypedTag +final class SelfOutTypeTag implements TypedTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/TemplateTag.php b/src/PhpDoc/Tag/TemplateTag.php index a14fa2c6ab..a7ab4ac8b4 100644 --- a/src/PhpDoc/Tag/TemplateTag.php +++ b/src/PhpDoc/Tag/TemplateTag.php @@ -7,9 +7,8 @@ /** * @api - * @final */ -class TemplateTag +final class TemplateTag { /** diff --git a/src/PhpDoc/Tag/ThrowsTag.php b/src/PhpDoc/Tag/ThrowsTag.php index 220eefae95..1c1e30b897 100644 --- a/src/PhpDoc/Tag/ThrowsTag.php +++ b/src/PhpDoc/Tag/ThrowsTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class ThrowsTag +final class ThrowsTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/TypeAliasTag.php b/src/PhpDoc/Tag/TypeAliasTag.php index 5a360b8613..d5cd10e5d6 100644 --- a/src/PhpDoc/Tag/TypeAliasTag.php +++ b/src/PhpDoc/Tag/TypeAliasTag.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class TypeAliasTag +final class TypeAliasTag { public function __construct( diff --git a/src/PhpDoc/Tag/UsesTag.php b/src/PhpDoc/Tag/UsesTag.php index 63ec60d0b4..1679997ed3 100644 --- a/src/PhpDoc/Tag/UsesTag.php +++ b/src/PhpDoc/Tag/UsesTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class UsesTag +final class UsesTag { public function __construct(private Type $type) diff --git a/src/PhpDoc/Tag/VarTag.php b/src/PhpDoc/Tag/VarTag.php index 0d93daeac8..c4d5842474 100644 --- a/src/PhpDoc/Tag/VarTag.php +++ b/src/PhpDoc/Tag/VarTag.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class VarTag implements TypedTag +final class VarTag implements TypedTag { public function __construct(private Type $type) diff --git a/src/Reflection/Assertions.php b/src/Reflection/Assertions.php index 988652d0d4..a1f7ebfa6d 100644 --- a/src/Reflection/Assertions.php +++ b/src/Reflection/Assertions.php @@ -12,9 +12,8 @@ /** * @api - * @final */ -class Assertions +final class Assertions { private static ?self $empty = null; diff --git a/src/Reflection/ClassConstantReflection.php b/src/Reflection/ClassConstantReflection.php index f54fc37ba4..78cec7e379 100644 --- a/src/Reflection/ClassConstantReflection.php +++ b/src/Reflection/ClassConstantReflection.php @@ -12,9 +12,8 @@ /** * @api - * @final */ -class ClassConstantReflection implements ConstantReflection +final class ClassConstantReflection implements ConstantReflection { private ?Type $valueType = null; diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index d980be7864..fe4204dddf 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -71,9 +71,8 @@ /** * @api - * @final */ -class ClassReflection +final class ClassReflection { /** @var ExtendedMethodReflection[] */ diff --git a/src/Reflection/EnumCaseReflection.php b/src/Reflection/EnumCaseReflection.php index 234ccbf95b..2ce5cc63cf 100644 --- a/src/Reflection/EnumCaseReflection.php +++ b/src/Reflection/EnumCaseReflection.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class EnumCaseReflection +final class EnumCaseReflection { public function __construct(private ClassReflection $declaringEnum, private string $name, private ?Type $backingValueType) diff --git a/src/Reflection/InitializerExprContext.php b/src/Reflection/InitializerExprContext.php index 4289056bcf..9d7d9aa5bf 100644 --- a/src/Reflection/InitializerExprContext.php +++ b/src/Reflection/InitializerExprContext.php @@ -17,9 +17,8 @@ /** * @api - * @final */ -class InitializerExprContext implements NamespaceAnswerer +final class InitializerExprContext implements NamespaceAnswerer { /** diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index f9f66c7531..d78cb09f33 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -55,9 +55,8 @@ /** * @api - * @final */ -class ParametersAcceptorSelector +final class ParametersAcceptorSelector { /** diff --git a/src/Reflection/PassedByReference.php b/src/Reflection/PassedByReference.php index 5a6bbd4a04..9a5c95f806 100644 --- a/src/Reflection/PassedByReference.php +++ b/src/Reflection/PassedByReference.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class PassedByReference +final class PassedByReference { private const NO = 1; diff --git a/src/Reflection/Php/PhpMethodFromParserNodeReflection.php b/src/Reflection/Php/PhpMethodFromParserNodeReflection.php index a05f550105..329ad1de61 100644 --- a/src/Reflection/Php/PhpMethodFromParserNodeReflection.php +++ b/src/Reflection/Php/PhpMethodFromParserNodeReflection.php @@ -25,9 +25,8 @@ /** * @api - * @final */ -class PhpMethodFromParserNodeReflection extends PhpFunctionFromParserNodeReflection implements ExtendedMethodReflection +final class PhpMethodFromParserNodeReflection extends PhpFunctionFromParserNodeReflection implements ExtendedMethodReflection { /** diff --git a/src/Reflection/Php/PhpMethodReflection.php b/src/Reflection/Php/PhpMethodReflection.php index 390ebc886a..8de0a7870e 100644 --- a/src/Reflection/Php/PhpMethodReflection.php +++ b/src/Reflection/Php/PhpMethodReflection.php @@ -47,9 +47,8 @@ /** * @api - * @final */ -class PhpMethodReflection implements ExtendedMethodReflection +final class PhpMethodReflection implements ExtendedMethodReflection { /** @var PhpParameterReflection[]|null */ diff --git a/src/Reflection/Php/PhpPropertyReflection.php b/src/Reflection/Php/PhpPropertyReflection.php index b1f2c18656..28e559719a 100644 --- a/src/Reflection/Php/PhpPropertyReflection.php +++ b/src/Reflection/Php/PhpPropertyReflection.php @@ -15,9 +15,8 @@ /** * @api - * @final */ -class PhpPropertyReflection implements ExtendedPropertyReflection +final class PhpPropertyReflection implements ExtendedPropertyReflection { private ?Type $finalNativeType = null; diff --git a/src/Reflection/TrivialParametersAcceptor.php b/src/Reflection/TrivialParametersAcceptor.php index b6e638c979..1d9f2aa628 100644 --- a/src/Reflection/TrivialParametersAcceptor.php +++ b/src/Reflection/TrivialParametersAcceptor.php @@ -13,9 +13,8 @@ /** * @api - * @final */ -class TrivialParametersAcceptor implements ParametersAcceptorWithPhpDocs, CallableParametersAcceptor +final class TrivialParametersAcceptor implements ParametersAcceptorWithPhpDocs, CallableParametersAcceptor { /** @api */ diff --git a/src/Rules/DirectRegistry.php b/src/Rules/DirectRegistry.php index 0dfb5d71ec..7cc3d331ca 100644 --- a/src/Rules/DirectRegistry.php +++ b/src/Rules/DirectRegistry.php @@ -6,10 +6,7 @@ use function class_implements; use function class_parents; -/** - * @final - */ -class DirectRegistry implements Registry +final class DirectRegistry implements Registry { /** @var Rule[][] */ diff --git a/src/Rules/Exceptions/DefaultExceptionTypeResolver.php b/src/Rules/Exceptions/DefaultExceptionTypeResolver.php index fd6866bc72..75f020fe77 100644 --- a/src/Rules/Exceptions/DefaultExceptionTypeResolver.php +++ b/src/Rules/Exceptions/DefaultExceptionTypeResolver.php @@ -9,9 +9,8 @@ /** * @api - * @final */ -class DefaultExceptionTypeResolver implements ExceptionTypeResolver +final class DefaultExceptionTypeResolver implements ExceptionTypeResolver { /** diff --git a/src/Rules/FoundTypeResult.php b/src/Rules/FoundTypeResult.php index 4e89ed8ec5..61702c6194 100644 --- a/src/Rules/FoundTypeResult.php +++ b/src/Rules/FoundTypeResult.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class FoundTypeResult +final class FoundTypeResult { /** diff --git a/src/Rules/RuleErrorBuilder.php b/src/Rules/RuleErrorBuilder.php index bf673c0fe8..cb714dfd2c 100644 --- a/src/Rules/RuleErrorBuilder.php +++ b/src/Rules/RuleErrorBuilder.php @@ -13,10 +13,9 @@ /** * @api - * @final * @template-covariant T of RuleError */ -class RuleErrorBuilder +final class RuleErrorBuilder { private const TYPE_MESSAGE = 1; diff --git a/src/TrinaryLogic.php b/src/TrinaryLogic.php index 7e387901e0..569d5d2ec1 100644 --- a/src/TrinaryLogic.php +++ b/src/TrinaryLogic.php @@ -10,10 +10,9 @@ /** * @api - * @final * @see https://phpstan.org/developing-extensions/trinary-logic */ -class TrinaryLogic +final class TrinaryLogic { private const YES = 1; diff --git a/src/Type/AcceptsResult.php b/src/Type/AcceptsResult.php index 4cfecb05f6..949151542c 100644 --- a/src/Type/AcceptsResult.php +++ b/src/Type/AcceptsResult.php @@ -11,9 +11,8 @@ /** * @api - * @final */ -class AcceptsResult +final class AcceptsResult { /** diff --git a/src/Type/ClosureTypeFactory.php b/src/Type/ClosureTypeFactory.php index a0e82946ff..fb36d04c44 100644 --- a/src/Type/ClosureTypeFactory.php +++ b/src/Type/ClosureTypeFactory.php @@ -25,9 +25,8 @@ /** * @api - * @final */ -class ClosureTypeFactory +final class ClosureTypeFactory { public function __construct( diff --git a/src/Type/Constant/ConstantArrayTypeAndMethod.php b/src/Type/Constant/ConstantArrayTypeAndMethod.php index 01e735d949..07f4156550 100644 --- a/src/Type/Constant/ConstantArrayTypeAndMethod.php +++ b/src/Type/Constant/ConstantArrayTypeAndMethod.php @@ -8,9 +8,8 @@ /** * @api - * @final */ -class ConstantArrayTypeAndMethod +final class ConstantArrayTypeAndMethod { private function __construct( diff --git a/src/Type/Constant/ConstantArrayTypeBuilder.php b/src/Type/Constant/ConstantArrayTypeBuilder.php index 952254e1b9..5b8bb62bcb 100644 --- a/src/Type/Constant/ConstantArrayTypeBuilder.php +++ b/src/Type/Constant/ConstantArrayTypeBuilder.php @@ -24,9 +24,8 @@ /** * @api - * @final */ -class ConstantArrayTypeBuilder +final class ConstantArrayTypeBuilder { public const ARRAY_COUNT_LIMIT = 256; diff --git a/src/Type/ConstantTypeHelper.php b/src/Type/ConstantTypeHelper.php index 48cc18025b..29a36e42f1 100644 --- a/src/Type/ConstantTypeHelper.php +++ b/src/Type/ConstantTypeHelper.php @@ -22,9 +22,8 @@ /** * @api - * @final */ -class ConstantTypeHelper +final class ConstantTypeHelper { /** diff --git a/src/Type/Generic/TemplateTypeMap.php b/src/Type/Generic/TemplateTypeMap.php index 00fbc34a1d..e631819818 100644 --- a/src/Type/Generic/TemplateTypeMap.php +++ b/src/Type/Generic/TemplateTypeMap.php @@ -11,9 +11,8 @@ /** * @api - * @final */ -class TemplateTypeMap +final class TemplateTypeMap { private static ?TemplateTypeMap $empty = null; diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index b3089b62eb..ff7d609881 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -14,9 +14,8 @@ /** * @api - * @final */ -class TemplateTypeVariance +final class TemplateTypeVariance { private const INVARIANT = 1; diff --git a/src/Type/Generic/TemplateTypeVarianceMap.php b/src/Type/Generic/TemplateTypeVarianceMap.php index bcbb23ea42..072c7952e5 100644 --- a/src/Type/Generic/TemplateTypeVarianceMap.php +++ b/src/Type/Generic/TemplateTypeVarianceMap.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class TemplateTypeVarianceMap +final class TemplateTypeVarianceMap { private static ?TemplateTypeVarianceMap $empty = null; diff --git a/src/Type/GenericTypeVariableResolver.php b/src/Type/GenericTypeVariableResolver.php index 8c3f7d2da5..732e57c10a 100644 --- a/src/Type/GenericTypeVariableResolver.php +++ b/src/Type/GenericTypeVariableResolver.php @@ -6,9 +6,8 @@ /** * @api - * @final */ -class GenericTypeVariableResolver +final class GenericTypeVariableResolver { /** diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 3d2edcc419..7a016c7bee 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -38,9 +38,8 @@ /** * @api - * @final */ -class TypeCombinator +final class TypeCombinator { public static function addNull(Type $type): Type diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 8ae601b832..6987e9482b 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -17,9 +17,8 @@ /** * @api - * @final */ -class TypeUtils +final class TypeUtils { /** From dfc1c316dbae1d9c43043155b9fa552355818dbb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:30:15 +0200 Subject: [PATCH 232/508] [BCB] Removed unused config parameter `staticReflectionClassNamePatterns` --- UPGRADING.md | 1 + conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 6dc6ec47e3..1650428bab 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -101,6 +101,7 @@ Appending `(?)` in `ignoreErrors` is not supported. * Removed unused config parameter `cache.nodesByFileCountMax` * Removed unused config parameter `memoryLimitFile` * Removed unused feature toggle `disableRuntimeReflectionProvider` +* Removed unused config parameter `staticReflectionClassNamePatterns` ## Upgrading guide for extension developers diff --git a/conf/config.neon b/conf/config.neon index 05aab74b88..3a18b983b8 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -125,7 +125,6 @@ parameters: tempResultCachePath: %tmpDir%/resultCaches resultCachePath: %tmpDir%/resultCache.php resultCacheChecksProjectExtensionFilesDependencies: false - staticReflectionClassNamePatterns: [] dynamicConstantNames: - ICONV_IMPL - LIBXML_VERSION diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 7307fc8571..143187dd1d 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -140,7 +140,6 @@ parametersSchema: tempResultCachePath: string() resultCachePath: string() resultCacheChecksProjectExtensionFilesDependencies: bool() - staticReflectionClassNamePatterns: listOf(string()) dynamicConstantNames: listOf(string()) customRulesetUsed: schema(bool(), nullable()) rootDir: string() From df278a95b2f69972a0a21398a1121ba1762975e2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:31:54 +0200 Subject: [PATCH 233/508] [BCB] Removed `ReflectionProvider::supportsAnonymousClasses()` --- UPGRADING.md | 1 + src/Broker/Broker.php | 8 -------- .../BetterReflection/BetterReflectionProvider.php | 5 ----- src/Reflection/ReflectionProvider.php | 2 -- .../ReflectionProvider/DummyReflectionProvider.php | 5 ----- .../ReflectionProvider/MemoizingReflectionProvider.php | 5 ----- 6 files changed, 1 insertion(+), 25 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 1650428bab..52bc5808de 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -223,3 +223,4 @@ As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtensio * ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) * `Type::getSmallerType()`, `Type::getSmallerOrEqualType()`, `Type::getGreaterType()`, `Type::getGreaterOrEqualType()`, `Type::isSmallerThan()`, `Type::isSmallerThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. * `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. +* Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes) diff --git a/src/Broker/Broker.php b/src/Broker/Broker.php index 080d3accc8..5465a4fb45 100644 --- a/src/Broker/Broker.php +++ b/src/Broker/Broker.php @@ -69,14 +69,6 @@ public function getClassName(string $className): string return $this->reflectionProvider->getClassName($className); } - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function supportsAnonymousClasses(): bool - { - return $this->reflectionProvider->supportsAnonymousClasses(); - } - /** * @deprecated Use PHPStan\Reflection\ReflectionProvider instead */ diff --git a/src/Reflection/BetterReflection/BetterReflectionProvider.php b/src/Reflection/BetterReflection/BetterReflectionProvider.php index be27dd03a0..0bc2758152 100644 --- a/src/Reflection/BetterReflection/BetterReflectionProvider.php +++ b/src/Reflection/BetterReflection/BetterReflectionProvider.php @@ -179,11 +179,6 @@ public function getClassName(string $className): string return $reflectionClass->getName(); } - public function supportsAnonymousClasses(): bool - { - return true; - } - public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $scope): ClassReflection { if (isset($classNode->namespacedName)) { diff --git a/src/Reflection/ReflectionProvider.php b/src/Reflection/ReflectionProvider.php index e268800f5a..e0a3c6efce 100644 --- a/src/Reflection/ReflectionProvider.php +++ b/src/Reflection/ReflectionProvider.php @@ -16,8 +16,6 @@ public function getClass(string $className): ClassReflection; public function getClassName(string $className): string; - public function supportsAnonymousClasses(): bool; - public function getAnonymousClassReflection( Node\Stmt\Class_ $classNode, Scope $scope, diff --git a/src/Reflection/ReflectionProvider/DummyReflectionProvider.php b/src/Reflection/ReflectionProvider/DummyReflectionProvider.php index 7ee5729483..1fbe97ae5d 100644 --- a/src/Reflection/ReflectionProvider/DummyReflectionProvider.php +++ b/src/Reflection/ReflectionProvider/DummyReflectionProvider.php @@ -29,11 +29,6 @@ public function getClassName(string $className): string return $className; } - public function supportsAnonymousClasses(): bool - { - return false; - } - public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $scope): ClassReflection { throw new ShouldNotHappenException(); diff --git a/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php b/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php index 9d6cacd951..17dc5ad4ea 100644 --- a/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php +++ b/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php @@ -56,11 +56,6 @@ public function getClassName(string $className): string return $this->classNames[$lowerClassName] = $this->provider->getClassName($className); } - public function supportsAnonymousClasses(): bool - { - return $this->provider->supportsAnonymousClasses(); - } - public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $scope): ClassReflection { return $this->provider->getAnonymousClassReflection($classNode, $scope); From 30b9eb8b9879bb4bd92f99ee3a235ac3d81ea2fb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:35:52 +0200 Subject: [PATCH 234/508] [BCB] Removed `Broker` --- UPGRADING.md | 8 + conf/config.neon | 9 -- phpstan-baseline.neon | 40 ----- src/Broker/Broker.php | 138 ------------------ src/Broker/BrokerFactory.php | 15 -- src/DependencyInjection/ContainerFactory.php | 3 - ...assReflectionExtensionRegistryProvider.php | 2 - ...micReturnTypeExtensionRegistryProvider.php | 2 - ...ypeSpecifyingExtensionRegistryProvider.php | 2 - .../ValidateIgnoredErrorsExtension.php | 2 +- src/PhpDoc/StubValidator.php | 3 - .../BetterReflectionProvider.php | 7 +- src/Reflection/BrokerAwareExtension.php | 16 -- src/Reflection/ClassReflection.php | 1 - .../ClassReflectionExtensionRegistry.php | 10 -- ...alObjectCratesClassReflectionExtension.php | 20 ++- src/Reflection/ReflectionProvider.php | 3 + .../DummyReflectionProvider.php | 5 + .../MemoizingReflectionProvider.php | 5 + src/Testing/PHPStanTestCase.php | 10 -- .../DynamicReturnTypeExtensionRegistry.php | 10 -- src/Type/ObjectShapeType.php | 3 - src/Type/ObjectType.php | 2 - ...peratorTypeSpecifyingExtensionRegistry.php | 14 -- tests/PHPStan/Type/FileTypeMapperTest.php | 3 +- 25 files changed, 45 insertions(+), 288 deletions(-) delete mode 100644 src/Broker/Broker.php delete mode 100644 src/Reflection/BrokerAwareExtension.php diff --git a/UPGRADING.md b/UPGRADING.md index 52bc5808de..729d6066b5 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -215,6 +215,14 @@ Learn more: https://phpstan.org/blog/preprocessing-ast-for-custom-rules As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtension`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.ExpressionTypeResolverExtension.html) interface instead and register it as a service. +### Removed `PHPStan\Broker\Broker` + +Use [`PHPStan\Reflection\ReflectionProvider`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ReflectionProvider.html) instead. + +`BrokerAwareExtension` was also removed. Ask for `ReflectionProvider` in the extension constructor instead. + +Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createReflectionProvider()`. + ### Minor backward compatibility breaks * Classes that were previously `@final` were made `final` diff --git a/conf/config.neon b/conf/config.neon index 3a18b983b8..5dc867fc1b 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1881,15 +1881,6 @@ services: parentDirectory: %currentWorkingDirectory% autowired: false - broker: - class: PHPStan\Broker\Broker - factory: @brokerFactory::create - autowired: - - PHPStan\Broker\Broker - - brokerFactory: - class: PHPStan\Broker\BrokerFactory - cacheStorage: class: PHPStan\Cache\FileCacheStorage arguments: diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 81b6bc27c6..80700ff58b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -189,14 +189,6 @@ parameters: count: 1 path: src/PhpDoc/ResolvedPhpDocBlock.php - - - message: """ - #^Call to deprecated method getInstance\\(\\) of class PHPStan\\\\Broker\\\\Broker\\: - Use PHPStan\\\\Reflection\\\\ReflectionProviderStaticAccessor instead$# - """ - count: 1 - path: src/PhpDoc/StubValidator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" count: 1 @@ -1161,22 +1153,6 @@ parameters: count: 3 path: src/Type/NullType.php - - - message: """ - #^Call to deprecated method getInstance\\(\\) of class PHPStan\\\\Broker\\\\Broker\\: - Use PHPStan\\\\Reflection\\\\ReflectionProviderStaticAccessor instead$# - """ - count: 2 - path: src/Type/ObjectShapeType.php - - - - message: """ - #^Call to deprecated method getUniversalObjectCratesClasses\\(\\) of class PHPStan\\\\Broker\\\\Broker\\: - Inject %%universalObjectCratesClasses%% parameter instead\\.$# - """ - count: 2 - path: src/Type/ObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 @@ -1192,22 +1168,6 @@ parameters: count: 1 path: src/Type/ObjectShapeType.php - - - message: """ - #^Call to deprecated method getInstance\\(\\) of class PHPStan\\\\Broker\\\\Broker\\: - Use PHPStan\\\\Reflection\\\\ReflectionProviderStaticAccessor instead$# - """ - count: 1 - path: src/Type/ObjectType.php - - - - message: """ - #^Call to deprecated method getUniversalObjectCratesClasses\\(\\) of class PHPStan\\\\Broker\\\\Broker\\: - Inject %%universalObjectCratesClasses%% parameter instead\\.$# - """ - count: 1 - path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" count: 1 diff --git a/src/Broker/Broker.php b/src/Broker/Broker.php deleted file mode 100644 index 5465a4fb45..0000000000 --- a/src/Broker/Broker.php +++ /dev/null @@ -1,138 +0,0 @@ -reflectionProvider->hasClass($className); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function getClass(string $className): ClassReflection - { - return $this->reflectionProvider->getClass($className); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function getClassName(string $className): string - { - return $this->reflectionProvider->getClassName($className); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $scope): ClassReflection - { - return $this->reflectionProvider->getAnonymousClassReflection($classNode, $scope); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function hasFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): bool - { - return $this->reflectionProvider->hasFunction($nameNode, $namespaceAnswerer); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function getFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): FunctionReflection - { - return $this->reflectionProvider->getFunction($nameNode, $namespaceAnswerer); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function resolveFunctionName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ?string - { - return $this->reflectionProvider->resolveFunctionName($nameNode, $namespaceAnswerer); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function hasConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): bool - { - return $this->reflectionProvider->hasConstant($nameNode, $namespaceAnswerer); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): GlobalConstantReflection - { - return $this->reflectionProvider->getConstant($nameNode, $namespaceAnswerer); - } - - /** - * @deprecated Use PHPStan\Reflection\ReflectionProvider instead - */ - public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ?string - { - return $this->reflectionProvider->resolveConstantName($nameNode, $namespaceAnswerer); - } - - /** - * @deprecated Inject %universalObjectCratesClasses% parameter instead. - * - * @return string[] - */ - public function getUniversalObjectCratesClasses(): array - { - return $this->universalObjectCratesClasses; - } - -} diff --git a/src/Broker/BrokerFactory.php b/src/Broker/BrokerFactory.php index 177b6b5843..bbd8d97a3d 100644 --- a/src/Broker/BrokerFactory.php +++ b/src/Broker/BrokerFactory.php @@ -2,9 +2,6 @@ namespace PHPStan\Broker; -use PHPStan\DependencyInjection\Container; -use PHPStan\Reflection\ReflectionProvider; - final class BrokerFactory { @@ -17,16 +14,4 @@ final class BrokerFactory public const OPERATOR_TYPE_SPECIFYING_EXTENSION_TAG = 'phpstan.broker.operatorTypeSpecifyingExtension'; public const EXPRESSION_TYPE_RESOLVER_EXTENSION_TAG = 'phpstan.broker.expressionTypeResolverExtension'; - public function __construct(private Container $container) - { - } - - public function create(): Broker - { - return new Broker( - $this->container->getByType(ReflectionProvider::class), - $this->container->getParameter('universalObjectCratesClasses'), - ); - } - } diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index 4ab01e56c9..c997c65ec2 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -22,7 +22,6 @@ use PHPStan\BetterReflection\Reflector\Reflector; use PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber; use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator; -use PHPStan\Broker\Broker; use PHPStan\Command\CommandHelper; use PHPStan\File\FileHelper; use PHPStan\Node\Printer\Printer; @@ -181,8 +180,6 @@ public static function postInitializeContainer(Container $container): void $container->getByType(Printer::class), ); - $broker = $container->getByType(Broker::class); - Broker::registerInstance($broker); ReflectionProviderStaticAccessor::registerInstance($container->getByType(ReflectionProvider::class)); PhpVersionStaticAccessor::registerInstance($container->getByType(PhpVersion::class)); ObjectType::resetCaches(); diff --git a/src/DependencyInjection/Reflection/LazyClassReflectionExtensionRegistryProvider.php b/src/DependencyInjection/Reflection/LazyClassReflectionExtensionRegistryProvider.php index cb8c2d6543..7e47b6498c 100644 --- a/src/DependencyInjection/Reflection/LazyClassReflectionExtensionRegistryProvider.php +++ b/src/DependencyInjection/Reflection/LazyClassReflectionExtensionRegistryProvider.php @@ -2,7 +2,6 @@ namespace PHPStan\DependencyInjection\Reflection; -use PHPStan\Broker\Broker; use PHPStan\Broker\BrokerFactory; use PHPStan\DependencyInjection\Container; use PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension; @@ -35,7 +34,6 @@ public function getRegistry(): ClassReflectionExtensionRegistry $mixinPropertiesClassReflectionExtension = $this->container->getByType(MixinPropertiesClassReflectionExtension::class); $this->registry = new ClassReflectionExtensionRegistry( - $this->container->getByType(Broker::class), array_merge([$phpClassReflectionExtension], $this->container->getServicesByTag(BrokerFactory::PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG), [$annotationsPropertiesClassReflectionExtension, $mixinPropertiesClassReflectionExtension]), array_merge([$phpClassReflectionExtension], $this->container->getServicesByTag(BrokerFactory::METHODS_CLASS_REFLECTION_EXTENSION_TAG), [$annotationsMethodsClassReflectionExtension, $mixinMethodsClassReflectionExtension]), $this->container->getServicesByTag(BrokerFactory::ALLOWED_SUB_TYPES_CLASS_REFLECTION_EXTENSION_TAG), diff --git a/src/DependencyInjection/Type/LazyDynamicReturnTypeExtensionRegistryProvider.php b/src/DependencyInjection/Type/LazyDynamicReturnTypeExtensionRegistryProvider.php index 9a15af910f..3dea120177 100644 --- a/src/DependencyInjection/Type/LazyDynamicReturnTypeExtensionRegistryProvider.php +++ b/src/DependencyInjection/Type/LazyDynamicReturnTypeExtensionRegistryProvider.php @@ -2,7 +2,6 @@ namespace PHPStan\DependencyInjection\Type; -use PHPStan\Broker\Broker; use PHPStan\Broker\BrokerFactory; use PHPStan\DependencyInjection\Container; use PHPStan\Reflection\ReflectionProvider; @@ -21,7 +20,6 @@ public function getRegistry(): DynamicReturnTypeExtensionRegistry { if ($this->registry === null) { $this->registry = new DynamicReturnTypeExtensionRegistry( - $this->container->getByType(Broker::class), $this->container->getByType(ReflectionProvider::class), $this->container->getServicesByTag(BrokerFactory::DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG), $this->container->getServicesByTag(BrokerFactory::DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG), diff --git a/src/DependencyInjection/Type/LazyOperatorTypeSpecifyingExtensionRegistryProvider.php b/src/DependencyInjection/Type/LazyOperatorTypeSpecifyingExtensionRegistryProvider.php index 5f1a719b48..2be97ee777 100644 --- a/src/DependencyInjection/Type/LazyOperatorTypeSpecifyingExtensionRegistryProvider.php +++ b/src/DependencyInjection/Type/LazyOperatorTypeSpecifyingExtensionRegistryProvider.php @@ -2,7 +2,6 @@ namespace PHPStan\DependencyInjection\Type; -use PHPStan\Broker\Broker; use PHPStan\Broker\BrokerFactory; use PHPStan\DependencyInjection\Container; use PHPStan\Type\OperatorTypeSpecifyingExtensionRegistry; @@ -20,7 +19,6 @@ public function getRegistry(): OperatorTypeSpecifyingExtensionRegistry { if ($this->registry === null) { $this->registry = new OperatorTypeSpecifyingExtensionRegistry( - $this->container->getByType(Broker::class), $this->container->getServicesByTag(BrokerFactory::OPERATOR_TYPE_SPECIFYING_EXTENSION_TAG), ); } diff --git a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php index 0f5dc0d9e2..87d7a31a2e 100644 --- a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php +++ b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php @@ -103,7 +103,7 @@ public function resolveTypeAlias(string $aliasName, NameScope $nameScope): ?Type public function getRegistry(): OperatorTypeSpecifyingExtensionRegistry { - return new OperatorTypeSpecifyingExtensionRegistry(null, []); + return new OperatorTypeSpecifyingExtensionRegistry([]); } }, new OversizedArrayBuilder(), true), diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index 96922b4c09..a0539b7168 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -6,7 +6,6 @@ use PHPStan\Analyser\FileAnalyser; use PHPStan\Analyser\InternalError; use PHPStan\Analyser\NodeScopeResolver; -use PHPStan\Broker\Broker; use PHPStan\Collectors\Registry as CollectorRegistry; use PHPStan\DependencyInjection\Container; use PHPStan\DependencyInjection\DerivativeContainerFactory; @@ -109,7 +108,6 @@ public function validate(array $stubFiles, bool $debug): array return []; } - $originalBroker = Broker::getInstance(); $originalReflectionProvider = ReflectionProviderStaticAccessor::getInstance(); $originalPhpVersion = PhpVersionStaticAccessor::getInstance(); $container = $this->derivativeContainerFactory->create([ @@ -158,7 +156,6 @@ static function (): void { } } - Broker::registerInstance($originalBroker); ReflectionProviderStaticAccessor::registerInstance($originalReflectionProvider); PhpVersionStaticAccessor::registerInstance($originalPhpVersion); ObjectType::resetCaches(); diff --git a/src/Reflection/BetterReflection/BetterReflectionProvider.php b/src/Reflection/BetterReflection/BetterReflectionProvider.php index 0bc2758152..06e94ae718 100644 --- a/src/Reflection/BetterReflection/BetterReflectionProvider.php +++ b/src/Reflection/BetterReflection/BetterReflectionProvider.php @@ -75,7 +75,7 @@ final class BetterReflectionProvider implements ReflectionProvider private array $cachedConstants = []; /** - * @param string[] $universalObjectCratesClasses + * @param list $universalObjectCratesClasses */ public function __construct( private ReflectionProvider\ReflectionProviderProvider $reflectionProviderProvider, @@ -257,6 +257,11 @@ public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $ return self::$anonymousClasses[$className]; } + public function getUniversalObjectCratesClasses(): array + { + return $this->universalObjectCratesClasses; + } + public function hasFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): bool { return $this->resolveFunctionName($nameNode, $namespaceAnswerer) !== null; diff --git a/src/Reflection/BrokerAwareExtension.php b/src/Reflection/BrokerAwareExtension.php deleted file mode 100644 index 9ca104d127..0000000000 --- a/src/Reflection/BrokerAwareExtension.php +++ /dev/null @@ -1,16 +0,0 @@ -reflectionProvider, - $this->universalObjectCratesClasses, $this, )) { return true; diff --git a/src/Reflection/ClassReflectionExtensionRegistry.php b/src/Reflection/ClassReflectionExtensionRegistry.php index 2dd864952a..1705f47461 100644 --- a/src/Reflection/ClassReflectionExtensionRegistry.php +++ b/src/Reflection/ClassReflectionExtensionRegistry.php @@ -2,10 +2,8 @@ namespace PHPStan\Reflection; -use PHPStan\Broker\Broker; use PHPStan\Reflection\RequireExtension\RequireExtendsMethodsClassReflectionExtension; use PHPStan\Reflection\RequireExtension\RequireExtendsPropertiesClassReflectionExtension; -use function array_merge; final class ClassReflectionExtensionRegistry { @@ -16,7 +14,6 @@ final class ClassReflectionExtensionRegistry * @param AllowedSubTypesClassReflectionExtension[] $allowedSubTypesClassReflectionExtensions */ public function __construct( - Broker $broker, private array $propertiesClassReflectionExtensions, private array $methodsClassReflectionExtensions, private array $allowedSubTypesClassReflectionExtensions, @@ -24,13 +21,6 @@ public function __construct( private RequireExtendsMethodsClassReflectionExtension $requireExtendsMethodsClassReflectionExtension, ) { - foreach (array_merge($propertiesClassReflectionExtensions, $methodsClassReflectionExtensions, $allowedSubTypesClassReflectionExtensions) as $extension) { - if (!($extension instanceof BrokerAwareExtension)) { - continue; - } - - $extension->setBroker($broker); - } } /** diff --git a/src/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php b/src/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php index a39fe6c67b..df06443436 100644 --- a/src/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php +++ b/src/Reflection/Php/UniversalObjectCratesClassReflectionExtension.php @@ -14,7 +14,7 @@ final class UniversalObjectCratesClassReflectionExtension { /** - * @param string[] $classes + * @param list $classes */ public function __construct( private ReflectionProvider $reflectionProvider, @@ -26,17 +26,29 @@ public function __construct( public function hasProperty(ClassReflection $classReflection, string $propertyName): bool { - return self::isUniversalObjectCrate( + return self::isUniversalObjectCrateImplementation( $this->reflectionProvider, $this->classes, $classReflection, ); } + public static function isUniversalObjectCrate( + ReflectionProvider $reflectionProvider, + ClassReflection $classReflection, + ): bool + { + return self::isUniversalObjectCrateImplementation( + $reflectionProvider, + $reflectionProvider->getUniversalObjectCratesClasses(), + $classReflection, + ); + } + /** - * @param string[] $classes + * @param list $classes */ - public static function isUniversalObjectCrate( + private static function isUniversalObjectCrateImplementation( ReflectionProvider $reflectionProvider, array $classes, ClassReflection $classReflection, diff --git a/src/Reflection/ReflectionProvider.php b/src/Reflection/ReflectionProvider.php index e0a3c6efce..2e0cc7ee20 100644 --- a/src/Reflection/ReflectionProvider.php +++ b/src/Reflection/ReflectionProvider.php @@ -21,6 +21,9 @@ public function getAnonymousClassReflection( Scope $scope, ): ClassReflection; + /** @return list */ + public function getUniversalObjectCratesClasses(): array; + public function hasFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): bool; public function getFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): FunctionReflection; diff --git a/src/Reflection/ReflectionProvider/DummyReflectionProvider.php b/src/Reflection/ReflectionProvider/DummyReflectionProvider.php index 1fbe97ae5d..2f96b7016f 100644 --- a/src/Reflection/ReflectionProvider/DummyReflectionProvider.php +++ b/src/Reflection/ReflectionProvider/DummyReflectionProvider.php @@ -34,6 +34,11 @@ public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $ throw new ShouldNotHappenException(); } + public function getUniversalObjectCratesClasses(): array + { + return []; + } + public function hasFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): bool { return false; diff --git a/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php b/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php index 17dc5ad4ea..48060fdfbd 100644 --- a/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php +++ b/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php @@ -61,6 +61,11 @@ public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $ return $this->provider->getAnonymousClassReflection($classNode, $scope); } + public function getUniversalObjectCratesClasses(): array + { + return $this->provider->getUniversalObjectCratesClasses(); + } + public function hasFunction(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): bool { return $this->provider->hasFunction($nameNode, $namespaceAnswerer); diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index c5d0a651a6..73c2e19947 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -12,7 +12,6 @@ use PHPStan\BetterReflection\Reflector\ConstantReflector; use PHPStan\BetterReflection\Reflector\FunctionReflector; use PHPStan\BetterReflection\Reflector\Reflector; -use PHPStan\Broker\Broker; use PHPStan\DependencyInjection\Container; use PHPStan\DependencyInjection\ContainerFactory; use PHPStan\DependencyInjection\Reflection\ClassReflectionExtensionRegistryProvider; @@ -115,15 +114,6 @@ public static function getParser(): Parser return $parser; } - /** - * @api - * @deprecated Use createReflectionProvider() instead - */ - public function createBroker(): Broker - { - return self::getContainer()->getByType(Broker::class); - } - /** @api */ public static function createReflectionProvider(): ReflectionProvider { diff --git a/src/Type/DynamicReturnTypeExtensionRegistry.php b/src/Type/DynamicReturnTypeExtensionRegistry.php index 002a87f66e..e2a30437b3 100644 --- a/src/Type/DynamicReturnTypeExtensionRegistry.php +++ b/src/Type/DynamicReturnTypeExtensionRegistry.php @@ -2,8 +2,6 @@ namespace PHPStan\Type; -use PHPStan\Broker\Broker; -use PHPStan\Reflection\BrokerAwareExtension; use PHPStan\Reflection\ReflectionProvider; use function array_merge; use function strtolower; @@ -23,20 +21,12 @@ final class DynamicReturnTypeExtensionRegistry * @param DynamicFunctionReturnTypeExtension[] $dynamicFunctionReturnTypeExtensions */ public function __construct( - Broker $broker, private ReflectionProvider $reflectionProvider, private array $dynamicMethodReturnTypeExtensions, private array $dynamicStaticMethodReturnTypeExtensions, private array $dynamicFunctionReturnTypeExtensions, ) { - foreach (array_merge($dynamicMethodReturnTypeExtensions, $dynamicStaticMethodReturnTypeExtensions, $dynamicFunctionReturnTypeExtensions) as $extension) { - if (!($extension instanceof BrokerAwareExtension)) { - continue; - } - - $extension->setBroker($broker); - } } /** diff --git a/src/Type/ObjectShapeType.php b/src/Type/ObjectShapeType.php index a00324259a..aeba44bb19 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -3,7 +3,6 @@ namespace PHPStan\Type; use PHPStan\Analyser\OutOfClassScope; -use PHPStan\Broker\Broker; use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode; use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; @@ -138,7 +137,6 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult foreach ($type->getObjectClassReflections() as $classReflection) { if (!UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate( $reflectionProvider, - Broker::getInstance()->getUniversalObjectCratesClasses(), $classReflection, )) { continue; @@ -251,7 +249,6 @@ public function isSuperTypeOf(Type $type): TrinaryLogic foreach ($type->getObjectClassReflections() as $classReflection) { if (!UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate( $reflectionProvider, - Broker::getInstance()->getUniversalObjectCratesClasses(), $classReflection, )) { continue; diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 31a9613e91..672b1f57c8 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -13,7 +13,6 @@ use Iterator; use IteratorAggregate; use PHPStan\Analyser\OutOfClassScope; -use PHPStan\Broker\Broker; use PHPStan\Broker\ClassNotFoundException; use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; @@ -619,7 +618,6 @@ public function toArray(): Type !$classReflection->getNativeReflection()->isUserDefined() || UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate( $reflectionProvider, - Broker::getInstance()->getUniversalObjectCratesClasses(), $classReflection, ) ) { diff --git a/src/Type/OperatorTypeSpecifyingExtensionRegistry.php b/src/Type/OperatorTypeSpecifyingExtensionRegistry.php index 809ba5bd20..7b84648f28 100644 --- a/src/Type/OperatorTypeSpecifyingExtensionRegistry.php +++ b/src/Type/OperatorTypeSpecifyingExtensionRegistry.php @@ -2,8 +2,6 @@ namespace PHPStan\Type; -use PHPStan\Broker\Broker; -use PHPStan\Reflection\BrokerAwareExtension; use function array_filter; use function array_values; @@ -14,21 +12,9 @@ final class OperatorTypeSpecifyingExtensionRegistry * @param OperatorTypeSpecifyingExtension[] $extensions */ public function __construct( - ?Broker $broker, private array $extensions, ) { - if ($broker === null) { - return; - } - - foreach ($extensions as $extension) { - if (!$extension instanceof BrokerAwareExtension) { - continue; - } - - $extension->setBroker($broker); - } } /** diff --git a/tests/PHPStan/Type/FileTypeMapperTest.php b/tests/PHPStan/Type/FileTypeMapperTest.php index a5be40c268..c1af0c7740 100644 --- a/tests/PHPStan/Type/FileTypeMapperTest.php +++ b/tests/PHPStan/Type/FileTypeMapperTest.php @@ -3,7 +3,6 @@ namespace PHPStan\Type; use DependentPhpDocs\Foo; -use PHPStan\Broker\Broker; use PHPStan\PhpDoc\Tag\ReturnTag; use PHPStan\ShouldNotHappenException; use PHPStan\Testing\PHPStanTestCase; @@ -161,7 +160,7 @@ public function testFileThrowsPhpDocs(): void public function testFileWithCyclicPhpDocs(): void { - self::getContainer()->getByType(Broker::class); + $this->createReflectionProvider(); /** @var FileTypeMapper $fileTypeMapper */ $fileTypeMapper = self::getContainer()->getByType(FileTypeMapper::class); From 4213c244ca3aff6d3fda7d045fecc4e3ad0564c4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:49:04 +0200 Subject: [PATCH 235/508] Fix build --- phpstan-baseline.neon | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 80700ff58b..95c67cfed4 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,10 @@ parameters: ignoreErrors: + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + count: 1 + path: build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php + - message: "#^Method PHPStan\\\\Analyser\\\\AnalyserResultFinalizer\\:\\:finalize\\(\\) throws checked exception Throwable but it's missing from the PHPDoc @throws tag\\.$#" count: 1 @@ -159,11 +164,6 @@ parameters: count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" - count: 1 - path: build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php - - message: "#^Variable method call on PHPStan\\\\Reflection\\\\ClassReflection\\.$#" count: 2 From 248ce53a7e52c2435c39df7785486ee0d5bbb866 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:50:49 +0200 Subject: [PATCH 236/508] [BCB] Remove `ArrayType::generalizeKeys()` --- UPGRADING.md | 1 + src/Type/ArrayType.php | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 729d6066b5..d75f6b3a3c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -232,3 +232,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * `Type::getSmallerType()`, `Type::getSmallerOrEqualType()`, `Type::getGreaterType()`, `Type::getGreaterOrEqualType()`, `Type::isSmallerThan()`, `Type::isSmallerThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. * `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. * Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes) +* Remove `ArrayType::generalizeKeys()` diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index db1c331ea6..98acab68df 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -183,14 +183,6 @@ function () use ($level, $isMixedKeyType, $isMixedItemType): string { ); } - /** - * @deprecated - */ - public function generalizeKeys(): self - { - return new self($this->keyType->generalize(GeneralizePrecision::lessSpecific()), $this->itemType); - } - public function generalizeValues(): self { return new self($this->keyType, $this->itemType->generalize(GeneralizePrecision::lessSpecific())); From 73a63f111b41744d2d43c5c8b04ade35e5b24a73 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:51:14 +0200 Subject: [PATCH 237/508] [BCB] Remove `ArrayType::count()` --- UPGRADING.md | 1 + src/Type/ArrayType.php | 6 ------ src/Type/Constant/ConstantArrayType.php | 6 ------ 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index d75f6b3a3c..ae40bcc88a 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -233,3 +233,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. * Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes) * Remove `ArrayType::generalizeKeys()` +* Remove `ArrayType::count()` diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 98acab68df..4e18f428fc 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -638,12 +638,6 @@ public function toArrayKey(): Type return new ErrorType(); } - /** @deprecated Use getArraySize() instead */ - public function count(): Type - { - return $this->getArraySize(); - } - /** @deprecated Use $offsetType->toArrayKey() instead */ public static function castToArrayKeyType(Type $offsetType): Type { diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 6063a96ef2..5b6700d80b 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -1421,12 +1421,6 @@ private function getKeysOrValuesArray(array $types): self return new self($keyTypes, $valueTypes, $autoIndexes, $optionalKeys, TrinaryLogic::createYes()); } - /** @deprecated Use getArraySize() instead */ - public function count(): Type - { - return $this->getArraySize(); - } - public function describe(VerbosityLevel $level): string { $describeValue = function (bool $truncate) use ($level): string { From 68f6ec0699b1749ca14ab3ca7a2c72bff77799ba Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:51:46 +0200 Subject: [PATCH 238/508] [BCB] Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead --- UPGRADING.md | 1 + src/Type/ArrayType.php | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index ae40bcc88a..b4a7fdfe32 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -234,3 +234,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes) * Remove `ArrayType::generalizeKeys()` * Remove `ArrayType::count()` +* Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 4e18f428fc..dc9c6ec228 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -638,12 +638,6 @@ public function toArrayKey(): Type return new ErrorType(); } - /** @deprecated Use $offsetType->toArrayKey() instead */ - public static function castToArrayKeyType(Type $offsetType): Type - { - return $offsetType->toArrayKey(); - } - public function inferTemplateTypes(Type $receivedType): TemplateTypeMap { if ($receivedType instanceof UnionType || $receivedType instanceof IntersectionType) { From 8e2cf7bd957dbbab1c43f3d0983c8cf2108b55da Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:52:06 +0200 Subject: [PATCH 239/508] Upgrading note --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index b4a7fdfe32..154776b331 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -233,5 +233,5 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. * Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes) * Remove `ArrayType::generalizeKeys()` -* Remove `ArrayType::count()` +* Remove `ArrayType::count()`, use `Type::getArraySize()` instead * Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead From 9bab8ca6ebe55b2cbdba5c07bbed26411d6b25eb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:53:06 +0200 Subject: [PATCH 240/508] Remove AppendedArrayKeyTypeRule and AppendedArrayItemTypeRule --- phpstan-baseline.neon | 32 ------- .../Arrays/AppendedArrayItemTypeRule.php | 93 ------------------- src/Rules/Arrays/AppendedArrayKeyTypeRule.php | 89 ------------------ .../Arrays/AppendedArrayItemTypeRuleTest.php | 65 ------------- .../Arrays/AppendedArrayKeyTypeRuleTest.php | 71 -------------- 5 files changed, 350 deletions(-) delete mode 100644 src/Rules/Arrays/AppendedArrayItemTypeRule.php delete mode 100644 src/Rules/Arrays/AppendedArrayKeyTypeRule.php delete mode 100644 tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php delete mode 100644 tests/PHPStan/Rules/Arrays/AppendedArrayKeyTypeRuleTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 95c67cfed4..f7e243fc88 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1677,38 +1677,6 @@ parameters: count: 1 path: tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php - - - message: """ - #^Instantiation of deprecated class PHPStan\\\\Rules\\\\Arrays\\\\AppendedArrayItemTypeRule\\: - Replaced by PHPStan\\\\Rules\\\\Properties\\\\TypesAssignedToPropertiesRule$# - """ - count: 1 - path: tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php - - - - message: """ - #^Return type of method PHPStan\\\\Rules\\\\Arrays\\\\AppendedArrayItemTypeRuleTest\\:\\:getRule\\(\\) has typehint with deprecated class PHPStan\\\\Rules\\\\Arrays\\\\AppendedArrayItemTypeRule\\: - Replaced by PHPStan\\\\Rules\\\\Properties\\\\TypesAssignedToPropertiesRule$# - """ - count: 1 - path: tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php - - - - message: """ - #^Instantiation of deprecated class PHPStan\\\\Rules\\\\Arrays\\\\AppendedArrayKeyTypeRule\\: - Replaced by PHPStan\\\\Rules\\\\Properties\\\\TypesAssignedToPropertiesRule$# - """ - count: 1 - path: tests/PHPStan/Rules/Arrays/AppendedArrayKeyTypeRuleTest.php - - - - message: """ - #^Return type of method PHPStan\\\\Rules\\\\Arrays\\\\AppendedArrayKeyTypeRuleTest\\:\\:getRule\\(\\) has typehint with deprecated class PHPStan\\\\Rules\\\\Arrays\\\\AppendedArrayKeyTypeRule\\: - Replaced by PHPStan\\\\Rules\\\\Properties\\\\TypesAssignedToPropertiesRule$# - """ - count: 1 - path: tests/PHPStan/Rules/Arrays/AppendedArrayKeyTypeRuleTest.php - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" count: 1 diff --git a/src/Rules/Arrays/AppendedArrayItemTypeRule.php b/src/Rules/Arrays/AppendedArrayItemTypeRule.php deleted file mode 100644 index dee1dc6c30..0000000000 --- a/src/Rules/Arrays/AppendedArrayItemTypeRule.php +++ /dev/null @@ -1,93 +0,0 @@ - - */ -final class AppendedArrayItemTypeRule implements Rule -{ - - public function __construct( - private PropertyReflectionFinder $propertyReflectionFinder, - private RuleLevelHelper $ruleLevelHelper, - ) - { - } - - public function getNodeType(): string - { - return Node\Expr::class; - } - - public function processNode(Node $node, Scope $scope): array - { - if ( - !$node instanceof Assign - && !$node instanceof AssignOp - && !$node instanceof AssignRef - ) { - return []; - } - - if (!($node->var instanceof ArrayDimFetch)) { - return []; - } - - if ( - !$node->var->var instanceof Node\Expr\PropertyFetch - && !$node->var->var instanceof Node\Expr\StaticPropertyFetch - ) { - return []; - } - - $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node->var->var, $scope); - if ($propertyReflection === null) { - return []; - } - - $assignedToType = $propertyReflection->getWritableType(); - if (!$assignedToType->isArray()->yes()) { - return []; - } - - if ($node instanceof Assign || $node instanceof AssignRef) { - $assignedValueType = $scope->getType($node->expr); - } else { - $assignedValueType = $scope->getType($node); - } - - $itemType = $assignedToType->getIterableValueType(); - $accepts = $this->ruleLevelHelper->acceptsWithReason($itemType, $assignedValueType, $scope->isDeclareStrictTypes()); - if (!$accepts->result) { - $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($itemType, $assignedValueType); - return [ - RuleErrorBuilder::message(sprintf( - 'Array (%s) does not accept %s.', - $assignedToType->describe($verbosityLevel), - $assignedValueType->describe($verbosityLevel), - )) - ->acceptsReasonsTip($accepts->reasons) - ->identifier('array.valueType') - ->build(), - ]; - } - - return []; - } - -} diff --git a/src/Rules/Arrays/AppendedArrayKeyTypeRule.php b/src/Rules/Arrays/AppendedArrayKeyTypeRule.php deleted file mode 100644 index 3e91fe8dbe..0000000000 --- a/src/Rules/Arrays/AppendedArrayKeyTypeRule.php +++ /dev/null @@ -1,89 +0,0 @@ - - */ -final class AppendedArrayKeyTypeRule implements Rule -{ - - public function __construct( - private PropertyReflectionFinder $propertyReflectionFinder, - private bool $checkUnionTypes, - ) - { - } - - public function getNodeType(): string - { - return Assign::class; - } - - public function processNode(Node $node, Scope $scope): array - { - if (!($node->var instanceof ArrayDimFetch)) { - return []; - } - - if ( - !$node->var->var instanceof Node\Expr\PropertyFetch - && !$node->var->var instanceof Node\Expr\StaticPropertyFetch - ) { - return []; - } - - $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($node->var->var, $scope); - if ($propertyReflection === null) { - return []; - } - - $arrayType = $propertyReflection->getReadableType(); - if (!$arrayType->isArray()->yes()) { - return []; - } - - if ($node->var->dim !== null) { - $dimensionType = $scope->getType($node->var->dim); - $isValidKey = AllowedArrayKeysTypes::getType()->isSuperTypeOf($dimensionType); - if (!$isValidKey->yes()) { - // already handled by InvalidKeyInArrayDimFetchRule - return []; - } - - $keyType = $dimensionType->toArrayKey(); - if (!$this->checkUnionTypes && $keyType instanceof UnionType) { - return []; - } - } else { - $keyType = new IntegerType(); - } - - if (!$arrayType->getIterableKeyType()->isSuperTypeOf($keyType)->yes()) { - $verbosity = VerbosityLevel::getRecommendedLevelByType($arrayType->getIterableKeyType(), $keyType); - return [ - RuleErrorBuilder::message(sprintf( - 'Array (%s) does not accept key %s.', - $arrayType->describe($verbosity), - $keyType->describe(VerbosityLevel::value()), - ))->identifier('array.keyType')->build(), - ]; - } - - return []; - } - -} diff --git a/tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php b/tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php deleted file mode 100644 index 3a6c6dfb4f..0000000000 --- a/tests/PHPStan/Rules/Arrays/AppendedArrayItemTypeRuleTest.php +++ /dev/null @@ -1,65 +0,0 @@ - - */ -class AppendedArrayItemTypeRuleTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new AppendedArrayItemTypeRule( - new PropertyReflectionFinder(), - new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false, false, false), - ); - } - - public function testAppendedArrayItemType(): void - { - $this->analyse( - [__DIR__ . '/data/appended-array-item.php'], - [ - [ - 'Array (array) does not accept string.', - 18, - ], - [ - 'Array (array) does not accept array{1, 2, 3}.', - 20, - ], - [ - 'Array (array) does not accept array{\'AppendedArrayItem\\\\Foo\', \'classMethod\'}.', - 23, - ], - [ - 'Array (array) does not accept array{\'Foo\', \'Hello world\'}.', - 25, - ], - [ - 'Array (array) does not accept string.', - 27, - ], - [ - 'Array (array) does not accept string.', - 32, - ], - [ - 'Array (array) does not accept Closure(): 1.', - 45, - ], - [ - 'Array (array) does not accept AppendedArrayItem\Baz.', - 79, - ], - ], - ); - } - -} diff --git a/tests/PHPStan/Rules/Arrays/AppendedArrayKeyTypeRuleTest.php b/tests/PHPStan/Rules/Arrays/AppendedArrayKeyTypeRuleTest.php deleted file mode 100644 index d74a1ddd8e..0000000000 --- a/tests/PHPStan/Rules/Arrays/AppendedArrayKeyTypeRuleTest.php +++ /dev/null @@ -1,71 +0,0 @@ - - */ -class AppendedArrayKeyTypeRuleTest extends RuleTestCase -{ - - protected function getRule(): Rule - { - return new AppendedArrayKeyTypeRule( - new PropertyReflectionFinder(), - true, - ); - } - - public function testRule(): void - { - $this->analyse([__DIR__ . '/data/appended-array-key.php'], [ - [ - 'Array (array) does not accept key int|string.', - 28, - ], - [ - 'Array (array) does not accept key string.', - 30, - ], - [ - 'Array (array) does not accept key int.', - 31, - ], - [ - 'Array (array) does not accept key int|string.', - 33, - ], - [ - 'Array (array) does not accept key 0.', - 38, - ], - [ - 'Array (array) does not accept key 1.', - 46, - ], - [ - 'Array (array<1|2|3, string>) does not accept key int.', - 80, - ], - [ - 'Array (array<1|2|3, string>) does not accept key 4.', - 85, - ], - ]); - } - - public function testBug5372Two(): void - { - $this->analyse([__DIR__ . '/data/bug-5372_2.php'], []); - } - - public function testBug5447(): void - { - $this->analyse([__DIR__ . '/data/bug-5447.php'], []); - } - -} From 9b918e345dcc0c3864b88768138ff91b81001424 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:54:42 +0200 Subject: [PATCH 241/508] [BCB] Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead --- UPGRADING.md | 1 + src/Type/UnionType.php | 12 ------------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 154776b331..99092f8c03 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -235,3 +235,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ArrayType::generalizeKeys()` * Remove `ArrayType::count()`, use `Type::getArraySize()` instead * Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead +* Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 70b2a54a72..e6bfb30cab 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -1105,18 +1105,6 @@ protected function unionTypes(callable $getType): Type return TypeCombinator::union(...array_map($getType, $this->types)); } - /** - * @template T of Type - * @param callable(Type $type): list $getTypes - * @return list - * - * @deprecated Use pickFromTypes() instead. - */ - protected function pickTypes(callable $getTypes): array - { - return $this->pickFromTypes($getTypes, static fn () => false); - } - /** * @template T * @param callable(Type $type): list $getValues From 78db3ac64f3c50258d90e852ea037087e171ba91 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:55:23 +0200 Subject: [PATCH 242/508] [BCB] Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead --- UPGRADING.md | 1 + src/Type/Php/RegexArrayShapeMatcher.php | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 99092f8c03..a4f61a2a80 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -236,3 +236,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ArrayType::count()`, use `Type::getArraySize()` instead * Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead * Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead +* Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead diff --git a/src/Type/Php/RegexArrayShapeMatcher.php b/src/Type/Php/RegexArrayShapeMatcher.php index 7923e9744c..e2b489ddab 100644 --- a/src/Type/Php/RegexArrayShapeMatcher.php +++ b/src/Type/Php/RegexArrayShapeMatcher.php @@ -60,14 +60,6 @@ public function matchExpr(Expr $patternExpr, ?Type $flagsType, TrinaryLogic $was return $this->matchPatternType($this->getPatternType($patternExpr, $scope), $flagsType, $wasMatched, false); } - /** - * @deprecated use matchExpr() instead for a more precise result - */ - public function matchType(Type $patternType, ?Type $flagsType, TrinaryLogic $wasMatched): ?Type - { - return $this->matchPatternType($patternType, $flagsType, $wasMatched, false); - } - private function matchPatternType(Type $patternType, ?Type $flagsType, TrinaryLogic $wasMatched, bool $matchesAll): ?Type { if ($wasMatched->no()) { From 7186ce61bac221afffd6ef18d0ecb6d79aa322d6 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:56:25 +0200 Subject: [PATCH 243/508] [BCB] Remove unused `PHPStanTestCase::$useStaticReflectionProvider` --- UPGRADING.md | 1 + src/Testing/PHPStanTestCase.php | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index a4f61a2a80..64ba4f5839 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -237,3 +237,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead * Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead * Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead +* Remove unused `PHPStanTestCase::$useStaticReflectionProvider` diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index 73c2e19947..029e982bab 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -49,9 +49,6 @@ abstract class PHPStanTestCase extends TestCase { - /** @deprecated */ - public static bool $useStaticReflectionProvider = true; - /** @var array */ private static array $containers = []; From 2ab5f3d768fe39028b77506597663747dc3eccc3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:57:48 +0200 Subject: [PATCH 244/508] [BCB] Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead --- UPGRADING.md | 1 + src/Testing/PHPStanTestCase.php | 16 ---------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 64ba4f5839..fc7ea494cd 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -238,3 +238,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead * Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead * Remove unused `PHPStanTestCase::$useStaticReflectionProvider` +* Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index 029e982bab..cbb555e412 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -8,9 +8,6 @@ use PHPStan\Analyser\NodeScopeResolver; use PHPStan\Analyser\ScopeFactory; use PHPStan\Analyser\TypeSpecifier; -use PHPStan\BetterReflection\Reflector\ClassReflector; -use PHPStan\BetterReflection\Reflector\ConstantReflector; -use PHPStan\BetterReflection\Reflector\FunctionReflector; use PHPStan\BetterReflection\Reflector\Reflector; use PHPStan\DependencyInjection\Container; use PHPStan\DependencyInjection\ContainerFactory; @@ -122,19 +119,6 @@ public static function getReflector(): Reflector return self::getContainer()->getService('betterReflectionReflector'); } - /** - * @deprecated Use getReflector() instead. - * @return array{ClassReflector, FunctionReflector, ConstantReflector} - */ - public static function getReflectors(): array - { - return [ - self::getContainer()->getService('betterReflectionClassReflector'), - self::getContainer()->getService('betterReflectionFunctionReflector'), - self::getContainer()->getService('betterReflectionConstantReflector'), - ]; - } - public static function getClassReflectionExtensionRegistryProvider(): ClassReflectionExtensionRegistryProvider { return self::getContainer()->getByType(ClassReflectionExtensionRegistryProvider::class); From db02a30ca11c7b9839c30e0321ed403dd14f6c73 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 20:58:48 +0200 Subject: [PATCH 245/508] Renamed NewOptimizedDirectorySourceLocator to OptimizedDirectorySourceLocator --- phpstan-baseline.neon | 5 - .../NewOptimizedDirectorySourceLocator.php | 217 ------------------ .../OptimizedDirectorySourceLocator.php | 164 +------------ ...OptimizedDirectorySourceLocatorFactory.php | 8 +- ...imizedDirectorySourceLocatorRepository.php | 4 +- 5 files changed, 12 insertions(+), 386 deletions(-) delete mode 100644 src/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f7e243fc88..3c0e92416c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -247,11 +247,6 @@ parameters: count: 1 path: src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php - - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" - count: 1 - path: src/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" count: 1 diff --git a/src/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php b/src/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php deleted file mode 100644 index cc939049bc..0000000000 --- a/src/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php +++ /dev/null @@ -1,217 +0,0 @@ - $classToFile - * @param array> $functionToFiles - * @param array $constantToFile - */ - public function __construct( - private FileNodesFetcher $fileNodesFetcher, - private array $classToFile, - private array $functionToFiles, - private array $constantToFile, - ) - { - } - - public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection - { - if ($identifier->isClass()) { - $className = strtolower($identifier->getName()); - $file = $this->findFileByClass($className); - if ($file === null) { - return null; - } - - $fetchedClassNodes = $this->fileNodesFetcher->fetchNodes($file)->getClassNodes(); - - if (!array_key_exists($className, $fetchedClassNodes)) { - return null; - } - - /** @var FetchedNode $fetchedClassNode */ - $fetchedClassNode = current($fetchedClassNodes[$className]); - - return $this->nodeToReflection($reflector, $fetchedClassNode); - } - - if ($identifier->isFunction()) { - $functionName = strtolower($identifier->getName()); - $files = $this->findFilesByFunction($functionName); - - $fetchedFunctionNode = null; - foreach ($files as $file) { - $fetchedFunctionNodes = $this->fileNodesFetcher->fetchNodes($file)->getFunctionNodes(); - - if (!array_key_exists($functionName, $fetchedFunctionNodes)) { - continue; - } - - /** @var FetchedNode $fetchedFunctionNode */ - $fetchedFunctionNode = current($fetchedFunctionNodes[$functionName]); - } - - if ($fetchedFunctionNode === null) { - return null; - } - - return $this->nodeToReflection($reflector, $fetchedFunctionNode); - } - - if ($identifier->isConstant()) { - $constantName = ConstantNameHelper::normalize($identifier->getName()); - $file = $this->findFileByConstant($constantName); - - if ($file === null) { - return null; - } - - $fetchedConstantNodes = $this->fileNodesFetcher->fetchNodes($file)->getConstantNodes(); - - if (!array_key_exists($constantName, $fetchedConstantNodes)) { - return null; - } - - /** @var FetchedNode $fetchedConstantNode */ - $fetchedConstantNode = current($fetchedConstantNodes[$constantName]); - - return $this->nodeToReflection( - $reflector, - $fetchedConstantNode, - $this->findConstantPositionInConstNode($fetchedConstantNode->getNode(), $constantName), - ); - } - - return null; - } - - /** - * @param FetchedNode|FetchedNode|FetchedNode $fetchedNode - */ - private function nodeToReflection(Reflector $reflector, FetchedNode $fetchedNode, ?int $positionInNode = null): Reflection - { - $nodeToReflection = new NodeToReflection(); - return $nodeToReflection->__invoke( - $reflector, - $fetchedNode->getNode(), - $fetchedNode->getLocatedSource(), - $fetchedNode->getNamespace(), - $positionInNode, - ); - } - - private function findFileByClass(string $className): ?string - { - if (!array_key_exists($className, $this->classToFile)) { - return null; - } - - return $this->classToFile[$className]; - } - - private function findFileByConstant(string $constantName): ?string - { - if (!array_key_exists($constantName, $this->constantToFile)) { - return null; - } - - return $this->constantToFile[$constantName]; - } - - /** - * @return string[] - */ - private function findFilesByFunction(string $functionName): array - { - if (!array_key_exists($functionName, $this->functionToFiles)) { - return []; - } - - return $this->functionToFiles[$functionName]; - } - - /** - * @return list - */ - public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array - { - $reflections = []; - if ($identifierType->isClass()) { - foreach ($this->classToFile as $file) { - $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); - foreach ($fetchedNodesResult->getClassNodes() as $identifierName => $fetchedClassNodes) { - foreach ($fetchedClassNodes as $fetchedClassNode) { - $reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedClassNode); - } - } - } - } elseif ($identifierType->isFunction()) { - foreach ($this->functionToFiles as $files) { - foreach ($files as $file) { - $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); - foreach ($fetchedNodesResult->getFunctionNodes() as $identifierName => $fetchedFunctionNodes) { - foreach ($fetchedFunctionNodes as $fetchedFunctionNode) { - $reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedFunctionNode); - continue 2; - } - } - } - } - } elseif ($identifierType->isConstant()) { - foreach ($this->constantToFile as $file) { - $fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file); - foreach ($fetchedNodesResult->getConstantNodes() as $identifierName => $fetchedConstantNodes) { - foreach ($fetchedConstantNodes as $fetchedConstantNode) { - $reflections[$identifierName] = $this->nodeToReflection( - $reflector, - $fetchedConstantNode, - $this->findConstantPositionInConstNode($fetchedConstantNode->getNode(), $identifierName), - ); - } - } - } - } - - return array_values($reflections); - } - - private function findConstantPositionInConstNode(Node\Stmt\Const_|Node\Expr\FuncCall $constantNode, string $constantName): ?int - { - if ($constantNode instanceof Node\Expr\FuncCall) { - return null; - } - - /** @var int $position */ - foreach ($constantNode->consts as $position => $const) { - if ($const->namespacedName === null) { - throw new ShouldNotHappenException(); - } - - if (ConstantNameHelper::normalize($const->namespacedName->toString()) === $constantName) { - return $position; - } - } - - throw new ShouldNotHappenException(); - } - -} diff --git a/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php b/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php index 32fabbc757..b56a981bab 100644 --- a/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php +++ b/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php @@ -9,52 +9,28 @@ use PHPStan\BetterReflection\Reflector\Reflector; use PHPStan\BetterReflection\SourceLocator\Ast\Strategy\NodeToReflection; use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator; -use PHPStan\Php\PhpVersion; use PHPStan\Reflection\ConstantNameHelper; use PHPStan\ShouldNotHappenException; use function array_key_exists; use function array_values; -use function count; use function current; -use function in_array; -use function ltrim; -use function php_strip_whitespace; -use function preg_match_all; -use function preg_replace; -use function sprintf; use function strtolower; -/** - * @deprecated Use NewOptimizedDirectorySourceLocator - */ final class OptimizedDirectorySourceLocator implements SourceLocator { - private PhpFileCleaner $cleaner; - - private string $extraTypes; - - /** @var array|null */ - private ?array $classToFile = null; - - /** @var array|null */ - private ?array $constantToFile = null; - - /** @var array>|null */ - private ?array $functionToFiles = null; - /** - * @param string[] $files + * @param array $classToFile + * @param array> $functionToFiles + * @param array $constantToFile */ public function __construct( private FileNodesFetcher $fileNodesFetcher, - private PhpVersion $phpVersion, - private array $files, + private array $classToFile, + private array $functionToFiles, + private array $constantToFile, ) { - $this->extraTypes = $this->phpVersion->supportsEnums() ? '|enum' : ''; - - $this->cleaner = new PhpFileCleaner(); } public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection @@ -145,13 +121,6 @@ private function nodeToReflection(Reflector $reflector, FetchedNode $fetchedNode private function findFileByClass(string $className): ?string { - if ($this->classToFile === null) { - $this->init(); - if ($this->classToFile === null) { - throw new ShouldNotHappenException(); - } - } - if (!array_key_exists($className, $this->classToFile)) { return null; } @@ -161,13 +130,6 @@ private function findFileByClass(string $className): ?string private function findFileByConstant(string $constantName): ?string { - if ($this->constantToFile === null) { - $this->init(); - if ($this->constantToFile === null) { - throw new ShouldNotHappenException(); - } - } - if (!array_key_exists($constantName, $this->constantToFile)) { return null; } @@ -180,13 +142,6 @@ private function findFileByConstant(string $constantName): ?string */ private function findFilesByFunction(string $functionName): array { - if ($this->functionToFiles === null) { - $this->init(); - if ($this->functionToFiles === null) { - throw new ShouldNotHappenException(); - } - } - if (!array_key_exists($functionName, $this->functionToFiles)) { return []; } @@ -194,118 +149,11 @@ private function findFilesByFunction(string $functionName): array return $this->functionToFiles[$functionName]; } - private function init(): void - { - $classToFile = []; - $constantToFile = []; - $functionToFiles = []; - foreach ($this->files as $file) { - $symbols = $this->findSymbols($file); - foreach ($symbols['classes'] as $classInFile) { - $classToFile[$classInFile] = $file; - } - foreach ($symbols['constants'] as $constantInFile) { - $constantToFile[$constantInFile] = $file; - } - foreach ($symbols['functions'] as $functionInFile) { - if (!array_key_exists($functionInFile, $functionToFiles)) { - $functionToFiles[$functionInFile] = []; - } - $functionToFiles[$functionInFile][] = $file; - } - } - - $this->classToFile = $classToFile; - $this->functionToFiles = $functionToFiles; - $this->constantToFile = $constantToFile; - } - - /** - * Inspired by Composer\Autoload\ClassMapGenerator::findClasses() - * @link https://github.com/composer/composer/blob/45d3e133a4691eccb12e9cd6f9dfd76eddc1906d/src/Composer/Autoload/ClassMapGenerator.php#L216 - * - * @return array{classes: string[], functions: string[], constants: string[]} - */ - private function findSymbols(string $file): array - { - $contents = @php_strip_whitespace($file); - if ($contents === '') { - return ['classes' => [], 'functions' => [], 'constants' => []]; - } - - $matchResults = (bool) preg_match_all(sprintf('{\b(?:(?:class|interface|trait|const|function%s)\s)|(?:define\s*\()}i', $this->extraTypes), $contents, $matches); - if (!$matchResults) { - return ['classes' => [], 'functions' => [], 'constants' => []]; - } - - $contents = $this->cleaner->clean($contents, count($matches[0])); - - preg_match_all(sprintf('{ - (?: - \b(?])(?: - (?: (?Pclass|interface|trait%s) \s++ (?P[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\-]*+) ) - | (?: (?Pfunction) \s++ (?:&\s*)? (?P[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\-]*+) \s*+ [&\(] ) - | (?: (?Pconst) \s++ (?P[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\-]*+) \s*+ [^;] ) - | (?: (?:\\\)? (?Pdefine) \s*+ \( \s*+ [\'"] (?P[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:[\\\\]{1,2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+) ) - | (?: (?Pnamespace) (?P\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;] ) - ) - ) - }ix', $this->extraTypes), $contents, $matches); - - $classes = []; - $functions = []; - $constants = []; - $namespace = ''; - - for ($i = 0, $len = count($matches['type']); $i < $len; $i++) { - if (isset($matches['ns'][$i]) && $matches['ns'][$i] !== '') { - $namespace = preg_replace('~\s+~', '', strtolower($matches['nsname'][$i])) . '\\'; - continue; - } - - if ($matches['function'][$i] !== '') { - $functions[] = strtolower(ltrim($namespace . $matches['fname'][$i], '\\')); - continue; - } - - if ($matches['constant'][$i] !== '') { - $constants[] = ConstantNameHelper::normalize(ltrim($namespace . $matches['cname'][$i], '\\')); - } - - if ($matches['define'][$i] !== '') { - $constants[] = ConstantNameHelper::normalize($matches['dname'][$i]); - continue; - } - - $name = $matches['name'][$i]; - - // skip anon classes extending/implementing - if (in_array($name, ['extends', 'implements'], true)) { - continue; - } - - $classes[] = strtolower(ltrim($namespace . $name, '\\')); - } - - return [ - 'classes' => $classes, - 'functions' => $functions, - 'constants' => $constants, - ]; - } - /** * @return list */ public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array { - if ($this->classToFile === null || $this->functionToFiles === null || $this->constantToFile === null) { - $this->init(); - if ($this->classToFile === null || $this->functionToFiles === null || $this->constantToFile === null) { - throw new ShouldNotHappenException(); - } - } - $reflections = []; if ($identifierType->isClass()) { foreach ($this->classToFile as $file) { diff --git a/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorFactory.php b/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorFactory.php index 864f1fff21..620284912f 100644 --- a/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorFactory.php +++ b/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorFactory.php @@ -35,7 +35,7 @@ public function __construct( $this->cleaner = new PhpFileCleaner(); } - public function createByDirectory(string $directory): NewOptimizedDirectorySourceLocator + public function createByDirectory(string $directory): OptimizedDirectorySourceLocator { $files = $this->fileFinder->findFiles([$directory])->getFiles(); $fileHashes = []; @@ -79,7 +79,7 @@ public function createByDirectory(string $directory): NewOptimizedDirectorySourc [$classToFile, $functionToFiles, $constantToFile] = $this->changeStructure($cached); - return new NewOptimizedDirectorySourceLocator( + return new OptimizedDirectorySourceLocator( $this->fileNodesFetcher, $classToFile, $functionToFiles, @@ -90,7 +90,7 @@ public function createByDirectory(string $directory): NewOptimizedDirectorySourc /** * @param string[] $files */ - public function createByFiles(array $files): NewOptimizedDirectorySourceLocator + public function createByFiles(array $files): OptimizedDirectorySourceLocator { $symbols = []; foreach ($files as $file) { @@ -100,7 +100,7 @@ public function createByFiles(array $files): NewOptimizedDirectorySourceLocator [$classToFile, $functionToFiles, $constantToFile] = $this->changeStructure($symbols); - return new NewOptimizedDirectorySourceLocator( + return new OptimizedDirectorySourceLocator( $this->fileNodesFetcher, $classToFile, $functionToFiles, diff --git a/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorRepository.php b/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorRepository.php index 25f5bd3e84..f71d4dcf8a 100644 --- a/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorRepository.php +++ b/src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorRepository.php @@ -7,14 +7,14 @@ final class OptimizedDirectorySourceLocatorRepository { - /** @var array */ + /** @var array */ private array $locators = []; public function __construct(private OptimizedDirectorySourceLocatorFactory $factory) { } - public function getOrCreate(string $directory): NewOptimizedDirectorySourceLocator + public function getOrCreate(string $directory): OptimizedDirectorySourceLocator { if (array_key_exists($directory, $this->locators)) { return $this->locators[$directory]; From 7888327799c86536c6b876334955338cf1f46147 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 26 Sep 2024 21:00:47 +0200 Subject: [PATCH 246/508] [BCB] Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead --- UPGRADING.md | 1 + src/Reflection/ClassReflection.php | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index fc7ea494cd..b87762ce06 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -239,3 +239,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead * Remove unused `PHPStanTestCase::$useStaticReflectionProvider` * Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead +* Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index d0e68e6453..2e1e7ae611 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -198,14 +198,6 @@ public function getFileName(): ?string return $this->filename = $fileName; } - /** - * @deprecated Use getFileName() - */ - public function getFileNameWithPhpDocs(): ?string - { - return $this->getFileName(); - } - public function getParentClass(): ?ClassReflection { if (!is_bool($this->cachedParentClass)) { From 93b3bf58ad2ce6b0cf3558b3ee2697f56113b593 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:10:34 +0200 Subject: [PATCH 247/508] [BCB] Remove `AnalysisResult::getInternalErrors()` --- UPGRADING.md | 1 + src/Command/AnalysisResult.php | 10 ---------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index b87762ce06..ad9f8379e1 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -240,3 +240,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove unused `PHPStanTestCase::$useStaticReflectionProvider` * Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead * Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead +* Remove `AnalysisResult::getInternalErrors()`, use `getInternalErrorObjects()` instead diff --git a/src/Command/AnalysisResult.php b/src/Command/AnalysisResult.php index 4b090e8a35..1697b5f38a 100644 --- a/src/Command/AnalysisResult.php +++ b/src/Command/AnalysisResult.php @@ -5,7 +5,6 @@ use PHPStan\Analyser\Error; use PHPStan\Analyser\InternalError; use PHPStan\Collectors\CollectedData; -use function array_map; use function count; use function usort; @@ -82,15 +81,6 @@ public function getNotFileSpecificErrors(): array return $this->notFileSpecificErrors; } - /** - * @deprecated Use getInternalErrorObjects - * @return list - */ - public function getInternalErrors(): array - { - return array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $this->internalErrors); - } - /** * @return list */ From 93201eb45a9ee9d4d8c8098849fe64bd97167c34 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:12:29 +0200 Subject: [PATCH 248/508] [BCB] Remove `ConstantReflection::getValue()` --- UPGRADING.md | 1 + src/Reflection/ClassConstantReflection.php | 15 --------------- src/Reflection/ConstantReflection.php | 6 ------ src/Reflection/Dummy/DummyConstantReflection.php | 10 ---------- 4 files changed, 1 insertion(+), 31 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index ad9f8379e1..1012b56795 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -241,3 +241,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead * Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead * Remove `AnalysisResult::getInternalErrors()`, use `getInternalErrorObjects()` instead +* Remove `ConstantReflection::getValue()`, use `getValueExpr()` instead. To get `Type` from `Expr`, use `Scope::getType()` or `InitializerExprTypeResolver::getType()` diff --git a/src/Reflection/ClassConstantReflection.php b/src/Reflection/ClassConstantReflection.php index 78cec7e379..7afcb0d9e2 100644 --- a/src/Reflection/ClassConstantReflection.php +++ b/src/Reflection/ClassConstantReflection.php @@ -3,12 +3,10 @@ namespace PHPStan\Reflection; use PhpParser\Node\Expr; -use PHPStan\BetterReflection\NodeCompiler\Exception\UnableToCompileNode; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; use PHPStan\Type\TypehintHelper; -use const NAN; /** * @api @@ -41,19 +39,6 @@ public function getFileName(): ?string return $this->declaringClass->getFileName(); } - /** - * @deprecated Use getValueExpr() - * @return mixed - */ - public function getValue() - { - try { - return $this->reflection->getValue(); - } catch (UnableToCompileNode) { - return NAN; - } - } - public function getValueExpr(): Expr { return $this->reflection->getValueExpression(); diff --git a/src/Reflection/ConstantReflection.php b/src/Reflection/ConstantReflection.php index 5e3d2548c1..6a13877990 100644 --- a/src/Reflection/ConstantReflection.php +++ b/src/Reflection/ConstantReflection.php @@ -8,12 +8,6 @@ interface ConstantReflection extends ClassMemberReflection, GlobalConstantReflection { - /** - * @deprecated Use getValueExpr() - * @return mixed - */ - public function getValue(); - public function getValueExpr(): Expr; } diff --git a/src/Reflection/Dummy/DummyConstantReflection.php b/src/Reflection/Dummy/DummyConstantReflection.php index 330c77562c..b7d563a615 100644 --- a/src/Reflection/Dummy/DummyConstantReflection.php +++ b/src/Reflection/Dummy/DummyConstantReflection.php @@ -51,16 +51,6 @@ public function getName(): string return $this->name; } - /** - * @deprecated - * @return mixed - */ - public function getValue() - { - // so that Scope::getTypeFromValue() returns mixed - return new stdClass(); - } - public function getValueType(): Type { return new MixedType(); From fd561e213eb4ac68566378f483d66f1f8164f359 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:14:08 +0200 Subject: [PATCH 249/508] [BCB] Remove `PropertyTag::getType()` --- UPGRADING.md | 1 + src/PhpDoc/PhpDocNodeResolver.php | 3 --- src/PhpDoc/Tag/PropertyTag.php | 9 --------- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 1012b56795..9321607fa9 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -242,3 +242,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead * Remove `AnalysisResult::getInternalErrors()`, use `getInternalErrorObjects()` instead * Remove `ConstantReflection::getValue()`, use `getValueExpr()` instead. To get `Type` from `Expr`, use `Scope::getType()` or `InitializerExprTypeResolver::getType()` +* Remove `PropertyTag::getType()`, use `getReadableType()` / `getWritableType()` instead diff --git a/src/PhpDoc/PhpDocNodeResolver.php b/src/PhpDoc/PhpDocNodeResolver.php index 75857e5eed..7476af723d 100644 --- a/src/PhpDoc/PhpDocNodeResolver.php +++ b/src/PhpDoc/PhpDocNodeResolver.php @@ -112,7 +112,6 @@ public function resolvePropertyTags(PhpDocNode $phpDocNode, NameScope $nameScope $resolved[$propertyName] = new PropertyTag( $propertyType, $propertyType, - $propertyType, ); } } @@ -128,7 +127,6 @@ public function resolvePropertyTags(PhpDocNode $phpDocNode, NameScope $nameScope } $resolved[$propertyName] = new PropertyTag( - $propertyType, $propertyType, $writableType, ); @@ -146,7 +144,6 @@ public function resolvePropertyTags(PhpDocNode $phpDocNode, NameScope $nameScope } $resolved[$propertyName] = new PropertyTag( - $readableType ?? $propertyType, $readableType, $propertyType, ); diff --git a/src/PhpDoc/Tag/PropertyTag.php b/src/PhpDoc/Tag/PropertyTag.php index 372e8b3cb9..16090c44b0 100644 --- a/src/PhpDoc/Tag/PropertyTag.php +++ b/src/PhpDoc/Tag/PropertyTag.php @@ -11,21 +11,12 @@ final class PropertyTag { public function __construct( - private Type $type, private ?Type $readableType, private ?Type $writableType, ) { } - /** - * @deprecated Use getReadableType() / getWritableType() - */ - public function getType(): Type - { - return $this->type; - } - public function getReadableType(): ?Type { return $this->readableType; From df7200d41b1f237259c825931d2411828ee59a4b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:15:35 +0200 Subject: [PATCH 250/508] [BCB] Remove `GenericTypeVariableResolver` --- UPGRADING.md | 1 + src/Type/GenericTypeVariableResolver.php | 52 ------------------------ 2 files changed, 1 insertion(+), 52 deletions(-) delete mode 100644 src/Type/GenericTypeVariableResolver.php diff --git a/UPGRADING.md b/UPGRADING.md index 9321607fa9..65733774f5 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -243,3 +243,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `AnalysisResult::getInternalErrors()`, use `getInternalErrorObjects()` instead * Remove `ConstantReflection::getValue()`, use `getValueExpr()` instead. To get `Type` from `Expr`, use `Scope::getType()` or `InitializerExprTypeResolver::getType()` * Remove `PropertyTag::getType()`, use `getReadableType()` / `getWritableType()` instead +* Remove `GenericTypeVariableResolver`, use [`Type::getTemplateType()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getTemplateType) instead diff --git a/src/Type/GenericTypeVariableResolver.php b/src/Type/GenericTypeVariableResolver.php deleted file mode 100644 index 732e57c10a..0000000000 --- a/src/Type/GenericTypeVariableResolver.php +++ /dev/null @@ -1,52 +0,0 @@ -getClassReflection(); - if ($classReflection === null) { - return null; - } - $ancestorClassReflection = $classReflection->getAncestorWithClassName($genericClassName); - if ($ancestorClassReflection === null) { - return null; - } - - $activeTemplateTypeMap = $ancestorClassReflection->getPossiblyIncompleteActiveTemplateTypeMap(); - - $type = $activeTemplateTypeMap->getType($typeVariableName); - if ($type instanceof ErrorType) { - $templateTypeMap = $ancestorClassReflection->getTemplateTypeMap(); - $templateType = $templateTypeMap->getType($typeVariableName); - if ($templateType === null) { - return $type; - } - - $bound = TemplateTypeHelper::resolveToBounds($templateType); - if ($bound instanceof MixedType && $bound->isExplicitMixed()) { - return new MixedType(false); - } - - return $bound; - } - - return $type; - } - -} From d904afcf06b277f12f51f71ff134331e1b8e83e7 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:18:52 +0200 Subject: [PATCH 251/508] [BCB] Rename `Type::isClassStringType()` to `Type::isClassString()` --- UPGRADING.md | 1 + src/Dependency/DependencyResolver.php | 2 +- src/Reflection/InitializerExprTypeResolver.php | 2 +- src/Rules/Methods/MethodCallCheck.php | 2 +- src/Type/Accessory/AccessoryArrayListType.php | 2 +- .../Accessory/AccessoryLiteralStringType.php | 2 +- .../Accessory/AccessoryLowercaseStringType.php | 2 +- .../Accessory/AccessoryNonEmptyStringType.php | 2 +- .../Accessory/AccessoryNonFalsyStringType.php | 2 +- .../Accessory/AccessoryNumericStringType.php | 2 +- src/Type/Accessory/HasOffsetType.php | 2 +- src/Type/Accessory/HasOffsetValueType.php | 2 +- src/Type/Accessory/NonEmptyArrayType.php | 2 +- src/Type/Accessory/OversizedArrayType.php | 2 +- src/Type/ArrayType.php | 2 +- src/Type/CallableType.php | 2 +- src/Type/ClassStringType.php | 6 +++--- src/Type/ClosureType.php | 2 +- src/Type/Constant/ConstantStringType.php | 16 ++++------------ src/Type/FloatType.php | 2 +- src/Type/Generic/GenericClassStringType.php | 8 ++++---- src/Type/IntersectionType.php | 4 ++-- src/Type/IterableType.php | 2 +- src/Type/JustNullableTypeTrait.php | 2 +- src/Type/MixedType.php | 4 ++-- src/Type/NeverType.php | 2 +- src/Type/NullType.php | 2 +- src/Type/ObjectType.php | 2 +- ...lassImplementsFunctionReturnTypeExtension.php | 2 +- .../Php/LtrimFunctionReturnTypeExtension.php | 2 +- .../Php/MethodExistsTypeSpecifyingExtension.php | 2 +- src/Type/StaticType.php | 4 ++-- src/Type/StrictMixedType.php | 2 +- src/Type/StringType.php | 4 ++-- src/Type/Traits/LateResolvableTypeTrait.php | 4 ++-- src/Type/Traits/ObjectTypeTrait.php | 2 +- src/Type/Type.php | 2 +- src/Type/UnionType.php | 4 ++-- src/Type/VoidType.php | 2 +- tests/PHPStan/Type/MixedTypeTest.php | 2 +- 40 files changed, 54 insertions(+), 61 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 65733774f5..8b14609497 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -244,3 +244,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ConstantReflection::getValue()`, use `getValueExpr()` instead. To get `Type` from `Expr`, use `Scope::getType()` or `InitializerExprTypeResolver::getType()` * Remove `PropertyTag::getType()`, use `getReadableType()` / `getWritableType()` instead * Remove `GenericTypeVariableResolver`, use [`Type::getTemplateType()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getTemplateType) instead +* Rename `Type::isClassStringType()` to `Type::isClassString()` diff --git a/src/Dependency/DependencyResolver.php b/src/Dependency/DependencyResolver.php index 86192c0a6c..12635a0913 100644 --- a/src/Dependency/DependencyResolver.php +++ b/src/Dependency/DependencyResolver.php @@ -477,7 +477,7 @@ private function considerArrayForCallableTest(Scope $scope, Array_ $arrayNode): } $itemType = $scope->getType($items[0]->value); - return $itemType->isClassStringType()->yes(); + return $itemType->isClassString()->yes(); } /** diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 0c355a2160..2f6d8a0cc8 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -1916,7 +1916,7 @@ function (Type $type, callable $traverse): Type { ); } - if ($constantClassType->isClassStringType()->yes()) { + if ($constantClassType->isClassString()->yes()) { if ($constantClassType->isConstantScalarValue()->yes()) { $isObject = false; } diff --git a/src/Rules/Methods/MethodCallCheck.php b/src/Rules/Methods/MethodCallCheck.php index 165f41741c..d20760f847 100644 --- a/src/Rules/Methods/MethodCallCheck.php +++ b/src/Rules/Methods/MethodCallCheck.php @@ -56,7 +56,7 @@ public function check( if ($type instanceof StaticType) { $typeForDescribe = $type->getStaticObjectType(); } - if (!$type->canCallMethods()->yes() || $type->isClassStringType()->yes()) { + if (!$type->canCallMethods()->yes() || $type->isClassString()->yes()) { return [ [ RuleErrorBuilder::message(sprintf( diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index 62cd108a77..930473cf03 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -391,7 +391,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/Accessory/AccessoryLiteralStringType.php b/src/Type/Accessory/AccessoryLiteralStringType.php index 110fbea58c..1a3a37858b 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.php @@ -302,7 +302,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } diff --git a/src/Type/Accessory/AccessoryLowercaseStringType.php b/src/Type/Accessory/AccessoryLowercaseStringType.php index 195a807dbc..c32ef8c506 100644 --- a/src/Type/Accessory/AccessoryLowercaseStringType.php +++ b/src/Type/Accessory/AccessoryLowercaseStringType.php @@ -298,7 +298,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createYes(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } diff --git a/src/Type/Accessory/AccessoryNonEmptyStringType.php b/src/Type/Accessory/AccessoryNonEmptyStringType.php index b911c21fbb..cc8e90f236 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -299,7 +299,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } diff --git a/src/Type/Accessory/AccessoryNonFalsyStringType.php b/src/Type/Accessory/AccessoryNonFalsyStringType.php index 5703420e9f..82460ea1a1 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.php @@ -299,7 +299,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } diff --git a/src/Type/Accessory/AccessoryNumericStringType.php b/src/Type/Accessory/AccessoryNumericStringType.php index 9cb274782d..a7c56c56ed 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.php @@ -301,7 +301,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/Accessory/HasOffsetType.php b/src/Type/Accessory/HasOffsetType.php index 2194a10cef..969a99df7a 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -302,7 +302,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } diff --git a/src/Type/Accessory/HasOffsetValueType.php b/src/Type/Accessory/HasOffsetValueType.php index 853645c91a..0481c3939b 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -358,7 +358,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } diff --git a/src/Type/Accessory/NonEmptyArrayType.php b/src/Type/Accessory/NonEmptyArrayType.php index 293e1f111f..fbe23d4534 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -369,7 +369,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/Accessory/OversizedArrayType.php b/src/Type/Accessory/OversizedArrayType.php index fa64240e89..365431f4ac 100644 --- a/src/Type/Accessory/OversizedArrayType.php +++ b/src/Type/Accessory/OversizedArrayType.php @@ -365,7 +365,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index dc9c6ec228..c868b64613 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -355,7 +355,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 82b3645a27..20cfeafa67 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -596,7 +596,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } diff --git a/src/Type/ClassStringType.php b/src/Type/ClassStringType.php index eaca9d4572..ed622e5817 100644 --- a/src/Type/ClassStringType.php +++ b/src/Type/ClassStringType.php @@ -32,7 +32,7 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult return $type->isAcceptedWithReasonBy($this, $strictTypes); } - return new AcceptsResult($type->isClassStringType(), []); + return new AcceptsResult($type->isClassString(), []); } public function isSuperTypeOf(Type $type): TrinaryLogic @@ -41,7 +41,7 @@ public function isSuperTypeOf(Type $type): TrinaryLogic return $type->isSubTypeOf($this); } - return $type->isClassStringType(); + return $type->isClassString(); } public function isString(): TrinaryLogic @@ -74,7 +74,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createYes(); } diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index e55847aae0..751239ab73 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -718,7 +718,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/Constant/ConstantStringType.php b/src/Type/Constant/ConstantStringType.php index 7917cbfda3..a5b39335cd 100644 --- a/src/Type/Constant/ConstantStringType.php +++ b/src/Type/Constant/ConstantStringType.php @@ -82,7 +82,7 @@ public function getConstantStrings(): array return [$this]; } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { if ($this->isClassString) { return TrinaryLogic::createYes(); @@ -95,7 +95,7 @@ public function isClassStringType(): TrinaryLogic public function getClassStringObjectType(): Type { - if ($this->isClassStringType()->yes()) { + if ($this->isClassString()->yes()) { return new ObjectType($this->value); } @@ -107,14 +107,6 @@ public function getObjectTypeOrClassStringObjectType(): Type return $this->getClassStringObjectType(); } - /** - * @deprecated use isClassStringType() instead - */ - public function isClassString(): bool - { - return $this->isClassStringType()->yes(); - } - public function describe(VerbosityLevel $level): string { return $level->handle( @@ -176,7 +168,7 @@ public function isSuperTypeOf(Type $type): TrinaryLogic return TrinaryLogic::createNo(); } if ($type instanceof ClassStringType) { - return $this->isClassStringType()->yes() ? TrinaryLogic::createMaybe() : TrinaryLogic::createNo(); + return $this->isClassString()->yes() ? TrinaryLogic::createMaybe() : TrinaryLogic::createNo(); } if ($type instanceof self) { @@ -534,7 +526,7 @@ public function getGreaterOrEqualType(PhpVersion $phpVersion): Type public function canAccessConstants(): TrinaryLogic { - return $this->isClassStringType(); + return $this->isClassString(); } public function hasConstant(string $constantName): TrinaryLogic diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index 0ffa96e002..890e13994a 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -234,7 +234,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/Generic/GenericClassStringType.php b/src/Type/Generic/GenericClassStringType.php index fd6ecd5f03..d9b06d68bf 100644 --- a/src/Type/Generic/GenericClassStringType.php +++ b/src/Type/Generic/GenericClassStringType.php @@ -67,7 +67,7 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult } if ($type instanceof ConstantStringType) { - if (!$type->isClassStringType()->yes()) { + if (!$type->isClassString()->yes()) { return AcceptsResult::createNo(); } @@ -113,7 +113,7 @@ public function isSuperTypeOf(Type $type): TrinaryLogic $isSuperType = $genericType->isSuperTypeOf($objectType); } - if (!$type->isClassStringType()->yes()) { + if (!$type->isClassString()->yes()) { $isSuperType = $isSuperType->and(TrinaryLogic::createMaybe()); } @@ -157,7 +157,7 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap $typeToInfer = new ObjectType($receivedType->getValue()); } elseif ($receivedType instanceof self) { $typeToInfer = $receivedType->type; - } elseif ($receivedType->isClassStringType()->yes()) { + } elseif ($receivedType->isClassString()->yes()) { $typeToInfer = $this->type; if ($typeToInfer instanceof TemplateType) { $typeToInfer = $typeToInfer->getBound(); @@ -215,7 +215,7 @@ public function toPhpDocNode(): TypeNode public function tryRemove(Type $typeToRemove): ?Type { - if ($typeToRemove instanceof ConstantStringType && $typeToRemove->isClassStringType()->yes()) { + if ($typeToRemove instanceof ConstantStringType && $typeToRemove->isClassString()->yes()) { $generic = $this->getGenericType(); $genericObjectClassNames = $generic->getObjectClassNames(); diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index fb41aebbad..f7d92dd554 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -648,9 +648,9 @@ public function isLowercaseString(): TrinaryLogic return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isLowercaseString()); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { - return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isClassStringType()); + return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isClassString()); } public function getClassStringObjectType(): Type diff --git a/src/Type/IterableType.php b/src/Type/IterableType.php index 6ef8ff5ee3..fe0af6a812 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -377,7 +377,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/JustNullableTypeTrait.php b/src/Type/JustNullableTypeTrait.php index 7f48131262..912dd68499 100644 --- a/src/Type/JustNullableTypeTrait.php +++ b/src/Type/JustNullableTypeTrait.php @@ -152,7 +152,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index 0a0fdd88ef..bf9f5bde68 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -933,7 +933,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { if ($this->subtractedType !== null) { if ($this->subtractedType->isSuperTypeOf(new StringType())->yes()) { @@ -949,7 +949,7 @@ public function isClassStringType(): TrinaryLogic public function getClassStringObjectType(): Type { - if (!$this->isClassStringType()->no()) { + if (!$this->isClassString()->no()) { return new ObjectWithoutClassType(); } diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index 1523562cab..68be84499a 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -481,7 +481,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/NullType.php b/src/Type/NullType.php index a8601a0b9e..c90a5b29e6 100644 --- a/src/Type/NullType.php +++ b/src/Type/NullType.php @@ -300,7 +300,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 672b1f57c8..0d12a7f532 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1039,7 +1039,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/Php/ClassImplementsFunctionReturnTypeExtension.php b/src/Type/Php/ClassImplementsFunctionReturnTypeExtension.php index 17e293973b..df1b7022ab 100644 --- a/src/Type/Php/ClassImplementsFunctionReturnTypeExtension.php +++ b/src/Type/Php/ClassImplementsFunctionReturnTypeExtension.php @@ -57,7 +57,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, return $variant->getReturnType(); } - if ($firstArgType->isClassStringType()->no()) { + if ($firstArgType->isClassString()->no()) { return new ConstantBooleanType(false); } diff --git a/src/Type/Php/LtrimFunctionReturnTypeExtension.php b/src/Type/Php/LtrimFunctionReturnTypeExtension.php index b8b5b38c6f..284be58a82 100644 --- a/src/Type/Php/LtrimFunctionReturnTypeExtension.php +++ b/src/Type/Php/LtrimFunctionReturnTypeExtension.php @@ -29,7 +29,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $string = $scope->getType($functionCall->getArgs()[0]->value); $trimChars = $scope->getType($functionCall->getArgs()[1]->value); - if ($trimChars instanceof ConstantStringType && $trimChars->getValue() === '\\' && $string->isClassStringType()->yes()) { + if ($trimChars instanceof ConstantStringType && $trimChars->getValue() === '\\' && $string->isClassString()->yes()) { if ($string instanceof ConstantStringType) { return new ConstantStringType(ltrim($string->getValue(), $trimChars->getValue()), true); } diff --git a/src/Type/Php/MethodExistsTypeSpecifyingExtension.php b/src/Type/Php/MethodExistsTypeSpecifyingExtension.php index bc00486cbf..ba67e53322 100644 --- a/src/Type/Php/MethodExistsTypeSpecifyingExtension.php +++ b/src/Type/Php/MethodExistsTypeSpecifyingExtension.php @@ -53,7 +53,7 @@ public function specifyTypes( $objectType = $scope->getType($node->getArgs()[0]->value); if ($objectType->isString()->yes()) { - if ($objectType->isClassStringType()->yes()) { + if ($objectType->isClassString()->yes()) { return $this->typeSpecifier->create( $node->getArgs()[0]->value, new IntersectionType([ diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index e0d2924951..55190656a4 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -570,9 +570,9 @@ public function isLowercaseString(): TrinaryLogic return $this->getStaticObjectType()->isLowercaseString(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { - return $this->getStaticObjectType()->isClassStringType(); + return $this->getStaticObjectType()->isClassString(); } public function getClassStringObjectType(): Type diff --git a/src/Type/StrictMixedType.php b/src/Type/StrictMixedType.php index 00a9141233..3f86776840 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -280,7 +280,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/StringType.php b/src/Type/StringType.php index 9fcd1e1895..b022f2b397 100644 --- a/src/Type/StringType.php +++ b/src/Type/StringType.php @@ -245,7 +245,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createMaybe(); } @@ -272,7 +272,7 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType public function hasMethod(string $methodName): TrinaryLogic { - if ($this->isClassStringType()->yes()) { + if ($this->isClassString()->yes()) { return TrinaryLogic::createMaybe(); } return TrinaryLogic::createNo(); diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index e2cdc07e57..d3a0083da6 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -457,9 +457,9 @@ public function isLowercaseString(): TrinaryLogic return $this->resolve()->isLowercaseString(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { - return $this->resolve()->isClassStringType(); + return $this->resolve()->isClassString(); } public function getClassStringObjectType(): Type diff --git a/src/Type/Traits/ObjectTypeTrait.php b/src/Type/Traits/ObjectTypeTrait.php index 8ca9c69c29..2fd278e34b 100644 --- a/src/Type/Traits/ObjectTypeTrait.php +++ b/src/Type/Traits/ObjectTypeTrait.php @@ -203,7 +203,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/src/Type/Type.php b/src/Type/Type.php index a456a0e846..ce306ee9f5 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -263,7 +263,7 @@ public function isLiteralString(): TrinaryLogic; public function isLowercaseString(): TrinaryLogic; - public function isClassStringType(): TrinaryLogic; + public function isClassString(): TrinaryLogic; public function isVoid(): TrinaryLogic; diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index e6bfb30cab..1316f9369d 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -617,9 +617,9 @@ public function isLowercaseString(): TrinaryLogic return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $type->isLowercaseString()); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { - return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $type->isClassStringType()); + return $this->notBenevolentUnionResults(static fn (Type $type): TrinaryLogic => $type->isClassString()); } public function getClassStringObjectType(): Type diff --git a/src/Type/VoidType.php b/src/Type/VoidType.php index add4ffca45..2bea11cb04 100644 --- a/src/Type/VoidType.php +++ b/src/Type/VoidType.php @@ -212,7 +212,7 @@ public function isLowercaseString(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isClassStringType(): TrinaryLogic + public function isClassString(): TrinaryLogic { return TrinaryLogic::createNo(); } diff --git a/tests/PHPStan/Type/MixedTypeTest.php b/tests/PHPStan/Type/MixedTypeTest.php index 5fe7d0c409..3ffc8f9db7 100644 --- a/tests/PHPStan/Type/MixedTypeTest.php +++ b/tests/PHPStan/Type/MixedTypeTest.php @@ -598,7 +598,7 @@ public function dataSubstractedIsLiteralString(): array public function testSubstractedIsClassString(MixedType $mixedType, Type $typeToSubtract, TrinaryLogic $expectedResult): void { $subtracted = $mixedType->subtract($typeToSubtract); - $actualResult = $subtracted->isClassStringType(); + $actualResult = $subtracted->isClassString(); $this->assertSame( $expectedResult->describe(), From 49eb18f317b00238827084016e0d643ef39dd5fb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:21:25 +0200 Subject: [PATCH 252/508] [BCB] Remove `Scope::isSpecified()` --- UPGRADING.md | 1 + src/Analyser/MutatingScope.php | 9 --------- src/Analyser/Scope.php | 3 --- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 8b14609497..0d975f2429 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -245,3 +245,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `PropertyTag::getType()`, use `getReadableType()` / `getWritableType()` instead * Remove `GenericTypeVariableResolver`, use [`Type::getTemplateType()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getTemplateType) instead * Rename `Type::isClassStringType()` to `Type::isClassString()` +* Remove `Scope::isSpecified()`, use `hasExpressionType()` instead diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 686b70bab8..f619db2fef 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -2781,15 +2781,6 @@ public function getTypeFromValue($value): Type return ConstantTypeHelper::getTypeFromValue($value); } - /** - * @api - * @deprecated use hasExpressionType instead - */ - public function isSpecified(Expr $node): bool - { - return !$node instanceof Variable && $this->hasExpressionType($node)->yes(); - } - /** @api */ public function hasExpressionType(Expr $node): TrinaryLogic { diff --git a/src/Analyser/Scope.php b/src/Analyser/Scope.php index 0c1682209d..6284d454f1 100644 --- a/src/Analyser/Scope.php +++ b/src/Analyser/Scope.php @@ -105,9 +105,6 @@ public function resolveTypeByName(Name $name): TypeWithClassName; */ public function getTypeFromValue($value): Type; - /** @deprecated use hasExpressionType instead */ - public function isSpecified(Expr $node): bool; - public function hasExpressionType(Expr $node): TrinaryLogic; public function isInClassExists(string $className): bool; From acd35c8e1b5f0faafe79f677692aa3eee1ce1574 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:27:08 +0200 Subject: [PATCH 253/508] Remove `MutatingScope::enterCatch()` --- src/Analyser/MutatingScope.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index f619db2fef..6af143689b 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3748,17 +3748,6 @@ public function enterForeachKey(self $originalScope, Expr $iteratee, string $key return $scope; } - /** - * @deprecated Use enterCatchType - * @param Node\Name[] $classes - */ - public function enterCatch(array $classes, ?string $variableName): self - { - $type = TypeCombinator::union(...array_map(static fn (Node\Name $class): ObjectType => new ObjectType((string) $class), $classes)); - - return $this->enterCatchType($type, $variableName); - } - public function enterCatchType(Type $catchType, ?string $variableName): self { if ($variableName === null) { From 9663f0edbecc7918a289bd4f2ef89e80392c2071 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:30:41 +0200 Subject: [PATCH 254/508] [BCB] Remove `ConstantArrayType::isEmpty()` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 0d975f2429..5609946f04 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -246,3 +246,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `GenericTypeVariableResolver`, use [`Type::getTemplateType()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getTemplateType) instead * Rename `Type::isClassStringType()` to `Type::isClassString()` * Remove `Scope::isSpecified()`, use `hasExpressionType()` instead +* Remove `ConstantArrayType::isEmpty()`, use `isIterableAtLeastOnce()->no()` instead diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 5b6700d80b..33b1370100 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -136,12 +136,6 @@ public function isConstantValue(): TrinaryLogic return TrinaryLogic::createYes(); } - /** @deprecated Use isIterableAtLeastOnce()->no() instead */ - public function isEmpty(): bool - { - return count($this->keyTypes) === 0; - } - /** * @return non-empty-list */ From 36ac734613290c400efa12397dc3f8062d72892f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:31:25 +0200 Subject: [PATCH 255/508] [BCB] Remove `ConstantArrayType::getNextAutoIndex()` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 5609946f04..9465e15518 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -247,3 +247,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Rename `Type::isClassStringType()` to `Type::isClassString()` * Remove `Scope::isSpecified()`, use `hasExpressionType()` instead * Remove `ConstantArrayType::isEmpty()`, use `isIterableAtLeastOnce()->no()` instead +* Remove `ConstantArrayType::getNextAutoIndex()` diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 33b1370100..95fc560c06 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -144,10 +144,7 @@ public function getNextAutoIndexes(): array return $this->nextAutoIndexes; } - /** - * @deprecated - */ - public function getNextAutoIndex(): int + private function getNextAutoIndex(): int { return $this->nextAutoIndexes[count($this->nextAutoIndexes) - 1]; } @@ -1076,7 +1073,7 @@ private function removeLastElements(int $length): self array_pop($valueTypes); $nextAutoindex = $removedKeyType instanceof ConstantIntegerType ? $removedKeyType->getValue() - : $this->getNextAutoIndex(); // @phpstan-ignore method.deprecated + : $this->getNextAutoIndex(); continue; } From d5a0ddb86998776a9e23e85e5657f054c86cc2f0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:31:58 +0200 Subject: [PATCH 256/508] [BCB] Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` --- UPGRADING.md | 2 ++ src/Type/Constant/ConstantArrayType.php | 24 ------------------------ 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 9465e15518..ee245c430b 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -248,3 +248,5 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `Scope::isSpecified()`, use `hasExpressionType()` instead * Remove `ConstantArrayType::isEmpty()`, use `isIterableAtLeastOnce()->no()` instead * Remove `ConstantArrayType::getNextAutoIndex()` +* Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` + * Use `getFirstIterable*Type` and `getLastIterable*Type` instead diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 95fc560c06..70c94efe76 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -242,18 +242,6 @@ public function getKeyTypes(): array return $this->keyTypes; } - /** @deprecated Use getFirstIterableKeyType() instead */ - public function getFirstKeyType(): Type - { - return $this->getFirstIterableKeyType(); - } - - /** @deprecated Use getLastIterableKeyType() instead */ - public function getLastKeyType(): Type - { - return $this->getLastIterableKeyType(); - } - /** * @return array */ @@ -262,18 +250,6 @@ public function getValueTypes(): array return $this->valueTypes; } - /** @deprecated Use getFirstIterableValueType() instead */ - public function getFirstValueType(): Type - { - return $this->getFirstIterableValueType(); - } - - /** @deprecated Use getLastIterableValueType() instead */ - public function getLastValueType(): Type - { - return $this->getLastIterableValueType(); - } - public function isOptionalKey(int $i): bool { return in_array($i, $this->optionalKeys, true); From 50135a9fefffd9eb883780577e89f68512200023 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 11:33:45 +0200 Subject: [PATCH 257/508] [BCB] Remove `ConstantArrayType::generalizeToArray()` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 20 -------------------- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index ee245c430b..0199fc4452 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -250,3 +250,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ConstantArrayType::getNextAutoIndex()` * Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` * Use `getFirstIterable*Type` and `getLastIterable*Type` instead +* Remove `ConstantArrayType::generalizeToArray()` diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 70c94efe76..0dc13355f2 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -1305,26 +1305,6 @@ public function generalizeValues(): ArrayType return new self($this->keyTypes, $valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); } - /** @deprecated */ - public function generalizeToArray(): Type - { - $isIterableAtLeastOnce = $this->isIterableAtLeastOnce(); - if ($isIterableAtLeastOnce->no()) { - return $this; - } - - $arrayType = new ArrayType($this->getIterableKeyType(), $this->getItemType()); - - if ($isIterableAtLeastOnce->yes()) { - $arrayType = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); - } - if ($this->isList->yes()) { - $arrayType = TypeCombinator::intersect($arrayType, new AccessoryArrayListType()); - } - - return $arrayType; - } - /** * @return self */ From 3f561479dbf419ffa9197c49c215c28fc663109c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 13:37:24 +0200 Subject: [PATCH 258/508] Fix E2E tests --- .github/workflows/e2e-tests.yml | 13 +++++++------ e2e/bug-9622-trait/baseline-1.neon | 2 +- e2e/bug-9622/baseline-1.neon | 2 +- e2e/discussion-11362/phpstan.neon | 2 -- e2e/env-parameter/phpstan.neon | 2 +- e2e/result-cache-5/phpstan.neon | 3 +++ e2e/result-cache-7/phpstan.neon | 3 +++ 7 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 3020a8545c..ba0c7ac476 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -137,17 +137,18 @@ jobs: ../../bin/phpstan -vvv - script: | cd e2e/env-parameter - export PHPSTAN_SCOPE_CLASS=MyTestScope - ACTUAL=$(../../bin/phpstan dump-parameters -c phpstan.neon --json -l 9 | jq --raw-output '.scopeClass') - [[ "$ACTUAL" == "MyTestScope" ]]; + export PHPSTAN_RESULT_CACHE_PATH=/some/path + ACTUAL=$(../../bin/phpstan dump-parameters -c phpstan.neon --json -l 9 | jq --raw-output '.resultCachePath') + [[ "$ACTUAL" == "/some/path" ]]; - script: | cd e2e/result-cache-8 composer install ../../bin/phpstan echo -en '\n' >> build/CustomRule.php - OUTPUT=$(../../bin/phpstan 2>&1) - grep 'Result cache might not behave correctly' <<< "$OUTPUT" - grep 'ResultCache8E2E\\CustomRule' <<< "$OUTPUT" + OUTPUT=$(../../bin/phpstan analyze 2>&1 || true) + echo "$OUTPUT" + ../bashunit -a contains 'Result cache might not behave correctly' "$OUTPUT" + ../bashunit -a contains 'ResultCache8E2E\\CustomRule' "$OUTPUT" - script: | cd e2e/env-int-key env 1=1 ../../bin/phpstan analyse test.php diff --git a/e2e/bug-9622-trait/baseline-1.neon b/e2e/bug-9622-trait/baseline-1.neon index 1548dbca10..caa24d89e8 100644 --- a/e2e/bug-9622-trait/baseline-1.neon +++ b/e2e/bug-9622-trait/baseline-1.neon @@ -1,6 +1,6 @@ parameters: ignoreErrors: - - message: "#^Offset 'foo' does not exist on array\\{foo\\?\\: int\\}\\.$#" + message: "#^Offset 'foo' might not exist on array\\{foo\\?\\: int\\}\\.$#" count: 1 path: src/UsesBar.php diff --git a/e2e/bug-9622/baseline-1.neon b/e2e/bug-9622/baseline-1.neon index a7df787390..0ae88bf65b 100644 --- a/e2e/bug-9622/baseline-1.neon +++ b/e2e/bug-9622/baseline-1.neon @@ -1,6 +1,6 @@ parameters: ignoreErrors: - - message: "#^Offset 'foo' does not exist on array\\{foo\\?\\: int\\}\\.$#" + message: "#^Offset 'foo' might not exist on array\\{foo\\?\\: int\\}\\.$#" count: 1 path: src/Bar.php diff --git a/e2e/discussion-11362/phpstan.neon b/e2e/discussion-11362/phpstan.neon index d9a4bd0ab3..2e6178c1a7 100644 --- a/e2e/discussion-11362/phpstan.neon +++ b/e2e/discussion-11362/phpstan.neon @@ -1,7 +1,5 @@ parameters: excludePaths: - analyseAndScan: - - .git analyse: - vendor diff --git a/e2e/env-parameter/phpstan.neon b/e2e/env-parameter/phpstan.neon index 9287016809..b92bf25f4a 100644 --- a/e2e/env-parameter/phpstan.neon +++ b/e2e/env-parameter/phpstan.neon @@ -1,2 +1,2 @@ parameters: - scopeClass: %env.PHPSTAN_SCOPE_CLASS% + resultCachePath: %env.PHPSTAN_RESULT_CACHE_PATH% diff --git a/e2e/result-cache-5/phpstan.neon b/e2e/result-cache-5/phpstan.neon index ddbf4c2114..7ef7b4e149 100644 --- a/e2e/result-cache-5/phpstan.neon +++ b/e2e/result-cache-5/phpstan.neon @@ -5,3 +5,6 @@ parameters: level: 8 paths: - src + ignoreErrors: + - + identifier: instanceof.alwaysTrue diff --git a/e2e/result-cache-7/phpstan.neon b/e2e/result-cache-7/phpstan.neon index ddbf4c2114..66c19c7166 100644 --- a/e2e/result-cache-7/phpstan.neon +++ b/e2e/result-cache-7/phpstan.neon @@ -5,3 +5,6 @@ parameters: level: 8 paths: - src + ignoreErrors: + - + identifier: trait.unused From 6a695613d09f4633e052ee8175c74c634c76b7a9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:04:15 +0200 Subject: [PATCH 259/508] Fix E2E tests --- .github/workflows/e2e-tests.yml | 2 +- e2e/result-cache-5/phpstan.neon | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index ba0c7ac476..2ad09cad2c 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -148,7 +148,7 @@ jobs: OUTPUT=$(../../bin/phpstan analyze 2>&1 || true) echo "$OUTPUT" ../bashunit -a contains 'Result cache might not behave correctly' "$OUTPUT" - ../bashunit -a contains 'ResultCache8E2E\\CustomRule' "$OUTPUT" + ../bashunit -a contains 'ResultCache8E2E\CustomRule' "$OUTPUT" - script: | cd e2e/env-int-key env 1=1 ../../bin/phpstan analyse test.php diff --git a/e2e/result-cache-5/phpstan.neon b/e2e/result-cache-5/phpstan.neon index 7ef7b4e149..7c3f71ae98 100644 --- a/e2e/result-cache-5/phpstan.neon +++ b/e2e/result-cache-5/phpstan.neon @@ -8,3 +8,4 @@ parameters: ignoreErrors: - identifier: instanceof.alwaysTrue + reportUnmatched: false From 3d2f492e6d1bba07704c349ead9bfde31e2c20eb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:10:59 +0200 Subject: [PATCH 260/508] [BCB] Remove `TypeUtils::getArrays()` --- UPGRADING.md | 1 + src/Type/TypeUtils.php | 46 ------------------------------------------ 2 files changed, 1 insertion(+), 46 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 0199fc4452..0580805b51 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -251,3 +251,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` * Use `getFirstIterable*Type` and `getLastIterable*Type` instead * Remove `ConstantArrayType::generalizeToArray()` +* Remove `TypeUtils::getArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 6987e9482b..f3d7998da2 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -21,52 +21,6 @@ final class TypeUtils { - /** - * @return ArrayType[] - * - * @deprecated Use PHPStan\Type\Type::getArrays() instead and handle optional ConstantArrayType keys if necessary. - */ - public static function getArrays(Type $type): array - { - if ($type instanceof ConstantArrayType) { - return $type->getAllArrays(); - } - - if ($type instanceof ArrayType) { - return [$type]; - } - - if ($type instanceof UnionType) { - $matchingTypes = []; - foreach ($type->getTypes() as $innerType) { - if (!$innerType instanceof ArrayType) { - return []; - } - foreach (self::getArrays($innerType) as $innerInnerType) { - $matchingTypes[] = $innerInnerType; - } - } - - return $matchingTypes; - } - - if ($type instanceof IntersectionType) { - $matchingTypes = []; - foreach ($type->getTypes() as $innerType) { - if (!$innerType instanceof ArrayType) { - continue; - } - foreach (self::getArrays($innerType) as $innerInnerType) { - $matchingTypes[] = $innerInnerType; - } - } - - return $matchingTypes; - } - - return []; - } - /** * @return ConstantArrayType[] * From c507bd3c7fbb91fcedc83dcac57525ed5c99c6f9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:12:48 +0200 Subject: [PATCH 261/508] [BCB] Remove `TypeUtils::getConstantArrays()` --- UPGRADING.md | 1 + src/Type/TypeUtils.php | 28 ---------------------------- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 0580805b51..a3f6619a0f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -252,3 +252,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Use `getFirstIterable*Type` and `getLastIterable*Type` instead * Remove `ConstantArrayType::generalizeToArray()` * Remove `TypeUtils::getArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead +* Remove `TypeUtils::getConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index f3d7998da2..2e12de1366 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -21,34 +21,6 @@ final class TypeUtils { - /** - * @return ConstantArrayType[] - * - * @deprecated Use PHPStan\Type\Type::getConstantArrays() instead and handle optional keys if necessary. - */ - public static function getConstantArrays(Type $type): array - { - if ($type instanceof ConstantArrayType) { - return $type->getAllArrays(); - } - - if ($type instanceof UnionType) { - $matchingTypes = []; - foreach ($type->getTypes() as $innerType) { - if (!$innerType instanceof ConstantArrayType) { - return []; - } - foreach (self::getConstantArrays($innerType) as $innerInnerType) { - $matchingTypes[] = $innerInnerType; - } - } - - return $matchingTypes; - } - - return []; - } - /** * @return ConstantStringType[] * From 9278af76c90f77f4a40bdfe6937f2a1a741f7891 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:15:25 +0200 Subject: [PATCH 262/508] [BCB] Remove `TypeUtils::getConstantStrings()` --- UPGRADING.md | 1 + src/Type/TypeUtils.php | 11 ----------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index a3f6619a0f..0a302e00d1 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -253,3 +253,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ConstantArrayType::generalizeToArray()` * Remove `TypeUtils::getArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead +* Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 2e12de1366..e76089a2ac 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -6,7 +6,6 @@ use PHPStan\Type\Accessory\HasPropertyType; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantIntegerType; -use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\Enum\EnumCaseObjectType; use PHPStan\Type\Generic\TemplateBenevolentUnionType; use PHPStan\Type\Generic\TemplateType; @@ -21,16 +20,6 @@ final class TypeUtils { - /** - * @return ConstantStringType[] - * - * @deprecated Use PHPStan\Type\Type::getConstantStrings() instead - */ - public static function getConstantStrings(Type $type): array - { - return self::map(ConstantStringType::class, $type, false); - } - /** * @return ConstantIntegerType[] */ From 3bfe27e06e9002068bfe74556fe208bba471963a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:17:45 +0200 Subject: [PATCH 263/508] [BCB] Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()` --- UPGRADING.md | 1 + src/Type/TypeUtils.php | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 0a302e00d1..065b68b214 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -254,3 +254,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::getArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead +* Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index e76089a2ac..2094ae13b7 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -28,24 +28,6 @@ public static function getConstantIntegers(Type $type): array return self::map(ConstantIntegerType::class, $type, false); } - /** - * @deprecated Use Type::isConstantValue() or Type::generalize() - * @return ConstantType[] - */ - public static function getConstantTypes(Type $type): array - { - return self::map(ConstantType::class, $type, false); - } - - /** - * @deprecated Use Type::isConstantValue() or Type::generalize() - * @return ConstantType[] - */ - public static function getAnyConstantTypes(Type $type): array - { - return self::map(ConstantType::class, $type, false, false); - } - /** * @return ArrayType[] * From 5b447846e986ebfa5fdd96af6ecac12059bb02da Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:39:11 +0200 Subject: [PATCH 264/508] [BCB] Remove `TypeUtils::getAnyArrays()` --- UPGRADING.md | 2 +- src/Analyser/MutatingScope.php | 4 ++-- src/Type/TypeUtils.php | 10 ---------- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 065b68b214..b065245f9b 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -251,7 +251,7 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` * Use `getFirstIterable*Type` and `getLastIterable*Type` instead * Remove `ConstantArrayType::generalizeToArray()` -* Remove `TypeUtils::getArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead +* Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead * Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 6af143689b..02340153bb 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -5251,11 +5251,11 @@ private static function generalizeType(Type $a, Type $b, int $depth): Type private static function getArrayDepth(Type $type): int { $depth = 0; - $arrays = TypeUtils::getAnyArrays($type); + $arrays = TypeUtils::toBenevolentUnion($type)->getArrays(); while (count($arrays) > 0) { $temp = $type->getIterableValueType(); $type = $temp; - $arrays = TypeUtils::getAnyArrays($type); + $arrays = TypeUtils::toBenevolentUnion($type)->getArrays(); $depth++; } diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 2094ae13b7..81400df4c3 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -28,16 +28,6 @@ public static function getConstantIntegers(Type $type): array return self::map(ConstantIntegerType::class, $type, false); } - /** - * @return ArrayType[] - * - * @deprecated Use PHPStan\Type\Type::getArrays() instead. - */ - public static function getAnyArrays(Type $type): array - { - return self::map(ArrayType::class, $type, true, false); - } - /** * @deprecated Use PHPStan\Type\Type::generalize() instead. */ From 426d94831b34c1072ae7b4bed0a4ce16a64f69fa Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:44:30 +0200 Subject: [PATCH 265/508] [BCB] Remove `TypeUtils::generalizeType()` --- UPGRADING.md | 1 + src/Type/TypeUtils.php | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index b065245f9b..100c8d213d 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -255,3 +255,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::getConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead * Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) +* Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 81400df4c3..0929b11499 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -28,14 +28,6 @@ public static function getConstantIntegers(Type $type): array return self::map(ConstantIntegerType::class, $type, false); } - /** - * @deprecated Use PHPStan\Type\Type::generalize() instead. - */ - public static function generalizeType(Type $type, GeneralizePrecision $precision): Type - { - return $type->generalize($precision); - } - /** * @return list * From 6e263d05fd2a14b8832a8b30ecc9b4d8554c6166 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:48:10 +0200 Subject: [PATCH 266/508] [BCB] Remove `TypeUtils::getDirectClassNames()` --- UPGRADING.md | 1 + src/Type/TypeUtils.php | 27 --------------------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 100c8d213d..31f50bcea0 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -256,3 +256,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead * Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) * Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead +* Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead. diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 0929b11499..2c8941dec0 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -11,8 +11,6 @@ use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\Generic\TemplateUnionType; use function array_merge; -use function array_unique; -use function array_values; /** * @api @@ -28,31 +26,6 @@ public static function getConstantIntegers(Type $type): array return self::map(ConstantIntegerType::class, $type, false); } - /** - * @return list - * - * @deprecated Use Type::getObjectClassNames() instead. - */ - public static function getDirectClassNames(Type $type): array - { - if ($type instanceof TypeWithClassName) { - return [$type->getClassName()]; - } - - if ($type instanceof UnionType || $type instanceof IntersectionType) { - $classNames = []; - foreach ($type->getTypes() as $innerType) { - foreach (self::getDirectClassNames($innerType) as $n) { - $classNames[] = $n; - } - } - - return array_values(array_unique($classNames)); - } - - return []; - } - /** * @return IntegerRangeType[] */ From c8e4ed97bc3f500201cd109f6cd4a6c45f8f5176 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:49:36 +0200 Subject: [PATCH 267/508] Stop using TypeUtils in InArrayFunctionTypeSpecifyingExtension --- .../Php/InArrayFunctionTypeSpecifyingExtension.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php index a91974e466..62c022c8e1 100644 --- a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php @@ -18,7 +18,6 @@ use PHPStan\Type\FunctionTypeSpecifyingExtension; use PHPStan\Type\MixedType; use PHPStan\Type\TypeCombinator; -use PHPStan\Type\TypeUtils; use function count; use function strtolower; @@ -111,10 +110,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $context->true() || ( $context->false() - && ( - count(TypeUtils::getConstantScalars($arrayValueType)) > 0 - || count(TypeUtils::getEnumCaseObjects($arrayValueType)) > 0 - ) + && count($arrayValueType->getFiniteTypes()) === 1 ) ) { $specifiedTypes = $this->typeSpecifier->create( @@ -137,10 +133,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $context->true() || ( $context->false() - && ( - count(TypeUtils::getConstantScalars($needleType)) === 1 - || count(TypeUtils::getEnumCaseObjects($needleType)) === 1 - ) + && count($needleType->getFiniteTypes()) === 1 ) ) { if ($context->true()) { From c98dd894fcd32a9652f3ee910681a31c2754fa57 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:50:16 +0200 Subject: [PATCH 268/508] [BCB] Remove `TypeUtils::getOldConstantArrays()` --- UPGRADING.md | 2 +- src/Type/TypeUtils.php | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 31f50bcea0..5088ba6f55 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -252,7 +252,7 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Use `getFirstIterable*Type` and `getLastIterable*Type` instead * Remove `ConstantArrayType::generalizeToArray()` * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead -* Remove `TypeUtils::getConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead +* Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead * Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) * Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 2c8941dec0..bfa15b092e 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -52,17 +52,6 @@ public static function getEnumCaseObjects(Type $type): array return self::map(EnumCaseObjectType::class, $type, false); } - /** - * @internal - * @return ConstantArrayType[] - * - * @deprecated Use PHPStan\Type\Type::getConstantArrays(). - */ - public static function getOldConstantArrays(Type $type): array - { - return self::map(ConstantArrayType::class, $type, false); - } - /** * @return mixed[] */ From b9ad2ecf81ea6bc1b3ca483a2b03bf4ec271be95 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:53:26 +0200 Subject: [PATCH 269/508] [BCB] Remove `TypeUtils::getConstantScalars()` --- UPGRADING.md | 3 ++- src/Type/TypeUtils.php | 9 --------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 5088ba6f55..1806a07768 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -256,4 +256,5 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead * Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) * Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead -* Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead. +* Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead +* Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index bfa15b092e..ff44d43b2f 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -34,15 +34,6 @@ public static function getIntegerRanges(Type $type): array return self::map(IntegerRangeType::class, $type, false); } - /** - * @deprecated Use Type::isConstantScalarValue() or Type::getConstantScalarTypes() or Type::getConstantScalarValues() - * @return ConstantScalarType[] - */ - public static function getConstantScalars(Type $type): array - { - return self::map(ConstantScalarType::class, $type, false); - } - /** * @deprecated Use Type::getEnumCases() * @return EnumCaseObjectType[] From 7088d79490567ceadff35b286a82dcad397a627d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:54:24 +0200 Subject: [PATCH 270/508] [BCB] Remove `TypeUtils::getEnumCaseObjects()` --- UPGRADING.md | 1 + src/Type/TypeUtils.php | 10 ---------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 1806a07768..831b93d9af 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -258,3 +258,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead * Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead * Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead +* Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index ff44d43b2f..4d838b2b3e 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -6,7 +6,6 @@ use PHPStan\Type\Accessory\HasPropertyType; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantIntegerType; -use PHPStan\Type\Enum\EnumCaseObjectType; use PHPStan\Type\Generic\TemplateBenevolentUnionType; use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\Generic\TemplateUnionType; @@ -34,15 +33,6 @@ public static function getIntegerRanges(Type $type): array return self::map(IntegerRangeType::class, $type, false); } - /** - * @deprecated Use Type::getEnumCases() - * @return EnumCaseObjectType[] - */ - public static function getEnumCaseObjects(Type $type): array - { - return self::map(EnumCaseObjectType::class, $type, false); - } - /** * @return mixed[] */ From 239db410533843df98f88c98846c38c4c7a15c26 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:56:05 +0200 Subject: [PATCH 271/508] [BCB] Remove `TypeUtils::containsCallable()` --- UPGRADING.md | 1 + src/Type/TypeUtils.php | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 831b93d9af..7e31663790 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -259,3 +259,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead * Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead * Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead +* Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index 4d838b2b3e..c00c7602ec 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -198,24 +198,6 @@ public static function getAccessoryTypes(Type $type): array return self::map(AccessoryType::class, $type, true, false); } - /** @deprecated Use PHPStan\Type\Type::isCallable() instead. */ - public static function containsCallable(Type $type): bool - { - if ($type->isCallable()->yes()) { - return true; - } - - if ($type instanceof UnionType) { - foreach ($type->getTypes() as $innerType) { - if ($innerType->isCallable()->yes()) { - return true; - } - } - } - - return false; - } - public static function containsTemplateType(Type $type): bool { $containsTemplateType = false; From 1c44510c8886911431f37a97887f243eded071a9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 14:56:28 +0200 Subject: [PATCH 272/508] Indent TypeUtils upgrading notes --- UPGRADING.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 7e31663790..59eec7ee5a 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -251,12 +251,13 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` * Use `getFirstIterable*Type` and `getLastIterable*Type` instead * Remove `ConstantArrayType::generalizeToArray()` -* Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead -* Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead -* Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead -* Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) -* Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead -* Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead -* Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead -* Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead -* Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead +* Made `TypeUtils` thinner by removing methods: + * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead + * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead + * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead + * Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) + * Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead + * Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead + * Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead + * Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead + * Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead From 65019b249ecd220bad0c225e2e28bd60199f88d7 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:06:12 +0200 Subject: [PATCH 273/508] Update baseline --- phpstan-baseline.neon | 38 ++------------------------------------ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 3c0e92416c..5c198cf5ac 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -15,14 +15,6 @@ parameters: count: 1 path: src/Analyser/Ignore/IgnoredErrorHelperResult.php - - - message: """ - #^Call to deprecated method getAnyArrays\\(\\) of class PHPStan\\\\Type\\\\TypeUtils\\: - Use PHPStan\\\\Type\\\\Type\\:\\:getArrays\\(\\) instead\\.$# - """ - count: 2 - path: src/Analyser/MutatingScope.php - - message: """ #^Call to deprecated method getTypeFromValue\\(\\) of class PHPStan\\\\Type\\\\ConstantTypeHelper\\: @@ -1278,22 +1270,6 @@ parameters: count: 1 path: src/Type/Php/ImplodeFunctionReturnTypeExtension.php - - - message: """ - #^Call to deprecated method getConstantScalars\\(\\) of class PHPStan\\\\Type\\\\TypeUtils\\: - Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\)$# - """ - count: 2 - path: src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php - - - - message: """ - #^Call to deprecated method getEnumCaseObjects\\(\\) of class PHPStan\\\\Type\\\\TypeUtils\\: - Use Type\\:\\:getEnumCases\\(\\)$# - """ - count: 2 - path: src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 @@ -1522,24 +1498,14 @@ parameters: count: 1 path: src/Type/TypeCombinator.php - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" - count: 3 - path: src/Type/TypeUtils.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" - count: 5 + count: 2 path: src/Type/TypeUtils.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" - count: 5 - path: src/Type/TypeUtils.php - - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" - count: 1 + count: 3 path: src/Type/TypeUtils.php - From 83845202806f9104af2788784dc02c42f3fde9eb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:10:46 +0200 Subject: [PATCH 274/508] [BCB] Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead --- UPGRADING.md | 1 + src/Analyser/MutatingScope.php | 4 ---- src/Analyser/Scope.php | 5 ----- src/Rules/Comparison/ImpossibleCheckTypeHelper.php | 6 ++++++ 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 59eec7ee5a..264980ab6a 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -261,3 +261,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead * Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead * Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead +* Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 02340153bb..d68b07e630 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -2587,10 +2587,6 @@ public function getKeepVoidType(Expr $node): Type return $this->getType($clonedNode); } - /** - * @api - * @deprecated Use getNativeType() - */ public function doNotTreatPhpDocTypesAsCertain(): Scope { return $this->promoteNativeTypes(); diff --git a/src/Analyser/Scope.php b/src/Analyser/Scope.php index 6284d454f1..96859d4c5e 100644 --- a/src/Analyser/Scope.php +++ b/src/Analyser/Scope.php @@ -91,11 +91,6 @@ public function getNativeType(Expr $expr): Type; public function getKeepVoidType(Expr $node): Type; - /** - * @deprecated Use getNativeType() - */ - public function doNotTreatPhpDocTypesAsCertain(): self; - public function resolveName(Name $name): string; public function resolveTypeByName(Name $name): TypeWithClassName; diff --git a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php index 45574a089a..b61904f26b 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php @@ -8,11 +8,13 @@ use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\StaticCall; +use PHPStan\Analyser\MutatingScope; use PHPStan\Analyser\Scope; use PHPStan\Analyser\TypeSpecifier; use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Reflection\ReflectionProvider; +use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantBooleanType; @@ -234,6 +236,10 @@ public function findSpecifiedType( } } + if (!$scope instanceof MutatingScope) { + throw new ShouldNotHappenException(); + } + $typeSpecifierScope = $this->treatPhpDocTypesAsCertain ? $scope : $scope->doNotTreatPhpDocTypesAsCertain(); $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($typeSpecifierScope, $node, $this->determineContext($typeSpecifierScope, $node)); From 0cb872021f595c331334d521b14740106f59c349 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:19:56 +0200 Subject: [PATCH 275/508] Removed some unnecessary `@api` in MutatingScope --- phpstan-baseline.neon | 16 ---------------- src/Analyser/MutatingScope.php | 4 +--- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 5c198cf5ac..9d922a2fc9 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -43,14 +43,6 @@ parameters: count: 1 path: src/Analyser/MutatingScope.php - - - message: """ - #^Call to deprecated method doNotTreatPhpDocTypesAsCertain\\(\\) of class PHPStan\\\\Analyser\\\\MutatingScope\\: - Use getNativeType\\(\\)$# - """ - count: 1 - path: src/Analyser/NodeScopeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 3 @@ -417,14 +409,6 @@ parameters: count: 2 path: src/Rules/Comparison/IfConstantConditionRule.php - - - message: """ - #^Call to deprecated method doNotTreatPhpDocTypesAsCertain\\(\\) of interface PHPStan\\\\Analyser\\\\Scope\\: - Use getNativeType\\(\\)$# - """ - count: 1 - path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 2 diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index d68b07e630..659dc7f833 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -2639,8 +2639,7 @@ private function hasPropertyNativeType($propertyFetch): bool return !$propertyReflection->getNativeType() instanceof MixedType; } - /** @api */ - protected function getTypeFromArrayDimFetch( + private function getTypeFromArrayDimFetch( Expr\ArrayDimFetch $arrayDimFetch, Type $offsetType, Type $offsetAccessibleType, @@ -5574,7 +5573,6 @@ public function getMethodReflection(Type $typeWithMethod, string $methodName): ? return $type->getMethod($methodName, $this); } - /** @api */ public function getNakedMethod(Type $typeWithMethod, string $methodName): ?ExtendedMethodReflection { $type = $this->filterTypeWithMethod($typeWithMethod, $methodName); From 42bb08a9ecff9901952f6380d632e6acd552292c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:23:47 +0200 Subject: [PATCH 276/508] [BCB] Remove `ConstantArrayType::findTypeAndMethodName()` --- UPGRADING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPGRADING.md b/UPGRADING.md index 264980ab6a..235bb0e936 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -251,6 +251,7 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` * Use `getFirstIterable*Type` and `getLastIterable*Type` instead * Remove `ConstantArrayType::generalizeToArray()` +* Remove `ConstantArrayType::findTypeAndMethodName()`, use `findTypeAndMethodNames()` instead * Made `TypeUtils` thinner by removing methods: * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead From 8c752e4c7e94641009b7b2e86c86c3499b702457 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:28:45 +0200 Subject: [PATCH 277/508] [BCB] Remove `ConstantArrayType::removeLast()` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 36 ------------------------- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 235bb0e936..aa7e28968e 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -252,6 +252,7 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Use `getFirstIterable*Type` and `getLastIterable*Type` instead * Remove `ConstantArrayType::generalizeToArray()` * Remove `ConstantArrayType::findTypeAndMethodName()`, use `findTypeAndMethodNames()` instead +* Remove `ConstantArrayType::removeLast()`, use [`Type::popArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_popArray) instead * Made `TypeUtils` thinner by removing methods: * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 0dc13355f2..957eb84b01 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -489,36 +489,6 @@ private function getClassOrObjectAndMethods(): array return [$classOrObject, $method]; } - /** @deprecated Use findTypeAndMethodNames() instead */ - public function findTypeAndMethodName(): ?ConstantArrayTypeAndMethod - { - $callableArray = $this->getClassOrObjectAndMethods(); - if ($callableArray === []) { - return null; - } - - [$classOrObject, $method] = $callableArray; - if (!$method instanceof ConstantStringType) { - return ConstantArrayTypeAndMethod::createUnknown(); - } - - $type = $classOrObject->getObjectTypeOrClassStringObjectType(); - if (!$type->isObject()->yes()) { - return ConstantArrayTypeAndMethod::createUnknown(); - } - - $has = $type->hasMethod($method->getValue()); - if (!$has->no()) { - if ($this->isOptionalKey(0) || $this->isOptionalKey(1)) { - $has = $has->and(TrinaryLogic::createMaybe()); - } - - return ConstantArrayTypeAndMethod::createConcrete($type, $method->getValue(), $has); - } - - return null; - } - /** @return ConstantArrayTypeAndMethod[] */ public function findTypeAndMethodNames(): array { @@ -1010,12 +980,6 @@ public function isList(): TrinaryLogic return $this->isList; } - /** @deprecated Use popArray() instead */ - public function removeLast(): self - { - return $this->removeLastElements(1); - } - /** @param positive-int $length */ private function removeLastElements(int $length): self { From bb488992346f121b4b0cb6ff9d7174bac9bb683e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:29:20 +0200 Subject: [PATCH 278/508] [BCB] Remove `ConstantArrayType::removeFirst()` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index aa7e28968e..e1b2c2406c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -253,6 +253,7 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ConstantArrayType::generalizeToArray()` * Remove `ConstantArrayType::findTypeAndMethodName()`, use `findTypeAndMethodNames()` instead * Remove `ConstantArrayType::removeLast()`, use [`Type::popArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_popArray) instead +* Remove `ConstantArrayType::removeFirst()`, use [`Type::shiftArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_shiftArray) instead * Made `TypeUtils` thinner by removing methods: * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 957eb84b01..f9f9be47c8 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -1034,12 +1034,6 @@ private function removeLastElements(int $length): self ); } - /** @deprecated Use shiftArray() instead */ - public function removeFirst(): self - { - return $this->removeFirstElements(1); - } - /** @param positive-int $length */ private function removeFirstElements(int $length, bool $reindex = true): self { From ee32a25452371d831e21ac70d38fe830b628edda Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:30:02 +0200 Subject: [PATCH 279/508] [BCB] Remove `ConstantArrayType::reverse()` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index e1b2c2406c..1d56408d06 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -254,6 +254,7 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ConstantArrayType::findTypeAndMethodName()`, use `findTypeAndMethodNames()` instead * Remove `ConstantArrayType::removeLast()`, use [`Type::popArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_popArray) instead * Remove `ConstantArrayType::removeFirst()`, use [`Type::shiftArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_shiftArray) instead +* Remove `ConstantArrayType::reverse()`, use [`Type::reverseArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_reverseArray) instead * Made `TypeUtils` thinner by removing methods: * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index f9f9be47c8..bf0c70d01e 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -1147,12 +1147,6 @@ public function slice(int $offset, ?int $limit, bool $preserveKeys = false): sel return $preserveKeys ? $slice : $slice->reindex(); } - /** @deprecated Use reverseArray() instead */ - public function reverse(bool $preserveKeys = false): self - { - return $this->reverseConstantArray(TrinaryLogic::createFromBoolean($preserveKeys)); - } - /** * @deprecated Use chunkArray() instead * @param positive-int $length From 7d38ffc6a7c70cec7a25fba3077f411273206e83 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:30:52 +0200 Subject: [PATCH 280/508] [BCB] Remove `ConstantArrayType::chunk()` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 22 ---------------------- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 1d56408d06..568b326d88 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -255,6 +255,7 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ConstantArrayType::removeLast()`, use [`Type::popArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_popArray) instead * Remove `ConstantArrayType::removeFirst()`, use [`Type::shiftArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_shiftArray) instead * Remove `ConstantArrayType::reverse()`, use [`Type::reverseArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_reverseArray) instead +* Remove `ConstantArrayType::chunk()`, use [`Type::chunkArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_chunkArray) instead * Made `TypeUtils` thinner by removing methods: * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index bf0c70d01e..e54da2ad1e 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -1147,28 +1147,6 @@ public function slice(int $offset, ?int $limit, bool $preserveKeys = false): sel return $preserveKeys ? $slice : $slice->reindex(); } - /** - * @deprecated Use chunkArray() instead - * @param positive-int $length - */ - public function chunk(int $length, bool $preserveKeys = false): self - { - $builder = ConstantArrayTypeBuilder::createEmpty(); - - $keyTypesCount = count($this->keyTypes); - for ($i = 0; $i < $keyTypesCount; $i += $length) { - $chunk = $this->slice($i, $length, true); - $builder->setOffsetValueType(null, $preserveKeys ? $chunk : $chunk->getValuesArray()); - } - - $chunks = $builder->getArray(); - if (!$chunks instanceof self) { - throw new ShouldNotHappenException(); - } - - return $chunks; - } - private function reindex(): self { $keyTypes = []; From 83e8c1d09d01435b6848240ef69ad6edf4a6226b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 27 Sep 2024 15:32:10 +0200 Subject: [PATCH 281/508] Update baseline --- phpstan-baseline.neon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 9d922a2fc9..b64fc25c61 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -731,12 +731,12 @@ parameters: - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" - count: 8 + count: 7 path: src/Type/Constant/ConstantArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" - count: 3 + count: 2 path: src/Type/Constant/ConstantArrayType.php - From 74e854997683fb7a64b6ccaf20742eb4b79f569c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 28 Sep 2024 09:49:41 +0200 Subject: [PATCH 282/508] [BCB] ConstantArrayType no longer extends ArrayType --- UPGRADING.md | 6 + phpstan-baseline.neon | 19 +- src/Analyser/NodeScopeResolver.php | 2 +- src/PhpDoc/TypeNodeResolver.php | 3 + .../MethodParameterComparisonHelper.php | 4 + src/Type/ArrayType.php | 198 +---------------- src/Type/Constant/ConstantArrayType.php | 140 +++++++++--- src/Type/Traits/ArrayTypeTrait.php | 201 ++++++++++++++++++ src/Type/Type.php | 2 +- src/Type/TypeCombinator.php | 10 +- src/Type/TypehintHelper.php | 7 +- 11 files changed, 354 insertions(+), 238 deletions(-) create mode 100644 src/Type/Traits/ArrayTypeTrait.php diff --git a/UPGRADING.md b/UPGRADING.md index 568b326d88..00d7c0766d 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -203,6 +203,12 @@ If you want to change `$overwrite` or `$rootExpr` (previous parameters also used If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by the constructor), call `setAlwaysOverwriteTypes()` and `setRootExpr()`. These methods return a new object (SpecifiedTypes is immutable). +### `ConstantArrayType` no longer extends `ArrayType` + +`Type::getArrays()` now returns `list`. + +Using `$type instanceof ArrayType` is [being deprecated anyway](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) so the impact of this change should be minimal. + ### Changed `TypeSpecifier::specifyTypesInCondition()` This method now longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable). diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 511ab3b9eb..4477db7fce 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -175,6 +175,11 @@ parameters: count: 1 path: src/PhpDoc/TypeNodeResolver.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 1 + path: src/PhpDoc/TypeNodeResolver.php + - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 1 @@ -505,6 +510,11 @@ parameters: count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 1 + path: src/Rules/Methods/MethodParameterComparisonHelper.php + - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 1 @@ -657,7 +667,7 @@ parameters: - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" - count: 1 + count: 2 path: src/Type/ArrayType.php - @@ -1392,7 +1402,7 @@ parameters: - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" - count: 10 + count: 14 path: src/Type/TypeCombinator.php - @@ -1465,6 +1475,11 @@ parameters: count: 3 path: src/Type/TypehintHelper.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + count: 3 + path: src/Type/TypehintHelper.php + - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 1 diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 4bdc434294..f2e43632a6 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -3868,7 +3868,7 @@ private function getArraySortPreserveListFunctionType(Type $type): Type return $traverse($type); } - if (!$type instanceof ArrayType) { + if (!$type instanceof ArrayType && !$type instanceof ConstantArrayType) { return $type; } diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php index 6ef403a0de..facec02644 100644 --- a/src/PhpDoc/TypeNodeResolver.php +++ b/src/PhpDoc/TypeNodeResolver.php @@ -59,6 +59,7 @@ use PHPStan\Type\ClosureType; use PHPStan\Type\ConditionalType; use PHPStan\Type\ConditionalTypeForParameter; +use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantArrayTypeBuilder; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantFloatType; @@ -571,6 +572,8 @@ private function resolveUnionTypeNode(UnionTypeNode $typeNode, NameScope $nameSc $type = new IntersectionType([$type, new IterableType(new MixedType(), $arrayTypeType)]); } elseif ($type instanceof ArrayType) { $type = new ArrayType(new MixedType(), $arrayTypeType); + } elseif ($type instanceof ConstantArrayType) { + $type = new ArrayType(new MixedType(), $arrayTypeType); } elseif ($type instanceof IterableType) { $type = new IterableType(new MixedType(), $arrayTypeType); } else { diff --git a/src/Rules/Methods/MethodParameterComparisonHelper.php b/src/Rules/Methods/MethodParameterComparisonHelper.php index 37fd21932a..34f66bb8bb 100644 --- a/src/Rules/Methods/MethodParameterComparisonHelper.php +++ b/src/Rules/Methods/MethodParameterComparisonHelper.php @@ -9,6 +9,7 @@ use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\ArrayType; +use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\IterableType; use PHPStan\Type\MixedType; use PHPStan\Type\Type; @@ -392,6 +393,9 @@ private function isTypeCompatible(Type $methodParameterType, Type $prototypePara if ($prototypeParameterType instanceof ArrayType) { return true; } + if ($prototypeParameterType instanceof ConstantArrayType) { + return true; + } if ($prototypeParameterType->isObject()->yes() && $prototypeParameterType->getObjectClassNames() === [Traversable::class]) { return true; } diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index c868b64613..4a9a03dd6b 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -11,7 +11,6 @@ use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\Accessory\AccessoryArrayListType; -use PHPStan\Type\Accessory\HasOffsetType; use PHPStan\Type\Accessory\HasOffsetValueType; use PHPStan\Type\Accessory\NonEmptyArrayType; use PHPStan\Type\Constant\ConstantArrayType; @@ -23,6 +22,7 @@ use PHPStan\Type\Generic\TemplateMixedType; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Generic\TemplateTypeVariance; +use PHPStan\Type\Traits\ArrayTypeTrait; use PHPStan\Type\Traits\MaybeCallableTypeTrait; use PHPStan\Type\Traits\NonGeneralizableTypeTrait; use PHPStan\Type\Traits\NonObjectTypeTrait; @@ -36,6 +36,7 @@ class ArrayType implements Type { + use ArrayTypeTrait; use MaybeCallableTypeTrait; use NonObjectTypeTrait; use UndecidedBooleanTypeTrait; @@ -74,21 +75,6 @@ public function getReferencedClasses(): array ); } - public function getObjectClassNames(): array - { - return []; - } - - public function getObjectClassReflections(): array - { - return []; - } - - public function getArrays(): array - { - return [$this]; - } - public function getConstantArrays(): array { return []; @@ -129,7 +115,7 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult public function isSuperTypeOf(Type $type): TrinaryLogic { - if ($type instanceof self) { + if ($type instanceof self || $type instanceof ConstantArrayType) { return $this->getItemType()->isSuperTypeOf($type->getItemType()) ->and($this->getIterableKeyType()->isSuperTypeOf($type->getIterableKeyType())); } @@ -144,7 +130,6 @@ public function isSuperTypeOf(Type $type): TrinaryLogic public function equals(Type $type): bool { return $type instanceof self - && $type->isConstantArray()->no() && $this->getItemType()->equals($type->getIterableValueType()) && $this->keyType->equals($type->keyType); } @@ -198,11 +183,6 @@ public function getValuesArray(): Type return TypeCombinator::intersect(new self(new IntegerType(), $this->itemType), new AccessoryArrayListType()); } - public function isIterable(): TrinaryLogic - { - return TrinaryLogic::createYes(); - } - public function isIterableAtLeastOnce(): TrinaryLogic { return TrinaryLogic::createMaybe(); @@ -251,21 +231,11 @@ public function getLastIterableValueType(): Type return $this->getItemType(); } - public function isArray(): TrinaryLogic - { - return TrinaryLogic::createYes(); - } - public function isConstantArray(): TrinaryLogic { return TrinaryLogic::createNo(); } - public function isOversizedArray(): TrinaryLogic - { - return TrinaryLogic::createMaybe(); - } - public function isList(): TrinaryLogic { if (IntegerRangeType::fromInterval(0, null)->isSuperTypeOf($this->getKeyType())->no()) { @@ -275,126 +245,16 @@ public function isList(): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isNull(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - public function isConstantValue(): TrinaryLogic { return TrinaryLogic::createNo(); } - public function isConstantScalarValue(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getConstantScalarTypes(): array - { - return []; - } - - public function getConstantScalarValues(): array - { - return []; - } - - public function isTrue(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isFalse(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isBoolean(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isFloat(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isInteger(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isString(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isNumericString(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isNonEmptyString(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isNonFalsyString(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isLiteralString(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isLowercaseString(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isClassString(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function getClassStringObjectType(): Type - { - return new ErrorType(); - } - - public function getObjectTypeOrClassStringObjectType(): Type - { - return new ErrorType(); - } - - public function isVoid(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - - public function isScalar(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { return new BooleanType(); } - public function isOffsetAccessible(): TrinaryLogic - { - return TrinaryLogic::createYes(); - } - - public function isOffsetAccessLegal(): TrinaryLogic - { - return TrinaryLogic::createYes(); - } - public function hasOffsetValueType(Type $offsetType): TrinaryLogic { $offsetType = $offsetType->toArrayKey(); @@ -510,20 +370,6 @@ public function unsetOffset(Type $offsetType): Type return $this; } - public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type - { - $chunkType = $preserveKeys->yes() - ? $this - : TypeCombinator::intersect(new ArrayType(new IntegerType(), $this->getIterableValueType()), new AccessoryArrayListType()); - $chunkType = TypeCombinator::intersect($chunkType, new NonEmptyArrayType()); - - $arrayType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $chunkType), new AccessoryArrayListType()); - - return $this->isIterableAtLeastOnce()->yes() - ? TypeCombinator::intersect($arrayType, new NonEmptyArrayType()) - : $arrayType; - } - public function fillKeysArray(Type $valueType): Type { $itemType = $this->getItemType(); @@ -597,21 +443,6 @@ public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope) return [new TrivialParametersAcceptor()]; } - public function toNumber(): Type - { - return new ErrorType(); - } - - public function toAbsoluteNumber(): Type - { - return new ErrorType(); - } - - public function toString(): Type - { - return new ErrorType(); - } - public function toInteger(): Type { return TypeCombinator::union( @@ -628,16 +459,6 @@ public function toFloat(): Type ); } - public function toArray(): Type - { - return $this; - } - - public function toArrayKey(): Type - { - return new ErrorType(); - } - public function inferTemplateTypes(Type $receivedType): TemplateTypeMap { if ($receivedType instanceof UnionType || $receivedType instanceof IntersectionType) { @@ -733,22 +554,9 @@ public function tryRemove(Type $typeToRemove): ?Type return new ConstantArrayType([], []); } - if ($this->isConstantArray()->yes() && $typeToRemove instanceof HasOffsetType) { - return $this->unsetOffset($typeToRemove->getOffsetType()); - } - - if ($this->isConstantArray()->yes() && $typeToRemove instanceof HasOffsetValueType) { - return $this->unsetOffset($typeToRemove->getOffsetType()); - } - return null; } - public function exponentiate(Type $exponent): Type - { - return new ErrorType(); - } - public function getFiniteTypes(): array { return []; diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index e54da2ad1e..5e24881e61 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -23,6 +23,7 @@ use PHPStan\TrinaryLogic; use PHPStan\Type\AcceptsResult; use PHPStan\Type\Accessory\AccessoryArrayListType; +use PHPStan\Type\Accessory\HasOffsetType; use PHPStan\Type\Accessory\HasOffsetValueType; use PHPStan\Type\Accessory\NonEmptyArrayType; use PHPStan\Type\ArrayType; @@ -38,6 +39,9 @@ use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; +use PHPStan\Type\Traits\ArrayTypeTrait; +use PHPStan\Type\Traits\NonObjectTypeTrait; +use PHPStan\Type\Traits\UndecidedComparisonTypeTrait; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\UnionType; @@ -68,9 +72,15 @@ /** * @api */ -class ConstantArrayType extends ArrayType implements ConstantType +class ConstantArrayType implements ConstantType { + use ArrayTypeTrait { + chunkArray as traitChunkArray; + } + use NonObjectTypeTrait; + use UndecidedComparisonTypeTrait; + private const DESCRIBE_LIMIT = 8; private const CHUNK_FINITE_TYPES_LIMIT = 5; @@ -82,6 +92,10 @@ class ConstantArrayType extends ArrayType implements ConstantType /** @var non-empty-list */ private array $nextAutoIndexes; + private ?Type $iterableKeyType = null; + + private ?Type $iterableValueType = null; + /** * @api * @param array $keyTypes @@ -107,23 +121,13 @@ public function __construct( $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { - $keyType = new NeverType(true); $isList = TrinaryLogic::createYes(); - } elseif ($keyTypesCount === 1) { - $keyType = $this->keyTypes[0]; - } else { - $keyType = new UnionType($this->keyTypes); } if (is_bool($isList)) { $isList = TrinaryLogic::createFromBoolean($isList); } $this->isList = $isList; - - parent::__construct( - $keyType, - count($valueTypes) > 0 ? TypeCombinator::union(...$valueTypes) : new NeverType(true), - ); } public function getConstantArrays(): array @@ -131,6 +135,61 @@ public function getConstantArrays(): array return [$this]; } + public function getReferencedClasses(): array + { + $referencedClasses = []; + foreach ($this->getKeyTypes() as $keyType) { + foreach ($keyType->getReferencedClasses() as $referencedClass) { + $referencedClasses[] = $referencedClass; + } + } + + foreach ($this->getValueTypes() as $valueType) { + foreach ($valueType->getReferencedClasses() as $referencedClass) { + $referencedClasses[] = $referencedClass; + } + } + + return $referencedClasses; + } + + public function getIterableKeyType(): Type + { + if ($this->iterableKeyType !== null) { + return $this->iterableKeyType; + } + + $keyTypesCount = count($this->keyTypes); + if ($keyTypesCount === 0) { + $keyType = new NeverType(true); + } elseif ($keyTypesCount === 1) { + $keyType = $this->keyTypes[0]; + } else { + $keyType = new UnionType($this->keyTypes); + } + + return $this->iterableKeyType = $keyType; + } + + public function getIterableValueType(): Type + { + if ($this->iterableValueType !== null) { + return $this->iterableValueType; + } + + return $this->iterableValueType = count($this->valueTypes) > 0 ? TypeCombinator::union(...$this->valueTypes) : new NeverType(true); + } + + public function getKeyType(): Type + { + return $this->getIterableKeyType(); + } + + public function getItemType(): Type + { + return $this->getIterableValueType(); + } + public function isConstantValue(): TrinaryLogic { return TrinaryLogic::createYes(); @@ -363,12 +422,12 @@ public function isSuperTypeOf(Type $type): TrinaryLogic return $result; } - $isKeySuperType = $this->getKeyType()->isSuperTypeOf($type->getKeyType()); + $isKeySuperType = $this->getIterableKeyType()->isSuperTypeOf($type->getKeyType()); if ($isKeySuperType->no()) { return TrinaryLogic::createNo(); } - return $result->and($isKeySuperType, $this->getItemType()->isSuperTypeOf($type->getItemType())); + return $result->and($isKeySuperType, $this->getIterableValueType()->isSuperTypeOf($type->getIterableKeyType())); } if ($type instanceof CompoundType) { @@ -738,7 +797,7 @@ public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type $results = []; foreach ($finiteTypes as $finiteType) { if (!$finiteType instanceof ConstantIntegerType || $finiteType->getValue() < 1) { - return parent::chunkArray($lengthType, $preserveKeys); + return $this->traitChunkArray($lengthType, $preserveKeys); } $length = $finiteType->getValue(); @@ -757,7 +816,7 @@ public function chunkArray(Type $lengthType, TrinaryLogic $preserveKeys): Type return TypeCombinator::union(...$results); } - return parent::chunkArray($lengthType, $preserveKeys); + return $this->traitChunkArray($lengthType, $preserveKeys); } public function fillKeysArray(Type $valueType): Type @@ -880,7 +939,7 @@ public function shuffleArray(): Type return $valuesArray; } - $generalizedArray = new ArrayType($valuesArray->getIterableKeyType(), $valuesArray->getItemType()); + $generalizedArray = new ArrayType($valuesArray->getIterableKeyType(), $valuesArray->getIterableValueType()); if ($isIterableAtLeastOnce->yes()) { $generalizedArray = TypeCombinator::intersect($generalizedArray, new NonEmptyArrayType()); @@ -1192,7 +1251,7 @@ public function generalize(GeneralizePrecision $precision): Type $arrayType = new ArrayType( $this->getIterableKeyType()->generalize($precision), - $this->getItemType()->generalize($precision), + $this->getIterableValueType()->generalize($precision), ); $keyTypesCount = count($this->keyTypes); @@ -1222,10 +1281,7 @@ public function generalize(GeneralizePrecision $precision): Type return $arrayType; } - /** - * @return self - */ - public function generalizeValues(): ArrayType + public function generalizeValues(): self { $valueTypes = []; foreach ($this->valueTypes as $valueType) { @@ -1235,18 +1291,12 @@ public function generalizeValues(): ArrayType return new self($this->keyTypes, $valueTypes, $this->nextAutoIndexes, $this->optionalKeys, $this->isList); } - /** - * @return self - */ - public function getKeysArray(): Type + public function getKeysArray(): self { return $this->getKeysOrValuesArray($this->keyTypes); } - /** - * @return self - */ - public function getValuesArray(): Type + public function getValuesArray(): self { return $this->getKeysOrValuesArray($this->valueTypes); } @@ -1343,7 +1393,7 @@ public function describe(VerbosityLevel $level): string ); }; return $level->handle( - fn (): string => parent::describe($level), + fn (): string => $this->isIterableAtLeastOnce()->no() ? 'array' : sprintf('array<%s, %s>', $this->getIterableKeyType()->describe($level), $this->getIterableValueType()->describe($level)), static fn (): string => $describeValue(true), static fn (): string => $describeValue(false), ); @@ -1369,7 +1419,14 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap return $typeMap; } - return parent::inferTemplateTypes($receivedType); + if ($receivedType->isArray()->yes()) { + $keyTypeMap = $this->getIterableKeyType()->inferTemplateTypes($receivedType->getIterableKeyType()); + $itemTypeMap = $this->getIterableValueType()->inferTemplateTypes($receivedType->getIterableValueType()); + + return $keyTypeMap->union($itemTypeMap); + } + + return TemplateTypeMap::createEmpty(); } public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array @@ -1392,6 +1449,27 @@ public function getReferencedTemplateTypes(TemplateTypeVariance $positionVarianc return $references; } + public function tryRemove(Type $typeToRemove): ?Type + { + if ($typeToRemove->isConstantArray()->yes() && $typeToRemove->isIterableAtLeastOnce()->no()) { + return TypeCombinator::intersect($this, new NonEmptyArrayType()); + } + + if ($typeToRemove instanceof NonEmptyArrayType) { + return new ConstantArrayType([], []); + } + + if ($typeToRemove instanceof HasOffsetType) { + return $this->unsetOffset($typeToRemove->getOffsetType()); + } + + if ($typeToRemove instanceof HasOffsetValueType) { + return $this->unsetOffset($typeToRemove->getOffsetType()); + } + + return null; + } + public function traverse(callable $cb): Type { $valueTypes = []; diff --git a/src/Type/Traits/ArrayTypeTrait.php b/src/Type/Traits/ArrayTypeTrait.php new file mode 100644 index 0000000000..ee77d47162 --- /dev/null +++ b/src/Type/Traits/ArrayTypeTrait.php @@ -0,0 +1,201 @@ +yes() + ? $this + : TypeCombinator::intersect(new ArrayType(new IntegerType(), $this->getIterableValueType()), new AccessoryArrayListType()); + $chunkType = TypeCombinator::intersect($chunkType, new NonEmptyArrayType()); + + $arrayType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $chunkType), new AccessoryArrayListType()); + + return $this->isIterableAtLeastOnce()->yes() + ? TypeCombinator::intersect($arrayType, new NonEmptyArrayType()) + : $arrayType; + } + +} diff --git a/src/Type/Type.php b/src/Type/Type.php index ce306ee9f5..fec6ead728 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -56,7 +56,7 @@ public function isObject(): TrinaryLogic; public function isEnum(): TrinaryLogic; - /** @return list */ + /** @return list */ public function getArrays(): array; /** @return list */ diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 7a016c7bee..c67cb05ff7 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -807,7 +807,7 @@ private static function optimizeConstantArrays(array $types): array $innerValueType = $type->getValueTypes()[$i]; $generalizedValueType = TypeTraverser::map($innerValueType, static function (Type $type, callable $innerTraverse) use ($traverse): Type { - if ($type instanceof ArrayType) { + if ($type instanceof ArrayType || $type instanceof ConstantArrayType) { return TypeCombinator::intersect($type, new OversizedArrayType()); } @@ -1207,7 +1207,7 @@ public static function intersect(Type ...$types): Type continue 2; } - if ($types[$i] instanceof ConstantArrayType && $types[$j] instanceof ArrayType) { + if ($types[$i] instanceof ConstantArrayType && ($types[$j] instanceof ArrayType || $types[$j] instanceof ConstantArrayType)) { $newArray = ConstantArrayTypeBuilder::createEmpty(); $valueTypes = $types[$i]->getValueTypes(); foreach ($types[$i]->getKeyTypes() as $k => $keyType) { @@ -1223,7 +1223,7 @@ public static function intersect(Type ...$types): Type continue 2; } - if ($types[$j] instanceof ConstantArrayType && $types[$i] instanceof ArrayType) { + if ($types[$j] instanceof ConstantArrayType && ($types[$i] instanceof ArrayType || $types[$i] instanceof ConstantArrayType)) { $newArray = ConstantArrayTypeBuilder::createEmpty(); $valueTypes = $types[$j]->getValueTypes(); foreach ($types[$j]->getKeyTypes() as $k => $keyType) { @@ -1240,8 +1240,8 @@ public static function intersect(Type ...$types): Type } if ( - ($types[$i] instanceof ArrayType || $types[$i] instanceof IterableType) && - ($types[$j] instanceof ArrayType || $types[$j] instanceof IterableType) + ($types[$i] instanceof ArrayType || $types[$i] instanceof ConstantArrayType || $types[$i] instanceof IterableType) && + ($types[$j] instanceof ArrayType || $types[$j] instanceof ConstantArrayType || $types[$j] instanceof IterableType) ) { $keyType = self::intersect($types[$i]->getIterableKeyType(), $types[$j]->getKeyType()); $itemType = self::intersect($types[$i]->getItemType(), $types[$j]->getItemType()); diff --git a/src/Type/TypehintHelper.php b/src/Type/TypehintHelper.php index 5538370ccb..f2e2109820 100644 --- a/src/Type/TypehintHelper.php +++ b/src/Type/TypehintHelper.php @@ -10,6 +10,7 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\ShouldNotHappenException; +use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Generic\TemplateTypeHelper; use ReflectionType; use function array_map; @@ -30,7 +31,7 @@ public static function decideTypeFromReflection( ): Type { if ($reflectionType === null) { - if ($isVariadic && $phpDocType instanceof ArrayType) { + if ($isVariadic && ($phpDocType instanceof ArrayType || $phpDocType instanceof ConstantArrayType)) { $phpDocType = $phpDocType->getItemType(); } return $phpDocType ?? new MixedType(); @@ -109,7 +110,7 @@ public static function decideType( if ($phpDocType instanceof UnionType) { $innerTypes = []; foreach ($phpDocType->getTypes() as $innerType) { - if ($innerType instanceof ArrayType) { + if ($innerType instanceof ArrayType || $innerType instanceof ConstantArrayType) { $innerTypes[] = new IterableType( $innerType->getIterableKeyType(), $innerType->getItemType(), @@ -119,7 +120,7 @@ public static function decideType( } } $phpDocType = new UnionType($innerTypes); - } elseif ($phpDocType instanceof ArrayType) { + } elseif ($phpDocType instanceof ArrayType || $phpDocType instanceof ConstantArrayType) { $phpDocType = new IterableType( $phpDocType->getKeyType(), $phpDocType->getItemType(), From 45b4a854ada757044ddab1b2f783027c1f54e8cd Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 29 Sep 2024 13:55:23 +0200 Subject: [PATCH 283/508] Regression test Closes https://github.com/phpstan/phpstan/issues/7173 --- ...rictComparisonOfDifferentTypesRuleTest.php | 5 +++++ .../Rules/Comparison/data/bug-7173.php | 19 +++++++++++++++++++ .../WrongVariableNameInVarTagRuleTest.php | 4 ++++ .../PhpDoc/data/wrong-variable-name-var.php | 17 +++++++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 tests/PHPStan/Rules/Comparison/data/bug-7173.php diff --git a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php index 08a7ecfb87..65e47459f0 100644 --- a/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php @@ -906,4 +906,9 @@ public function testBug10493(): void $this->analyse([__DIR__ . '/data/bug-10493.php'], []); } + public function testBug7173(): void + { + $this->analyse([__DIR__ . '/data/bug-7173.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-7173.php b/tests/PHPStan/Rules/Comparison/data/bug-7173.php new file mode 100644 index 0000000000..039b2bd667 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-7173.php @@ -0,0 +1,19 @@ + 0, + 'item1' => 0, + ]; + + call_user_func(function () use (&$a1) { + $a1['item2'] = 3; + $a1['item1'] = 1; + }); + + if (['item2' => 3, 'item1' => 1] === $a1) { + throw new \Exception(); + } +}; diff --git a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php index 155c0d6ea4..f0c8cd0025 100644 --- a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php @@ -140,6 +140,10 @@ public function testRule(): void 'PHPDoc tag @var above a function has no effect.', 313, ], + [ + "PHPDoc tag @var with type array is not subtype of native type array{: 'empty', 1: '1'}.", + 324, + ], ]); } diff --git a/tests/PHPStan/Rules/PhpDoc/data/wrong-variable-name-var.php b/tests/PHPStan/Rules/PhpDoc/data/wrong-variable-name-var.php index a769c5f2dd..30f7dd3182 100644 --- a/tests/PHPStan/Rules/PhpDoc/data/wrong-variable-name-var.php +++ b/tests/PHPStan/Rules/PhpDoc/data/wrong-variable-name-var.php @@ -314,3 +314,20 @@ function doFoo(): void { } + +class VarTagAboveLiteralArray +{ + + public function doFoo(): void + { + /** @var array */ + $arr = ['' => 'empty', 1 => '1']; + } + + public function doFoo2(): void + { + /** @var array */ + $arr = ['' => 'empty', 1 => '1']; + } + +} From e75996b626ccef553e413c6535107ba5669c6938 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 29 Sep 2024 14:02:03 +0200 Subject: [PATCH 284/508] [BCB] Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 7 +++---- src/Type/Php/RegexArrayShapeMatcher.php | 4 ++-- .../Type/Constant/ConstantArrayTypeTest.php | 20 +++++++++---------- tests/PHPStan/Type/TypeGetFiniteTypesTest.php | 9 +++++---- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 00d7c0766d..bfba8f8dd9 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -273,3 +273,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead * Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead * Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead +* Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer bool diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 5e24881e61..498d59f41d 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -59,7 +59,6 @@ use function count; use function implode; use function in_array; -use function is_bool; use function is_int; use function is_string; use function min; @@ -108,7 +107,7 @@ public function __construct( private array $valueTypes, int|array $nextAutoIndexes = [0], private array $optionalKeys = [], - bool|TrinaryLogic $isList = false, + ?TrinaryLogic $isList = null, ) { assert(count($keyTypes) === count($valueTypes)); @@ -124,8 +123,8 @@ public function __construct( $isList = TrinaryLogic::createYes(); } - if (is_bool($isList)) { - $isList = TrinaryLogic::createFromBoolean($isList); + if ($isList === null) { + $isList = TrinaryLogic::createNo(); } $this->isList = $isList; } diff --git a/src/Type/Php/RegexArrayShapeMatcher.php b/src/Type/Php/RegexArrayShapeMatcher.php index e2b489ddab..a433c4a89b 100644 --- a/src/Type/Php/RegexArrayShapeMatcher.php +++ b/src/Type/Php/RegexArrayShapeMatcher.php @@ -149,7 +149,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched if (!$this->containsUnmatchedAsNull($flags, $matchesAll)) { // positive match has a subject but not any capturing group $combiType = TypeCombinator::union( - new ConstantArrayType([new ConstantIntegerType(0)], [$this->createSubjectValueType($flags, $matchesAll)], [1], [], true), + new ConstantArrayType([new ConstantIntegerType(0)], [$this->createSubjectValueType($flags, $matchesAll)], [1], [], TrinaryLogic::createYes()), $combiType, ); } @@ -214,7 +214,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched ) ) { // positive match has a subject but not any capturing group - $combiTypes[] = new ConstantArrayType([new ConstantIntegerType(0)], [$this->createSubjectValueType($flags, $matchesAll)], [1], [], true); + $combiTypes[] = new ConstantArrayType([new ConstantIntegerType(0)], [$this->createSubjectValueType($flags, $matchesAll)], [1], [], TrinaryLogic::createYes()); } return TypeCombinator::union(...$combiTypes); diff --git a/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php b/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php index 727fd65d01..62ed2ebb9b 100644 --- a/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php +++ b/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php @@ -886,14 +886,14 @@ public function dataValuesArray(): iterable ], [ new ConstantStringType('a'), new ConstantStringType('b'), - ], [20], [], false), + ], [20], [], TrinaryLogic::createNo()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), ], [ new ConstantStringType('a'), new ConstantStringType('b'), - ], [2], [], true), + ], [2], [], TrinaryLogic::createYes()), ]; yield 'optional-1' => [ @@ -909,7 +909,7 @@ public function dataValuesArray(): iterable new ConstantStringType('c'), new ConstantStringType('d'), new ConstantStringType('e'), - ], [15], [1, 3], false), + ], [15], [1, 3], TrinaryLogic::createNo()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), @@ -922,7 +922,7 @@ public function dataValuesArray(): iterable new UnionType([new ConstantStringType('c'), new ConstantStringType('d'), new ConstantStringType('e')]), new UnionType([new ConstantStringType('d'), new ConstantStringType('e')]), new ConstantStringType('e'), - ], [3, 4, 5], [3, 4], true), + ], [3, 4, 5], [3, 4], TrinaryLogic::createYes()), ]; yield 'optional-2' => [ @@ -938,7 +938,7 @@ public function dataValuesArray(): iterable new ConstantStringType('c'), new ConstantStringType('d'), new ConstantStringType('e'), - ], [15], [0, 2, 4], false), + ], [15], [0, 2, 4], TrinaryLogic::createNo()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), @@ -951,7 +951,7 @@ public function dataValuesArray(): iterable new UnionType([new ConstantStringType('c'), new ConstantStringType('d'), new ConstantStringType('e')]), new UnionType([new ConstantStringType('d'), new ConstantStringType('e')]), new ConstantStringType('e'), - ], [2, 3, 4, 5], [2, 3, 4], true), + ], [2, 3, 4, 5], [2, 3, 4], TrinaryLogic::createYes()), ]; yield 'optional-at-end-and-list' => [ @@ -963,7 +963,7 @@ public function dataValuesArray(): iterable new ConstantStringType('a'), new ConstantStringType('b'), new ConstantStringType('c'), - ], [11, 12, 13], [1, 2], true), + ], [11, 12, 13], [1, 2], TrinaryLogic::createYes()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), @@ -972,7 +972,7 @@ public function dataValuesArray(): iterable new ConstantStringType('a'), new ConstantStringType('b'), new ConstantStringType('c'), - ], [1, 2, 3], [1, 2], true), + ], [1, 2, 3], [1, 2], TrinaryLogic::createYes()), ]; yield 'optional-at-end-but-not-list' => [ @@ -984,7 +984,7 @@ public function dataValuesArray(): iterable new ConstantStringType('a'), new ConstantStringType('b'), new ConstantStringType('c'), - ], [11, 12, 13], [1, 2], false), + ], [11, 12, 13], [1, 2], TrinaryLogic::createNo()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), @@ -993,7 +993,7 @@ public function dataValuesArray(): iterable new ConstantStringType('a'), new UnionType([new ConstantStringType('b'), new ConstantStringType('c')]), new ConstantStringType('c'), - ], [1, 2, 3], [1, 2], true), + ], [1, 2, 3], [1, 2], TrinaryLogic::createYes()), ]; } diff --git a/tests/PHPStan/Type/TypeGetFiniteTypesTest.php b/tests/PHPStan/Type/TypeGetFiniteTypesTest.php index ce605f3d5a..c2f0f96191 100644 --- a/tests/PHPStan/Type/TypeGetFiniteTypesTest.php +++ b/tests/PHPStan/Type/TypeGetFiniteTypesTest.php @@ -3,6 +3,7 @@ namespace PHPStan\Type; use PHPStan\Testing\PHPStanTestCase; +use PHPStan\TrinaryLogic; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantIntegerType; @@ -96,28 +97,28 @@ public function dataGetFiniteTypes(): iterable ], [ new ConstantBooleanType(true), new ConstantBooleanType(true), - ], 2, [], true), + ], 2, [], TrinaryLogic::createYes()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), ], [ new ConstantBooleanType(true), new ConstantBooleanType(false), - ], 2, [], true), + ], 2, [], TrinaryLogic::createYes()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), ], [ new ConstantBooleanType(false), new ConstantBooleanType(true), - ], 2, [], true), + ], 2, [], TrinaryLogic::createYes()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), ], [ new ConstantBooleanType(false), new ConstantBooleanType(false), - ], 2, [], true), + ], 2, [], TrinaryLogic::createYes()), ], ]; } From f302c9069274afa63ec1b4f313ca72340699e9d8 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 19 Nov 2023 10:28:35 +0100 Subject: [PATCH 285/508] Remove unneded abstraction --- .../Native/NativeMethodReflection.php | 8 +- .../Php/BuiltinMethodReflection.php | 60 ------- .../Php/NativeBuiltinMethodReflection.php | 148 ------------------ .../Php/PhpClassReflectionExtension.php | 53 +++---- src/Reflection/Php/PhpMethodReflection.php | 7 +- .../Php/PhpMethodReflectionFactory.php | 3 +- src/Rules/Methods/MethodSignatureRule.php | 3 +- src/Rules/Methods/OverridingMethodRule.php | 3 +- 8 files changed, 34 insertions(+), 251 deletions(-) delete mode 100644 src/Reflection/Php/BuiltinMethodReflection.php delete mode 100644 src/Reflection/Php/NativeBuiltinMethodReflection.php diff --git a/src/Reflection/Native/NativeMethodReflection.php b/src/Reflection/Native/NativeMethodReflection.php index d588cea558..68ee421e38 100644 --- a/src/Reflection/Native/NativeMethodReflection.php +++ b/src/Reflection/Native/NativeMethodReflection.php @@ -2,13 +2,13 @@ namespace PHPStan\Reflection\Native; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\MethodPrototypeReflection; use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; -use PHPStan\Reflection\Php\BuiltinMethodReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; @@ -28,7 +28,7 @@ final class NativeMethodReflection implements ExtendedMethodReflection public function __construct( private ReflectionProvider $reflectionProvider, private ClassReflection $declaringClass, - private BuiltinMethodReflection $reflection, + private ReflectionMethod $reflection, private array $variants, private ?array $namedArgumentsVariants, private TrinaryLogic $hasSideEffects, @@ -133,7 +133,7 @@ public function getDeprecatedDescription(): ?string public function isDeprecated(): TrinaryLogic { - return $this->reflection->isDeprecated(); + return TrinaryLogic::createFromBoolean($this->reflection->isDeprecated()); } public function isInternal(): TrinaryLogic @@ -212,7 +212,7 @@ public function getSelfOutType(): ?Type public function returnsByReference(): TrinaryLogic { - return $this->reflection->returnsByReference(); + return TrinaryLogic::createFromBoolean($this->reflection->returnsReference()); } } diff --git a/src/Reflection/Php/BuiltinMethodReflection.php b/src/Reflection/Php/BuiltinMethodReflection.php deleted file mode 100644 index d2d55336aa..0000000000 --- a/src/Reflection/Php/BuiltinMethodReflection.php +++ /dev/null @@ -1,60 +0,0 @@ -reflection->getName(); - } - - public function getReflection(): ReflectionMethod - { - return $this->reflection; - } - - public function getFileName(): ?string - { - $fileName = $this->reflection->getFileName(); - if ($fileName === false) { - return null; - } - - return $fileName; - } - - public function getDeclaringClass(): ReflectionClass - { - return $this->reflection->getDeclaringClass(); - } - - public function getStartLine(): ?int - { - $line = $this->reflection->getStartLine(); - if ($line === false) { - return null; - } - - return $line; - } - - public function getEndLine(): ?int - { - $line = $this->reflection->getEndLine(); - if ($line === false) { - return null; - } - - return $line; - } - - public function getDocComment(): ?string - { - $docComment = $this->reflection->getDocComment(); - if ($docComment === false) { - return null; - } - - return $docComment; - } - - public function isStatic(): bool - { - return $this->reflection->isStatic(); - } - - public function isPrivate(): bool - { - return $this->reflection->isPrivate(); - } - - public function isPublic(): bool - { - return $this->reflection->isPublic(); - } - - public function isConstructor(): bool - { - return $this->reflection->isConstructor(); - } - - public function getPrototype(): BuiltinMethodReflection - { - return new self($this->reflection->getPrototype()); - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createFromBoolean($this->reflection->isDeprecated()); - } - - public function isFinal(): bool - { - return $this->reflection->isFinal(); - } - - public function isInternal(): bool - { - return $this->reflection->isInternal(); - } - - public function isAbstract(): bool - { - return $this->reflection->isAbstract(); - } - - public function isVariadic(): bool - { - return $this->reflection->isVariadic(); - } - - public function getReturnType(): ReflectionIntersectionType|ReflectionNamedType|ReflectionUnionType|null - { - return $this->reflection->getReturnType(); - } - - public function getTentativeReturnType(): ReflectionIntersectionType|ReflectionNamedType|ReflectionUnionType|null - { - return $this->reflection->getTentativeReturnType(); - } - - /** - * @return ReflectionParameter[] - */ - public function getParameters(): array - { - return $this->reflection->getParameters(); - } - - public function returnsByReference(): TrinaryLogic - { - return TrinaryLogic::createFromBoolean($this->reflection->returnsReference()); - } - -} diff --git a/src/Reflection/Php/PhpClassReflectionExtension.php b/src/Reflection/Php/PhpClassReflectionExtension.php index 9b9a9132e1..b7f438737a 100644 --- a/src/Reflection/Php/PhpClassReflectionExtension.php +++ b/src/Reflection/Php/PhpClassReflectionExtension.php @@ -10,6 +10,7 @@ use PHPStan\Analyser\NodeScopeResolver; use PHPStan\Analyser\ScopeContext; use PHPStan\Analyser\ScopeFactory; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionProperty; use PHPStan\Parser\Parser; @@ -384,7 +385,7 @@ public function getMethod(ClassReflection $classReflection, string $methodName): return $this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName]; } - $nativeMethodReflection = new NativeBuiltinMethodReflection($classReflection->getNativeReflection()->getMethod($methodName)); + $nativeMethodReflection = $classReflection->getNativeReflection()->getMethod($methodName); if (!isset($this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$nativeMethodReflection->getName()])) { $method = $this->createMethod($classReflection, $nativeMethodReflection, true); $this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$nativeMethodReflection->getName()] = $method; @@ -411,8 +412,7 @@ public function getNativeMethod(ClassReflection $classReflection, string $method throw new ShouldNotHappenException(); } - $reflectionMethod = $classReflection->getNativeReflection()->getMethod($methodName); - $nativeMethodReflection = new NativeBuiltinMethodReflection($reflectionMethod); + $nativeMethodReflection = $classReflection->getNativeReflection()->getMethod($methodName); if (!isset($this->nativeMethods[$classReflection->getCacheKey()][$nativeMethodReflection->getName()])) { $method = $this->createMethod($classReflection, $nativeMethodReflection, false); @@ -424,7 +424,7 @@ public function getNativeMethod(ClassReflection $classReflection, string $method private function createMethod( ClassReflection $classReflection, - BuiltinMethodReflection $methodReflection, + ReflectionMethod $methodReflection, bool $includingAnnotations, ): ExtendedMethodReflection { @@ -642,27 +642,25 @@ private function createMethod( ); } - public function createUserlandMethodReflection(ClassReflection $fileDeclaringClass, ClassReflection $actualDeclaringClass, BuiltinMethodReflection $methodReflection, ?string $declaringTraitName): PhpMethodReflection + public function createUserlandMethodReflection(ClassReflection $fileDeclaringClass, ClassReflection $actualDeclaringClass, ReflectionMethod $methodReflection, ?string $declaringTraitName): PhpMethodReflection { $resolvedPhpDoc = null; $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($fileDeclaringClass, $fileDeclaringClass, $methodReflection->getName(), array_map(static fn (ReflectionParameter $parameter): string => $parameter->getName(), $methodReflection->getParameters())); $phpDocBlockClassReflection = $fileDeclaringClass; - if ($methodReflection->getReflection() !== null) { - $methodDeclaringClass = $methodReflection->getReflection()->getBetterReflection()->getDeclaringClass(); - - if ($stubPhpDocPair === null && $methodDeclaringClass->isTrait()) { - if (! $methodReflection->getDeclaringClass()->isTrait() || $methodDeclaringClass->getName() !== $methodReflection->getDeclaringClass()->getName()) { - $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors( - $this->reflectionProviderProvider->getReflectionProvider()->getClass($methodDeclaringClass->getName()), - $this->reflectionProviderProvider->getReflectionProvider()->getClass($methodReflection->getDeclaringClass()->getName()), - $methodReflection->getName(), - array_map( - static fn (ReflectionParameter $parameter): string => $parameter->getName(), - $methodReflection->getParameters(), - ), - ); - } + $methodDeclaringClass = $methodReflection->getBetterReflection()->getDeclaringClass(); + + if ($stubPhpDocPair === null && $methodDeclaringClass->isTrait()) { + if (! $methodReflection->getDeclaringClass()->isTrait() || $methodDeclaringClass->getName() !== $methodReflection->getDeclaringClass()->getName()) { + $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors( + $this->reflectionProviderProvider->getReflectionProvider()->getClass($methodDeclaringClass->getName()), + $this->reflectionProviderProvider->getReflectionProvider()->getClass($methodReflection->getDeclaringClass()->getName()), + $methodReflection->getName(), + array_map( + static fn (ReflectionParameter $parameter): string => $parameter->getName(), + $methodReflection->getParameters(), + ), + ); } } @@ -671,7 +669,7 @@ public function createUserlandMethodReflection(ClassReflection $fileDeclaringCla } if ($resolvedPhpDoc === null) { - $docComment = $methodReflection->getDocComment(); + $docComment = $methodReflection->getDocComment() !== false ? $methodReflection->getDocComment() : null; $positionalParameterNames = array_map(static fn (ReflectionParameter $parameter): string => $parameter->getName(), $methodReflection->getParameters()); $resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForMethod( @@ -694,10 +692,7 @@ public function createUserlandMethodReflection(ClassReflection $fileDeclaringCla } $phpDocParameterTypes = []; - if ( - $methodReflection instanceof NativeBuiltinMethodReflection - && $methodReflection->isConstructor() - ) { + if ($methodReflection->isConstructor()) { foreach ($methodReflection->getParameters() as $parameter) { if (!$parameter->isPromoted()) { continue; @@ -922,14 +917,10 @@ private function findPropertyTrait(ReflectionProperty $propertyReflection): ?str } private function findMethodTrait( - BuiltinMethodReflection $methodReflection, + ReflectionMethod $methodReflection, ): ?string { - if ($methodReflection->getReflection() === null) { - return null; - } - - $declaringClass = $methodReflection->getReflection()->getBetterReflection()->getDeclaringClass(); + $declaringClass = $methodReflection->getBetterReflection()->getDeclaringClass(); if ($declaringClass->isTrait()) { if ($methodReflection->getDeclaringClass()->isTrait() && $declaringClass->getName() === $methodReflection->getDeclaringClass()->getName()) { return null; diff --git a/src/Reflection/Php/PhpMethodReflection.php b/src/Reflection/Php/PhpMethodReflection.php index 8de0a7870e..7188551137 100644 --- a/src/Reflection/Php/PhpMethodReflection.php +++ b/src/Reflection/Php/PhpMethodReflection.php @@ -7,6 +7,7 @@ use PhpParser\Node\Stmt\Declare_; use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Namespace_; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter; use PHPStan\Cache\Cache; use PHPStan\Parser\FunctionCallStatementFinder; @@ -71,7 +72,7 @@ public function __construct( private InitializerExprTypeResolver $initializerExprTypeResolver, private ClassReflection $declaringClass, private ?ClassReflection $declaringTrait, - private BuiltinMethodReflection $reflection, + private ReflectionMethod $reflection, private ReflectionProvider $reflectionProvider, private Parser $parser, private FunctionCallStatementFinder $functionCallStatementFinder, @@ -409,7 +410,7 @@ public function isDeprecated(): TrinaryLogic return TrinaryLogic::createYes(); } - return $this->reflection->isDeprecated(); + return TrinaryLogic::createFromBoolean($this->reflection->isDeprecated()); } public function isInternal(): TrinaryLogic @@ -478,7 +479,7 @@ public function getDocComment(): ?string public function returnsByReference(): TrinaryLogic { - return $this->reflection->returnsByReference(); + return TrinaryLogic::createFromBoolean($this->reflection->returnsReference()); } public function isPure(): TrinaryLogic diff --git a/src/Reflection/Php/PhpMethodReflectionFactory.php b/src/Reflection/Php/PhpMethodReflectionFactory.php index 77de1aa1b7..22028286d3 100644 --- a/src/Reflection/Php/PhpMethodReflectionFactory.php +++ b/src/Reflection/Php/PhpMethodReflectionFactory.php @@ -2,6 +2,7 @@ namespace PHPStan\Reflection\Php; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassReflection; use PHPStan\TrinaryLogic; @@ -20,7 +21,7 @@ interface PhpMethodReflectionFactory public function create( ClassReflection $declaringClass, ?ClassReflection $declaringTrait, - BuiltinMethodReflection $reflection, + ReflectionMethod $reflection, TemplateTypeMap $templateTypeMap, array $phpDocParameterTypes, ?Type $phpDocReturnType, diff --git a/src/Rules/Methods/MethodSignatureRule.php b/src/Rules/Methods/MethodSignatureRule.php index 5a1a007253..bac3f273ad 100644 --- a/src/Rules/Methods/MethodSignatureRule.php +++ b/src/Rules/Methods/MethodSignatureRule.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; -use PHPStan\Reflection\Php\NativeBuiltinMethodReflection; use PHPStan\Reflection\Php\PhpClassReflectionExtension; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\Rule; @@ -182,7 +181,7 @@ private function collectParentMethods(string $methodName, ClassReflection $class $this->phpClassReflectionExtension->createUserlandMethodReflection( $trait, $class, - new NativeBuiltinMethodReflection($methodReflection), + $methodReflection, $declaringTrait->getName(), ), $declaringTrait, diff --git a/src/Rules/Methods/OverridingMethodRule.php b/src/Rules/Methods/OverridingMethodRule.php index 37de68b4f6..0a78f8d382 100644 --- a/src/Rules/Methods/OverridingMethodRule.php +++ b/src/Rules/Methods/OverridingMethodRule.php @@ -11,7 +11,6 @@ use PHPStan\Reflection\FunctionVariantWithPhpDocs; use PHPStan\Reflection\MethodPrototypeReflection; use PHPStan\Reflection\Native\NativeMethodReflection; -use PHPStan\Reflection\Php\NativeBuiltinMethodReflection; use PHPStan\Reflection\Php\PhpClassReflectionExtension; use PHPStan\Reflection\Php\PhpMethodReflection; use PHPStan\Rules\IdentifierRuleError; @@ -368,7 +367,7 @@ private function findPrototype(ClassReflection $classReflection, string $methodN $this->phpClassReflectionExtension->createUserlandMethodReflection( $trait, $classReflection, - new NativeBuiltinMethodReflection($methodReflection), + $methodReflection, $declaringTrait->getName(), ), $declaringTrait, From a5297b0c2354e08ba7b3e5d53110a4504db1cd66 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 29 Sep 2024 14:15:08 +0200 Subject: [PATCH 286/508] [BCB] Remove `ConstantType` interface --- UPGRADING.md | 1 + phpstan-baseline.neon | 5 ----- src/Rules/Api/ApiInstanceofTypeRule.php | 2 -- src/Type/Constant/ConstantArrayType.php | 3 +-- src/Type/ConstantScalarType.php | 2 +- src/Type/ConstantType.php | 9 --------- src/Type/Php/MinMaxFunctionReturnTypeExtension.php | 4 +--- 7 files changed, 4 insertions(+), 22 deletions(-) delete mode 100644 src/Type/ConstantType.php diff --git a/UPGRADING.md b/UPGRADING.md index bfba8f8dd9..4fb0823cf3 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -274,3 +274,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead * Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead * Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer bool +* Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 4477db7fce..23d822be89 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1285,11 +1285,6 @@ parameters: count: 4 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantValue\\(\\) or Type\\:\\:generalize\\(\\) instead\\.$#" - count: 1 - path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 2 diff --git a/src/Rules/Api/ApiInstanceofTypeRule.php b/src/Rules/Api/ApiInstanceofTypeRule.php index 35ed6d3cf8..118c8d5b9f 100644 --- a/src/Rules/Api/ApiInstanceofTypeRule.php +++ b/src/Rules/Api/ApiInstanceofTypeRule.php @@ -29,7 +29,6 @@ use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ConstantScalarType; -use PHPStan\Type\ConstantType; use PHPStan\Type\Enum\EnumCaseObjectType; use PHPStan\Type\FloatType; use PHPStan\Type\Generic\GenericClassStringType; @@ -75,7 +74,6 @@ final class ApiInstanceofTypeRule implements Rule GenericClassStringType::class => 'Type::isClassStringType() and Type::getClassStringObjectType()', GenericObjectType::class => null, IntersectionType::class => null, - ConstantType::class => 'Type::isConstantValue() or Type::generalize()', ConstantScalarType::class => 'Type::isConstantScalarValue() or Type::getConstantScalarTypes() or Type::getConstantScalarValues()', ObjectShapeType::class => 'Type::isObject() and Type::hasProperty()', diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 498d59f41d..09eda329e3 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -30,7 +30,6 @@ use PHPStan\Type\BooleanType; use PHPStan\Type\CompoundType; use PHPStan\Type\ConstantScalarType; -use PHPStan\Type\ConstantType; use PHPStan\Type\ErrorType; use PHPStan\Type\GeneralizePrecision; use PHPStan\Type\Generic\TemplateTypeMap; @@ -71,7 +70,7 @@ /** * @api */ -class ConstantArrayType implements ConstantType +class ConstantArrayType implements Type { use ArrayTypeTrait { diff --git a/src/Type/ConstantScalarType.php b/src/Type/ConstantScalarType.php index f44e18333b..b84b381717 100644 --- a/src/Type/ConstantScalarType.php +++ b/src/Type/ConstantScalarType.php @@ -3,7 +3,7 @@ namespace PHPStan\Type; /** @api */ -interface ConstantScalarType extends ConstantType +interface ConstantScalarType extends Type { /** diff --git a/src/Type/ConstantType.php b/src/Type/ConstantType.php deleted file mode 100644 index d5fab2b652..0000000000 --- a/src/Type/ConstantType.php +++ /dev/null @@ -1,9 +0,0 @@ -isConstantValue()->yes()) { return TypeCombinator::union(...$types); } - if ($resultType === null) { $resultType = $type; continue; From bd4c3ed608d9554c6f468bd11cc27a92a41b4e14 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 29 Sep 2024 14:26:42 +0200 Subject: [PATCH 287/508] [BCB] Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list` --- UPGRADING.md | 1 + src/Type/Constant/ConstantArrayType.php | 29 ++++--------- .../Type/Constant/ConstantArrayTypeTest.php | 42 +++++++++---------- .../Type/SimultaneousTypeTraverserTest.php | 6 +-- tests/PHPStan/Type/TypeCombinatorTest.php | 10 ++--- tests/PHPStan/Type/TypeGetFiniteTypesTest.php | 10 ++--- tests/PHPStan/Type/UnionTypeTest.php | 16 +++---- 7 files changed, 50 insertions(+), 64 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 4fb0823cf3..cd3d44175a 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -274,4 +274,5 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead * Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead * Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer bool +* Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list`, no longer int * Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 09eda329e3..a257437061 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -58,7 +58,6 @@ use function count; use function implode; use function in_array; -use function is_int; use function is_string; use function min; use function pow; @@ -87,9 +86,6 @@ class ConstantArrayType implements Type /** @var self[]|null */ private ?array $allArrays = null; - /** @var non-empty-list */ - private array $nextAutoIndexes; - private ?Type $iterableKeyType = null; private ?Type $iterableValueType = null; @@ -98,25 +94,19 @@ class ConstantArrayType implements Type * @api * @param array $keyTypes * @param array $valueTypes - * @param non-empty-list|int $nextAutoIndexes + * @param non-empty-list $nextAutoIndexes * @param int[] $optionalKeys */ public function __construct( private array $keyTypes, private array $valueTypes, - int|array $nextAutoIndexes = [0], + private array $nextAutoIndexes = [0], private array $optionalKeys = [], ?TrinaryLogic $isList = null, ) { assert(count($keyTypes) === count($valueTypes)); - if (is_int($nextAutoIndexes)) { - $nextAutoIndexes = [$nextAutoIndexes]; - } - - $this->nextAutoIndexes = $nextAutoIndexes; - $keyTypesCount = count($this->keyTypes); if ($keyTypesCount === 0) { $isList = TrinaryLogic::createYes(); @@ -201,11 +191,6 @@ public function getNextAutoIndexes(): array return $this->nextAutoIndexes; } - private function getNextAutoIndex(): int - { - return $this->nextAutoIndexes[count($this->nextAutoIndexes) - 1]; - } - /** * @return int[] */ @@ -1048,7 +1033,7 @@ private function removeLastElements(int $length): self $keyTypes = $this->keyTypes; $valueTypes = $this->valueTypes; $optionalKeys = $this->optionalKeys; - $nextAutoindex = $this->nextAutoIndexes; + $nextAutoindexes = $this->nextAutoIndexes; $optionalKeysRemoved = 0; $newLength = $keyTypesCount - $length; @@ -1068,9 +1053,9 @@ private function removeLastElements(int $length): self $removedKeyType = array_pop($keyTypes); array_pop($valueTypes); - $nextAutoindex = $removedKeyType instanceof ConstantIntegerType - ? $removedKeyType->getValue() - : $this->getNextAutoIndex(); + $nextAutoindexes = $removedKeyType instanceof ConstantIntegerType + ? [$removedKeyType->getValue()] + : $this->nextAutoIndexes; continue; } @@ -1085,7 +1070,7 @@ private function removeLastElements(int $length): self return new self( $keyTypes, $valueTypes, - $nextAutoindex, + $nextAutoindexes, array_values($optionalKeys), $this->isList, ); diff --git a/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php b/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php index 62ed2ebb9b..9e814dfaf8 100644 --- a/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php +++ b/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php @@ -189,7 +189,7 @@ public function dataAccepts(): iterable ], [ new StringType(), new IntegerType(), - ], 0, [0, 1]), + ], [0], [0, 1]), new ConstantArrayType([ new ConstantStringType('sorton'), new ConstantStringType('limit'), @@ -225,7 +225,7 @@ public function dataAccepts(): iterable ], [ new StringType(), new IntegerType(), - ], 0, [1]), + ], [0], [1]), new ConstantArrayType([ new ConstantStringType('sorton'), new ConstantStringType('limit'), @@ -241,7 +241,7 @@ public function dataAccepts(): iterable new ConstantStringType('limit'), ], [ new IntegerType(), - ], 0, [0]), + ], [0], [0]), new ConstantArrayType([ new ConstantStringType('limit'), ], [ @@ -255,7 +255,7 @@ public function dataAccepts(): iterable new ConstantStringType('limit'), ], [ new IntegerType(), - ], 0), + ], [0]), new ConstantArrayType([ new ConstantStringType('limit'), ], [ @@ -271,7 +271,7 @@ public function dataAccepts(): iterable ], [ new StringType(), new StringType(), - ], 0, [0, 1]), + ], [0], [0, 1]), new ConstantArrayType([ new ConstantStringType('sorton'), new ConstantStringType('limit'), @@ -289,7 +289,7 @@ public function dataAccepts(): iterable ], [ new StringType(), new StringType(), - ], 0, [0, 1]), + ], [0], [0, 1]), new ConstantArrayType([ new ConstantStringType('color'), ], [ @@ -305,7 +305,7 @@ public function dataAccepts(): iterable ], [ new StringType(), new StringType(), - ], 0, [0, 1]), + ], [0], [0, 1]), new ConstantArrayType([ new ConstantStringType('sound'), ], [ @@ -321,14 +321,14 @@ public function dataAccepts(): iterable ], [ new StringType(), new StringType(), - ], 0, [0, 1]), + ], [0], [0, 1]), new ConstantArrayType([ new ConstantStringType('foo'), new ConstantStringType('bar'), ], [ new ConstantStringType('s'), new ConstantStringType('m'), - ], 0, [0, 1]), + ], [0], [0, 1]), TrinaryLogic::createYes(), ]; @@ -339,7 +339,7 @@ public function dataAccepts(): iterable ], [ new StringType(), new IntegerType(), - ], 0, [0, 1]), + ], [0], [0, 1]), new ConstantArrayType([ new ConstantStringType('sorton'), new ConstantStringType('limit'), @@ -522,7 +522,7 @@ public function dataIsSuperTypeOf(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2), + ], [2]), new ConstantArrayType([], []), TrinaryLogic::createNo(), ]; @@ -534,7 +534,7 @@ public function dataIsSuperTypeOf(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2, [0]), + ], [2], [0]), new ConstantArrayType([], []), TrinaryLogic::createNo(), ]; @@ -546,7 +546,7 @@ public function dataIsSuperTypeOf(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2, [0, 1]), + ], [2], [0, 1]), new ConstantArrayType([], []), TrinaryLogic::createYes(), ]; @@ -558,12 +558,12 @@ public function dataIsSuperTypeOf(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2, [0, 1]), + ], [2], [0, 1]), new ConstantArrayType([ new ConstantStringType('foo'), ], [ new IntegerType(), - ], 1, [0]), + ], [1], [0]), TrinaryLogic::createYes(), ]; @@ -579,7 +579,7 @@ public function dataIsSuperTypeOf(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2, [0, 1]), + ], [2], [0, 1]), TrinaryLogic::createMaybe(), ]; @@ -595,7 +595,7 @@ public function dataIsSuperTypeOf(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2, [0, 1]), + ], [2], [0, 1]), TrinaryLogic::createNo(), ]; @@ -606,7 +606,7 @@ public function dataIsSuperTypeOf(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2, [0, 1]), + ], [2], [0, 1]), new ConstantArrayType([ new ConstantStringType('foo'), ], [ @@ -623,7 +623,7 @@ public function dataIsSuperTypeOf(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2, [0, 1]), + ], [2], [0, 1]), TrinaryLogic::createMaybe(), ]; @@ -632,7 +632,7 @@ public function dataIsSuperTypeOf(): iterable new ConstantStringType('foo'), ], [ new IntegerType(), - ], 1, [0]), + ], [1], [0]), new ConstantArrayType([ new ConstantStringType('foo'), ], [ @@ -651,7 +651,7 @@ public function dataIsSuperTypeOf(): iterable new ConstantStringType('foo'), ], [ new IntegerType(), - ], 1, [0]), + ], [1], [0]), TrinaryLogic::createMaybe(), ]; } diff --git a/tests/PHPStan/Type/SimultaneousTypeTraverserTest.php b/tests/PHPStan/Type/SimultaneousTypeTraverserTest.php index e9cb8ada70..3917423ff3 100644 --- a/tests/PHPStan/Type/SimultaneousTypeTraverserTest.php +++ b/tests/PHPStan/Type/SimultaneousTypeTraverserTest.php @@ -22,7 +22,7 @@ public function dataChangeStringIntoNonEmptyString(): iterable new ConstantArrayType( [new ConstantIntegerType(0)], [new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()])], - 1, + [1], ), 'array', ]; @@ -31,7 +31,7 @@ public function dataChangeStringIntoNonEmptyString(): iterable new ConstantArrayType( [new ConstantIntegerType(0)], [new IntersectionType([new StringType(), new AccessoryNonEmptyStringType()])], - 1, + [1], ), 'array', ]; @@ -40,7 +40,7 @@ public function dataChangeStringIntoNonEmptyString(): iterable new ConstantArrayType( [new ConstantIntegerType(0)], [new IntegerType()], - 1, + [1], ), 'array', ]; diff --git a/tests/PHPStan/Type/TypeCombinatorTest.php b/tests/PHPStan/Type/TypeCombinatorTest.php index 55dc30542b..d9d6eefe66 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -1794,7 +1794,7 @@ public function dataUnion(): iterable new ConstantIntegerType(0), ], [ new StringType(), - ], 1, [0]), + ], [1], [0]), ], UnionType::class, 'array{}|array{0?: string}', @@ -3766,7 +3766,7 @@ public function dataIntersect(): iterable ], [ new IntegerType(), new IntegerType(), - ], 2, [0]), + ], [2], [0]), new HasOffsetType(new ConstantStringType('a')), ], ConstantArrayType::class, @@ -4900,7 +4900,7 @@ public function dataRemove(): array ], [ new StringType(), new StringType(), - ], 2), + ], [2]), new HasOffsetType(new ConstantIntegerType(1)), NeverType::class, '*NEVER*=implicit', @@ -4912,7 +4912,7 @@ public function dataRemove(): array ], [ new StringType(), new StringType(), - ], 2, [1]), + ], [2], [1]), new HasOffsetType(new ConstantIntegerType(1)), ConstantArrayType::class, 'array{string}', @@ -4924,7 +4924,7 @@ public function dataRemove(): array ], [ new StringType(), new StringType(), - ], 2, [1]), + ], [2], [1]), new HasOffsetType(new ConstantIntegerType(0)), NeverType::class, '*NEVER*=implicit', diff --git a/tests/PHPStan/Type/TypeGetFiniteTypesTest.php b/tests/PHPStan/Type/TypeGetFiniteTypesTest.php index c2f0f96191..9770a62a72 100644 --- a/tests/PHPStan/Type/TypeGetFiniteTypesTest.php +++ b/tests/PHPStan/Type/TypeGetFiniteTypesTest.php @@ -89,7 +89,7 @@ public function dataGetFiniteTypes(): iterable ], [ new BooleanType(), new BooleanType(), - ], 2), + ], [2]), [ new ConstantArrayType([ new ConstantIntegerType(0), @@ -97,28 +97,28 @@ public function dataGetFiniteTypes(): iterable ], [ new ConstantBooleanType(true), new ConstantBooleanType(true), - ], 2, [], TrinaryLogic::createYes()), + ], [2], [], TrinaryLogic::createYes()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), ], [ new ConstantBooleanType(true), new ConstantBooleanType(false), - ], 2, [], TrinaryLogic::createYes()), + ], [2], [], TrinaryLogic::createYes()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), ], [ new ConstantBooleanType(false), new ConstantBooleanType(true), - ], 2, [], TrinaryLogic::createYes()), + ], [2], [], TrinaryLogic::createYes()), new ConstantArrayType([ new ConstantIntegerType(0), new ConstantIntegerType(1), ], [ new ConstantBooleanType(false), new ConstantBooleanType(false), - ], 2, [], TrinaryLogic::createYes()), + ], [2], [], TrinaryLogic::createYes()), ], ]; } diff --git a/tests/PHPStan/Type/UnionTypeTest.php b/tests/PHPStan/Type/UnionTypeTest.php index cd0ee180cc..83ec097e23 100644 --- a/tests/PHPStan/Type/UnionTypeTest.php +++ b/tests/PHPStan/Type/UnionTypeTest.php @@ -111,7 +111,7 @@ public function dataSelfCompare(): Iterator yield [new CallableType([$mixedParam, $integerParam], $stringType, false)]; yield [new ClassStringType()]; yield [new ClosureType([$mixedParam, $integerParam], $stringType, false)]; - yield [new ConstantArrayType([$constantStringType, $constantIntegerType], [$mixedType, $stringType], 10, [1])]; + yield [new ConstantArrayType([$constantStringType, $constantIntegerType], [$mixedType, $stringType], [10], [1])]; yield [new ConstantBooleanType(true)]; yield [new ConstantFloatType(3.14)]; yield [$constantIntegerType]; @@ -1418,7 +1418,7 @@ public function dataGetConstantArrays(): iterable new ConstantArrayType( [new ConstantIntegerType(1), new ConstantIntegerType(2)], [new IntegerType(), new StringType()], - 2, + [2], [0, 1], ), new NonEmptyArrayType(), @@ -1426,7 +1426,7 @@ public function dataGetConstantArrays(): iterable new ConstantArrayType( [new ConstantIntegerType(0), new ConstantIntegerType(1)], [new ObjectType(Foo::class), new ObjectType(stdClass::class)], - 2, + [2], ), ], [ @@ -1440,7 +1440,7 @@ public function dataGetConstantArrays(): iterable new ConstantArrayType( [new ConstantIntegerType(1), new ConstantIntegerType(2)], [new IntegerType(), new StringType()], - 2, + [2], [0, 1], ), ), @@ -1602,7 +1602,7 @@ public function dataGetArrays(): iterable new ConstantArrayType( [new ConstantIntegerType(1), new ConstantIntegerType(2)], [new IntegerType(), new StringType()], - 2, + [2], [0, 1], ), new NonEmptyArrayType(), @@ -1610,7 +1610,7 @@ public function dataGetArrays(): iterable new ConstantArrayType( [new ConstantIntegerType(0), new ConstantIntegerType(1)], [new ObjectType(Foo::class), new ObjectType(stdClass::class)], - 2, + [2], ), ), [ @@ -1624,13 +1624,13 @@ public function dataGetArrays(): iterable new ConstantArrayType( [new ConstantIntegerType(1), new ConstantIntegerType(2)], [new IntegerType(), new StringType()], - 2, + [2], [0, 1], ), new ConstantArrayType( [new ConstantIntegerType(0), new ConstantIntegerType(1)], [new ObjectType(Foo::class), new ObjectType(stdClass::class)], - 2, + [2], ), ), [ From 1b45eaee2dc3011cf4fca4bd706cdad1cb7273b4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 09:24:58 +0200 Subject: [PATCH 288/508] [BCB] `acceptsNamedArguments()` returns `TrinaryLogic` instead of `bool` --- UPGRADING.md | 1 + src/Analyser/ArgumentsNormalizer.php | 7 ++++--- src/Analyser/MutatingScope.php | 10 +++++----- .../Annotations/AnnotationMethodReflection.php | 4 ++-- src/Reflection/CallableFunctionVariantWithPhpDocs.php | 4 ++-- .../Callables/CallableParametersAcceptor.php | 2 +- src/Reflection/Callables/FunctionCallableVariant.php | 2 +- src/Reflection/Dummy/ChangedTypeMethodReflection.php | 2 +- src/Reflection/Dummy/DummyConstructorReflection.php | 4 ++-- src/Reflection/Dummy/DummyMethodReflection.php | 4 ++-- src/Reflection/ExtendedMethodReflection.php | 2 +- src/Reflection/FunctionReflection.php | 2 +- src/Reflection/InaccessibleMethod.php | 2 +- src/Reflection/Native/NativeFunctionReflection.php | 4 ++-- src/Reflection/Native/NativeMethodReflection.php | 4 ++-- src/Reflection/ParametersAcceptorSelector.php | 4 ++-- src/Reflection/Php/ClosureCallMethodReflection.php | 2 +- src/Reflection/Php/EnumCasesMethodReflection.php | 4 ++-- src/Reflection/Php/ExitFunctionReflection.php | 4 ++-- .../Php/PhpFunctionFromParserNodeReflection.php | 4 ++-- src/Reflection/Php/PhpFunctionReflection.php | 4 ++-- src/Reflection/Php/PhpMethodReflection.php | 6 ++++-- .../ResolvedFunctionVariantWithCallable.php | 4 ++-- src/Reflection/ResolvedMethodReflection.php | 2 +- src/Reflection/TrivialParametersAcceptor.php | 4 ++-- .../Type/IntersectionTypeMethodReflection.php | 9 ++------- src/Reflection/Type/UnionTypeMethodReflection.php | 9 ++------- src/Reflection/WrappedExtendedMethodReflection.php | 4 ++-- src/Rules/FunctionCallParametersCheck.php | 5 +++-- src/Rules/Functions/CallCallablesRule.php | 5 +++-- src/Type/CallableType.php | 4 ++-- src/Type/ClosureType.php | 11 +++++++++-- 32 files changed, 71 insertions(+), 68 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index cd3d44175a..378e11d2ca 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -276,3 +276,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer bool * Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list`, no longer int * Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead +* `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool` diff --git a/src/Analyser/ArgumentsNormalizer.php b/src/Analyser/ArgumentsNormalizer.php index 6baa6e0c6b..0b68559b42 100644 --- a/src/Analyser/ArgumentsNormalizer.php +++ b/src/Analyser/ArgumentsNormalizer.php @@ -11,6 +11,7 @@ use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\ShouldNotHappenException; +use PHPStan\TrinaryLogic; use PHPStan\Type\Constant\ConstantArrayType; use function array_key_exists; use function array_keys; @@ -27,7 +28,7 @@ final class ArgumentsNormalizer public const ORIGINAL_ARG_ATTRIBUTE = 'originalArg'; /** - * @return array{ParametersAcceptor, FuncCall, bool}|null + * @return array{ParametersAcceptor, FuncCall, TrinaryLogic}|null */ public static function reorderCallUserFuncArguments( FuncCall $callUserFuncCall, @@ -73,9 +74,9 @@ public static function reorderCallUserFuncArguments( null, ); - $acceptsNamedArguments = true; + $acceptsNamedArguments = TrinaryLogic::createYes(); foreach ($callableParametersAcceptors as $callableParametersAcceptor) { - $acceptsNamedArguments = $acceptsNamedArguments && $callableParametersAcceptor->acceptsNamedArguments(); + $acceptsNamedArguments = $acceptsNamedArguments->and($callableParametersAcceptor->acceptsNamedArguments()); } return [$parametersAcceptor, new FuncCall( diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 659dc7f833..99cd3e3c5b 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -1357,7 +1357,7 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu $cachedClosureData['impurePoints'], $cachedClosureData['invalidateExpressions'], $cachedClosureData['usedVariables'], - true, + TrinaryLogic::createYes(), ); } if (self::$resolveClosureTypeDepth >= 2) { @@ -1572,7 +1572,7 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu $impurePointsForClosureType, $invalidateExpressions, $usedVariables, - true, + TrinaryLogic::createYes(), ); } elseif ($node instanceof New_) { if ($node->class instanceof Name) { @@ -2521,7 +2521,7 @@ private function createFirstClassCallable( $throwPoints = []; $impurePoints = []; - $acceptsNamedArguments = true; + $acceptsNamedArguments = TrinaryLogic::createYes(); if ($variant instanceof CallableParametersAcceptor) { $throwPoints = $variant->getThrowPoints(); $impurePoints = $variant->getImpurePoints(); @@ -3151,7 +3151,7 @@ private function enterFunctionLike( $paramExprString = '$' . $parameter->getName(); if ($parameter->isVariadic()) { - if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()) { + if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()->yes()) { $parameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $parameterType); } else { $parameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $parameterType), new AccessoryArrayListType()); @@ -3166,7 +3166,7 @@ private function enterFunctionLike( $nativeParameterType = $parameter->getNativeType(); if ($parameter->isVariadic()) { - if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()) { + if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()->yes()) { $nativeParameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $nativeParameterType); } else { $nativeParameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $nativeParameterType), new AccessoryArrayListType()); diff --git a/src/Reflection/Annotations/AnnotationMethodReflection.php b/src/Reflection/Annotations/AnnotationMethodReflection.php index b4065332ce..6b2ff2afdb 100644 --- a/src/Reflection/Annotations/AnnotationMethodReflection.php +++ b/src/Reflection/Annotations/AnnotationMethodReflection.php @@ -147,9 +147,9 @@ public function getAsserts(): Assertions return Assertions::createEmpty(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->declaringClass->acceptsNamedArguments(); + return TrinaryLogic::createFromBoolean($this->declaringClass->acceptsNamedArguments()); } public function getSelfOutType(): ?Type diff --git a/src/Reflection/CallableFunctionVariantWithPhpDocs.php b/src/Reflection/CallableFunctionVariantWithPhpDocs.php index 9e6644c0f1..fd6c62afd5 100644 --- a/src/Reflection/CallableFunctionVariantWithPhpDocs.php +++ b/src/Reflection/CallableFunctionVariantWithPhpDocs.php @@ -35,7 +35,7 @@ public function __construct( private array $impurePoints, private array $invalidateExpressions, private array $usedVariables, - private bool $acceptsNamedArguments, + private TrinaryLogic $acceptsNamedArguments, ) { parent::__construct( @@ -75,7 +75,7 @@ public function getUsedVariables(): array return $this->usedVariables; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { return $this->acceptsNamedArguments; } diff --git a/src/Reflection/Callables/CallableParametersAcceptor.php b/src/Reflection/Callables/CallableParametersAcceptor.php index 259ede81fa..25ff7d770c 100644 --- a/src/Reflection/Callables/CallableParametersAcceptor.php +++ b/src/Reflection/Callables/CallableParametersAcceptor.php @@ -19,7 +19,7 @@ public function getThrowPoints(): array; public function isPure(): TrinaryLogic; - public function acceptsNamedArguments(): bool; + public function acceptsNamedArguments(): TrinaryLogic; /** * @return SimpleImpurePoint[] diff --git a/src/Reflection/Callables/FunctionCallableVariant.php b/src/Reflection/Callables/FunctionCallableVariant.php index aef7210140..82eb478fc3 100644 --- a/src/Reflection/Callables/FunctionCallableVariant.php +++ b/src/Reflection/Callables/FunctionCallableVariant.php @@ -163,7 +163,7 @@ public function getUsedVariables(): array return []; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { return $this->function->acceptsNamedArguments(); } diff --git a/src/Reflection/Dummy/ChangedTypeMethodReflection.php b/src/Reflection/Dummy/ChangedTypeMethodReflection.php index b81e30e846..3dc1cd56b0 100644 --- a/src/Reflection/Dummy/ChangedTypeMethodReflection.php +++ b/src/Reflection/Dummy/ChangedTypeMethodReflection.php @@ -119,7 +119,7 @@ public function getAsserts(): Assertions return $this->reflection->getAsserts(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { return $this->reflection->acceptsNamedArguments(); } diff --git a/src/Reflection/Dummy/DummyConstructorReflection.php b/src/Reflection/Dummy/DummyConstructorReflection.php index ca67c3c2e2..36b143ed12 100644 --- a/src/Reflection/Dummy/DummyConstructorReflection.php +++ b/src/Reflection/Dummy/DummyConstructorReflection.php @@ -117,9 +117,9 @@ public function getAsserts(): Assertions return Assertions::createEmpty(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->declaringClass->acceptsNamedArguments(); + return TrinaryLogic::createFromBoolean($this->declaringClass->acceptsNamedArguments()); } public function getSelfOutType(): ?Type diff --git a/src/Reflection/Dummy/DummyMethodReflection.php b/src/Reflection/Dummy/DummyMethodReflection.php index ba4faeded3..c6157c17db 100644 --- a/src/Reflection/Dummy/DummyMethodReflection.php +++ b/src/Reflection/Dummy/DummyMethodReflection.php @@ -114,9 +114,9 @@ public function getAsserts(): Assertions return Assertions::createEmpty(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return true; + return TrinaryLogic::createYes(); } public function getSelfOutType(): ?Type diff --git a/src/Reflection/ExtendedMethodReflection.php b/src/Reflection/ExtendedMethodReflection.php index 7cb583f1dc..43f27903f9 100644 --- a/src/Reflection/ExtendedMethodReflection.php +++ b/src/Reflection/ExtendedMethodReflection.php @@ -37,7 +37,7 @@ public function getOnlyVariant(): ParametersAcceptorWithPhpDocs; */ public function getNamedArgumentsVariants(): ?array; - public function acceptsNamedArguments(): bool; + public function acceptsNamedArguments(): TrinaryLogic; public function getAsserts(): Assertions; diff --git a/src/Reflection/FunctionReflection.php b/src/Reflection/FunctionReflection.php index e09ceb27ed..66ef61928f 100644 --- a/src/Reflection/FunctionReflection.php +++ b/src/Reflection/FunctionReflection.php @@ -28,7 +28,7 @@ public function getOnlyVariant(): ParametersAcceptorWithPhpDocs; */ public function getNamedArgumentsVariants(): ?array; - public function acceptsNamedArguments(): bool; + public function acceptsNamedArguments(): TrinaryLogic; public function isDeprecated(): TrinaryLogic; diff --git a/src/Reflection/InaccessibleMethod.php b/src/Reflection/InaccessibleMethod.php index eaf63ef8a1..fef9716d6c 100644 --- a/src/Reflection/InaccessibleMethod.php +++ b/src/Reflection/InaccessibleMethod.php @@ -86,7 +86,7 @@ public function getUsedVariables(): array return []; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { return $this->methodReflection->acceptsNamedArguments(); } diff --git a/src/Reflection/Native/NativeFunctionReflection.php b/src/Reflection/Native/NativeFunctionReflection.php index 82a26d08f7..7a7e137d9c 100644 --- a/src/Reflection/Native/NativeFunctionReflection.php +++ b/src/Reflection/Native/NativeFunctionReflection.php @@ -142,9 +142,9 @@ public function returnsByReference(): TrinaryLogic return $this->returnsByReference; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->acceptsNamedArguments; + return TrinaryLogic::createFromBoolean($this->acceptsNamedArguments); } } diff --git a/src/Reflection/Native/NativeMethodReflection.php b/src/Reflection/Native/NativeMethodReflection.php index 68ee421e38..1671c55aab 100644 --- a/src/Reflection/Native/NativeMethodReflection.php +++ b/src/Reflection/Native/NativeMethodReflection.php @@ -200,9 +200,9 @@ public function getAsserts(): Assertions return $this->assertions; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->declaringClass->acceptsNamedArguments() && $this->acceptsNamedArguments; + return TrinaryLogic::createFromBoolean($this->declaringClass->acceptsNamedArguments() && $this->acceptsNamedArguments); } public function getSelfOutType(): ?Type diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index d78cb09f33..93db8e9834 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -581,7 +581,7 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit $impurePoints = []; $invalidateExpressions = []; $usedVariables = []; - $acceptsNamedArguments = false; + $acceptsNamedArguments = TrinaryLogic::createNo(); foreach ($acceptors as $acceptor) { $returnTypes[] = $acceptor->getReturnType(); @@ -597,7 +597,7 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit $impurePoints = array_merge($impurePoints, $acceptor->getImpurePoints()); $invalidateExpressions = array_merge($invalidateExpressions, $acceptor->getInvalidateExpressions()); $usedVariables = array_merge($usedVariables, $acceptor->getUsedVariables()); - $acceptsNamedArguments = $acceptsNamedArguments || $acceptor->acceptsNamedArguments(); + $acceptsNamedArguments = $acceptsNamedArguments->or($acceptor->acceptsNamedArguments()); } $isVariadic = $isVariadic || $acceptor->isVariadic(); diff --git a/src/Reflection/Php/ClosureCallMethodReflection.php b/src/Reflection/Php/ClosureCallMethodReflection.php index be5d97660f..1bb9d201c8 100644 --- a/src/Reflection/Php/ClosureCallMethodReflection.php +++ b/src/Reflection/Php/ClosureCallMethodReflection.php @@ -156,7 +156,7 @@ public function getAsserts(): Assertions return $this->nativeMethodReflection->getAsserts(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { return $this->nativeMethodReflection->acceptsNamedArguments(); } diff --git a/src/Reflection/Php/EnumCasesMethodReflection.php b/src/Reflection/Php/EnumCasesMethodReflection.php index ff5fd5f9a5..bd706e7c98 100644 --- a/src/Reflection/Php/EnumCasesMethodReflection.php +++ b/src/Reflection/Php/EnumCasesMethodReflection.php @@ -126,9 +126,9 @@ public function getAsserts(): Assertions return Assertions::createEmpty(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->declaringClass->acceptsNamedArguments(); + return TrinaryLogic::createFromBoolean($this->declaringClass->acceptsNamedArguments()); } public function getSelfOutType(): ?Type diff --git a/src/Reflection/Php/ExitFunctionReflection.php b/src/Reflection/Php/ExitFunctionReflection.php index dc8f74ecea..85e6210699 100644 --- a/src/Reflection/Php/ExitFunctionReflection.php +++ b/src/Reflection/Php/ExitFunctionReflection.php @@ -82,9 +82,9 @@ public function getNamedArgumentsVariants(): array return $this->getVariants(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return true; + return TrinaryLogic::createYes(); } public function isDeprecated(): TrinaryLogic diff --git a/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php b/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php index 96ba2f6be1..5710ce56a0 100644 --- a/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php +++ b/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php @@ -280,9 +280,9 @@ public function isGenerator(): bool return $this->nodeIsOrContainsYield($this->functionLike); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->acceptsNamedArguments; + return TrinaryLogic::createFromBoolean($this->acceptsNamedArguments); } private function nodeIsOrContainsYield(Node $node): bool diff --git a/src/Reflection/Php/PhpFunctionReflection.php b/src/Reflection/Php/PhpFunctionReflection.php index 1f3ffee131..5bdbd199be 100644 --- a/src/Reflection/Php/PhpFunctionReflection.php +++ b/src/Reflection/Php/PhpFunctionReflection.php @@ -300,9 +300,9 @@ public function returnsByReference(): TrinaryLogic return TrinaryLogic::createFromBoolean($this->reflection->returnsReference()); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->acceptsNamedArguments; + return TrinaryLogic::createFromBoolean($this->acceptsNamedArguments); } private function isFunctionNodeVariadic(Function_ $node): bool diff --git a/src/Reflection/Php/PhpMethodReflection.php b/src/Reflection/Php/PhpMethodReflection.php index 7188551137..ea1bc0c6c0 100644 --- a/src/Reflection/Php/PhpMethodReflection.php +++ b/src/Reflection/Php/PhpMethodReflection.php @@ -462,9 +462,11 @@ public function getAsserts(): Assertions return $this->asserts; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->declaringClass->acceptsNamedArguments() && $this->acceptsNamedArguments; + return TrinaryLogic::createFromBoolean( + $this->declaringClass->acceptsNamedArguments() && $this->acceptsNamedArguments, + ); } public function getSelfOutType(): ?Type diff --git a/src/Reflection/ResolvedFunctionVariantWithCallable.php b/src/Reflection/ResolvedFunctionVariantWithCallable.php index ab121486a1..7dbd382405 100644 --- a/src/Reflection/ResolvedFunctionVariantWithCallable.php +++ b/src/Reflection/ResolvedFunctionVariantWithCallable.php @@ -27,7 +27,7 @@ public function __construct( private array $impurePoints, private array $invalidateExpressions, private array $usedVariables, - private bool $acceptsNamedArguments, + private TrinaryLogic $acceptsNamedArguments, ) { } @@ -112,7 +112,7 @@ public function getUsedVariables(): array return $this->usedVariables; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { return $this->acceptsNamedArguments; } diff --git a/src/Reflection/ResolvedMethodReflection.php b/src/Reflection/ResolvedMethodReflection.php index 477cbdea74..1ce0c0dc71 100644 --- a/src/Reflection/ResolvedMethodReflection.php +++ b/src/Reflection/ResolvedMethodReflection.php @@ -175,7 +175,7 @@ public function getAsserts(): Assertions )); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { return $this->reflection->acceptsNamedArguments(); } diff --git a/src/Reflection/TrivialParametersAcceptor.php b/src/Reflection/TrivialParametersAcceptor.php index 1d9f2aa628..05a4888c27 100644 --- a/src/Reflection/TrivialParametersAcceptor.php +++ b/src/Reflection/TrivialParametersAcceptor.php @@ -93,9 +93,9 @@ public function getUsedVariables(): array return []; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return true; + return TrinaryLogic::createYes(); } } diff --git a/src/Reflection/Type/IntersectionTypeMethodReflection.php b/src/Reflection/Type/IntersectionTypeMethodReflection.php index 65c3b8b152..d27576767f 100644 --- a/src/Reflection/Type/IntersectionTypeMethodReflection.php +++ b/src/Reflection/Type/IntersectionTypeMethodReflection.php @@ -198,14 +198,9 @@ public function getAsserts(): Assertions return $assertions; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - $accepts = true; - foreach ($this->methods as $method) { - $accepts = $accepts && $method->acceptsNamedArguments(); - } - - return $accepts; + return TrinaryLogic::lazyMaxMin($this->methods, static fn (MethodReflection $method): TrinaryLogic => $method->acceptsNamedArguments()); } public function getSelfOutType(): ?Type diff --git a/src/Reflection/Type/UnionTypeMethodReflection.php b/src/Reflection/Type/UnionTypeMethodReflection.php index 3808304444..140ce0bd2e 100644 --- a/src/Reflection/Type/UnionTypeMethodReflection.php +++ b/src/Reflection/Type/UnionTypeMethodReflection.php @@ -175,14 +175,9 @@ public function getAsserts(): Assertions return Assertions::createEmpty(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - $accepts = true; - foreach ($this->methods as $method) { - $accepts = $accepts && $method->acceptsNamedArguments(); - } - - return $accepts; + return TrinaryLogic::lazyExtremeIdentity($this->methods, static fn (ExtendedMethodReflection $method): TrinaryLogic => $method->acceptsNamedArguments()); } public function getSelfOutType(): ?Type diff --git a/src/Reflection/WrappedExtendedMethodReflection.php b/src/Reflection/WrappedExtendedMethodReflection.php index 12d263b0e6..2f348095ff 100644 --- a/src/Reflection/WrappedExtendedMethodReflection.php +++ b/src/Reflection/WrappedExtendedMethodReflection.php @@ -142,9 +142,9 @@ public function getAsserts(): Assertions return Assertions::createEmpty(); } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return $this->getDeclaringClass()->acceptsNamedArguments(); + return TrinaryLogic::createFromBoolean($this->getDeclaringClass()->acceptsNamedArguments()); } public function getSelfOutType(): ?Type diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 9f42773237..787d6136da 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -14,6 +14,7 @@ use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper; use PHPStan\Rules\Properties\PropertyReflectionFinder; use PHPStan\ShouldNotHappenException; +use PHPStan\TrinaryLogic; use PHPStan\Type\ConditionalType; use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\ErrorType; @@ -63,7 +64,7 @@ public function check( $funcCall, array $messages, string $nodeType, - bool $acceptsNamedArguments, + TrinaryLogic $acceptsNamedArguments, ): array { $functionParametersMinCount = 0; @@ -289,7 +290,7 @@ public function check( } } - if (!$acceptsNamedArguments && isset($messages[14])) { + if (!$acceptsNamedArguments->yes() && isset($messages[14])) { if ($argumentName !== null) { $errors[] = RuleErrorBuilder::message(sprintf($messages[14], sprintf('named argument $%s', $argumentName))) ->identifier('argument.named') diff --git a/src/Rules/Functions/CallCallablesRule.php b/src/Rules/Functions/CallCallablesRule.php index d8fb352e52..05cd89d0a7 100644 --- a/src/Rules/Functions/CallCallablesRule.php +++ b/src/Rules/Functions/CallCallablesRule.php @@ -12,6 +12,7 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; +use PHPStan\TrinaryLogic; use PHPStan\Type\ClosureType; use PHPStan\Type\ErrorType; use PHPStan\Type\Type; @@ -79,9 +80,9 @@ public function processNode( $parametersAcceptors = $type->getCallableParametersAcceptors($scope); $messages = []; - $acceptsNamedArguments = true; + $acceptsNamedArguments = TrinaryLogic::createYes(); foreach ($parametersAcceptors as $parametersAcceptor) { - $acceptsNamedArguments = $acceptsNamedArguments && $parametersAcceptor->acceptsNamedArguments(); + $acceptsNamedArguments = $acceptsNamedArguments->and($parametersAcceptor->acceptsNamedArguments()); } if ( diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 20cfeafa67..de594f9683 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -294,9 +294,9 @@ public function getUsedVariables(): array return []; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { - return true; + return TrinaryLogic::createYes(); } public function toNumber(): Type diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index 751239ab73..708257ea1f 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -77,6 +77,8 @@ class ClosureType implements TypeWithClassName, CallableParametersAcceptor /** @var SimpleImpurePoint[] */ private array $impurePoints; + private TrinaryLogic $acceptsNamedArguments; + /** * @api * @param array|null $parameters @@ -98,9 +100,14 @@ public function __construct( ?array $impurePoints = null, private array $invalidateExpressions = [], private array $usedVariables = [], - private bool $acceptsNamedArguments = true, + ?TrinaryLogic $acceptsNamedArguments = null, ) { + if ($acceptsNamedArguments === null) { + $acceptsNamedArguments = TrinaryLogic::createYes(); + } + $this->acceptsNamedArguments = $acceptsNamedArguments; + $this->parameters = $parameters ?? []; $this->returnType = $returnType ?? new MixedType(); $this->isCommonCallable = $parameters === null && $returnType === null; @@ -407,7 +414,7 @@ public function getUsedVariables(): array return $this->usedVariables; } - public function acceptsNamedArguments(): bool + public function acceptsNamedArguments(): TrinaryLogic { return $this->acceptsNamedArguments; } From b1ea97a4da3751ff0206e5491d1790b732e08a74 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 10:04:37 +0200 Subject: [PATCH 289/508] Remove nette/neon patch for backward compatibility with old multi-line string encoding --- composer.json | 1 - composer.lock | 2 +- patches/NetteNeonStringNode.patch | 40 -- phpstan-baseline.neon | 642 +++++++++++++++--------------- 4 files changed, 322 insertions(+), 363 deletions(-) delete mode 100644 patches/NetteNeonStringNode.patch diff --git a/composer.json b/composer.json index e7d2b401bb..a97d401104 100644 --- a/composer.json +++ b/composer.json @@ -119,7 +119,6 @@ "patches/DependencyChecker.patch" ], "nette/neon": [ - "patches/NetteNeonStringNode.patch", "patches/NeonParser.patch" ] } diff --git a/composer.lock b/composer.lock index 2bf4e1b5f2..f836c7ee65 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3745d8358f113e8d1a7c6b1066a9db0a", + "content-hash": "3a133a74db439ecb38147f64988135c9", "packages": [ { "name": "clue/ndjson-react", diff --git a/patches/NetteNeonStringNode.patch b/patches/NetteNeonStringNode.patch deleted file mode 100644 index ff7332693f..0000000000 --- a/patches/NetteNeonStringNode.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- src/Neon/Node/StringNode.php 2022-03-10 03:04:26 -+++ src/Neon/Node/StringNode.php 2024-08-26 14:53:45 -@@ -79,27 +79,18 @@ - - public function toString(): string - { -- if (strpos($this->value, "\n") === false) { -- return "'" . str_replace("'", "''", $this->value) . "'"; -+ $res = json_encode($this->value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); -+ if ($res === false) { -+ throw new Nette\Neon\Exception('Invalid UTF-8 sequence: ' . $this->value); -+ } - -- } elseif (preg_match('~\n[\t ]+\'{3}~', $this->value)) { -- $s = json_encode($this->value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); -- $s = preg_replace_callback( -- '#[^\\\\]|\\\\(.)#s', -- function ($m) { -- return ['n' => "\n", 't' => "\t", '"' => '"'][$m[1] ?? ''] ?? $m[0]; -- }, -- substr($s, 1, -1) -- ); -- $s = str_replace('"""', '""\"', $s); -- $delim = '"""'; -- -- } else { -- $s = $this->value; -- $delim = "'''"; -+ if (strpos($this->value, "\n") !== false) { -+ $res = preg_replace_callback('#[^\\\\]|\\\\(.)#s', function ($m) { -+ return ['n' => "\n\t", 't' => "\t", '"' => '"'][$m[1] ?? ''] ?? $m[0]; -+ }, $res); -+ $res = '"""' . "\n\t" . substr($res, 1, -1) . "\n" . '"""'; - } - -- $s = preg_replace('#^(?=.)#m', "\t", $s); -- return $delim . "\n" . $s . "\n" . $delim; -+ return $res; - } - } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 23d822be89..0f3487007a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,1606 +1,1606 @@ parameters: ignoreErrors: - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php - - message: "#^Method PHPStan\\\\Analyser\\\\AnalyserResultFinalizer\\:\\:finalize\\(\\) throws checked exception Throwable but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method PHPStan\\Analyser\\AnalyserResultFinalizer\:\:finalize\(\) throws checked exception Throwable but it''s missing from the PHPDoc @throws tag\.$#' count: 1 path: src/Analyser/AnalyserResultFinalizer.php - - message: "#^Cannot assign offset 'realCount' to array\\|string\\.$#" + message: '#^Cannot assign offset ''realCount'' to array\|string\.$#' count: 1 path: src/Analyser/Ignore/IgnoredErrorHelperResult.php - - message: "#^Casting to string something that's already string\\.$#" + message: '#^Casting to string something that''s already string\.$#' count: 3 path: src/Analyser/MutatingScope.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 4 path: src/Analyser/MutatingScope.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 3 path: src/Analyser/MutatingScope.php - - message: "#^Only numeric types are allowed in pre\\-increment, float\\|int\\|string\\|null given\\.$#" + message: '#^Only numeric types are allowed in pre\-increment, float\|int\|string\|null given\.$#' count: 1 path: src/Analyser/MutatingScope.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 3 path: src/Analyser/NodeScopeResolver.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' count: 1 path: src/Analyser/NodeScopeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 2 path: src/Analyser/TypeSpecifier.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 5 path: src/Analyser/TypeSpecifier.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 3 path: src/Analyser/TypeSpecifier.php - - message: "#^Template type TNodeType is declared as covariant, but occurs in contravariant position in parameter node of method PHPStan\\\\Collectors\\\\Collector\\:\\:processNode\\(\\)\\.$#" + message: '#^Template type TNodeType is declared as covariant, but occurs in contravariant position in parameter node of method PHPStan\\Collectors\\Collector\:\:processNode\(\)\.$#' count: 1 path: src/Collectors/Collector.php - - message: "#^Method PHPStan\\\\Collectors\\\\Registry\\:\\:__construct\\(\\) has parameter \\$collectors with generic interface PHPStan\\\\Collectors\\\\Collector but does not specify its types\\: TNodeType, TValue$#" + message: '#^Method PHPStan\\Collectors\\Registry\:\:__construct\(\) has parameter \$collectors with generic interface PHPStan\\Collectors\\Collector but does not specify its types\: TNodeType, TValue$#' count: 1 path: src/Collectors/Registry.php - - message: "#^Property PHPStan\\\\Collectors\\\\Registry\\:\\:\\$cache with generic interface PHPStan\\\\Collectors\\\\Collector does not specify its types\\: TNodeType, TValue$#" + message: '#^Property PHPStan\\Collectors\\Registry\:\:\$cache with generic interface PHPStan\\Collectors\\Collector does not specify its types\: TNodeType, TValue$#' count: 1 path: src/Collectors/Registry.php - - message: "#^Property PHPStan\\\\Collectors\\\\Registry\\:\\:\\$collectors with generic interface PHPStan\\\\Collectors\\\\Collector does not specify its types\\: TNodeType, TValue$#" + message: '#^Property PHPStan\\Collectors\\Registry\:\:\$collectors with generic interface PHPStan\\Collectors\\Collector does not specify its types\: TNodeType, TValue$#' count: 1 path: src/Collectors/Registry.php - - message: "#^Anonymous function has an unused use \\$container\\.$#" + message: '#^Anonymous function has an unused use \$container\.$#' count: 1 path: src/Command/CommandHelper.php - - message: "#^Parameter \\#1 \\$path of function dirname expects string, string\\|false given\\.$#" + message: '#^Parameter \#1 \$path of function dirname expects string, string\|false given\.$#' count: 1 path: src/Command/CommandHelper.php - - message: "#^Static property PHPStan\\\\Command\\\\CommandHelper\\:\\:\\$reservedMemory is never read, only written\\.$#" + message: '#^Static property PHPStan\\Command\\CommandHelper\:\:\$reservedMemory is never read, only written\.$#' count: 1 path: src/Command/CommandHelper.php - - message: "#^Parameter \\#1 \\$headers \\(array\\\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$headers \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\StyleInterface\\:\\:table\\(\\)$#" + message: '#^Parameter \#1 \$headers \(array\\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$headers \(array\) of method Symfony\\Component\\Console\\Style\\StyleInterface\:\:table\(\)$#' count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: "#^Parameter \\#1 \\$headers \\(array\\\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$headers \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\SymfonyStyle\\:\\:table\\(\\)$#" + message: '#^Parameter \#1 \$headers \(array\\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$headers \(array\) of method Symfony\\Component\\Console\\Style\\SymfonyStyle\:\:table\(\)$#' count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: "#^Parameter \\#2 \\$rows \\(array\\\\>\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$rows \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\StyleInterface\\:\\:table\\(\\)$#" + message: '#^Parameter \#2 \$rows \(array\\>\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$rows \(array\) of method Symfony\\Component\\Console\\Style\\StyleInterface\:\:table\(\)$#' count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: "#^Parameter \\#2 \\$rows \\(array\\\\>\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$rows \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\SymfonyStyle\\:\\:table\\(\\)$#" + message: '#^Parameter \#2 \$rows \(array\\>\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$rows \(array\) of method Symfony\\Component\\Console\\Style\\SymfonyStyle\:\:table\(\)$#' count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: "#^Variable method call on Nette\\\\Schema\\\\Elements\\\\AnyOf\\|Nette\\\\Schema\\\\Elements\\\\Structure\\|Nette\\\\Schema\\\\Elements\\\\Type\\.$#" + message: '#^Variable method call on Nette\\Schema\\Elements\\AnyOf\|Nette\\Schema\\Elements\\Structure\|Nette\\Schema\\Elements\\Type\.$#' count: 1 path: src/DependencyInjection/ContainerFactory.php - - message: "#^Variable static method call on Nette\\\\Schema\\\\Expect\\.$#" + message: '#^Variable static method call on Nette\\Schema\\Expect\.$#' count: 1 path: src/DependencyInjection/ContainerFactory.php - - message: "#^Fetching class constant PREVENT_MERGING of deprecated class Nette\\\\DI\\\\Config\\\\Helpers\\.$#" + message: '#^Fetching class constant PREVENT_MERGING of deprecated class Nette\\DI\\Config\\Helpers\.$#' count: 1 path: src/DependencyInjection/NeonAdapter.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - - message: "#^Parameter \\#1 \\$path of function dirname expects string, string\\|false given\\.$#" + message: '#^Parameter \#1 \$path of function dirname expects string, string\|false given\.$#' count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - - message: "#^Variable method call on PHPStan\\\\Reflection\\\\ClassReflection\\.$#" + message: '#^Variable method call on PHPStan\\Reflection\\ClassReflection\.$#' count: 2 path: src/PhpDoc/PhpDocBlock.php - - message: "#^Variable static method call on PHPStan\\\\PhpDoc\\\\PhpDocBlock\\.$#" + message: '#^Variable static method call on PHPStan\\PhpDoc\\PhpDocBlock\.$#' count: 1 path: src/PhpDoc/PhpDocBlock.php - - message: "#^Call to function method_exists\\(\\) with PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\PhpDocNode and 'getParamOutTypeTagV…' will always evaluate to true\\.$#" + message: '#^Call to function method_exists\(\) with PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode and ''getParamOutTypeTagV…'' will always evaluate to true\.$#' count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - - message: "#^Call to function method_exists\\(\\) with PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\PhpDocNode and 'getSelfOutTypeTagVa…' will always evaluate to true\\.$#" + message: '#^Call to function method_exists\(\) with PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode and ''getSelfOutTypeTagVa…'' will always evaluate to true\.$#' count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - - message: "#^Method PHPStan\\\\PhpDoc\\\\ResolvedPhpDocBlock\\:\\:getNameScope\\(\\) should return PHPStan\\\\Analyser\\\\NameScope but returns PHPStan\\\\Analyser\\\\NameScope\\|null\\.$#" + message: '#^Method PHPStan\\PhpDoc\\ResolvedPhpDocBlock\:\:getNameScope\(\) should return PHPStan\\Analyser\\NameScope but returns PHPStan\\Analyser\\NameScope\|null\.$#' count: 1 path: src/PhpDoc/ResolvedPhpDocBlock.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 2 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\Identifier\\\\Exception\\\\InvalidIdentifierName is never thrown in the try block\\.$#" + message: '#^Dead catch \- PHPStan\\BetterReflection\\Identifier\\Exception\\InvalidIdentifierName is never thrown in the try block\.$#' count: 3 path: src/Reflection/BetterReflection/BetterReflectionProvider.php - - message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\NodeCompiler\\\\Exception\\\\UnableToCompileNode is never thrown in the try block\\.$#" + message: '#^Dead catch \- PHPStan\\BetterReflection\\NodeCompiler\\Exception\\UnableToCompileNode is never thrown in the try block\.$#' count: 1 path: src/Reflection/BetterReflection/BetterReflectionProvider.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: "#^Creating new ReflectionFunction is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionFunction is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: "#^Method PHPStan\\\\Reflection\\\\BetterReflection\\\\SourceLocator\\\\FileReadTrapStreamWrapper\\:\\:invokeWithRealFileStreamWrapper\\(\\) has parameter \\$cb with no signature specified for callable\\.$#" + message: '#^Method PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FileReadTrapStreamWrapper\:\:invokeWithRealFileStreamWrapper\(\) has parameter \$cb with no signature specified for callable\.$#' count: 1 path: src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" + message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\ClassLike\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Function_ given\.$#' count: 1 path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' count: 2 path: src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Reflection/BetterReflection/SourceLocator/ReflectionClassSourceLocator.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' count: 3 path: src/Reflection/ClassReflection.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 1 path: src/Reflection/ClassReflection.php - - message: "#^Method PHPStan\\\\Reflection\\\\ClassReflection\\:\\:getCacheKey\\(\\) should return string but returns string\\|null\\.$#" + message: '#^Method PHPStan\\Reflection\\ClassReflection\:\:getCacheKey\(\) should return string but returns string\|null\.$#' count: 1 path: src/Reflection/ClassReflection.php - - message: "#^Binary operation \"&\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "&" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\*\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\*" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\+\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\+" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\-\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\-" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\^\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\^" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\|\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\|" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 22 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 4 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 3 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 10 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" + message: '#^PHPDoc tag @var with type float\|int is not subtype of native type int\.$#' count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^PHPDoc tag @var with type float\\|int is not subtype of type int\\.$#" + message: '#^PHPDoc tag @var with type float\|int is not subtype of type int\.$#' count: 4 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^PHPDoc tag @var with type float\\|int\\|null is not subtype of type int\\|null\\.$#" + message: '#^PHPDoc tag @var with type float\|int\|null is not subtype of type int\|null\.$#' count: 6 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' count: 1 path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Rules/Api/NodeConnectingVisitorAttributesRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 1 path: src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Classes/ImpossibleInstanceOfRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 2 path: src/Rules/Classes/RequireExtendsRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 1 path: src/Rules/Classes/RequireImplementsRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 6 path: src/Rules/Comparison/BooleanAndConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/BooleanNotConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 6 path: src/Rules/Comparison/BooleanOrConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/ConstantLooseComparisonRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/DoWhileLoopConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/ElseIfConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/IfConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 2 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 3 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' count: 1 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 4 path: src/Rules/Comparison/LogicalXorConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 4 path: src/Rules/Comparison/MatchExpressionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/NumberComparisonOperatorsConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Rules/Comparison/TernaryOperatorConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 1 path: src/Rules/Comparison/WhileLoopAlwaysFalseConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 1 path: src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php - - message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Function class_implements\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Function class_parents\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Function class_parents\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Method PHPStan\\\\Rules\\\\DirectRegistry\\:\\:__construct\\(\\) has parameter \\$rules with generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Rules\\DirectRegistry\:\:__construct\(\) has parameter \$rules with generic interface PHPStan\\Rules\\Rule but does not specify its types\: TNodeType$#' count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Property PHPStan\\\\Rules\\\\DirectRegistry\\:\\:\\$cache with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Property PHPStan\\Rules\\DirectRegistry\:\:\$cache with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Property PHPStan\\\\Rules\\\\DirectRegistry\\:\\:\\$rules with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Property PHPStan\\Rules\\DirectRegistry\:\:\$rules with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' count: 1 path: src/Rules/Generics/GenericAncestorsCheck.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Rules/Generics/TemplateTypeCheck.php - - message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Function class_implements\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Function class_parents\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Function class_parents\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Method PHPStan\\\\Rules\\\\LazyRegistry\\:\\:getRulesFromContainer\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Rules\\LazyRegistry\:\:getRulesFromContainer\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Property PHPStan\\\\Rules\\\\LazyRegistry\\:\\:\\$cache with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Property PHPStan\\Rules\\LazyRegistry\:\:\$cache with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Property PHPStan\\\\Rules\\\\LazyRegistry\\:\\:\\$rules with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Property PHPStan\\Rules\\LazyRegistry\:\:\$rules with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' count: 1 path: src/Rules/Methods/StaticMethodCallCheck.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 1 path: src/Rules/PhpDoc/RequireExtendsCheck.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 1 path: src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' count: 1 path: src/Rules/PhpDoc/VarTagTypeRuleHelper.php - - message: "#^Access to an undefined property T of PHPStan\\\\Rules\\\\RuleError\\:\\:\\$tip\\.$#" + message: '#^Access to an undefined property T of PHPStan\\Rules\\RuleError\:\:\$tip\.$#' count: 2 path: src/Rules/RuleErrorBuilder.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Rules/RuleLevelHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 1 path: src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Rules/UnusedFunctionParametersCheck.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 1 path: src/Rules/Variables/CompactVariablesRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Rules/Variables/CompactVariablesRule.php - - message: "#^Anonymous function has an unused use \\$container\\.$#" + message: '#^Anonymous function has an unused use \$container\.$#' count: 1 path: src/Testing/PHPStanTestCase.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 2 path: src/Testing/TypeInferenceTestCase.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/AccessoryArrayListType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/AccessoryLiteralStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/AccessoryLowercaseStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Accessory/AccessoryNonEmptyStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/AccessoryNonEmptyStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/AccessoryNonFalsyStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Accessory/AccessoryNumericStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/AccessoryNumericStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/HasMethodType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/HasOffsetType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 2 path: src/Type/Accessory/HasOffsetValueType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 2 path: src/Type/Accessory/HasOffsetValueType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/HasOffsetValueType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/HasPropertyType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/NonEmptyArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Accessory/OversizedArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' count: 3 path: src/Type/ArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 2 path: src/Type/ArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 2 path: src/Type/ArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/ArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' count: 2 path: src/Type/BooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 1 path: src/Type/BooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' count: 4 path: src/Type/CallableType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 2 path: src/Type/CallableType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/ClosureType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' count: 1 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 7 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Type is always PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType\\|PHPStan\\\\Type\\\\Constant\\\\ConstantStringType but it's error\\-prone and dangerous\\.$#" + message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Type is always PHPStan\\Type\\Constant\\ConstantIntegerType\|PHPStan\\Type\\Constant\\ConstantStringType but it''s error\-prone and dangerous\.$#' count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" + message: '#^PHPDoc tag @var with type float\|int is not subtype of native type int\.$#' count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: "#^PHPDoc tag @var with type float\\|int is not subtype of type int\\.$#" + message: '#^PHPDoc tag @var with type float\|int is not subtype of type int\.$#' count: 1 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' count: 1 path: src/Type/Constant/ConstantBooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 4 path: src/Type/Constant/ConstantBooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 3 path: src/Type/Constant/ConstantBooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 4 path: src/Type/Constant/ConstantFloatType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' count: 1 path: src/Type/Constant/ConstantFloatType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 4 path: src/Type/Constant/ConstantIntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' count: 1 path: src/Type/Constant/ConstantIntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' count: 1 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 4 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 4 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' count: 1 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' count: 1 path: src/Type/Constant/ConstantStringType.php - - message: "#^PHPDoc tag @var with type int\\|string is not subtype of type string\\.$#" + message: '#^PHPDoc tag @var with type int\|string is not subtype of type string\.$#' count: 1 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 1 path: src/Type/Constant/OversizedArrayBuilder.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Enum\\EnumCaseObjectType is error\-prone and deprecated\. Use Type\:\:getEnumCases\(\) instead\.$#' count: 2 path: src/Type/Enum/EnumCaseObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 2 path: src/Type/ExponentiateHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' count: 1 path: src/Type/FileTypeMapper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' count: 2 path: src/Type/FloatType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' count: 1 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 4 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' count: 4 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' count: 2 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 1 path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' count: 2 path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateBenevolentUnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateBooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateConstantIntegerType.php - - message: "#^Method PHPStan\\\\Type\\\\Generic\\\\TemplateConstantIntegerType\\:\\:toPhpDocNode\\(\\) should return PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\ConstTypeNode but returns PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\IdentifierTypeNode\\.$#" + message: '#^Method PHPStan\\Type\\Generic\\TemplateConstantIntegerType\:\:toPhpDocNode\(\) should return PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode but returns PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode\.$#' count: 1 path: src/Type/Generic/TemplateConstantIntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateFloatType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateGenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateIntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateIntersectionType.php - - message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\IntersectionType will always evaluate to false\\.$#" + message: '#^Instanceof between PHPStan\\Type\\Type and PHPStan\\Type\\IntersectionType will always evaluate to false\.$#' count: 2 path: src/Type/Generic/TemplateIntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateKeyOfType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 2 path: src/Type/Generic/TemplateMixedType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateObjectWithoutClassType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 2 path: src/Type/Generic/TemplateStrictMixedType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/Generic/TemplateUnionType.php - - message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\UnionType will always evaluate to false\\.$#" + message: '#^Instanceof between PHPStan\\Type\\Type and PHPStan\\Type\\UnionType will always evaluate to false\.$#' count: 2 path: src/Type/Generic/TemplateUnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 1 path: src/Type/IntegerRangeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' count: 3 path: src/Type/IntegerRangeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/IntegerRangeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' count: 2 path: src/Type/IntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' count: 3 path: src/Type/IntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' count: 1 path: src/Type/IntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' count: 2 path: src/Type/IntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 4 path: src/Type/IntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 2 path: src/Type/IterableType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' count: 2 path: src/Type/IterableType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 3 path: src/Type/NullType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' count: 3 path: src/Type/NullType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 1 path: src/Type/ObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' count: 2 path: src/Type/ObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' count: 1 path: src/Type/ObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Enum\\EnumCaseObjectType is error\-prone and deprecated\. Use Type\:\:getEnumCases\(\) instead\.$#' count: 1 path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' count: 1 path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 6 path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' count: 3 path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' count: 2 path: src/Type/ObjectWithoutClassType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' count: 4 path: src/Type/ObjectWithoutClassType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 2 path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 1 path: src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 4 path: src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 1 path: src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 16 path: src/Type/Php/BcMathStringOrNullReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 1 path: src/Type/Php/CompactFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/CompactFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/DefineConstantTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/DefinedConstantTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' count: 1 path: src/Type/Php/DsMapDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 2 path: src/Type/Php/FilterFunctionReturnTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/FilterFunctionReturnTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 1 path: src/Type/Php/ImplodeFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/IsAFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' count: 2 path: src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 2 path: src/Type/Php/LtrimFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/MbStrlenFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/MethodExistsTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 4 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 2 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 1 path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 2 path: src/Type/Php/PropertyExistsTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 2 path: src/Type/Php/RangeFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' count: 1 path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php - - message: "#^Cannot access offset int\\<0, max\\> on \\(float\\|int\\)\\.$#" + message: '#^Cannot access offset int\<0, max\> on \(float\|int\)\.$#' count: 2 path: src/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/StrRepeatFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/Php/StrlenFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' count: 2 path: src/Type/StaticType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' count: 1 path: src/Type/StaticType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 1 path: src/Type/StringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' count: 2 path: src/Type/StringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' count: 5 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 14 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 5 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' count: 2 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' count: 8 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' count: 2 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' count: 2 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Instanceof between PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType and PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType will always evaluate to true\\.$#" + message: '#^Instanceof between PHPStan\\Type\\Constant\\ConstantIntegerType and PHPStan\\Type\\Constant\\ConstantIntegerType will always evaluate to true\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Result of \\|\\| is always true\\.$#" + message: '#^Result of \|\| is always true\.$#' count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 2 path: src/Type/TypeUtils.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 3 path: src/Type/TypeUtils.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' count: 3 path: src/Type/TypehintHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' count: 3 path: src/Type/TypehintHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' count: 1 path: src/Type/TypehintHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' count: 2 path: src/Type/UnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' count: 1 path: src/Type/UnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' count: 2 path: src/Type/UnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' count: 1 path: src/Type/UnionType.php - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Type is always PHPStan\\\\Type\\\\BooleanType but it's error\\-prone and dangerous\\.$#" + message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Type is always PHPStan\\Type\\BooleanType but it''s error\-prone and dangerous\.$#' count: 1 path: src/Type/UnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' count: 3 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' count: 4 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\VoidType is error\\-prone and deprecated\\. Use Type\\:\\:isVoid\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\VoidType is error\-prone and deprecated\. Use Type\:\:isVoid\(\) instead\.$#' count: 2 path: src/Type/VoidType.php - - message: "#^Unreachable statement \\- code above always terminates\\.$#" + message: '#^Unreachable statement \- code above always terminates\.$#' count: 1 path: tests/PHPStan/Analyser/AnalyserTest.php - - message: "#^Class PHPStan\\\\Analyser\\\\AnonymousClassNameRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + message: '#^Class PHPStan\\Analyser\\AnonymousClassNameRuleTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' count: 1 path: tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php - - message: "#^Method PHPStan\\\\Analyser\\\\AnonymousClassNameRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Analyser\\AnonymousClassNameRuleTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' count: 1 path: tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php - - message: "#^Class PHPStan\\\\Analyser\\\\EvaluationOrderTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + message: '#^Class PHPStan\\Analyser\\EvaluationOrderTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' count: 1 path: tests/PHPStan/Analyser/EvaluationOrderTest.php - - message: "#^Method PHPStan\\\\Analyser\\\\EvaluationOrderTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Analyser\\EvaluationOrderTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' count: 1 path: tests/PHPStan/Analyser/EvaluationOrderTest.php - - message: "#^Constant SOME_CONSTANT_IN_AUTOLOAD_FILE not found\\.$#" + message: '#^Constant SOME_CONSTANT_IN_AUTOLOAD_FILE not found\.$#' count: 1 path: tests/PHPStan/Command/AnalyseCommandTest.php - - message: "#^Class PHPStan\\\\Node\\\\FileNodeTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + message: '#^Class PHPStan\\Node\\FileNodeTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' count: 1 path: tests/PHPStan/Node/FileNodeTest.php - - message: "#^Method PHPStan\\\\Node\\\\FileNodeTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Node\\FileNodeTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' count: 1 path: tests/PHPStan/Node/FileNodeTest.php - - message: "#^PHPDoc tag @var with type string is not subtype of type class\\-string\\.$#" + message: '#^PHPDoc tag @var with type string is not subtype of type class\-string\.$#' count: 1 path: tests/PHPStan/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorTest.php - - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' count: 1 path: tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php - - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' count: 1 path: tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" + message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Generic\\TemplateType is always PHPStan\\Type\\Generic\\TemplateMixedType but it''s error\-prone and dangerous\.$#' count: 1 path: tests/PHPStan/Type/IterableTypeTest.php From 977f2b4999ccde42372589124aae3b85b63184d0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 10:21:37 +0200 Subject: [PATCH 290/508] [BCB] Remove `FunctionReflection::isFinal()` --- UPGRADING.md | 1 + src/Analyser/MutatingScope.php | 2 -- src/Analyser/NodeScopeResolver.php | 3 +-- src/Reflection/FunctionReflection.php | 2 -- .../Native/NativeFunctionReflection.php | 5 ----- src/Reflection/Php/ExitFunctionReflection.php | 5 ----- .../PhpFunctionFromParserNodeReflection.php | 19 ------------------- src/Reflection/Php/PhpFunctionReflection.php | 5 ----- .../Php/PhpMethodFromParserNodeReflection.php | 15 ++++++++++++--- .../Annotations/FinalAnnotationsTest.php | 11 ----------- .../Annotations/data/annotations-final.php | 13 ------------- .../ReflectionProviderGoldenTest.php | 2 +- 12 files changed, 15 insertions(+), 68 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 378e11d2ca..c3bf1e8995 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -277,3 +277,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list`, no longer int * Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead * `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool` +* Remove `FunctionReflection::isFinal()` diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 99cd3e3c5b..4317d5945a 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3075,7 +3075,6 @@ public function enterFunction( ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, - bool $isFinal, ?bool $isPure = null, bool $acceptsNamedArguments = true, ?Assertions $asserts = null, @@ -3099,7 +3098,6 @@ public function enterFunction( $deprecatedDescription, $isDeprecated, $isInternal, - $isFinal, $isPure, $acceptsNamedArguments, $asserts ?? Assertions::createEmpty(), diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index f2e43632a6..74f2c58c71 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -513,7 +513,7 @@ private function processStmtNode( $throwPoints = []; $impurePoints = []; $this->processAttributeGroups($stmt, $stmt->attrGroups, $scope, $nodeCallback); - [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal, $isPure, $acceptsNamedArguments, , $phpDocComment, $asserts,, $phpDocParameterOutTypes] = $this->getPhpDocs($scope, $stmt); + [$templateTypeMap, $phpDocParameterTypes, $phpDocImmediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, , $isPure, $acceptsNamedArguments, , $phpDocComment, $asserts,, $phpDocParameterOutTypes] = $this->getPhpDocs($scope, $stmt); foreach ($stmt->params as $param) { $this->processParamNode($stmt, $param, $scope, $nodeCallback); @@ -532,7 +532,6 @@ private function processStmtNode( $deprecatedDescription, $isDeprecated, $isInternal, - $isFinal, $isPure, $acceptsNamedArguments, $asserts, diff --git a/src/Reflection/FunctionReflection.php b/src/Reflection/FunctionReflection.php index 66ef61928f..09232a4d8a 100644 --- a/src/Reflection/FunctionReflection.php +++ b/src/Reflection/FunctionReflection.php @@ -34,8 +34,6 @@ public function isDeprecated(): TrinaryLogic; public function getDeprecatedDescription(): ?string; - public function isFinal(): TrinaryLogic; - public function isInternal(): TrinaryLogic; public function getThrowType(): ?Type; diff --git a/src/Reflection/Native/NativeFunctionReflection.php b/src/Reflection/Native/NativeFunctionReflection.php index 7a7e137d9c..529bd5fbbf 100644 --- a/src/Reflection/Native/NativeFunctionReflection.php +++ b/src/Reflection/Native/NativeFunctionReflection.php @@ -88,11 +88,6 @@ public function isInternal(): TrinaryLogic return TrinaryLogic::createNo(); } - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - public function hasSideEffects(): TrinaryLogic { if ($this->isVoid()) { diff --git a/src/Reflection/Php/ExitFunctionReflection.php b/src/Reflection/Php/ExitFunctionReflection.php index 85e6210699..331105aceb 100644 --- a/src/Reflection/Php/ExitFunctionReflection.php +++ b/src/Reflection/Php/ExitFunctionReflection.php @@ -97,11 +97,6 @@ public function getDeprecatedDescription(): ?string return null; } - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createNo(); - } - public function isInternal(): TrinaryLogic { return TrinaryLogic::createYes(); diff --git a/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php b/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php index 5710ce56a0..227b23ddab 100644 --- a/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php +++ b/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php @@ -58,7 +58,6 @@ public function __construct( private ?string $deprecatedDescription, private bool $isDeprecated, private bool $isInternal, - private bool $isFinal, protected ?bool $isPure, private bool $acceptsNamedArguments, private Assertions $assertions, @@ -235,24 +234,6 @@ public function isInternal(): TrinaryLogic return TrinaryLogic::createFromBoolean($this->isInternal); } - public function isFinal(): TrinaryLogic - { - $finalMethod = false; - if ($this->functionLike instanceof ClassMethod) { - $finalMethod = $this->functionLike->isFinal(); - } - return TrinaryLogic::createFromBoolean($finalMethod || $this->isFinal); - } - - public function isFinalByKeyword(): TrinaryLogic - { - $finalMethod = false; - if ($this->functionLike instanceof ClassMethod) { - $finalMethod = $this->functionLike->isFinal(); - } - return TrinaryLogic::createFromBoolean($finalMethod); - } - public function getThrowType(): ?Type { return $this->throwType; diff --git a/src/Reflection/Php/PhpFunctionReflection.php b/src/Reflection/Php/PhpFunctionReflection.php index 5bdbd199be..6aba725f1c 100644 --- a/src/Reflection/Php/PhpFunctionReflection.php +++ b/src/Reflection/Php/PhpFunctionReflection.php @@ -249,11 +249,6 @@ public function isInternal(): TrinaryLogic return TrinaryLogic::createFromBoolean($this->isInternal); } - public function isFinal(): TrinaryLogic - { - return TrinaryLogic::createFromBoolean($this->isFinal); - } - public function getThrowType(): ?Type { return $this->phpDocThrowType; diff --git a/src/Reflection/Php/PhpMethodFromParserNodeReflection.php b/src/Reflection/Php/PhpMethodFromParserNodeReflection.php index 329ad1de61..8cd703c8b2 100644 --- a/src/Reflection/Php/PhpMethodFromParserNodeReflection.php +++ b/src/Reflection/Php/PhpMethodFromParserNodeReflection.php @@ -38,7 +38,7 @@ final class PhpMethodFromParserNodeReflection extends PhpFunctionFromParserNodeR */ public function __construct( private ClassReflection $declaringClass, - ClassMethod $classMethod, + private ClassMethod $classMethod, string $fileName, TemplateTypeMap $templateTypeMap, array $realParameterTypes, @@ -50,7 +50,7 @@ public function __construct( ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, - bool $isFinal, + private bool $isFinal, ?bool $isPure, bool $acceptsNamedArguments, Assertions $assertions, @@ -107,7 +107,6 @@ public function __construct( $deprecatedDescription, $isDeprecated, $isInternal, - $isFinal || $classMethod->isFinal(), $isPure, $acceptsNamedArguments, $assertions, @@ -154,6 +153,16 @@ public function isPublic(): bool return $this->getClassMethod()->isPublic(); } + public function isFinal(): TrinaryLogic + { + return TrinaryLogic::createFromBoolean($this->classMethod->isFinal() || $this->isFinal); + } + + public function isFinalByKeyword(): TrinaryLogic + { + return TrinaryLogic::createFromBoolean($this->classMethod->isFinal()); + } + public function isBuiltin(): bool { return false; diff --git a/tests/PHPStan/Reflection/Annotations/FinalAnnotationsTest.php b/tests/PHPStan/Reflection/Annotations/FinalAnnotationsTest.php index fb61a5c90e..6df44ad440 100644 --- a/tests/PHPStan/Reflection/Annotations/FinalAnnotationsTest.php +++ b/tests/PHPStan/Reflection/Annotations/FinalAnnotationsTest.php @@ -4,7 +4,6 @@ use FinalAnnotations\FinalFoo; use FinalAnnotations\Foo; -use PhpParser\Node\Name; use PHPStan\Analyser\Scope; use PHPStan\Testing\PHPStanTestCase; @@ -58,14 +57,4 @@ public function testFinalAnnotations(bool $final, string $className, array $fina } } - public function testFinalUserFunctions(): void - { - require_once __DIR__ . '/data/annotations-final.php'; - - $reflectionProvider = $this->createReflectionProvider(); - - $this->assertFalse($reflectionProvider->getFunction(new Name\FullyQualified('FinalAnnotations\foo'), null)->isFinal()->yes()); - $this->assertTrue($reflectionProvider->getFunction(new Name\FullyQualified('FinalAnnotations\finalFoo'), null)->isFinal()->yes()); - } - } diff --git a/tests/PHPStan/Reflection/Annotations/data/annotations-final.php b/tests/PHPStan/Reflection/Annotations/data/annotations-final.php index cb3932500f..f7c7c2da25 100644 --- a/tests/PHPStan/Reflection/Annotations/data/annotations-final.php +++ b/tests/PHPStan/Reflection/Annotations/data/annotations-final.php @@ -2,19 +2,6 @@ namespace FinalAnnotations; -function foo() -{ - -} - -/** - * @final - */ -function finalFoo() -{ - -} - class Foo { diff --git a/tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php b/tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php index d7b8ee4599..bfafb5996e 100644 --- a/tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php +++ b/tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php @@ -341,7 +341,7 @@ private static function generateFunctionMethodBaseDescription($reflection): stri $result .= 'Is deprecated: ' . $reflection->isDeprecated()->describe() . "\n"; } - if (! $reflection->isFinal()->no()) { + if ($reflection instanceof MethodReflection && ! $reflection->isFinal()->no()) { $result .= 'Is final: ' . $reflection->isFinal()->describe() . "\n"; } From ce1f2bfdf99910921ae315df5e42b6459994e44b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 10:46:46 +0200 Subject: [PATCH 291/508] min/max fix --- src/Type/Php/MinMaxFunctionReturnTypeExtension.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Type/Php/MinMaxFunctionReturnTypeExtension.php b/src/Type/Php/MinMaxFunctionReturnTypeExtension.php index d6e1361dab..c10150b748 100644 --- a/src/Type/Php/MinMaxFunctionReturnTypeExtension.php +++ b/src/Type/Php/MinMaxFunctionReturnTypeExtension.php @@ -160,6 +160,10 @@ private function processType( } $compareResult = $this->compareTypes($resultType, $type); + if ($compareResult === null) { + return TypeCombinator::union(...$types); + } + if ($functionName === 'min') { if ($compareResult === $type) { $resultType = $type; From 96d74b1973240baec2676432fd3b568a5a09510e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 11:11:06 +0200 Subject: [PATCH 292/508] Revert "Remove nette/neon patch for backward compatibility with old multi-line string encoding" This reverts commit b1ea97a4da3751ff0206e5491d1790b732e08a74. --- composer.json | 1 + composer.lock | 2 +- patches/NetteNeonStringNode.patch | 40 ++ phpstan-baseline.neon | 642 +++++++++++++++--------------- 4 files changed, 363 insertions(+), 322 deletions(-) create mode 100644 patches/NetteNeonStringNode.patch diff --git a/composer.json b/composer.json index a97d401104..e7d2b401bb 100644 --- a/composer.json +++ b/composer.json @@ -119,6 +119,7 @@ "patches/DependencyChecker.patch" ], "nette/neon": [ + "patches/NetteNeonStringNode.patch", "patches/NeonParser.patch" ] } diff --git a/composer.lock b/composer.lock index f836c7ee65..2bf4e1b5f2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3a133a74db439ecb38147f64988135c9", + "content-hash": "3745d8358f113e8d1a7c6b1066a9db0a", "packages": [ { "name": "clue/ndjson-react", diff --git a/patches/NetteNeonStringNode.patch b/patches/NetteNeonStringNode.patch new file mode 100644 index 0000000000..ff7332693f --- /dev/null +++ b/patches/NetteNeonStringNode.patch @@ -0,0 +1,40 @@ +--- src/Neon/Node/StringNode.php 2022-03-10 03:04:26 ++++ src/Neon/Node/StringNode.php 2024-08-26 14:53:45 +@@ -79,27 +79,18 @@ + + public function toString(): string + { +- if (strpos($this->value, "\n") === false) { +- return "'" . str_replace("'", "''", $this->value) . "'"; ++ $res = json_encode($this->value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ++ if ($res === false) { ++ throw new Nette\Neon\Exception('Invalid UTF-8 sequence: ' . $this->value); ++ } + +- } elseif (preg_match('~\n[\t ]+\'{3}~', $this->value)) { +- $s = json_encode($this->value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +- $s = preg_replace_callback( +- '#[^\\\\]|\\\\(.)#s', +- function ($m) { +- return ['n' => "\n", 't' => "\t", '"' => '"'][$m[1] ?? ''] ?? $m[0]; +- }, +- substr($s, 1, -1) +- ); +- $s = str_replace('"""', '""\"', $s); +- $delim = '"""'; +- +- } else { +- $s = $this->value; +- $delim = "'''"; ++ if (strpos($this->value, "\n") !== false) { ++ $res = preg_replace_callback('#[^\\\\]|\\\\(.)#s', function ($m) { ++ return ['n' => "\n\t", 't' => "\t", '"' => '"'][$m[1] ?? ''] ?? $m[0]; ++ }, $res); ++ $res = '"""' . "\n\t" . substr($res, 1, -1) . "\n" . '"""'; + } + +- $s = preg_replace('#^(?=.)#m', "\t", $s); +- return $delim . "\n" . $s . "\n" . $delim; ++ return $res; + } + } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 0f3487007a..23d822be89 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,1606 +1,1606 @@ parameters: ignoreErrors: - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php - - message: '#^Method PHPStan\\Analyser\\AnalyserResultFinalizer\:\:finalize\(\) throws checked exception Throwable but it''s missing from the PHPDoc @throws tag\.$#' + message: "#^Method PHPStan\\\\Analyser\\\\AnalyserResultFinalizer\\:\\:finalize\\(\\) throws checked exception Throwable but it's missing from the PHPDoc @throws tag\\.$#" count: 1 path: src/Analyser/AnalyserResultFinalizer.php - - message: '#^Cannot assign offset ''realCount'' to array\|string\.$#' + message: "#^Cannot assign offset 'realCount' to array\\|string\\.$#" count: 1 path: src/Analyser/Ignore/IgnoredErrorHelperResult.php - - message: '#^Casting to string something that''s already string\.$#' + message: "#^Casting to string something that's already string\\.$#" count: 3 path: src/Analyser/MutatingScope.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 4 path: src/Analyser/MutatingScope.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 3 path: src/Analyser/MutatingScope.php - - message: '#^Only numeric types are allowed in pre\-increment, float\|int\|string\|null given\.$#' + message: "#^Only numeric types are allowed in pre\\-increment, float\\|int\\|string\\|null given\\.$#" count: 1 path: src/Analyser/MutatingScope.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 3 path: src/Analyser/NodeScopeResolver.php - - message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 1 path: src/Analyser/NodeScopeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 2 path: src/Analyser/TypeSpecifier.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 5 path: src/Analyser/TypeSpecifier.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 3 path: src/Analyser/TypeSpecifier.php - - message: '#^Template type TNodeType is declared as covariant, but occurs in contravariant position in parameter node of method PHPStan\\Collectors\\Collector\:\:processNode\(\)\.$#' + message: "#^Template type TNodeType is declared as covariant, but occurs in contravariant position in parameter node of method PHPStan\\\\Collectors\\\\Collector\\:\\:processNode\\(\\)\\.$#" count: 1 path: src/Collectors/Collector.php - - message: '#^Method PHPStan\\Collectors\\Registry\:\:__construct\(\) has parameter \$collectors with generic interface PHPStan\\Collectors\\Collector but does not specify its types\: TNodeType, TValue$#' + message: "#^Method PHPStan\\\\Collectors\\\\Registry\\:\\:__construct\\(\\) has parameter \\$collectors with generic interface PHPStan\\\\Collectors\\\\Collector but does not specify its types\\: TNodeType, TValue$#" count: 1 path: src/Collectors/Registry.php - - message: '#^Property PHPStan\\Collectors\\Registry\:\:\$cache with generic interface PHPStan\\Collectors\\Collector does not specify its types\: TNodeType, TValue$#' + message: "#^Property PHPStan\\\\Collectors\\\\Registry\\:\\:\\$cache with generic interface PHPStan\\\\Collectors\\\\Collector does not specify its types\\: TNodeType, TValue$#" count: 1 path: src/Collectors/Registry.php - - message: '#^Property PHPStan\\Collectors\\Registry\:\:\$collectors with generic interface PHPStan\\Collectors\\Collector does not specify its types\: TNodeType, TValue$#' + message: "#^Property PHPStan\\\\Collectors\\\\Registry\\:\\:\\$collectors with generic interface PHPStan\\\\Collectors\\\\Collector does not specify its types\\: TNodeType, TValue$#" count: 1 path: src/Collectors/Registry.php - - message: '#^Anonymous function has an unused use \$container\.$#' + message: "#^Anonymous function has an unused use \\$container\\.$#" count: 1 path: src/Command/CommandHelper.php - - message: '#^Parameter \#1 \$path of function dirname expects string, string\|false given\.$#' + message: "#^Parameter \\#1 \\$path of function dirname expects string, string\\|false given\\.$#" count: 1 path: src/Command/CommandHelper.php - - message: '#^Static property PHPStan\\Command\\CommandHelper\:\:\$reservedMemory is never read, only written\.$#' + message: "#^Static property PHPStan\\\\Command\\\\CommandHelper\\:\\:\\$reservedMemory is never read, only written\\.$#" count: 1 path: src/Command/CommandHelper.php - - message: '#^Parameter \#1 \$headers \(array\\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$headers \(array\) of method Symfony\\Component\\Console\\Style\\StyleInterface\:\:table\(\)$#' + message: "#^Parameter \\#1 \\$headers \\(array\\\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$headers \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\StyleInterface\\:\\:table\\(\\)$#" count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: '#^Parameter \#1 \$headers \(array\\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$headers \(array\) of method Symfony\\Component\\Console\\Style\\SymfonyStyle\:\:table\(\)$#' + message: "#^Parameter \\#1 \\$headers \\(array\\\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$headers \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\SymfonyStyle\\:\\:table\\(\\)$#" count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: '#^Parameter \#2 \$rows \(array\\>\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$rows \(array\) of method Symfony\\Component\\Console\\Style\\StyleInterface\:\:table\(\)$#' + message: "#^Parameter \\#2 \\$rows \\(array\\\\>\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$rows \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\StyleInterface\\:\\:table\\(\\)$#" count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: '#^Parameter \#2 \$rows \(array\\>\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$rows \(array\) of method Symfony\\Component\\Console\\Style\\SymfonyStyle\:\:table\(\)$#' + message: "#^Parameter \\#2 \\$rows \\(array\\\\>\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$rows \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\SymfonyStyle\\:\\:table\\(\\)$#" count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: '#^Variable method call on Nette\\Schema\\Elements\\AnyOf\|Nette\\Schema\\Elements\\Structure\|Nette\\Schema\\Elements\\Type\.$#' + message: "#^Variable method call on Nette\\\\Schema\\\\Elements\\\\AnyOf\\|Nette\\\\Schema\\\\Elements\\\\Structure\\|Nette\\\\Schema\\\\Elements\\\\Type\\.$#" count: 1 path: src/DependencyInjection/ContainerFactory.php - - message: '#^Variable static method call on Nette\\Schema\\Expect\.$#' + message: "#^Variable static method call on Nette\\\\Schema\\\\Expect\\.$#" count: 1 path: src/DependencyInjection/ContainerFactory.php - - message: '#^Fetching class constant PREVENT_MERGING of deprecated class Nette\\DI\\Config\\Helpers\.$#' + message: "#^Fetching class constant PREVENT_MERGING of deprecated class Nette\\\\DI\\\\Config\\\\Helpers\\.$#" count: 1 path: src/DependencyInjection/NeonAdapter.php - - message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - - message: '#^Parameter \#1 \$path of function dirname expects string, string\|false given\.$#' + message: "#^Parameter \\#1 \\$path of function dirname expects string, string\\|false given\\.$#" count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - - message: '#^Variable method call on PHPStan\\Reflection\\ClassReflection\.$#' + message: "#^Variable method call on PHPStan\\\\Reflection\\\\ClassReflection\\.$#" count: 2 path: src/PhpDoc/PhpDocBlock.php - - message: '#^Variable static method call on PHPStan\\PhpDoc\\PhpDocBlock\.$#' + message: "#^Variable static method call on PHPStan\\\\PhpDoc\\\\PhpDocBlock\\.$#" count: 1 path: src/PhpDoc/PhpDocBlock.php - - message: '#^Call to function method_exists\(\) with PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode and ''getParamOutTypeTagV…'' will always evaluate to true\.$#' + message: "#^Call to function method_exists\\(\\) with PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\PhpDocNode and 'getParamOutTypeTagV…' will always evaluate to true\\.$#" count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - - message: '#^Call to function method_exists\(\) with PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode and ''getSelfOutTypeTagVa…'' will always evaluate to true\.$#' + message: "#^Call to function method_exists\\(\\) with PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\PhpDocNode and 'getSelfOutTypeTagVa…' will always evaluate to true\\.$#" count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - - message: '#^Method PHPStan\\PhpDoc\\ResolvedPhpDocBlock\:\:getNameScope\(\) should return PHPStan\\Analyser\\NameScope but returns PHPStan\\Analyser\\NameScope\|null\.$#' + message: "#^Method PHPStan\\\\PhpDoc\\\\ResolvedPhpDocBlock\\:\\:getNameScope\\(\\) should return PHPStan\\\\Analyser\\\\NameScope but returns PHPStan\\\\Analyser\\\\NameScope\\|null\\.$#" count: 1 path: src/PhpDoc/ResolvedPhpDocBlock.php - - message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 2 path: src/PhpDoc/TypeNodeResolver.php - - message: '#^Dead catch \- PHPStan\\BetterReflection\\Identifier\\Exception\\InvalidIdentifierName is never thrown in the try block\.$#' + message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\Identifier\\\\Exception\\\\InvalidIdentifierName is never thrown in the try block\\.$#" count: 3 path: src/Reflection/BetterReflection/BetterReflectionProvider.php - - message: '#^Dead catch \- PHPStan\\BetterReflection\\NodeCompiler\\Exception\\UnableToCompileNode is never thrown in the try block\.$#' + message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\NodeCompiler\\\\Exception\\\\UnableToCompileNode is never thrown in the try block\\.$#" count: 1 path: src/Reflection/BetterReflection/BetterReflectionProvider.php - - message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: '#^Creating new ReflectionFunction is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Creating new ReflectionFunction is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: '#^Method PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FileReadTrapStreamWrapper\:\:invokeWithRealFileStreamWrapper\(\) has parameter \$cb with no signature specified for callable\.$#' + message: "#^Method PHPStan\\\\Reflection\\\\BetterReflection\\\\SourceLocator\\\\FileReadTrapStreamWrapper\\:\\:invokeWithRealFileStreamWrapper\\(\\) has parameter \\$cb with no signature specified for callable\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php - - message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\ClassLike\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Function_ given\.$#' + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php - - message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' + message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" count: 2 path: src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php - - message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/ReflectionClassSourceLocator.php - - message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.php - - message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" count: 3 path: src/Reflection/ClassReflection.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 1 path: src/Reflection/ClassReflection.php - - message: '#^Method PHPStan\\Reflection\\ClassReflection\:\:getCacheKey\(\) should return string but returns string\|null\.$#' + message: "#^Method PHPStan\\\\Reflection\\\\ClassReflection\\:\\:getCacheKey\\(\\) should return string but returns string\\|null\\.$#" count: 1 path: src/Reflection/ClassReflection.php - - message: '#^Binary operation "&" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' + message: "#^Binary operation \"&\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Binary operation "\*" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' + message: "#^Binary operation \"\\*\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Binary operation "\+" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' + message: "#^Binary operation \"\\+\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Binary operation "\-" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' + message: "#^Binary operation \"\\-\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Binary operation "\^" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' + message: "#^Binary operation \"\\^\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Binary operation "\|" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' + message: "#^Binary operation \"\\|\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 22 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 4 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 3 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 10 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^PHPDoc tag @var with type float\|int is not subtype of native type int\.$#' + message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^PHPDoc tag @var with type float\|int is not subtype of type int\.$#' + message: "#^PHPDoc tag @var with type float\\|int is not subtype of type int\\.$#" count: 4 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^PHPDoc tag @var with type float\|int\|null is not subtype of type int\|null\.$#' + message: "#^PHPDoc tag @var with type float\\|int\\|null is not subtype of type int\\|null\\.$#" count: 6 path: src/Reflection/InitializerExprTypeResolver.php - - message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' + message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" count: 1 path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Rules/Api/NodeConnectingVisitorAttributesRule.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 1 path: src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Classes/ImpossibleInstanceOfRule.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 2 path: src/Rules/Classes/RequireExtendsRule.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 1 path: src/Rules/Classes/RequireImplementsRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 6 path: src/Rules/Comparison/BooleanAndConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/BooleanNotConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 6 path: src/Rules/Comparison/BooleanOrConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/ConstantLooseComparisonRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/DoWhileLoopConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/ElseIfConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/IfConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 3 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" count: 1 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 4 path: src/Rules/Comparison/LogicalXorConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 4 path: src/Rules/Comparison/MatchExpressionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/NumberComparisonOperatorsConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Rules/Comparison/TernaryOperatorConstantConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 1 path: src/Rules/Comparison/WhileLoopAlwaysFalseConditionRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 1 path: src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php - - message: '#^Function class_implements\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Rules/DirectRegistry.php - - message: '#^Function class_parents\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Function class_parents\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Rules/DirectRegistry.php - - message: '#^Method PHPStan\\Rules\\DirectRegistry\:\:__construct\(\) has parameter \$rules with generic interface PHPStan\\Rules\\Rule but does not specify its types\: TNodeType$#' + message: "#^Method PHPStan\\\\Rules\\\\DirectRegistry\\:\\:__construct\\(\\) has parameter \\$rules with generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#" count: 1 path: src/Rules/DirectRegistry.php - - message: '#^Property PHPStan\\Rules\\DirectRegistry\:\:\$cache with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' + message: "#^Property PHPStan\\\\Rules\\\\DirectRegistry\\:\\:\\$cache with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" count: 1 path: src/Rules/DirectRegistry.php - - message: '#^Property PHPStan\\Rules\\DirectRegistry\:\:\$rules with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' + message: "#^Property PHPStan\\\\Rules\\\\DirectRegistry\\:\\:\\$rules with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" count: 1 path: src/Rules/DirectRegistry.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" count: 1 path: src/Rules/Generics/GenericAncestorsCheck.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Rules/Generics/TemplateTypeCheck.php - - message: '#^Function class_implements\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Rules/LazyRegistry.php - - message: '#^Function class_parents\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' + message: "#^Function class_parents\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" count: 1 path: src/Rules/LazyRegistry.php - - message: '#^Method PHPStan\\Rules\\LazyRegistry\:\:getRulesFromContainer\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' + message: "#^Method PHPStan\\\\Rules\\\\LazyRegistry\\:\\:getRulesFromContainer\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" count: 1 path: src/Rules/LazyRegistry.php - - message: '#^Property PHPStan\\Rules\\LazyRegistry\:\:\$cache with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' + message: "#^Property PHPStan\\\\Rules\\\\LazyRegistry\\:\\:\\$cache with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" count: 1 path: src/Rules/LazyRegistry.php - - message: '#^Property PHPStan\\Rules\\LazyRegistry\:\:\$rules with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' + message: "#^Property PHPStan\\\\Rules\\\\LazyRegistry\\:\\:\\$rules with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" count: 1 path: src/Rules/LazyRegistry.php - - message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" count: 1 path: src/Rules/Methods/StaticMethodCallCheck.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 1 path: src/Rules/PhpDoc/RequireExtendsCheck.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 1 path: src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" count: 1 path: src/Rules/PhpDoc/VarTagTypeRuleHelper.php - - message: '#^Access to an undefined property T of PHPStan\\Rules\\RuleError\:\:\$tip\.$#' + message: "#^Access to an undefined property T of PHPStan\\\\Rules\\\\RuleError\\:\\:\\$tip\\.$#" count: 2 path: src/Rules/RuleErrorBuilder.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Rules/RuleLevelHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 1 path: src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Rules/UnusedFunctionParametersCheck.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 1 path: src/Rules/Variables/CompactVariablesRule.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Rules/Variables/CompactVariablesRule.php - - message: '#^Anonymous function has an unused use \$container\.$#' + message: "#^Anonymous function has an unused use \\$container\\.$#" count: 1 path: src/Testing/PHPStanTestCase.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 2 path: src/Testing/TypeInferenceTestCase.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/AccessoryArrayListType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/AccessoryLiteralStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/AccessoryLowercaseStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Accessory/AccessoryNonEmptyStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/AccessoryNonEmptyStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/AccessoryNonFalsyStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Accessory/AccessoryNumericStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/AccessoryNumericStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/HasMethodType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/HasOffsetType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 2 path: src/Type/Accessory/HasOffsetValueType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 2 path: src/Type/Accessory/HasOffsetValueType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/HasOffsetValueType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/HasPropertyType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/NonEmptyArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Accessory/OversizedArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" count: 3 path: src/Type/ArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 2 path: src/Type/ArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 2 path: src/Type/ArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/ArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" count: 2 path: src/Type/BooleanType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 1 path: src/Type/BooleanType.php - - message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" count: 4 path: src/Type/CallableType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 2 path: src/Type/CallableType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/ClosureType.php - - message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" count: 1 path: src/Type/Constant/ConstantArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 7 path: src/Type/Constant/ConstantArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Type is always PHPStan\\Type\\Constant\\ConstantIntegerType\|PHPStan\\Type\\Constant\\ConstantStringType but it''s error\-prone and dangerous\.$#' + message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Type is always PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType\\|PHPStan\\\\Type\\\\Constant\\\\ConstantStringType but it's error\\-prone and dangerous\\.$#" count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: '#^PHPDoc tag @var with type float\|int is not subtype of native type int\.$#' + message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: '#^PHPDoc tag @var with type float\|int is not subtype of type int\.$#' + message: "#^PHPDoc tag @var with type float\\|int is not subtype of type int\\.$#" count: 1 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" count: 1 path: src/Type/Constant/ConstantBooleanType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 4 path: src/Type/Constant/ConstantBooleanType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 3 path: src/Type/Constant/ConstantBooleanType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 4 path: src/Type/Constant/ConstantFloatType.php - - message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" count: 1 path: src/Type/Constant/ConstantFloatType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 4 path: src/Type/Constant/ConstantIntegerType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" count: 1 path: src/Type/Constant/ConstantIntegerType.php - - message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" count: 1 path: src/Type/Constant/ConstantStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 4 path: src/Type/Constant/ConstantStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 4 path: src/Type/Constant/ConstantStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" count: 1 path: src/Type/Constant/ConstantStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" count: 1 path: src/Type/Constant/ConstantStringType.php - - message: '#^PHPDoc tag @var with type int\|string is not subtype of type string\.$#' + message: "#^PHPDoc tag @var with type int\\|string is not subtype of type string\\.$#" count: 1 path: src/Type/Constant/ConstantStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 1 path: src/Type/Constant/OversizedArrayBuilder.php - - message: '#^Doing instanceof PHPStan\\Type\\Enum\\EnumCaseObjectType is error\-prone and deprecated\. Use Type\:\:getEnumCases\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" count: 2 path: src/Type/Enum/EnumCaseObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 2 path: src/Type/ExponentiateHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/FileTypeMapper.php - - message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" count: 2 path: src/Type/FloatType.php - - message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/GenericClassStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 4 path: src/Type/Generic/GenericClassStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" count: 4 path: src/Type/Generic/GenericClassStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Generic/GenericClassStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" count: 2 path: src/Type/Generic/GenericClassStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/GenericObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Generic/GenericObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/GenericObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" count: 2 path: src/Type/Generic/GenericObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateBenevolentUnionType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateBooleanType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateConstantArrayType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateConstantIntegerType.php - - message: '#^Method PHPStan\\Type\\Generic\\TemplateConstantIntegerType\:\:toPhpDocNode\(\) should return PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode but returns PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode\.$#' + message: "#^Method PHPStan\\\\Type\\\\Generic\\\\TemplateConstantIntegerType\\:\\:toPhpDocNode\\(\\) should return PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\ConstTypeNode but returns PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\IdentifierTypeNode\\.$#" count: 1 path: src/Type/Generic/TemplateConstantIntegerType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateConstantStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateFloatType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateGenericObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateIntegerType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateIntersectionType.php - - message: '#^Instanceof between PHPStan\\Type\\Type and PHPStan\\Type\\IntersectionType will always evaluate to false\.$#' + message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\IntersectionType will always evaluate to false\\.$#" count: 2 path: src/Type/Generic/TemplateIntersectionType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateKeyOfType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 2 path: src/Type/Generic/TemplateMixedType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateObjectShapeType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateObjectWithoutClassType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 2 path: src/Type/Generic/TemplateStrictMixedType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateStringType.php - - message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/Generic/TemplateUnionType.php - - message: '#^Instanceof between PHPStan\\Type\\Type and PHPStan\\Type\\UnionType will always evaluate to false\.$#' + message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\UnionType will always evaluate to false\\.$#" count: 2 path: src/Type/Generic/TemplateUnionType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 1 path: src/Type/IntegerRangeType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" count: 3 path: src/Type/IntegerRangeType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/IntegerRangeType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" count: 2 path: src/Type/IntegerType.php - - message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" count: 3 path: src/Type/IntersectionType.php - - message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" count: 1 path: src/Type/IntersectionType.php - - message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" count: 2 path: src/Type/IntersectionType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 4 path: src/Type/IntersectionType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 2 path: src/Type/IterableType.php - - message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 2 path: src/Type/IterableType.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 3 path: src/Type/NullType.php - - message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" count: 3 path: src/Type/NullType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/ObjectShapeType.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" count: 2 path: src/Type/ObjectShapeType.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" count: 1 path: src/Type/ObjectShapeType.php - - message: '#^Doing instanceof PHPStan\\Type\\Enum\\EnumCaseObjectType is error\-prone and deprecated\. Use Type\:\:getEnumCases\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" count: 1 path: src/Type/ObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" count: 1 path: src/Type/ObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 6 path: src/Type/ObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" count: 3 path: src/Type/ObjectType.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" count: 2 path: src/Type/ObjectWithoutClassType.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" count: 4 path: src/Type/ObjectWithoutClassType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 2 path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 4 path: src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 16 path: src/Type/Php/BcMathStringOrNullReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 1 path: src/Type/Php/CompactFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/CompactFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/DefineConstantTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/DefinedConstantTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" count: 1 path: src/Type/Php/DsMapDynamicReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 2 path: src/Type/Php/FilterFunctionReturnTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/FilterFunctionReturnTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ImplodeFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/IsAFunctionTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" count: 2 path: src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 2 path: src/Type/Php/LtrimFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/MbStrlenFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/MethodExistsTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 4 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 2 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 1 path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 2 path: src/Type/Php/PropertyExistsTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 2 path: src/Type/Php/RangeFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" count: 1 path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php - - message: '#^Cannot access offset int\<0, max\> on \(float\|int\)\.$#' + message: "#^Cannot access offset int\\<0, max\\> on \\(float\\|int\\)\\.$#" count: 2 path: src/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/StrRepeatFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/Php/StrlenFunctionReturnTypeExtension.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" count: 2 path: src/Type/StaticType.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" count: 1 path: src/Type/StaticType.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 1 path: src/Type/StringType.php - - message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" count: 2 path: src/Type/StringType.php - - message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" count: 5 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 14 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 5 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" count: 2 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 8 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" count: 2 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" count: 2 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Instanceof between PHPStan\\Type\\Constant\\ConstantIntegerType and PHPStan\\Type\\Constant\\ConstantIntegerType will always evaluate to true\.$#' + message: "#^Instanceof between PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType and PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType will always evaluate to true\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Result of \|\| is always true\.$#' + message: "#^Result of \\|\\| is always true\\.$#" count: 1 path: src/Type/TypeCombinator.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 2 path: src/Type/TypeUtils.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 3 path: src/Type/TypeUtils.php - - message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" count: 3 path: src/Type/TypehintHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" count: 3 path: src/Type/TypehintHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 1 path: src/Type/TypehintHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" count: 2 path: src/Type/UnionType.php - - message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" count: 1 path: src/Type/UnionType.php - - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" count: 2 path: src/Type/UnionType.php - - message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 1 path: src/Type/UnionType.php - - message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Type is always PHPStan\\Type\\BooleanType but it''s error\-prone and dangerous\.$#' + message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Type is always PHPStan\\\\Type\\\\BooleanType but it's error\\-prone and dangerous\\.$#" count: 1 path: src/Type/UnionType.php - - message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" count: 3 path: src/Type/UnionTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" count: 2 path: src/Type/UnionTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" count: 4 path: src/Type/UnionTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" count: 2 path: src/Type/UnionTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" count: 2 path: src/Type/UnionTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" count: 2 path: src/Type/UnionTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" count: 2 path: src/Type/UnionTypeHelper.php - - message: '#^Doing instanceof PHPStan\\Type\\VoidType is error\-prone and deprecated\. Use Type\:\:isVoid\(\) instead\.$#' + message: "#^Doing instanceof PHPStan\\\\Type\\\\VoidType is error\\-prone and deprecated\\. Use Type\\:\\:isVoid\\(\\) instead\\.$#" count: 2 path: src/Type/VoidType.php - - message: '#^Unreachable statement \- code above always terminates\.$#' + message: "#^Unreachable statement \\- code above always terminates\\.$#" count: 1 path: tests/PHPStan/Analyser/AnalyserTest.php - - message: '#^Class PHPStan\\Analyser\\AnonymousClassNameRuleTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' + message: "#^Class PHPStan\\\\Analyser\\\\AnonymousClassNameRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" count: 1 path: tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php - - message: '#^Method PHPStan\\Analyser\\AnonymousClassNameRuleTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' + message: "#^Method PHPStan\\\\Analyser\\\\AnonymousClassNameRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" count: 1 path: tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php - - message: '#^Class PHPStan\\Analyser\\EvaluationOrderTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' + message: "#^Class PHPStan\\\\Analyser\\\\EvaluationOrderTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" count: 1 path: tests/PHPStan/Analyser/EvaluationOrderTest.php - - message: '#^Method PHPStan\\Analyser\\EvaluationOrderTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' + message: "#^Method PHPStan\\\\Analyser\\\\EvaluationOrderTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" count: 1 path: tests/PHPStan/Analyser/EvaluationOrderTest.php - - message: '#^Constant SOME_CONSTANT_IN_AUTOLOAD_FILE not found\.$#' + message: "#^Constant SOME_CONSTANT_IN_AUTOLOAD_FILE not found\\.$#" count: 1 path: tests/PHPStan/Command/AnalyseCommandTest.php - - message: '#^Class PHPStan\\Node\\FileNodeTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' + message: "#^Class PHPStan\\\\Node\\\\FileNodeTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" count: 1 path: tests/PHPStan/Node/FileNodeTest.php - - message: '#^Method PHPStan\\Node\\FileNodeTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' + message: "#^Method PHPStan\\\\Node\\\\FileNodeTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" count: 1 path: tests/PHPStan/Node/FileNodeTest.php - - message: '#^PHPDoc tag @var with type string is not subtype of type class\-string\.$#' + message: "#^PHPDoc tag @var with type string is not subtype of type class\\-string\\.$#" count: 1 path: tests/PHPStan/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorTest.php - - message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' + message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" count: 1 path: tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php - - message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' + message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" count: 1 path: tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php - - message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Generic\\TemplateType is always PHPStan\\Type\\Generic\\TemplateMixedType but it''s error\-prone and dangerous\.$#' + message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" count: 1 path: tests/PHPStan/Type/IterableTypeTest.php From ec6fbe2cab1a1687959b3bbaca4c77bb93c30d7c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 12:29:42 +0200 Subject: [PATCH 293/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 14 +++++++------- conf/config.neon | 21 --------------------- 3 files changed, 8 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index e7d2b401bb..1ebc818e9f 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.2.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.42.0.8", + "ondrejmirtes/better-reflection": "6.42.0.9", "phpstan/php-8-stubs": "0.3.111", "phpstan/phpdoc-parser": "^2.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 2bf4e1b5f2..184b4f0320 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3745d8358f113e8d1a7c6b1066a9db0a", + "content-hash": "25426f4d76b14416d019ce2466d96971", "packages": [ { "name": "clue/ndjson-react", @@ -2179,16 +2179,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.42.0.8", + "version": "6.42.0.9", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "00d3413be6f1f9c012b935fbf7aec900bcdde4db" + "reference": "28d0aa833b53a038c6e10480770b17fb643323b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/00d3413be6f1f9c012b935fbf7aec900bcdde4db", - "reference": "00d3413be6f1f9c012b935fbf7aec900bcdde4db", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/28d0aa833b53a038c6e10480770b17fb643323b1", + "reference": "28d0aa833b53a038c6e10480770b17fb643323b1", "shasum": "" }, "require": { @@ -2244,9 +2244,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.42.0.8" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.42.0.9" }, - "time": "2024-09-10T09:57:34+00:00" + "time": "2024-09-30T10:27:49+00:00" }, { "name": "phpstan/php-8-stubs", diff --git a/conf/config.neon b/conf/config.neon index 5dc867fc1b..3d05cf2669 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1971,27 +1971,6 @@ services: reflector: @originalBetterReflectionReflector autowired: false - # deprecated - betterReflectionClassReflector: - class: PHPStan\BetterReflection\Reflector\ClassReflector - arguments: - sourceLocator: @betterReflectionSourceLocator - autowired: false - - # deprecated - betterReflectionFunctionReflector: - class: PHPStan\BetterReflection\Reflector\FunctionReflector - arguments: - sourceLocator: @betterReflectionSourceLocator - autowired: false - - # deprecated - betterReflectionConstantReflector: - class: PHPStan\BetterReflection\Reflector\ConstantReflector - arguments: - sourceLocator: @betterReflectionSourceLocator - autowired: false - nodeScopeResolverReflector: factory: @betterReflectionReflector autowired: false From 392f090066bfc9946b4ad524ffecf3d420c23114 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 12:35:15 +0200 Subject: [PATCH 294/508] These can be a native return type thanks to PHP 7.4 return type covariance --- src/Dependency/ExportedNode/ExportedAttributeNode.php | 6 ++---- .../ExportedNode/ExportedClassConstantNode.php | 6 ++---- .../ExportedNode/ExportedClassConstantsNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedClassNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedEnumCaseNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedEnumNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedFunctionNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedInterfaceNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedMethodNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedParameterNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedPhpDocNode.php | 6 ++---- .../ExportedNode/ExportedPropertiesNode.php | 6 ++---- src/Dependency/ExportedNode/ExportedTraitNode.php | 6 ++---- .../ExportedNode/ExportedTraitUseAdaptation.php | 6 ++---- src/PhpDoc/Tag/ParamClosureThisTag.php | 5 +---- src/PhpDoc/Tag/ParamOutTag.php | 5 +---- src/PhpDoc/Tag/ParamTag.php | 5 +---- src/PhpDoc/Tag/ReturnTag.php | 5 +---- src/PhpDoc/Tag/SelfOutTypeTag.php | 5 +---- src/PhpDoc/Tag/VarTag.php | 5 +---- .../AnnotationsMethodsClassReflectionExtension.php | 6 +----- .../AnnotationsPropertiesClassReflectionExtension.php | 6 +----- src/Reflection/Php/PhpClassReflectionExtension.php | 11 ++--------- .../RequireExtendsMethodsClassReflectionExtension.php | 11 ++--------- ...quireExtendsPropertiesClassReflectionExtension.php | 6 +----- src/Type/ObjectType.php | 5 +---- src/Type/Type.php | 1 - 27 files changed, 42 insertions(+), 118 deletions(-) diff --git a/src/Dependency/ExportedNode/ExportedAttributeNode.php b/src/Dependency/ExportedNode/ExportedAttributeNode.php index 5612e74ea1..f7d00465ad 100644 --- a/src/Dependency/ExportedNode/ExportedAttributeNode.php +++ b/src/Dependency/ExportedNode/ExportedAttributeNode.php @@ -45,9 +45,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -72,9 +71,8 @@ public function jsonSerialize() /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedClassConstantNode.php b/src/Dependency/ExportedNode/ExportedClassConstantNode.php index 8827656c48..2aec4d44fa 100644 --- a/src/Dependency/ExportedNode/ExportedClassConstantNode.php +++ b/src/Dependency/ExportedNode/ExportedClassConstantNode.php @@ -45,9 +45,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -58,9 +57,8 @@ public static function __set_state(array $properties): ExportedNode /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedClassConstantsNode.php b/src/Dependency/ExportedNode/ExportedClassConstantsNode.php index 23ebd61ae0..e555874fc7 100644 --- a/src/Dependency/ExportedNode/ExportedClassConstantsNode.php +++ b/src/Dependency/ExportedNode/ExportedClassConstantsNode.php @@ -54,9 +54,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['constants'], @@ -69,9 +68,8 @@ public static function __set_state(array $properties): ExportedNode /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( array_map(static function (array $constantData): ExportedClassConstantNode { diff --git a/src/Dependency/ExportedNode/ExportedClassNode.php b/src/Dependency/ExportedNode/ExportedClassNode.php index b420a0a9ad..cb57bddb4c 100644 --- a/src/Dependency/ExportedNode/ExportedClassNode.php +++ b/src/Dependency/ExportedNode/ExportedClassNode.php @@ -96,9 +96,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -139,9 +138,8 @@ public function jsonSerialize() /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedEnumCaseNode.php b/src/Dependency/ExportedNode/ExportedEnumCaseNode.php index 19f8f6a22b..65b3273315 100644 --- a/src/Dependency/ExportedNode/ExportedEnumCaseNode.php +++ b/src/Dependency/ExportedNode/ExportedEnumCaseNode.php @@ -37,9 +37,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -50,9 +49,8 @@ public static function __set_state(array $properties): ExportedNode /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedEnumNode.php b/src/Dependency/ExportedNode/ExportedEnumNode.php index ea5ce3970b..b703518ab9 100644 --- a/src/Dependency/ExportedNode/ExportedEnumNode.php +++ b/src/Dependency/ExportedNode/ExportedEnumNode.php @@ -76,9 +76,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -111,9 +110,8 @@ public function jsonSerialize() /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedFunctionNode.php b/src/Dependency/ExportedNode/ExportedFunctionNode.php index c7e98d3643..d0ebd50613 100644 --- a/src/Dependency/ExportedNode/ExportedFunctionNode.php +++ b/src/Dependency/ExportedNode/ExportedFunctionNode.php @@ -74,9 +74,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -109,9 +108,8 @@ public function jsonSerialize() /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedInterfaceNode.php b/src/Dependency/ExportedNode/ExportedInterfaceNode.php index ef72841c5e..0e6d6632db 100644 --- a/src/Dependency/ExportedNode/ExportedInterfaceNode.php +++ b/src/Dependency/ExportedNode/ExportedInterfaceNode.php @@ -56,9 +56,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -87,9 +86,8 @@ public function jsonSerialize() /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedMethodNode.php b/src/Dependency/ExportedNode/ExportedMethodNode.php index 817482ef93..af2b4255ce 100644 --- a/src/Dependency/ExportedNode/ExportedMethodNode.php +++ b/src/Dependency/ExportedNode/ExportedMethodNode.php @@ -83,9 +83,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -128,9 +127,8 @@ public function jsonSerialize() /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedParameterNode.php b/src/Dependency/ExportedNode/ExportedParameterNode.php index c4a7769e28..9f4cf02d61 100644 --- a/src/Dependency/ExportedNode/ExportedParameterNode.php +++ b/src/Dependency/ExportedNode/ExportedParameterNode.php @@ -51,9 +51,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['name'], @@ -86,9 +85,8 @@ public function jsonSerialize() /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['name'], diff --git a/src/Dependency/ExportedNode/ExportedPhpDocNode.php b/src/Dependency/ExportedNode/ExportedPhpDocNode.php index a39cb4ef8a..9288a58107 100644 --- a/src/Dependency/ExportedNode/ExportedPhpDocNode.php +++ b/src/Dependency/ExportedNode/ExportedPhpDocNode.php @@ -48,18 +48,16 @@ public function jsonSerialize() /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self($properties['phpDocString'], $properties['namespace'], $properties['uses'], $properties['constUses'] ?? []); } /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self($data['phpDocString'], $data['namespace'], $data['uses'], $data['constUses'] ?? []); } diff --git a/src/Dependency/ExportedNode/ExportedPropertiesNode.php b/src/Dependency/ExportedNode/ExportedPropertiesNode.php index de0b4d2b49..af58d51738 100644 --- a/src/Dependency/ExportedNode/ExportedPropertiesNode.php +++ b/src/Dependency/ExportedNode/ExportedPropertiesNode.php @@ -76,9 +76,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['names'], @@ -94,9 +93,8 @@ public static function __set_state(array $properties): ExportedNode /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['names'], diff --git a/src/Dependency/ExportedNode/ExportedTraitNode.php b/src/Dependency/ExportedNode/ExportedTraitNode.php index f0f47ae021..8f6808f2b3 100644 --- a/src/Dependency/ExportedNode/ExportedTraitNode.php +++ b/src/Dependency/ExportedNode/ExportedTraitNode.php @@ -21,18 +21,16 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self($properties['traitName']); } /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self($data['traitName']); } diff --git a/src/Dependency/ExportedNode/ExportedTraitUseAdaptation.php b/src/Dependency/ExportedNode/ExportedTraitUseAdaptation.php index 38e9227624..85c515fac4 100644 --- a/src/Dependency/ExportedNode/ExportedTraitUseAdaptation.php +++ b/src/Dependency/ExportedNode/ExportedTraitUseAdaptation.php @@ -59,9 +59,8 @@ public function equals(ExportedNode $node): bool /** * @param mixed[] $properties - * @return self */ - public static function __set_state(array $properties): ExportedNode + public static function __set_state(array $properties): self { return new self( $properties['traitName'], @@ -74,9 +73,8 @@ public static function __set_state(array $properties): ExportedNode /** * @param mixed[] $data - * @return self */ - public static function decode(array $data): ExportedNode + public static function decode(array $data): self { return new self( $data['traitName'], diff --git a/src/PhpDoc/Tag/ParamClosureThisTag.php b/src/PhpDoc/Tag/ParamClosureThisTag.php index eba2903f21..92a91a4da8 100644 --- a/src/PhpDoc/Tag/ParamClosureThisTag.php +++ b/src/PhpDoc/Tag/ParamClosureThisTag.php @@ -21,10 +21,7 @@ public function getType(): Type return $this->type; } - /** - * @return self - */ - public function withType(Type $type): TypedTag + public function withType(Type $type): self { return new self($type); } diff --git a/src/PhpDoc/Tag/ParamOutTag.php b/src/PhpDoc/Tag/ParamOutTag.php index 50d289fc87..f720897deb 100644 --- a/src/PhpDoc/Tag/ParamOutTag.php +++ b/src/PhpDoc/Tag/ParamOutTag.php @@ -19,10 +19,7 @@ public function getType(): Type return $this->type; } - /** - * @return self - */ - public function withType(Type $type): TypedTag + public function withType(Type $type): self { return new self($type); } diff --git a/src/PhpDoc/Tag/ParamTag.php b/src/PhpDoc/Tag/ParamTag.php index 50a3e98cc8..498dd64ce7 100644 --- a/src/PhpDoc/Tag/ParamTag.php +++ b/src/PhpDoc/Tag/ParamTag.php @@ -27,10 +27,7 @@ public function isVariadic(): bool return $this->isVariadic; } - /** - * @return self - */ - public function withType(Type $type): TypedTag + public function withType(Type $type): self { return new self($type, $this->isVariadic); } diff --git a/src/PhpDoc/Tag/ReturnTag.php b/src/PhpDoc/Tag/ReturnTag.php index c2354fa3b1..b501dd67e1 100644 --- a/src/PhpDoc/Tag/ReturnTag.php +++ b/src/PhpDoc/Tag/ReturnTag.php @@ -24,10 +24,7 @@ public function isExplicit(): bool return $this->isExplicit; } - /** - * @return self - */ - public function withType(Type $type): TypedTag + public function withType(Type $type): self { return new self($type, $this->isExplicit); } diff --git a/src/PhpDoc/Tag/SelfOutTypeTag.php b/src/PhpDoc/Tag/SelfOutTypeTag.php index 63d275cc4c..10bb054179 100644 --- a/src/PhpDoc/Tag/SelfOutTypeTag.php +++ b/src/PhpDoc/Tag/SelfOutTypeTag.php @@ -19,10 +19,7 @@ public function getType(): Type return $this->type; } - /** - * @return self - */ - public function withType(Type $type): TypedTag + public function withType(Type $type): self { return new self($type); } diff --git a/src/PhpDoc/Tag/VarTag.php b/src/PhpDoc/Tag/VarTag.php index c4d5842474..85c26f1b6c 100644 --- a/src/PhpDoc/Tag/VarTag.php +++ b/src/PhpDoc/Tag/VarTag.php @@ -19,10 +19,7 @@ public function getType(): Type return $this->type; } - /** - * @return self - */ - public function withType(Type $type): TypedTag + public function withType(Type $type): self { return new self($type); } diff --git a/src/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php b/src/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php index c234e8e2d1..9ad470b0ee 100644 --- a/src/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php +++ b/src/Reflection/Annotations/AnnotationsMethodsClassReflectionExtension.php @@ -5,7 +5,6 @@ use PHPStan\PhpDoc\Tag\TemplateTag; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\MethodsClassReflectionExtension; use PHPStan\Type\Generic\TemplateTypeFactory; use PHPStan\Type\Generic\TemplateTypeHelper; @@ -35,10 +34,7 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): return isset($this->methods[$classReflection->getCacheKey()][$methodName]); } - /** - * @return ExtendedMethodReflection - */ - public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection + public function getMethod(ClassReflection $classReflection, string $methodName): ExtendedMethodReflection { return $this->methods[$classReflection->getCacheKey()][$methodName]; } diff --git a/src/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php b/src/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php index d6d69179d5..5d25367e70 100644 --- a/src/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php +++ b/src/Reflection/Annotations/AnnotationsPropertiesClassReflectionExtension.php @@ -5,7 +5,6 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\PropertiesClassReflectionExtension; -use PHPStan\Reflection\PropertyReflection; use PHPStan\Type\Generic\TemplateTypeHelper; use PHPStan\Type\Generic\TemplateTypeVariance; use PHPStan\Type\NeverType; @@ -29,10 +28,7 @@ public function hasProperty(ClassReflection $classReflection, string $propertyNa return isset($this->properties[$classReflection->getCacheKey()][$propertyName]); } - /** - * @return ExtendedPropertyReflection - */ - public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection + public function getProperty(ClassReflection $classReflection, string $propertyName): ExtendedPropertyReflection { return $this->properties[$classReflection->getCacheKey()][$propertyName]; } diff --git a/src/Reflection/Php/PhpClassReflectionExtension.php b/src/Reflection/Php/PhpClassReflectionExtension.php index b7f438737a..5a3606a66f 100644 --- a/src/Reflection/Php/PhpClassReflectionExtension.php +++ b/src/Reflection/Php/PhpClassReflectionExtension.php @@ -29,7 +29,6 @@ use PHPStan\Reflection\Native\NativeMethodReflection; use PHPStan\Reflection\Native\NativeParameterWithPhpDocsReflection; use PHPStan\Reflection\PropertiesClassReflectionExtension; -use PHPStan\Reflection\PropertyReflection; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Reflection\SignatureMap\FunctionSignature; use PHPStan\Reflection\SignatureMap\ParameterSignature; @@ -154,10 +153,7 @@ public function hasProperty(ClassReflection $classReflection, string $propertyNa return $classReflection->getNativeReflection()->hasProperty($propertyName); } - /** - * @return ExtendedPropertyReflection - */ - public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection + public function getProperty(ClassReflection $classReflection, string $propertyName): ExtendedPropertyReflection { if (!isset($this->propertiesIncludingAnnotations[$classReflection->getCacheKey()][$propertyName])) { $this->propertiesIncludingAnnotations[$classReflection->getCacheKey()][$propertyName] = $this->createProperty($classReflection, $propertyName, true); @@ -376,10 +372,7 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): return $classReflection->getNativeReflection()->hasMethod($methodName); } - /** - * @return ExtendedMethodReflection - */ - public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection + public function getMethod(ClassReflection $classReflection, string $methodName): ExtendedMethodReflection { if (isset($this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName])) { return $this->methodsIncludingAnnotations[$classReflection->getCacheKey()][$methodName]; diff --git a/src/Reflection/RequireExtension/RequireExtendsMethodsClassReflectionExtension.php b/src/Reflection/RequireExtension/RequireExtendsMethodsClassReflectionExtension.php index f439f811e9..ee6ada6f6f 100644 --- a/src/Reflection/RequireExtension/RequireExtendsMethodsClassReflectionExtension.php +++ b/src/Reflection/RequireExtension/RequireExtendsMethodsClassReflectionExtension.php @@ -5,7 +5,6 @@ use PHPStan\Analyser\OutOfClassScope; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\MethodsClassReflectionExtension; use PHPStan\ShouldNotHappenException; @@ -17,10 +16,7 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): return $this->findMethod($classReflection, $methodName) !== null; } - /** - * @return ExtendedMethodReflection - */ - public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection + public function getMethod(ClassReflection $classReflection, string $methodName): ExtendedMethodReflection { $method = $this->findMethod($classReflection, $methodName); if ($method === null) { @@ -30,10 +26,7 @@ public function getMethod(ClassReflection $classReflection, string $methodName): return $method; } - /** - * @return ExtendedMethodReflection|null - */ - private function findMethod(ClassReflection $classReflection, string $methodName): ?MethodReflection + private function findMethod(ClassReflection $classReflection, string $methodName): ?ExtendedMethodReflection { if (!$classReflection->isInterface()) { return null; diff --git a/src/Reflection/RequireExtension/RequireExtendsPropertiesClassReflectionExtension.php b/src/Reflection/RequireExtension/RequireExtendsPropertiesClassReflectionExtension.php index 294cc94b62..550a7bee59 100644 --- a/src/Reflection/RequireExtension/RequireExtendsPropertiesClassReflectionExtension.php +++ b/src/Reflection/RequireExtension/RequireExtendsPropertiesClassReflectionExtension.php @@ -6,7 +6,6 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\PropertiesClassReflectionExtension; -use PHPStan\Reflection\PropertyReflection; use PHPStan\ShouldNotHappenException; final class RequireExtendsPropertiesClassReflectionExtension implements PropertiesClassReflectionExtension @@ -17,10 +16,7 @@ public function hasProperty(ClassReflection $classReflection, string $propertyNa return $this->findProperty($classReflection, $propertyName) !== null; } - /** - * @return ExtendedPropertyReflection - */ - public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection + public function getProperty(ClassReflection $classReflection, string $propertyName): ExtendedPropertyReflection { $property = $this->findProperty($classReflection, $propertyName); if ($property === null) { diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 0d12a7f532..6db7a03eec 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1485,10 +1485,7 @@ public function getClassReflection(): ?ClassReflection return $classReflection; } - /** - * @return self|null - */ - public function getAncestorWithClassName(string $className): ?TypeWithClassName + public function getAncestorWithClassName(string $className): ?self { if ($this->className === $className) { return $this; diff --git a/src/Type/Type.php b/src/Type/Type.php index fec6ead728..e439af445b 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -10,7 +10,6 @@ use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; -use PHPStan\Reflection\PropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\TrinaryLogic; From d1d7d4abcca47bc1355099e2e5c540dabfb68b63 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 12:37:52 +0200 Subject: [PATCH 295/508] [BCB] `Type::getProperty()` now returns `ExtendedPropertyReflection` --- UPGRADING.md | 1 + src/Type/ClosureType.php | 4 ++-- src/Type/Generic/GenericObjectType.php | 4 ++-- src/Type/IntersectionType.php | 4 ++-- src/Type/MixedType.php | 4 ++-- src/Type/NeverType.php | 4 ++-- src/Type/NonexistentParentClassType.php | 4 ++-- src/Type/ObjectShapeType.php | 4 ++-- src/Type/ObjectType.php | 3 ++- src/Type/StaticType.php | 4 ++-- src/Type/StrictMixedType.php | 4 ++-- src/Type/Traits/LateResolvableTypeTrait.php | 4 ++-- src/Type/Traits/MaybeObjectTypeTrait.php | 4 ++-- src/Type/Traits/NonObjectTypeTrait.php | 4 ++-- src/Type/Traits/ObjectTypeTrait.php | 4 ++-- src/Type/Type.php | 5 +---- src/Type/UnionType.php | 4 ++-- 17 files changed, 32 insertions(+), 33 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index c3bf1e8995..a22375dd11 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -278,3 +278,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead * `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool` * Remove `FunctionReflection::isFinal()` +* [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html) diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index 708257ea1f..e09269ad83 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -20,13 +20,13 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Native\NativeParameterReflection; use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\PassedByReference; use PHPStan\Reflection\Php\ClosureCallUnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Php\DummyParameter; -use PHPStan\Reflection\PropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\TrinaryLogic; @@ -307,7 +307,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return $this->objectType->hasProperty($propertyName); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->objectType->getProperty($propertyName, $scope); } diff --git a/src/Type/Generic/GenericObjectType.php b/src/Type/Generic/GenericObjectType.php index 775134aab6..2747320c75 100644 --- a/src/Type/Generic/GenericObjectType.php +++ b/src/Type/Generic/GenericObjectType.php @@ -8,7 +8,7 @@ use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; @@ -228,7 +228,7 @@ public function getClassReflection(): ?ClassReflection ->withVariances($this->variances); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index f7d92dd554..27e7e623c1 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -10,8 +10,8 @@ use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\InitializerExprTypeResolver; -use PHPStan\Reflection\PropertyReflection; use PHPStan\Reflection\TrivialParametersAcceptor; use PHPStan\Reflection\Type\IntersectionTypeUnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\IntersectionTypeUnresolvedPropertyPrototypeReflection; @@ -466,7 +466,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasProperty($propertyName)); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index bf9f5bde68..def0bbd74a 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -12,7 +12,7 @@ use PHPStan\Reflection\Dummy\DummyMethodReflection; use PHPStan\Reflection\Dummy\DummyPropertyReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\TrivialParametersAcceptor; use PHPStan\Reflection\Type\CallbackUnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection; @@ -381,7 +381,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createYes(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index 68be84499a..bb2e9448f2 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -8,7 +8,7 @@ use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\ShouldNotHappenException; @@ -141,7 +141,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } diff --git a/src/Type/NonexistentParentClassType.php b/src/Type/NonexistentParentClassType.php index bbf9dceec8..3caabeee83 100644 --- a/src/Type/NonexistentParentClassType.php +++ b/src/Type/NonexistentParentClassType.php @@ -8,7 +8,7 @@ use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\ShouldNotHappenException; @@ -67,7 +67,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } diff --git a/src/Type/ObjectShapeType.php b/src/Type/ObjectShapeType.php index aeba44bb19..43b68b8dac 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -10,9 +10,9 @@ use PHPStan\PhpDocParser\Ast\Type\ObjectShapeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\ClassMemberAccessAnswerer; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\MissingPropertyFromReflectionException; use PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension; -use PHPStan\Reflection\PropertyReflection; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; @@ -102,7 +102,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createYes(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 6db7a03eec..e3711b8d73 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -23,6 +23,7 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension; use PHPStan\Reflection\PropertyReflection; use PHPStan\Reflection\ReflectionProviderStaticAccessor; @@ -160,7 +161,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index 55190656a4..5ef9ebc6c5 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -9,7 +9,7 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\Reflection\Type\CallbackUnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection; @@ -219,7 +219,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return $this->getStaticObjectType()->hasProperty($propertyName); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } diff --git a/src/Type/StrictMixedType.php b/src/Type/StrictMixedType.php index 3f86776840..944d0f2756 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -8,7 +8,7 @@ use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\ShouldNotHappenException; @@ -135,7 +135,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index d3a0083da6..03120df9f4 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -6,7 +6,7 @@ use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\TrinaryLogic; @@ -107,7 +107,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return $this->resolve()->hasProperty($propertyName); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->resolve()->getProperty($propertyName, $scope); } diff --git a/src/Type/Traits/MaybeObjectTypeTrait.php b/src/Type/Traits/MaybeObjectTypeTrait.php index b8097947b4..cc13c23a99 100644 --- a/src/Type/Traits/MaybeObjectTypeTrait.php +++ b/src/Type/Traits/MaybeObjectTypeTrait.php @@ -8,7 +8,7 @@ use PHPStan\Reflection\Dummy\DummyMethodReflection; use PHPStan\Reflection\Dummy\DummyPropertyReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\CallbackUnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -45,7 +45,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } diff --git a/src/Type/Traits/NonObjectTypeTrait.php b/src/Type/Traits/NonObjectTypeTrait.php index 3cba4b5bca..048ef5fb33 100644 --- a/src/Type/Traits/NonObjectTypeTrait.php +++ b/src/Type/Traits/NonObjectTypeTrait.php @@ -5,7 +5,7 @@ use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\ShouldNotHappenException; @@ -36,7 +36,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { throw new ShouldNotHappenException(); } diff --git a/src/Type/Traits/ObjectTypeTrait.php b/src/Type/Traits/ObjectTypeTrait.php index 2fd278e34b..174a6a2509 100644 --- a/src/Type/Traits/ObjectTypeTrait.php +++ b/src/Type/Traits/ObjectTypeTrait.php @@ -9,7 +9,7 @@ use PHPStan\Reflection\Dummy\DummyMethodReflection; use PHPStan\Reflection\Dummy\DummyPropertyReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\CallbackUnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -56,7 +56,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } diff --git a/src/Type/Type.php b/src/Type/Type.php index e439af445b..2d152cd73a 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -85,10 +85,7 @@ public function canAccessProperties(): TrinaryLogic; public function hasProperty(string $propertyName): TrinaryLogic; - /** - * @return ExtendedPropertyReflection - */ - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection; + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection; public function getUnresolvedPropertyPrototype(string $propertyName, ClassMemberAccessAnswerer $scope): UnresolvedPropertyPrototypeReflection; diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 1316f9369d..05d3f3ec92 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -11,8 +11,8 @@ use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\InitializerExprTypeResolver; -use PHPStan\Reflection\PropertyReflection; use PHPStan\Reflection\Type\UnionTypeUnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnionTypeUnresolvedPropertyPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -435,7 +435,7 @@ public function hasProperty(string $propertyName): TrinaryLogic return $this->unionResults(static fn (Type $type): TrinaryLogic => $type->hasProperty($propertyName)); } - public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection + public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): ExtendedPropertyReflection { return $this->getUnresolvedPropertyPrototype($propertyName, $scope)->getTransformedProperty(); } From f0a629685de2202687b9f92bd0e1a516daf2443e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 12:42:48 +0200 Subject: [PATCH 296/508] ReadWritePropertiesExtension - use ExtendedPropertyReflection in parameter type --- src/Rules/Properties/ReadWritePropertiesExtension.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Rules/Properties/ReadWritePropertiesExtension.php b/src/Rules/Properties/ReadWritePropertiesExtension.php index 1b1c695ef9..804619781c 100644 --- a/src/Rules/Properties/ReadWritePropertiesExtension.php +++ b/src/Rules/Properties/ReadWritePropertiesExtension.php @@ -2,7 +2,7 @@ namespace PHPStan\Rules\Properties; -use PHPStan\Reflection\PropertyReflection; +use PHPStan\Reflection\ExtendedPropertyReflection; /** * This is the extension interface to implement if you want to describe @@ -25,10 +25,10 @@ interface ReadWritePropertiesExtension { - public function isAlwaysRead(PropertyReflection $property, string $propertyName): bool; + public function isAlwaysRead(ExtendedPropertyReflection $property, string $propertyName): bool; - public function isAlwaysWritten(PropertyReflection $property, string $propertyName): bool; + public function isAlwaysWritten(ExtendedPropertyReflection $property, string $propertyName): bool; - public function isInitialized(PropertyReflection $property, string $propertyName): bool; + public function isInitialized(ExtendedPropertyReflection $property, string $propertyName): bool; } From 950a491485c46068074ca3f4f6dc5b970d41465a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 12:44:11 +0200 Subject: [PATCH 297/508] Revert "Dumb down parameter types in recently added stubs" This reverts commit 2d79c624d5b4e6a1659cf506328f8d697e4ac828. --- stubs/core.stub | 30 +++++++++---------- .../CallToFunctionParametersRuleTest.php | 8 ++--- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/stubs/core.stub b/stubs/core.stub index 853222642c..f2327d728f 100644 --- a/stubs/core.stub +++ b/stubs/core.stub @@ -222,9 +222,9 @@ function preg_match_all($pattern, $subject, &$matches = [], int $flags = 1, int function preg_match($pattern, $subject, &$matches = [], int $flags = 0, int $offset = 0) {} /** - * @param string|array $pattern - * @param callable(array):string $callback - * @param string|array $subject + * @param string|string[] $pattern + * @param callable(string[]):string $callback + * @param string|array $subject * @param int $count * @param-out 0|positive-int $count * @return ($subject is array ? list|null : string|null) @@ -232,9 +232,9 @@ function preg_match($pattern, $subject, &$matches = [], int $flags = 0, int $off function preg_replace_callback($pattern, $callback, $subject, int $limit = -1, &$count = null, int $flags = 0) {} /** - * @param string|array $pattern - * @param string|array $replacement - * @param string|array $subject + * @param string|string[] $pattern + * @param string|array $replacement + * @param string|array $subject * @param int $count * @param-out 0|positive-int $count * @return ($subject is array ? list|null : string|null) @@ -242,9 +242,9 @@ function preg_replace_callback($pattern, $callback, $subject, int $limit = -1, & function preg_replace($pattern, $replacement, $subject, int $limit = -1, &$count = null) {} /** - * @param string|array $pattern - * @param string|array $replacement - * @param string|array $subject + * @param string|string[] $pattern + * @param string|array $replacement + * @param string|array $subject * @param int $count * @param-out 0|positive-int $count * @return ($subject is array ? list : string|null) @@ -252,18 +252,18 @@ function preg_replace($pattern, $replacement, $subject, int $limit = -1, &$count function preg_filter($pattern, $replacement, $subject, int $limit = -1, &$count = null) {} /** - * @param array|string $search - * @param array|string $replace - * @param array|string $subject + * @param array|string $search + * @param array|string $replace + * @param array|string $subject * @param-out int $count * @return list|string */ function str_replace($search, $replace, $subject, ?int &$count = null) {} /** - * @param array|string $search - * @param array|string $replace - * @param array|string $subject + * @param array|string $search + * @param array|string $replace + * @param array|string $subject * @param-out int $count * @return list|string */ diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index 7bdc4d1e5f..eda1ad4ee3 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -654,19 +654,19 @@ public function testPregReplaceCallback(): void { $this->analyse([__DIR__ . '/data/preg_replace_callback.php'], [ [ - 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(string): string given.', + 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(string): string given.', 6, ], [ - 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(string): string given.', + 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(string): string given.', 13, ], [ - 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(array): void given.', + 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(array): void given.', 20, ], [ - 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(): void given.', + 'Parameter #2 $callback of function preg_replace_callback expects callable(array): string, Closure(): void given.', 25, ], ]); From 0972d76222f464841ebb5feecd9b0bfc7ccf31a2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 12:45:37 +0200 Subject: [PATCH 298/508] [BCB] additionalConfigFiles must be a list --- UPGRADING.md | 1 + conf/parametersSchema.neon | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index a22375dd11..1e33daa557 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -279,3 +279,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool` * Remove `FunctionReflection::isFinal()` * [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html) +* `additionalConfigFiles` config parameter must be a list diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 143187dd1d..1b399f95dd 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -170,7 +170,7 @@ parametersSchema: __validate: bool() # internal parameters only for DerivativeContainerFactory - additionalConfigFiles: arrayOf(string()) + additionalConfigFiles: listOf(string()) generateBaselineFile: schema(string(), nullable()) analysedPaths: listOf(string()) allConfigFiles: listOf(string()) From 933b48743ef363f3a7e8f39ec525e015d43b99ec Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 12:47:27 +0200 Subject: [PATCH 299/508] [BCB] Virtual node `PHPStan\Node\ClassMethod` is no longer a node --- src/Node/ClassMethod.php | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/Node/ClassMethod.php b/src/Node/ClassMethod.php index 3a30a402d6..2aec877cf5 100644 --- a/src/Node/ClassMethod.php +++ b/src/Node/ClassMethod.php @@ -2,32 +2,22 @@ namespace PHPStan\Node; -use PhpParser\Node\Stmt\ClassMethod as PhpParserClassMethod; - /** * @api */ -final class ClassMethod extends PhpParserClassMethod +final class ClassMethod { public function __construct( - \PhpParser\Node\Stmt\ClassMethod $node, + private \PhpParser\Node\Stmt\ClassMethod $node, private bool $isDeclaredInTrait, ) { - parent::__construct($node->name, [ - 'flags' => $node->flags, - 'byRef' => $node->byRef, - 'params' => $node->params, - 'returnType' => $node->returnType, - 'stmts' => $node->stmts, - 'attrGroups' => $node->attrGroups, - ], $node->attributes); } - public function getNode(): PhpParserClassMethod + public function getNode(): \PhpParser\Node\Stmt\ClassMethod { - return $this; + return $this->node; } public function isDeclaredInTrait(): bool From b41c19fdcda2ec68f5f9af7ceab452a49fb3b7cb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 12:48:58 +0200 Subject: [PATCH 300/508] Fix test --- .../Analyser/nsrt/preg_replace_callback_shapes-php72.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Analyser/nsrt/preg_replace_callback_shapes-php72.php b/tests/PHPStan/Analyser/nsrt/preg_replace_callback_shapes-php72.php index 2a3f437a81..f7230851e4 100644 --- a/tests/PHPStan/Analyser/nsrt/preg_replace_callback_shapes-php72.php +++ b/tests/PHPStan/Analyser/nsrt/preg_replace_callback_shapes-php72.php @@ -8,7 +8,7 @@ function (string $s): void { preg_replace_callback( $s, function ($matches) { - assertType('array', $matches); + assertType('array', $matches); return ''; }, $s From 84a3354543a798567fa5358a1065a9edc162061f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 17:11:03 +0200 Subject: [PATCH 301/508] No need to absolutize phpstan-symfony options with underscores --- src/DependencyInjection/NeonAdapter.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/DependencyInjection/NeonAdapter.php b/src/DependencyInjection/NeonAdapter.php index 4fb9f47156..0cd90db645 100644 --- a/src/DependencyInjection/NeonAdapter.php +++ b/src/DependencyInjection/NeonAdapter.php @@ -31,7 +31,7 @@ final class NeonAdapter implements Adapter { - public const CACHE_KEY = 'v29-excludes-analyse'; + public const CACHE_KEY = 'v30-no-underscore'; private const PREVENT_MERGING_SUFFIX = '!'; @@ -134,9 +134,7 @@ public function process(array $arr, string $fileKey, string $file): array '[parameters][memoryLimitFile]', '[parameters][benchmarkFile]', '[parameters][stubFiles][]', - '[parameters][symfony][console_application_loader]', '[parameters][symfony][consoleApplicationLoader]', - '[parameters][symfony][container_xml_path]', '[parameters][symfony][containerXmlPath]', '[parameters][doctrine][objectManagerLoader]', ], true) && is_string($val) && !str_contains($val, '%') && !str_starts_with($val, '*')) { From fc66c24113e9fe88c3155703224eb03768846fdd Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 17:34:50 +0200 Subject: [PATCH 302/508] TableErrorFormatter - always output identifiers --- .../ErrorFormatter/TableErrorFormatter.php | 28 +------------------ .../TableErrorFormatterTest.php | 7 +++-- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/src/Command/ErrorFormatter/TableErrorFormatter.php b/src/Command/ErrorFormatter/TableErrorFormatter.php index fb3d949c4e..7da56bdff1 100644 --- a/src/Command/ErrorFormatter/TableErrorFormatter.php +++ b/src/Command/ErrorFormatter/TableErrorFormatter.php @@ -9,12 +9,10 @@ use PHPStan\File\RelativePathHelper; use PHPStan\File\SimpleRelativePathHelper; use Symfony\Component\Console\Formatter\OutputFormatter; -use function array_key_exists; use function array_map; use function count; use function explode; use function getenv; -use function in_array; use function is_string; use function ltrim; use function sprintf; @@ -69,36 +67,12 @@ public function formatErrors( /** @var array $fileErrors */ $fileErrors = []; - $outputIdentifiers = $output->isVerbose(); - $outputIdentifiersInFile = []; foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { if (!isset($fileErrors[$fileSpecificError->getFile()])) { $fileErrors[$fileSpecificError->getFile()] = []; } $fileErrors[$fileSpecificError->getFile()][] = $fileSpecificError; - if ($outputIdentifiers) { - continue; - } - - $filePath = $fileSpecificError->getTraitFilePath() ?? $fileSpecificError->getFilePath(); - if (array_key_exists($filePath, $outputIdentifiersInFile)) { - continue; - } - - if ($fileSpecificError->getIdentifier() === null) { - continue; - } - - if (!in_array($fileSpecificError->getIdentifier(), [ - 'ignore.unmatchedIdentifier', - 'ignore.parseError', - 'ignore.unmatched', - ], true)) { - continue; - } - - $outputIdentifiersInFile[$filePath] = true; } foreach ($fileErrors as $file => $errors) { @@ -106,7 +80,7 @@ public function formatErrors( foreach ($errors as $error) { $message = $error->getMessage(); $filePath = $error->getTraitFilePath() ?? $error->getFilePath(); - if (($outputIdentifiers || array_key_exists($filePath, $outputIdentifiersInFile)) && $error->getIdentifier() !== null && $error->canBeIgnored()) { + if ($error->getIdentifier() !== null && $error->canBeIgnored()) { $message .= "\n"; $message .= '🪪 ' . $error->getIdentifier(); } diff --git a/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php index 85121ad337..40db6547a8 100644 --- a/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php @@ -190,12 +190,13 @@ public function dataFormatterOutputProvider(): iterable 'numGenericErrors' => 0, 'verbose' => false, 'extraEnvVars' => [], - 'expected' => ' ------ ------------ + 'expected' => ' ------ ---------------- Line foo.php - ------ ------------ + ------ ---------------- 5 Foobar\Buz + 🪪 foobar.buz 💡 a tip - ------ ------------ + ------ ---------------- [ERROR] Found 1 error From fff8f095988a66f298aa4037fe8e6ba98266063c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 6 Jan 2022 14:14:04 +0100 Subject: [PATCH 303/508] Do not apply heuristics of Collection<...>|Foo[] being resolved to Collection of Foo Closes https://github.com/phpstan/phpstan/issues/6228 --- phpstan-baseline.neon | 5 +++++ src/PhpDoc/TypeNodeResolver.php | 2 +- tests/PHPStan/Analyser/data/bug-4715.php | 4 ++-- tests/PHPStan/Analyser/nsrt/bug-6228.php | 16 ++++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-6228.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 23d822be89..b1010cff7b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -180,6 +180,11 @@ parameters: count: 1 path: src/PhpDoc/TypeNodeResolver.php + - + message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + count: 1 + path: src/PhpDoc/TypeNodeResolver.php + - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" count: 1 diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php index facec02644..ee7ef34786 100644 --- a/src/PhpDoc/TypeNodeResolver.php +++ b/src/PhpDoc/TypeNodeResolver.php @@ -568,7 +568,7 @@ private function resolveUnionTypeNode(UnionTypeNode $typeNode, NameScope $nameSc continue; } - if ($type instanceof ObjectType) { + if ($type instanceof ObjectType && !$type instanceof GenericObjectType) { $type = new IntersectionType([$type, new IterableType(new MixedType(), $arrayTypeType)]); } elseif ($type instanceof ArrayType) { $type = new ArrayType(new MixedType(), $arrayTypeType); diff --git a/tests/PHPStan/Analyser/data/bug-4715.php b/tests/PHPStan/Analyser/data/bug-4715.php index d51a97b3e4..508320fb8b 100644 --- a/tests/PHPStan/Analyser/data/bug-4715.php +++ b/tests/PHPStan/Analyser/data/bug-4715.php @@ -30,7 +30,7 @@ class Administration {} class Company { /** - * @var Collection|Administration[] + * @var Collection */ protected Collection $administrations; @@ -40,7 +40,7 @@ public function __construct() } /** - * @return Collection|Administration[] + * @return Collection */ public function getAdministrations() : Collection { diff --git a/tests/PHPStan/Analyser/nsrt/bug-6228.php b/tests/PHPStan/Analyser/nsrt/bug-6228.php new file mode 100644 index 0000000000..aee5112add --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-6228.php @@ -0,0 +1,16 @@ +|\DOMNode|\DOMNode[]|string|null $node + */ + public function __construct($node) + { + assertType('array|DOMNode|DOMNodeList|string|null', $node); + } +} From 1fb2cddebcde59c1b059eedc2d694146fc878951 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 30 Sep 2024 17:44:35 +0200 Subject: [PATCH 304/508] Declare more precise `getClass()` return types in extension interfaces --- src/Type/DynamicMethodReturnTypeExtension.php | 1 + src/Type/DynamicStaticMethodReturnTypeExtension.php | 1 + src/Type/MethodTypeSpecifyingExtension.php | 1 + src/Type/StaticMethodTypeSpecifyingExtension.php | 1 + 4 files changed, 4 insertions(+) diff --git a/src/Type/DynamicMethodReturnTypeExtension.php b/src/Type/DynamicMethodReturnTypeExtension.php index 6d03b43f10..e8af9137b0 100644 --- a/src/Type/DynamicMethodReturnTypeExtension.php +++ b/src/Type/DynamicMethodReturnTypeExtension.php @@ -26,6 +26,7 @@ interface DynamicMethodReturnTypeExtension { + /** @return class-string */ public function getClass(): string; public function isMethodSupported(MethodReflection $methodReflection): bool; diff --git a/src/Type/DynamicStaticMethodReturnTypeExtension.php b/src/Type/DynamicStaticMethodReturnTypeExtension.php index 87b74c9af4..e74f69460f 100644 --- a/src/Type/DynamicStaticMethodReturnTypeExtension.php +++ b/src/Type/DynamicStaticMethodReturnTypeExtension.php @@ -26,6 +26,7 @@ interface DynamicStaticMethodReturnTypeExtension { + /** @return class-string */ public function getClass(): string; public function isStaticMethodSupported(MethodReflection $methodReflection): bool; diff --git a/src/Type/MethodTypeSpecifyingExtension.php b/src/Type/MethodTypeSpecifyingExtension.php index 9e56ea330f..f0f11de2f4 100644 --- a/src/Type/MethodTypeSpecifyingExtension.php +++ b/src/Type/MethodTypeSpecifyingExtension.php @@ -28,6 +28,7 @@ interface MethodTypeSpecifyingExtension { + /** @return class-string */ public function getClass(): string; public function isMethodSupported(MethodReflection $methodReflection, MethodCall $node, TypeSpecifierContext $context): bool; diff --git a/src/Type/StaticMethodTypeSpecifyingExtension.php b/src/Type/StaticMethodTypeSpecifyingExtension.php index dbb6a49ffa..7421f3b896 100644 --- a/src/Type/StaticMethodTypeSpecifyingExtension.php +++ b/src/Type/StaticMethodTypeSpecifyingExtension.php @@ -28,6 +28,7 @@ interface StaticMethodTypeSpecifyingExtension { + /** @return class-string */ public function getClass(): string; public function isStaticMethodSupported(MethodReflection $staticMethodReflection, StaticCall $node, TypeSpecifierContext $context): bool; From 38cb5a315e5573231d8695df343c8ee87a8c3b2e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 28 Mar 2022 21:29:10 +0200 Subject: [PATCH 305/508] Remove `__set_state()` on objects that should not be serialized in cache --- UPGRADING.md | 1 + src/Analyser/NameScope.php | 17 --------------- .../Native/NativeParameterReflection.php | 15 ------------- .../NativeParameterWithPhpDocsReflection.php | 20 ------------------ src/Reflection/PassedByReference.php | 8 ------- src/TrinaryLogic.php | 8 ------- src/Type/Accessory/AccessoryArrayListType.php | 5 ----- .../Accessory/AccessoryLiteralStringType.php | 5 ----- .../AccessoryLowercaseStringType.php | 5 ----- .../Accessory/AccessoryNonEmptyStringType.php | 5 ----- .../Accessory/AccessoryNonFalsyStringType.php | 5 ----- .../Accessory/AccessoryNumericStringType.php | 5 ----- src/Type/Accessory/HasMethodType.php | 5 ----- src/Type/Accessory/HasOffsetType.php | 5 ----- src/Type/Accessory/HasOffsetValueType.php | 5 ----- src/Type/Accessory/HasPropertyType.php | 5 ----- src/Type/Accessory/NonEmptyArrayType.php | 5 ----- src/Type/Accessory/OversizedArrayType.php | 5 ----- src/Type/ArrayType.php | 11 ---------- src/Type/BenevolentUnionType.php | 8 ------- src/Type/BooleanType.php | 8 ------- src/Type/CallableType.php | 16 -------------- src/Type/ClassStringType.php | 8 ------- src/Type/ClosureType.php | 21 ------------------- src/Type/ConditionalType.php | 14 ------------- src/Type/ConditionalTypeForParameter.php | 14 ------------- src/Type/Constant/ConstantArrayType.php | 8 ------- src/Type/Constant/ConstantBooleanType.php | 8 ------- src/Type/Constant/ConstantFloatType.php | 8 ------- src/Type/Constant/ConstantIntegerType.php | 8 ------- src/Type/Constant/ConstantStringType.php | 8 ------- src/Type/Enum/EnumCaseObjectType.php | 8 ------- src/Type/ErrorType.php | 8 ------- src/Type/FloatType.php | 8 ------- src/Type/Generic/GenericClassStringType.php | 8 ------- src/Type/Generic/GenericObjectType.php | 14 ------------- .../Generic/TemplateTypeArgumentStrategy.php | 8 ------- src/Type/Generic/TemplateTypeMap.php | 11 ---------- .../Generic/TemplateTypeParameterStrategy.php | 8 ------- src/Type/Generic/TemplateTypeScope.php | 11 ---------- src/Type/Generic/TemplateTypeTrait.php | 14 ------------- src/Type/Generic/TemplateTypeVariance.php | 8 ------- src/Type/Helper/GetTemplateTypeType.php | 12 ----------- src/Type/IntegerRangeType.php | 8 ------- src/Type/IntegerType.php | 8 ------- src/Type/IntersectionType.php | 8 ------- src/Type/IterableType.php | 8 ------- src/Type/KeyOfType.php | 10 --------- src/Type/MixedType.php | 11 ---------- src/Type/NeverType.php | 8 ------- src/Type/NewObjectType.php | 10 --------- src/Type/NonexistentParentClassType.php | 8 ------- src/Type/NullType.php | 8 ------- src/Type/ObjectShapeType.php | 8 ------- src/Type/ObjectType.php | 11 ---------- src/Type/ObjectWithoutClassType.php | 8 ------- src/Type/OffsetAccessType.php | 11 ---------- src/Type/ResourceType.php | 8 ------- src/Type/StaticType.php | 14 ------------- src/Type/StrictMixedType.php | 8 ------- src/Type/StringType.php | 8 ------- src/Type/ThisType.php | 14 ------------- src/Type/Type.php | 5 ----- src/Type/UnionType.php | 8 ------- src/Type/ValueOfType.php | 10 --------- src/Type/VoidType.php | 8 ------- .../data/class-implements-out-of-phpstan.php | 6 ------ 67 files changed, 1 insertion(+), 600 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 1e33daa557..c7756d49ca 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -280,3 +280,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `FunctionReflection::isFinal()` * [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html) * `additionalConfigFiles` config parameter must be a list +* Remove `__set_state()` on objects that should not be serialized in cache diff --git a/src/Analyser/NameScope.php b/src/Analyser/NameScope.php index f7f54f0a6a..1426b804a1 100644 --- a/src/Analyser/NameScope.php +++ b/src/Analyser/NameScope.php @@ -222,21 +222,4 @@ public function hasTypeAlias(string $alias): bool return array_key_exists($alias, $this->typeAliasesMap); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return new self( - $properties['namespace'], - $properties['uses'], - $properties['className'], - $properties['functionName'], - $properties['templateTypeMap'], - $properties['typeAliasesMap'], - $properties['bypassTypeAliases'], - $properties['constUses'], - ); - } - } diff --git a/src/Reflection/Native/NativeParameterReflection.php b/src/Reflection/Native/NativeParameterReflection.php index bdfce9f04c..e812086830 100644 --- a/src/Reflection/Native/NativeParameterReflection.php +++ b/src/Reflection/Native/NativeParameterReflection.php @@ -63,19 +63,4 @@ public function union(self $other): self ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return new self( - $properties['name'], - $properties['optional'], - $properties['type'], - $properties['passedByReference'], - $properties['variadic'], - $properties['defaultValue'], - ); - } - } diff --git a/src/Reflection/Native/NativeParameterWithPhpDocsReflection.php b/src/Reflection/Native/NativeParameterWithPhpDocsReflection.php index 3e303b82b9..64aa593067 100644 --- a/src/Reflection/Native/NativeParameterWithPhpDocsReflection.php +++ b/src/Reflection/Native/NativeParameterWithPhpDocsReflection.php @@ -81,24 +81,4 @@ public function getClosureThisType(): ?Type return $this->closureThisType; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return new self( - $properties['name'], - $properties['optional'], - $properties['type'], - $properties['phpDocType'], - $properties['nativeType'], - $properties['passedByReference'], - $properties['variadic'], - $properties['defaultValue'], - $properties['outType'], - $properties['immediatelyInvokedCallable'], - $properties['closureThisType'], - ); - } - } diff --git a/src/Reflection/PassedByReference.php b/src/Reflection/PassedByReference.php index 9a5c95f806..804d049b43 100644 --- a/src/Reflection/PassedByReference.php +++ b/src/Reflection/PassedByReference.php @@ -76,12 +76,4 @@ public function combine(self $other): self return $this; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return new self($properties['value']); - } - } diff --git a/src/TrinaryLogic.php b/src/TrinaryLogic.php index 569d5d2ec1..a587099844 100644 --- a/src/TrinaryLogic.php +++ b/src/TrinaryLogic.php @@ -251,12 +251,4 @@ public function describe(): string return $labels[$this->value]; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return self::create($properties['value']); - } - } diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index 930473cf03..d41d3c510f 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -472,11 +472,6 @@ public function traverseSimultaneously(Type $right, callable $cb): Type return $this; } - public static function __set_state(array $properties): Type - { - return new self(); - } - public function exponentiate(Type $exponent): Type { return new ErrorType(); diff --git a/src/Type/Accessory/AccessoryLiteralStringType.php b/src/Type/Accessory/AccessoryLiteralStringType.php index 1a3a37858b..5f8705cfc5 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.php @@ -352,11 +352,6 @@ public function generalize(GeneralizePrecision $precision): Type return new StringType(); } - public static function __set_state(array $properties): Type - { - return new self(); - } - public function exponentiate(Type $exponent): Type { return new BenevolentUnionType([ diff --git a/src/Type/Accessory/AccessoryLowercaseStringType.php b/src/Type/Accessory/AccessoryLowercaseStringType.php index c32ef8c506..48bb4b3179 100644 --- a/src/Type/Accessory/AccessoryLowercaseStringType.php +++ b/src/Type/Accessory/AccessoryLowercaseStringType.php @@ -348,11 +348,6 @@ public function generalize(GeneralizePrecision $precision): Type return new StringType(); } - public static function __set_state(array $properties): Type - { - return new self(); - } - public function exponentiate(Type $exponent): Type { return new BenevolentUnionType([ diff --git a/src/Type/Accessory/AccessoryNonEmptyStringType.php b/src/Type/Accessory/AccessoryNonEmptyStringType.php index cc8e90f236..9815225062 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -344,11 +344,6 @@ public function generalize(GeneralizePrecision $precision): Type return new StringType(); } - public static function __set_state(array $properties): Type - { - return new self(); - } - public function tryRemove(Type $typeToRemove): ?Type { if ($typeToRemove instanceof ConstantStringType && $typeToRemove->getValue() === '0') { diff --git a/src/Type/Accessory/AccessoryNonFalsyStringType.php b/src/Type/Accessory/AccessoryNonFalsyStringType.php index 82460ea1a1..6dca5f0514 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.php @@ -344,11 +344,6 @@ public function generalize(GeneralizePrecision $precision): Type return new StringType(); } - public static function __set_state(array $properties): Type - { - return new self(); - } - public function exponentiate(Type $exponent): Type { return new BenevolentUnionType([ diff --git a/src/Type/Accessory/AccessoryNumericStringType.php b/src/Type/Accessory/AccessoryNumericStringType.php index a7c56c56ed..ae15b4623e 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.php @@ -346,11 +346,6 @@ public function generalize(GeneralizePrecision $precision): Type return new StringType(); } - public static function __set_state(array $properties): Type - { - return new self(); - } - public function tryRemove(Type $typeToRemove): ?Type { if ($typeToRemove instanceof ConstantStringType && $typeToRemove->getValue() === '0') { diff --git a/src/Type/Accessory/HasMethodType.php b/src/Type/Accessory/HasMethodType.php index 98503a13a8..a28497912d 100644 --- a/src/Type/Accessory/HasMethodType.php +++ b/src/Type/Accessory/HasMethodType.php @@ -200,11 +200,6 @@ public function getFiniteTypes(): array return []; } - public static function __set_state(array $properties): Type - { - return new self($properties['methodName']); - } - public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation diff --git a/src/Type/Accessory/HasOffsetType.php b/src/Type/Accessory/HasOffsetType.php index 969a99df7a..635f7d37ee 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -402,11 +402,6 @@ public function getFiniteTypes(): array return []; } - public static function __set_state(array $properties): Type - { - return new self($properties['offsetType']); - } - public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation diff --git a/src/Type/Accessory/HasOffsetValueType.php b/src/Type/Accessory/HasOffsetValueType.php index 0481c3939b..ec3a9908d1 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -458,11 +458,6 @@ public function getFiniteTypes(): array return []; } - public static function __set_state(array $properties): Type - { - return new self($properties['offsetType'], $properties['valueType']); - } - public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation diff --git a/src/Type/Accessory/HasPropertyType.php b/src/Type/Accessory/HasPropertyType.php index f508447135..fdbc9b0bcc 100644 --- a/src/Type/Accessory/HasPropertyType.php +++ b/src/Type/Accessory/HasPropertyType.php @@ -162,11 +162,6 @@ public function getFiniteTypes(): array return []; } - public static function __set_state(array $properties): Type - { - return new self($properties['propertyName']); - } - public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation diff --git a/src/Type/Accessory/NonEmptyArrayType.php b/src/Type/Accessory/NonEmptyArrayType.php index fbe23d4534..50ccdb308e 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -454,11 +454,6 @@ public function getFiniteTypes(): array return []; } - public static function __set_state(array $properties): Type - { - return new self(); - } - public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode('non-empty-array'); diff --git a/src/Type/Accessory/OversizedArrayType.php b/src/Type/Accessory/OversizedArrayType.php index 365431f4ac..113d0eb689 100644 --- a/src/Type/Accessory/OversizedArrayType.php +++ b/src/Type/Accessory/OversizedArrayType.php @@ -450,11 +450,6 @@ public function getFiniteTypes(): array return []; } - public static function __set_state(array $properties): Type - { - return new self(); - } - public function toPhpDocNode(): TypeNode { return new IdentifierTypeNode(''); // no PHPDoc representation diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 4a9a03dd6b..93d0094378 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -562,15 +562,4 @@ public function getFiniteTypes(): array return []; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['keyType'], - $properties['itemType'], - ); - } - } diff --git a/src/Type/BenevolentUnionType.php b/src/Type/BenevolentUnionType.php index dc1245ad45..c27a3d6cd0 100644 --- a/src/Type/BenevolentUnionType.php +++ b/src/Type/BenevolentUnionType.php @@ -173,12 +173,4 @@ public function traverseSimultaneously(Type $right, callable $cb): Type return $this; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['types']); - } - } diff --git a/src/Type/BooleanType.php b/src/Type/BooleanType.php index 72be662c95..df059481e6 100644 --- a/src/Type/BooleanType.php +++ b/src/Type/BooleanType.php @@ -163,12 +163,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('bool'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index de594f9683..0f733ca60a 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -680,20 +680,4 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - (bool) $properties['isCommonCallable'] ? null : $properties['parameters'], - (bool) $properties['isCommonCallable'] ? null : $properties['returnType'], - $properties['variadic'], - $properties['templateTypeMap'], - $properties['resolvedTemplateTypeMap'], - $properties['templateTags'], - $properties['isPure'], - ); - } - } diff --git a/src/Type/ClassStringType.php b/src/Type/ClassStringType.php index ed622e5817..4a74ec015a 100644 --- a/src/Type/ClassStringType.php +++ b/src/Type/ClassStringType.php @@ -94,12 +94,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('class-string'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index e09269ad83..90bef92255 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -799,25 +799,4 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['parameters'], - $properties['returnType'], - $properties['variadic'], - $properties['templateTypeMap'], - $properties['resolvedTemplateTypeMap'], - $properties['callSiteVarianceMap'], - $properties['templateTags'], - $properties['throwPoints'], - $properties['impurePoints'], - $properties['invalidateExpressions'], - $properties['usedVariables'], - $properties['acceptsNamedArguments'], - ); - } - } diff --git a/src/Type/ConditionalType.php b/src/Type/ConditionalType.php index aa5d8af0a6..96a1776e3f 100644 --- a/src/Type/ConditionalType.php +++ b/src/Type/ConditionalType.php @@ -188,20 +188,6 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['subject'], - $properties['target'], - $properties['if'], - $properties['else'], - $properties['negated'], - ); - } - private function getNormalizedIf(): Type { return $this->normalizedIf ??= TypeTraverser::map( diff --git a/src/Type/ConditionalTypeForParameter.php b/src/Type/ConditionalTypeForParameter.php index 57c2fe5d8d..a7c8095e69 100644 --- a/src/Type/ConditionalTypeForParameter.php +++ b/src/Type/ConditionalTypeForParameter.php @@ -175,18 +175,4 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['parameterName'], - $properties['target'], - $properties['if'], - $properties['else'], - $properties['negated'], - ); - } - } diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index a257437061..0d8d254eff 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -1712,12 +1712,4 @@ public function getFiniteTypes(): array return $finiteTypes; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['keyTypes'], $properties['valueTypes'], $properties['nextAutoIndexes'] ?? $properties['nextAutoIndex'], $properties['optionalKeys'] ?? [], $properties['isList'] ?? TrinaryLogic::createNo()); - } - } diff --git a/src/Type/Constant/ConstantBooleanType.php b/src/Type/Constant/ConstantBooleanType.php index cbebe5b48b..a01321c138 100644 --- a/src/Type/Constant/ConstantBooleanType.php +++ b/src/Type/Constant/ConstantBooleanType.php @@ -127,14 +127,6 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode($this->value ? 'true' : 'false'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['value']); - } - public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType { if ($type->isObject()->yes()) { diff --git a/src/Type/Constant/ConstantFloatType.php b/src/Type/Constant/ConstantFloatType.php index 3aeb1e2e18..0ac763af76 100644 --- a/src/Type/Constant/ConstantFloatType.php +++ b/src/Type/Constant/ConstantFloatType.php @@ -100,12 +100,4 @@ public function toPhpDocNode(): TypeNode return new ConstTypeNode(new ConstExprFloatNode($this->castFloatToString($this->value))); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['value']); - } - } diff --git a/src/Type/Constant/ConstantIntegerType.php b/src/Type/Constant/ConstantIntegerType.php index 9226acacc2..779dc83169 100644 --- a/src/Type/Constant/ConstantIntegerType.php +++ b/src/Type/Constant/ConstantIntegerType.php @@ -105,12 +105,4 @@ public function toPhpDocNode(): TypeNode return new ConstTypeNode(new ConstExprIntegerNode((string) $this->value)); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['value']); - } - } diff --git a/src/Type/Constant/ConstantStringType.php b/src/Type/Constant/ConstantStringType.php index a5b39335cd..a6fda677b7 100644 --- a/src/Type/Constant/ConstantStringType.php +++ b/src/Type/Constant/ConstantStringType.php @@ -553,12 +553,4 @@ public function toPhpDocNode(): TypeNode return new ConstTypeNode(new ConstExprStringNode($this->value, ConstExprStringNode::SINGLE_QUOTED)); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['value'], $properties['isClassString'] ?? false); - } - } diff --git a/src/Type/Enum/EnumCaseObjectType.php b/src/Type/Enum/EnumCaseObjectType.php index e0bc8c3340..5bb5d0b5b7 100644 --- a/src/Type/Enum/EnumCaseObjectType.php +++ b/src/Type/Enum/EnumCaseObjectType.php @@ -205,12 +205,4 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['className'], $properties['enumCaseName'], null); - } - } diff --git a/src/Type/ErrorType.php b/src/Type/ErrorType.php index 345465b306..751271aef3 100644 --- a/src/Type/ErrorType.php +++ b/src/Type/ErrorType.php @@ -41,12 +41,4 @@ public function equals(Type $type): bool return $type instanceof self; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index 890e13994a..21d0a96904 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -289,12 +289,4 @@ public function getFiniteTypes(): array return []; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/Generic/GenericClassStringType.php b/src/Type/Generic/GenericClassStringType.php index d9b06d68bf..f7ecec9d86 100644 --- a/src/Type/Generic/GenericClassStringType.php +++ b/src/Type/Generic/GenericClassStringType.php @@ -195,14 +195,6 @@ public function equals(Type $type): bool return true; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['type']); - } - public function toPhpDocNode(): TypeNode { return new GenericTypeNode( diff --git a/src/Type/Generic/GenericObjectType.php b/src/Type/Generic/GenericObjectType.php index 2747320c75..f13d52d4e3 100644 --- a/src/Type/Generic/GenericObjectType.php +++ b/src/Type/Generic/GenericObjectType.php @@ -398,18 +398,4 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['className'], - $properties['types'], - $properties['subtractedType'] ?? null, - null, - $properties['variances'] ?? [], - ); - } - } diff --git a/src/Type/Generic/TemplateTypeArgumentStrategy.php b/src/Type/Generic/TemplateTypeArgumentStrategy.php index deeb9b6ddd..8c98baaacc 100644 --- a/src/Type/Generic/TemplateTypeArgumentStrategy.php +++ b/src/Type/Generic/TemplateTypeArgumentStrategy.php @@ -43,12 +43,4 @@ public function isArgument(): bool return true; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return new self(); - } - } diff --git a/src/Type/Generic/TemplateTypeMap.php b/src/Type/Generic/TemplateTypeMap.php index e631819818..f1c598c7aa 100644 --- a/src/Type/Generic/TemplateTypeMap.php +++ b/src/Type/Generic/TemplateTypeMap.php @@ -213,15 +213,4 @@ public function resolveToBounds(): self return $this->resolvedToBounds = $this->map(static fn (string $name, Type $type): Type => TemplateTypeHelper::resolveToBounds($type)); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return new self( - $properties['types'], - $properties['lowerBoundTypes'] ?? [], - ); - } - } diff --git a/src/Type/Generic/TemplateTypeParameterStrategy.php b/src/Type/Generic/TemplateTypeParameterStrategy.php index 1ec43f153a..949f3bfa52 100644 --- a/src/Type/Generic/TemplateTypeParameterStrategy.php +++ b/src/Type/Generic/TemplateTypeParameterStrategy.php @@ -26,12 +26,4 @@ public function isArgument(): bool return false; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return new self(); - } - } diff --git a/src/Type/Generic/TemplateTypeScope.php b/src/Type/Generic/TemplateTypeScope.php index 8cc0e54e5e..f362ecadd4 100644 --- a/src/Type/Generic/TemplateTypeScope.php +++ b/src/Type/Generic/TemplateTypeScope.php @@ -68,15 +68,4 @@ public function describe(): string return sprintf('method %s::%s()', $this->className, $this->functionName); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self - { - return new self( - $properties['className'], - $properties['functionName'], - ); - } - } diff --git a/src/Type/Generic/TemplateTypeTrait.php b/src/Type/Generic/TemplateTypeTrait.php index 13440a54a7..e1a170a57d 100644 --- a/src/Type/Generic/TemplateTypeTrait.php +++ b/src/Type/Generic/TemplateTypeTrait.php @@ -351,18 +351,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode($this->name); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['scope'], - $properties['strategy'], - $properties['variance'], - $properties['name'], - $properties['bound'], - ); - } - } diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index ff7d609881..24f8fe2927 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -242,12 +242,4 @@ public function toPhpDocNodeVariance(): string throw new ShouldNotHappenException(); } - /** - * @param array{value: int} $properties - */ - public static function __set_state(array $properties): self - { - return new self($properties['value']); - } - } diff --git a/src/Type/Helper/GetTemplateTypeType.php b/src/Type/Helper/GetTemplateTypeType.php index e8af52e322..c45a7be5fa 100644 --- a/src/Type/Helper/GetTemplateTypeType.php +++ b/src/Type/Helper/GetTemplateTypeType.php @@ -103,16 +103,4 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['type'], - $properties['ancestorClassName'], - $properties['templateTypeName'], - ); - } - } diff --git a/src/Type/IntegerRangeType.php b/src/Type/IntegerRangeType.php index 9c9f841703..e957bee8ea 100644 --- a/src/Type/IntegerRangeType.php +++ b/src/Type/IntegerRangeType.php @@ -704,12 +704,4 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType return parent::looseCompare($type, $phpVersion); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['min'], $properties['max']); - } - } diff --git a/src/Type/IntegerType.php b/src/Type/IntegerType.php index f91a646c9d..cd19237733 100644 --- a/src/Type/IntegerType.php +++ b/src/Type/IntegerType.php @@ -49,14 +49,6 @@ public function getConstantStrings(): array return []; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - public function toNumber(): Type { return $this; diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index 27e7e623c1..3c193d15f5 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -1086,14 +1086,6 @@ public function getFiniteTypes(): array return $result; } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['types']); - } - /** * @param callable(Type $type): TrinaryLogic $getResult */ diff --git a/src/Type/IterableType.php b/src/Type/IterableType.php index fe0af6a812..b1dcbec2fe 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -517,12 +517,4 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['keyType'], $properties['itemType']); - } - } diff --git a/src/Type/KeyOfType.php b/src/Type/KeyOfType.php index 32eab8b019..10a4cb2ea5 100644 --- a/src/Type/KeyOfType.php +++ b/src/Type/KeyOfType.php @@ -91,14 +91,4 @@ public function toPhpDocNode(): TypeNode return new GenericTypeNode(new IdentifierTypeNode('key-of'), [$this->type->toPhpDocNode()]); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['type'], - ); - } - } diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index def0bbd74a..08f7f0f205 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -1023,15 +1023,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('mixed'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['isExplicitMixed'], - $properties['subtractedType'] ?? null, - ); - } - } diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index bb2e9448f2..66193ded71 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -531,12 +531,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('never'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['isExplicit']); - } - } diff --git a/src/Type/NewObjectType.php b/src/Type/NewObjectType.php index 57b932a398..93d14c6936 100644 --- a/src/Type/NewObjectType.php +++ b/src/Type/NewObjectType.php @@ -91,14 +91,4 @@ public function toPhpDocNode(): TypeNode return new GenericTypeNode(new IdentifierTypeNode('new'), [$this->type->toPhpDocNode()]); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['type'], - ); - } - } diff --git a/src/Type/NonexistentParentClassType.php b/src/Type/NonexistentParentClassType.php index 3caabeee83..29ae4f752c 100644 --- a/src/Type/NonexistentParentClassType.php +++ b/src/Type/NonexistentParentClassType.php @@ -192,12 +192,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('parent'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/NullType.php b/src/Type/NullType.php index c90a5b29e6..753dccc5d8 100644 --- a/src/Type/NullType.php +++ b/src/Type/NullType.php @@ -399,12 +399,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('null'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/ObjectShapeType.php b/src/Type/ObjectShapeType.php index 43b68b8dac..6878401ef0 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -527,12 +527,4 @@ public function toPhpDocNode(): TypeNode return new ObjectShapeNode($items); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['properties'], $properties['optionalProperties']); - } - } diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index e3711b8d73..2026e447f0 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1320,17 +1320,6 @@ public function isCloneable(): TrinaryLogic return TrinaryLogic::createYes(); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['className'], - $properties['subtractedType'] ?? null, - ); - } - public function isInstanceOf(string $className): TrinaryLogic { $classReflection = $this->getClassReflection(); diff --git a/src/Type/ObjectWithoutClassType.php b/src/Type/ObjectWithoutClassType.php index 1144acd2f8..5b388ba712 100644 --- a/src/Type/ObjectWithoutClassType.php +++ b/src/Type/ObjectWithoutClassType.php @@ -230,12 +230,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('object'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['subtractedType'] ?? null); - } - } diff --git a/src/Type/OffsetAccessType.php b/src/Type/OffsetAccessType.php index 430d38332c..5e4ef1aec3 100644 --- a/src/Type/OffsetAccessType.php +++ b/src/Type/OffsetAccessType.php @@ -114,15 +114,4 @@ public function toPhpDocNode(): TypeNode ); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['type'], - $properties['offset'], - ); - } - } diff --git a/src/Type/ResourceType.php b/src/Type/ResourceType.php index 4327f30bde..f62023f2c6 100644 --- a/src/Type/ResourceType.php +++ b/src/Type/ResourceType.php @@ -121,12 +121,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('resource'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index 5ef9ebc6c5..ab8fc9d1a0 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -10,7 +10,6 @@ use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; -use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\Reflection\Type\CallbackUnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -737,17 +736,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('static'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); - if ($reflectionProvider->hasClass($properties['baseClass'])) { - return new self($reflectionProvider->getClass($properties['baseClass']), $properties['subtractedType'] ?? null); - } - - return new ErrorType(); - } - } diff --git a/src/Type/StrictMixedType.php b/src/Type/StrictMixedType.php index 944d0f2756..c5d76697c6 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -440,12 +440,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('mixed'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/StringType.php b/src/Type/StringType.php index b022f2b397..55fb28c2c1 100644 --- a/src/Type/StringType.php +++ b/src/Type/StringType.php @@ -306,12 +306,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('string'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/src/Type/ThisType.php b/src/Type/ThisType.php index 963f98c191..954a7fffdf 100644 --- a/src/Type/ThisType.php +++ b/src/Type/ThisType.php @@ -5,7 +5,6 @@ use PHPStan\PhpDocParser\Ast\Type\ThisTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\TrinaryLogic; use function sprintf; @@ -87,17 +86,4 @@ public function toPhpDocNode(): TypeNode return new ThisTypeNode(); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); - if ($reflectionProvider->hasClass($properties['baseClass'])) { - return new self($reflectionProvider->getClass($properties['baseClass']), $properties['subtractedType'] ?? null); - } - - return new ErrorType(); - } - } diff --git a/src/Type/Type.php b/src/Type/Type.php index 2d152cd73a..0f89e01a93 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -349,9 +349,4 @@ public function tryRemove(Type $typeToRemove): ?Type; public function generalize(GeneralizePrecision $precision): Type; - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): self; - } diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 05d3f3ec92..454f511c75 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -1073,14 +1073,6 @@ public function getFiniteTypes(): array return array_values($uniquedTypes); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self($properties['types'], $properties['normalized']); - } - /** * @param callable(Type $type): TrinaryLogic $getResult */ diff --git a/src/Type/ValueOfType.php b/src/Type/ValueOfType.php index 9df5411c47..d02b7d11f7 100644 --- a/src/Type/ValueOfType.php +++ b/src/Type/ValueOfType.php @@ -100,14 +100,4 @@ public function toPhpDocNode(): TypeNode return new GenericTypeNode(new IdentifierTypeNode('value-of'), [$this->type->toPhpDocNode()]); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self( - $properties['type'], - ); - } - } diff --git a/src/Type/VoidType.php b/src/Type/VoidType.php index 2bea11cb04..16bf203351 100644 --- a/src/Type/VoidType.php +++ b/src/Type/VoidType.php @@ -267,12 +267,4 @@ public function toPhpDocNode(): TypeNode return new IdentifierTypeNode('void'); } - /** - * @param mixed[] $properties - */ - public static function __set_state(array $properties): Type - { - return new self(); - } - } diff --git a/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php b/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php index c5211fd650..ca38d7ec38 100644 --- a/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php +++ b/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php @@ -328,12 +328,6 @@ public function tryRemove(Type $typeToRemove): ?Type // TODO: Implement tryRemove() method. } - public static function __set_state(array $properties): \PHPStan\Type\Type - { - // TODO: Implement __set_state() method. - } - - } abstract class Dolor implements ReflectionProvider From fd35d2faf35e4c09d7394a36b40f60d3bb0c1379 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 18:01:08 +0200 Subject: [PATCH 306/508] Fix build --- .../AdapterReflectionEnumCaseDynamicReturnTypeExtension.php | 3 +++ .../NativeReflectionEnumReturnDynamicReturnTypeExtension.php | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php index 5ab5e725b9..d242403fb6 100644 --- a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php +++ b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php @@ -21,6 +21,9 @@ final class AdapterReflectionEnumCaseDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension { + /** + * @param class-string $class + */ public function __construct(private PhpVersion $phpVersion, private string $class) { } diff --git a/src/Reflection/PHPStan/NativeReflectionEnumReturnDynamicReturnTypeExtension.php b/src/Reflection/PHPStan/NativeReflectionEnumReturnDynamicReturnTypeExtension.php index 683a341f2e..fc9b44f79a 100644 --- a/src/Reflection/PHPStan/NativeReflectionEnumReturnDynamicReturnTypeExtension.php +++ b/src/Reflection/PHPStan/NativeReflectionEnumReturnDynamicReturnTypeExtension.php @@ -14,6 +14,9 @@ final class NativeReflectionEnumReturnDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension { + /** + * @param class-string $className + */ public function __construct(private PhpVersion $phpVersion, private string $className, private string $methodName) { } From 2b0963bf9896c6d5e0b65ebe7b16d32cca3f9a49 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 18:04:37 +0200 Subject: [PATCH 307/508] [BCB] `TypehintHelper::decideTypeFromReflection()` parameter `$selfClass` no longer accepts string --- UPGRADING.md | 1 + src/Reflection/Php/PhpMethodReflection.php | 2 +- src/Reflection/Php/PhpParameterReflection.php | 7 ++++--- src/Rules/Traits/ConflictingTraitConstantsRule.php | 10 +++++++--- src/Type/TypehintHelper.php | 12 +----------- .../Traits/ConflictingTraitConstantsRuleTest.php | 2 +- 6 files changed, 15 insertions(+), 19 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index c7756d49ca..4778a9efd9 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -281,3 +281,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html) * `additionalConfigFiles` config parameter must be a list * Remove `__set_state()` on objects that should not be serialized in cache +* Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts string diff --git a/src/Reflection/Php/PhpMethodReflection.php b/src/Reflection/Php/PhpMethodReflection.php index ea1bc0c6c0..d71fce1a4c 100644 --- a/src/Reflection/Php/PhpMethodReflection.php +++ b/src/Reflection/Php/PhpMethodReflection.php @@ -232,7 +232,7 @@ private function getParameters(): array $this->initializerExprTypeResolver, $reflection, $this->phpDocParameterTypes[$reflection->getName()] ?? null, - $this->getDeclaringClass()->getName(), + $this->getDeclaringClass(), $this->phpDocParameterOutTypes[$reflection->getName()] ?? null, $this->immediatelyInvokedCallableParameters[$reflection->getName()] ?? TrinaryLogic::createMaybe(), $this->phpDocClosureThisTypeParameters[$reflection->getName()] ?? null, diff --git a/src/Reflection/Php/PhpParameterReflection.php b/src/Reflection/Php/PhpParameterReflection.php index 26cb1be007..548d9bde47 100644 --- a/src/Reflection/Php/PhpParameterReflection.php +++ b/src/Reflection/Php/PhpParameterReflection.php @@ -3,6 +3,7 @@ namespace PHPStan\Reflection\Php; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter; +use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\InitializerExprContext; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\ParameterReflectionWithPhpDocs; @@ -24,7 +25,7 @@ public function __construct( private InitializerExprTypeResolver $initializerExprTypeResolver, private ReflectionParameter $reflection, private ?Type $phpDocType, - private ?string $declaringClassName, + private ?ClassReflection $declaringClass, private ?Type $outType, private TrinaryLogic $immediatelyInvokedCallable, private ?Type $closureThisType, @@ -62,7 +63,7 @@ public function getType(): Type $this->type = TypehintHelper::decideTypeFromReflection( $this->reflection->getType(), $phpDocType, - $this->declaringClassName, + $this->declaringClass, $this->isVariadic(), ); } @@ -97,7 +98,7 @@ public function getNativeType(): Type $this->nativeType = TypehintHelper::decideTypeFromReflection( $this->reflection->getType(), null, - $this->declaringClassName, + $this->declaringClass, $this->isVariadic(), ); } diff --git a/src/Rules/Traits/ConflictingTraitConstantsRule.php b/src/Rules/Traits/ConflictingTraitConstantsRule.php index 4dd23f32bd..4e38e44bcb 100644 --- a/src/Rules/Traits/ConflictingTraitConstantsRule.php +++ b/src/Rules/Traits/ConflictingTraitConstantsRule.php @@ -8,6 +8,7 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\InitializerExprContext; use PHPStan\Reflection\InitializerExprTypeResolver; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -22,7 +23,10 @@ final class ConflictingTraitConstantsRule implements Rule { - public function __construct(private InitializerExprTypeResolver $initializerExprTypeResolver) + public function __construct( + private InitializerExprTypeResolver $initializerExprTypeResolver, + private ReflectionProvider $reflectionProvider, + ) { } @@ -186,7 +190,7 @@ private function processSingleConstant(ClassReflection $classReflection, Reflect ->build(); } } elseif ($constantNativeType === null) { - $traitNativeTypeType = TypehintHelper::decideTypeFromReflection($traitNativeType, null, $traitDeclaringClass->getName()); + $traitNativeTypeType = TypehintHelper::decideTypeFromReflection($traitNativeType, null, $this->reflectionProvider->getClass($traitDeclaringClass->getName())); $errors[] = RuleErrorBuilder::message(sprintf( 'Constant %s::%s overriding constant %s::%s (%s) should also have native type %s.', $classReflection->getDisplayName(), @@ -200,7 +204,7 @@ private function processSingleConstant(ClassReflection $classReflection, Reflect ->identifier('classConstant.missingNativeType') ->build(); } else { - $traitNativeTypeType = TypehintHelper::decideTypeFromReflection($traitNativeType, null, $traitDeclaringClass->getName()); + $traitNativeTypeType = TypehintHelper::decideTypeFromReflection($traitNativeType, null, $this->reflectionProvider->getClass($traitDeclaringClass->getName())); $constantNativeTypeType = ParserNodeTypeToPHPStanType::resolve($constantNativeType, $classReflection); if (!$traitNativeTypeType->equals($constantNativeTypeType)) { $errors[] = RuleErrorBuilder::message(sprintf( diff --git a/src/Type/TypehintHelper.php b/src/Type/TypehintHelper.php index f2e2109820..333d9de4a7 100644 --- a/src/Type/TypehintHelper.php +++ b/src/Type/TypehintHelper.php @@ -8,7 +8,6 @@ use PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\ShouldNotHappenException; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Generic\TemplateTypeHelper; @@ -16,7 +15,6 @@ use function array_map; use function count; use function get_class; -use function is_string; use function sprintf; final class TypehintHelper @@ -26,7 +24,7 @@ final class TypehintHelper public static function decideTypeFromReflection( ?ReflectionType $reflectionType, ?Type $phpDocType = null, - ClassReflection|string|null $selfClass = null, + ClassReflection|null $selfClass = null, bool $isVariadic = false, ): Type { @@ -67,14 +65,6 @@ public static function decideTypeFromReflection( $typeNode = new FullyQualified($reflectionType->getName()); } - if (is_string($selfClass)) { - $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); - if ($reflectionProvider->hasClass($selfClass)) { - $selfClass = $reflectionProvider->getClass($selfClass); - } else { - $selfClass = null; - } - } $type = ParserNodeTypeToPHPStanType::resolve($typeNode, $selfClass); if ($reflectionType->allowsNull()) { $type = TypeCombinator::addNull($type); diff --git a/tests/PHPStan/Rules/Traits/ConflictingTraitConstantsRuleTest.php b/tests/PHPStan/Rules/Traits/ConflictingTraitConstantsRuleTest.php index fe5b5c6984..c3b06e73d0 100644 --- a/tests/PHPStan/Rules/Traits/ConflictingTraitConstantsRuleTest.php +++ b/tests/PHPStan/Rules/Traits/ConflictingTraitConstantsRuleTest.php @@ -14,7 +14,7 @@ class ConflictingTraitConstantsRuleTest extends RuleTestCase protected function getRule(): TRule { - return new ConflictingTraitConstantsRule(self::getContainer()->getByType(InitializerExprTypeResolver::class)); + return new ConflictingTraitConstantsRule(self::getContainer()->getByType(InitializerExprTypeResolver::class), $this->createReflectionProvider()); } public function testRule(): void From 0296a91505fee34b474a31917d51e847d6a7d416 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 18:08:16 +0200 Subject: [PATCH 308/508] Fix test --- tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php b/tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php index f2b13d25c2..e14d95f33e 100644 --- a/tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php +++ b/tests/PHPStan/Rules/Api/ApiClassImplementsRuleTest.php @@ -42,22 +42,22 @@ public function testRuleOutOfPhpStan(): void ], [ 'Implementing PHPStan\Reflection\ReflectionProvider is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 339, + 333, $tip, ], [ 'Implementing PHPStan\Analyser\Scope is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 344, + 338, $tip, ], [ 'Implementing PHPStan\Reflection\FunctionReflection is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 349, + 343, $tip, ], [ 'Implementing PHPStan\Reflection\ExtendedMethodReflection is not covered by backward compatibility promise. The interface might change in a minor PHPStan version.', - 353, + 347, $tip, ], ]); From b5accb3f6bbcffc8a44934539b88903e09b6a174 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 18:09:17 +0200 Subject: [PATCH 309/508] HasOffsetType - put constructor parameter type natively --- build/phpstan.neon | 1 - src/Type/Accessory/HasOffsetType.php | 3 +- ...yExistsFunctionTypeSpecifyingExtension.php | 15 ++++- .../Type/Accessory/HasMethodTypeTest.php | 5 -- .../Type/Accessory/HasPropertyTypeTest.php | 5 -- tests/PHPStan/Type/IntersectionTypeTest.php | 47 ------------- tests/PHPStan/Type/TypeCombinatorTest.php | 67 ------------------- 7 files changed, 14 insertions(+), 129 deletions(-) diff --git a/build/phpstan.neon b/build/phpstan.neon index 86610dc028..1b1bf800f9 100644 --- a/build/phpstan.neon +++ b/build/phpstan.neon @@ -89,7 +89,6 @@ parameters: message: "#^Parameter \\#1 (?:\\$argument|\\$objectOrClass) of class ReflectionClass constructor expects class\\-string\\\\|PHPStan\\\\ExtensionInstaller\\\\GeneratedConfig, string given\\.$#" count: 1 path: ../src/Diagnose/PHPStanDiagnoseExtension.php - - '#^Parameter \#1 \$offsetType of class PHPStan\\Type\\Accessory\\HasOffsetType constructor expects PHPStan\\Type\\Constant\\ConstantIntegerType\|PHPStan\\Type\\Constant\\ConstantStringType#' - '#^Short ternary operator is not allowed#' reportStaticMethodSignatures: true tmpDir: %rootDir%/tmp diff --git a/src/Type/Accessory/HasOffsetType.php b/src/Type/Accessory/HasOffsetType.php index 635f7d37ee..132ae28edd 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -44,9 +44,8 @@ class HasOffsetType implements CompoundType, AccessoryType /** * @api - * @param ConstantStringType|ConstantIntegerType $offsetType */ - public function __construct(private Type $offsetType) + public function __construct(private ConstantStringType|ConstantIntegerType $offsetType) { } diff --git a/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php b/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php index 35a3ecb8ea..7d2eb3b2a4 100644 --- a/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php @@ -14,6 +14,7 @@ use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\Accessory\HasOffsetType; +use PHPStan\Type\Accessory\NonEmptyArrayType; use PHPStan\Type\ArrayType; use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\Constant\ConstantStringType; @@ -58,10 +59,20 @@ public function specifyTypes( $keyType = $scope->getType($key); $arrayType = $scope->getType($array); - if (!$keyType instanceof ConstantIntegerType + if ( + !$keyType instanceof ConstantIntegerType && !$keyType instanceof ConstantStringType - && !$arrayType->isIterableAtLeastOnce()->no()) { + ) { if ($context->true()) { + if ($arrayType->isIterableAtLeastOnce()->no()) { + return $this->typeSpecifier->create( + $array, + new NonEmptyArrayType(), + $context, + $scope, + ); + } + $arrayKeyType = $arrayType->getIterableKeyType(); if ($keyType->isString()->yes()) { $arrayKeyType = $arrayKeyType->toString(); diff --git a/tests/PHPStan/Type/Accessory/HasMethodTypeTest.php b/tests/PHPStan/Type/Accessory/HasMethodTypeTest.php index a70ff82ceb..a941dd86ee 100644 --- a/tests/PHPStan/Type/Accessory/HasMethodTypeTest.php +++ b/tests/PHPStan/Type/Accessory/HasMethodTypeTest.php @@ -70,11 +70,6 @@ public function dataIsSuperTypeOf(): array new HasPropertyType('bar'), TrinaryLogic::createMaybe(), ], - [ - new HasMethodType('foo'), - new HasOffsetType(new MixedType()), - TrinaryLogic::createMaybe(), - ], [ new HasMethodType('foo'), new IterableType(new MixedType(), new MixedType()), diff --git a/tests/PHPStan/Type/Accessory/HasPropertyTypeTest.php b/tests/PHPStan/Type/Accessory/HasPropertyTypeTest.php index 52b44a6168..4cecca14c1 100644 --- a/tests/PHPStan/Type/Accessory/HasPropertyTypeTest.php +++ b/tests/PHPStan/Type/Accessory/HasPropertyTypeTest.php @@ -60,11 +60,6 @@ public function dataIsSuperTypeOf(): array new HasPropertyType('bar'), TrinaryLogic::createMaybe(), ], - [ - new HasPropertyType('foo'), - new HasOffsetType(new MixedType()), - TrinaryLogic::createMaybe(), - ], [ new HasPropertyType('foo'), new IterableType(new MixedType(), new MixedType()), diff --git a/tests/PHPStan/Type/IntersectionTypeTest.php b/tests/PHPStan/Type/IntersectionTypeTest.php index 7c9bcc0722..b6fa0c0b4a 100644 --- a/tests/PHPStan/Type/IntersectionTypeTest.php +++ b/tests/PHPStan/Type/IntersectionTypeTest.php @@ -8,7 +8,6 @@ use PHPStan\Testing\PHPStanTestCase; use PHPStan\TrinaryLogic; use PHPStan\Type\Accessory\AccessoryLowercaseStringType; -use PHPStan\Type\Accessory\HasOffsetType; use PHPStan\Type\Accessory\HasPropertyType; use PHPStan\Type\Accessory\NonEmptyArrayType; use PHPStan\Type\Accessory\OversizedArrayType; @@ -154,52 +153,6 @@ public function dataIsSuperTypeOf(): Iterator TrinaryLogic::createNo(), ]; - yield [ - new IntersectionType([ - new ArrayType(new MixedType(), new MixedType()), - new HasOffsetType(new StringType()), - ]), - new ConstantArrayType([ - new ConstantStringType('a'), - new ConstantStringType('b'), - new ConstantStringType('c'), - ], [ - new ConstantIntegerType(1), - new ConstantIntegerType(2), - new ConstantIntegerType(3), - ]), - TrinaryLogic::createMaybe(), - ]; - - yield [ - new IntersectionType([ - new ArrayType(new MixedType(), new MixedType()), - new HasOffsetType(new StringType()), - ]), - new ConstantArrayType([ - new ConstantStringType('a'), - new ConstantStringType('b'), - new ConstantStringType('c'), - new ConstantStringType('d'), - new ConstantStringType('e'), - new ConstantStringType('f'), - new ConstantStringType('g'), - new ConstantStringType('h'), - new ConstantStringType('i'), - ], [ - new ConstantIntegerType(1), - new ConstantIntegerType(2), - new ConstantIntegerType(3), - new ConstantIntegerType(1), - new ConstantIntegerType(2), - new ConstantIntegerType(3), - new ConstantIntegerType(1), - new ConstantIntegerType(2), - new ConstantIntegerType(3), - ]), - TrinaryLogic::createMaybe(), - ]; - yield [ new IntersectionType([ new ObjectType(Traversable::class), diff --git a/tests/PHPStan/Type/TypeCombinatorTest.php b/tests/PHPStan/Type/TypeCombinatorTest.php index d9d6eefe66..6084574e73 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -873,20 +873,6 @@ public function dataUnion(): iterable UnionType::class, "'bar'|'barr'|'baz'|'bazz'|'foo'|'fooo'|'lorem'|'loremm'|'loremmm'", ], - [ - [ - new IntersectionType([ - new ArrayType(new MixedType(), new StringType()), - new HasOffsetType(new StringType()), - ]), - new IntersectionType([ - new ArrayType(new MixedType(), new StringType()), - new HasOffsetType(new StringType()), - ]), - ], - IntersectionType::class, - 'array&hasOffset(string)', - ], [ [ new IntersectionType([ @@ -1857,22 +1843,6 @@ public function dataUnion(): iterable UnionType::class, 'array{a: int, b: int}|array{b: int, c: int}', ], - [ - [ - TypeCombinator::intersect(new StringType(), new HasOffsetType(new IntegerType())), - TypeCombinator::intersect(new StringType(), new HasOffsetType(new IntegerType())), - ], - IntersectionType::class, - 'string&hasOffset(int)', - ], - [ - [ - TypeCombinator::intersect(new ConstantStringType('abc'), new HasOffsetType(new IntegerType())), - TypeCombinator::intersect(new ConstantStringType('abc'), new HasOffsetType(new IntegerType())), - ], - IntersectionType::class, - '\'abc\'&hasOffset(int)', - ], [ [ StaticTypeFactory::falsey(), @@ -3150,24 +3120,6 @@ public function dataIntersect(): iterable IntersectionType::class, 'array&hasOffset(\'a\')', ], - [ - [ - new ArrayType(new StringType(), new StringType()), - new HasOffsetType(new StringType()), - new HasOffsetType(new StringType()), - ], - IntersectionType::class, - 'array&hasOffset(string)', - ], - [ - [ - new ArrayType(new MixedType(), new MixedType()), - new HasOffsetType(new StringType()), - new HasOffsetType(new StringType()), - ], - IntersectionType::class, - 'array&hasOffset(string)', - ], [ [ new ConstantArrayType( @@ -3253,17 +3205,6 @@ public function dataIntersect(): iterable ClosureType::class, 'Closure(): mixed', ], - [ - [ - new UnionType([ - new ArrayType(new MixedType(), new StringType()), - new NullType(), - ]), - new HasOffsetType(new StringType()), - ], - IntersectionType::class, - 'array&hasOffset(string)', - ], [ [ new ArrayType(new MixedType(), new MixedType()), @@ -3772,14 +3713,6 @@ public function dataIntersect(): iterable ConstantArrayType::class, 'array{a: int, b: int}', ], - [ - [ - new StringType(), - new HasOffsetType(new IntegerType()), - ], - IntersectionType::class, - 'string&hasOffset(int)', - ], [ [ new BenevolentUnionType([new IntegerType(), new StringType()]), From c5c03dd5bf0541aaf7272f32e5ce97e1b5cbb657 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:19:50 +0200 Subject: [PATCH 310/508] [BCB] Remove `fixerTmpDir` config parameter --- UPGRADING.md | 1 + conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 4778a9efd9..85a1d46a93 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -282,3 +282,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * `additionalConfigFiles` config parameter must be a list * Remove `__set_state()` on objects that should not be serialized in cache * Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts string +* Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead diff --git a/conf/config.neon b/conf/config.neon index 3d05cf2669..72d5042dea 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -76,7 +76,6 @@ parameters: polluteScopeWithBlock: true propertyAlwaysWrittenTags: [] propertyAlwaysReadTags: [] - fixerTmpDir: %pro.tmpDir% #unused additionalConstructors: [] treatPhpDocTypesAsCertain: true usePathConstantsAsConstantString: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 1b399f95dd..2969aeca73 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -149,7 +149,6 @@ parametersSchema: mixinExcludeClasses: listOf(string()) scanFiles: listOf(string()) scanDirectories: listOf(string()) - fixerTmpDir: string() #unused editorUrl: schema(string(), nullable()) editorUrlTitle: schema(string(), nullable()) errorFormat: schema(string(), nullable()) From 343a93a64f37a58fb8efd7cd99c19e68aee2d4ea Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:20:24 +0200 Subject: [PATCH 311/508] [BCB] `LevelsTestCase::dataTopics()` data provider made static --- UPGRADING.md | 1 + src/Testing/LevelsTestCase.php | 2 +- tests/PHPStan/Generics/GenericsIntegrationTest.php | 2 +- .../InferPrivatePropertyTypeFromConstructorIntegrationTest.php | 2 +- tests/PHPStan/Levels/LevelsIntegrationTest.php | 2 +- tests/PHPStan/Levels/NamedArgumentsIntegrationTest.php | 2 +- tests/PHPStan/Levels/StubValidatorIntegrationTest.php | 2 +- tests/PHPStan/Levels/StubsIntegrationTest.php | 2 +- 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 85a1d46a93..087dc7ee33 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -283,3 +283,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `__set_state()` on objects that should not be serialized in cache * Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts string * Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead +* `LevelsTestCase::dataTopics()` data provider made static diff --git a/src/Testing/LevelsTestCase.php b/src/Testing/LevelsTestCase.php index 7d0b1998a9..9946e97c05 100644 --- a/src/Testing/LevelsTestCase.php +++ b/src/Testing/LevelsTestCase.php @@ -30,7 +30,7 @@ abstract class LevelsTestCase extends TestCase /** * @return array> */ - abstract public function dataTopics(): array; + abstract public static function dataTopics(): array; abstract public function getDataPath(): string; diff --git a/tests/PHPStan/Generics/GenericsIntegrationTest.php b/tests/PHPStan/Generics/GenericsIntegrationTest.php index 6f25d37cd0..a100809355 100644 --- a/tests/PHPStan/Generics/GenericsIntegrationTest.php +++ b/tests/PHPStan/Generics/GenericsIntegrationTest.php @@ -10,7 +10,7 @@ class GenericsIntegrationTest extends LevelsTestCase { - public function dataTopics(): array + public static function dataTopics(): array { return [ ['functions'], diff --git a/tests/PHPStan/Levels/InferPrivatePropertyTypeFromConstructorIntegrationTest.php b/tests/PHPStan/Levels/InferPrivatePropertyTypeFromConstructorIntegrationTest.php index df0dd443c2..d8d3c28878 100644 --- a/tests/PHPStan/Levels/InferPrivatePropertyTypeFromConstructorIntegrationTest.php +++ b/tests/PHPStan/Levels/InferPrivatePropertyTypeFromConstructorIntegrationTest.php @@ -10,7 +10,7 @@ class InferPrivatePropertyTypeFromConstructorIntegrationTest extends LevelsTestCase { - public function dataTopics(): array + public static function dataTopics(): array { return [ ['inferPropertyType'], diff --git a/tests/PHPStan/Levels/LevelsIntegrationTest.php b/tests/PHPStan/Levels/LevelsIntegrationTest.php index ee86187c8c..7ac3a0276f 100644 --- a/tests/PHPStan/Levels/LevelsIntegrationTest.php +++ b/tests/PHPStan/Levels/LevelsIntegrationTest.php @@ -11,7 +11,7 @@ class LevelsIntegrationTest extends LevelsTestCase { - public function dataTopics(): array + public static function dataTopics(): array { $topics = [ ['returnTypes'], diff --git a/tests/PHPStan/Levels/NamedArgumentsIntegrationTest.php b/tests/PHPStan/Levels/NamedArgumentsIntegrationTest.php index 854d9ded9e..d35d7dade7 100644 --- a/tests/PHPStan/Levels/NamedArgumentsIntegrationTest.php +++ b/tests/PHPStan/Levels/NamedArgumentsIntegrationTest.php @@ -10,7 +10,7 @@ class NamedArgumentsIntegrationTest extends LevelsTestCase { - public function dataTopics(): array + public static function dataTopics(): array { return [ ['namedArguments'], diff --git a/tests/PHPStan/Levels/StubValidatorIntegrationTest.php b/tests/PHPStan/Levels/StubValidatorIntegrationTest.php index f4138d043f..59ded11998 100644 --- a/tests/PHPStan/Levels/StubValidatorIntegrationTest.php +++ b/tests/PHPStan/Levels/StubValidatorIntegrationTest.php @@ -10,7 +10,7 @@ class StubValidatorIntegrationTest extends LevelsTestCase { - public function dataTopics(): array + public static function dataTopics(): array { return [ ['stubValidator'], diff --git a/tests/PHPStan/Levels/StubsIntegrationTest.php b/tests/PHPStan/Levels/StubsIntegrationTest.php index dfec2e90f5..089c9b5495 100644 --- a/tests/PHPStan/Levels/StubsIntegrationTest.php +++ b/tests/PHPStan/Levels/StubsIntegrationTest.php @@ -10,7 +10,7 @@ class StubsIntegrationTest extends LevelsTestCase { - public function dataTopics(): array + public static function dataTopics(): array { require_once __DIR__ . '/data/stubs-functions.php'; From 25fbf7f38d77df993c5d6abc4a20c55a0aca81df Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:23:10 +0200 Subject: [PATCH 312/508] [BCB] Remove `tempResultCachePath` config parameter --- UPGRADING.md | 1 + conf/config.neon | 1 - conf/parametersSchema.neon | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 087dc7ee33..1afa0a1940 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -283,4 +283,5 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `__set_state()` on objects that should not be serialized in cache * Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts string * Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead +* Remove `tempResultCachePath` config parameter, use `resultCachePath` instead * `LevelsTestCase::dataTopics()` data provider made static diff --git a/conf/config.neon b/conf/config.neon index 72d5042dea..79b8fce3b4 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -121,7 +121,6 @@ parameters: - ../stubs/Countable.stub earlyTerminatingMethodCalls: [] earlyTerminatingFunctionCalls: [] - tempResultCachePath: %tmpDir%/resultCaches resultCachePath: %tmpDir%/resultCache.php resultCacheChecksProjectExtensionFilesDependencies: false dynamicConstantNames: diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 2969aeca73..d6e4a34882 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -137,7 +137,6 @@ parametersSchema: stubFiles: listOf(string()) earlyTerminatingMethodCalls: arrayOf(listOf(string())) earlyTerminatingFunctionCalls: listOf(string()) - tempResultCachePath: string() resultCachePath: string() resultCacheChecksProjectExtensionFilesDependencies: bool() dynamicConstantNames: listOf(string()) From 11afcb0dc92c4ff1402d0aed292e7bcdb852e645 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:27:00 +0200 Subject: [PATCH 313/508] Upgrading note about Docker images --- UPGRADING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 1afa0a1940..22a6c35d39 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -96,6 +96,10 @@ parameters: Appending `(?)` in `ignoreErrors` is not supported. +### Docker images no longer tagged without a PHP version + +Tags without a PHP version are no longer published - `nightly`, `2`, `latest` are no longer updated. Instead, use `nightly-php8.3`, `2-php8.3`, `latest-php8.3`. You can replace `8.3` with PHP versions `8.0`-`8.3`. + ### Minor backward compatibility breaks * Removed unused config parameter `cache.nodesByFileCountMax` From f347f22922ca970129cfa6a7df3310aa52ec923c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:31:12 +0200 Subject: [PATCH 314/508] Fix --- src/Command/CommandHelper.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index c3cfbbedfd..fdd3d74317 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -523,9 +523,6 @@ public static function begin( throw new InceptionNotSuccessfulException(); } - $tempResultCachePath = $container->getParameter('tempResultCachePath'); - $createDir($tempResultCachePath); - /** @var FileFinder $fileFinder */ $fileFinder = $container->getService('fileFinderAnalyse'); From 3999a7891b2aa409c8da1c570e29180cca7de542 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:34:09 +0200 Subject: [PATCH 315/508] [BCB] `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard` --- UPGRADING.md | 1 + conf/config.neon | 2 ++ 2 files changed, 3 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 22a6c35d39..679ada1d75 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -289,3 +289,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead * Remove `tempResultCachePath` config parameter, use `resultCachePath` instead * `LevelsTestCase::dataTopics()` data provider made static +* `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint diff --git a/conf/config.neon b/conf/config.neon index 79b8fce3b4..5ab30e7e53 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -311,6 +311,8 @@ services: - class: PHPStan\Node\Printer\Printer + autowired: + - PHPStan\Node\Printer\Printer - class: PHPStan\Broker\AnonymousClassNameHelper From b711b3b58e50fd64976e2ebfbd68cb3d3b151042 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:35:46 +0200 Subject: [PATCH 316/508] Update phpstan-strict-rules --- composer.lock | 8 ++++---- issue-bot/composer.lock | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index f71bf5c34d..60fb2a048d 100644 --- a/composer.lock +++ b/composer.lock @@ -4831,12 +4831,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "63956f7896780551ed1ab29e75a6a645d8a0919c" + "reference": "e208c9311872047b903511e2e03cb0df795014b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/63956f7896780551ed1ab29e75a6a645d8a0919c", - "reference": "63956f7896780551ed1ab29e75a6a645d8a0919c", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/e208c9311872047b903511e2e03cb0df795014b0", + "reference": "e208c9311872047b903511e2e03cb0df795014b0", "shasum": "" }, "require": { @@ -4872,7 +4872,7 @@ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-09-24T15:32:27+00:00" + "time": "2024-09-30T19:35:25+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/issue-bot/composer.lock b/issue-bot/composer.lock index c3d88dbcb3..be0c051842 100644 --- a/issue-bot/composer.lock +++ b/issue-bot/composer.lock @@ -1407,12 +1407,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "b1165b76fe8d451783d63ac99e3e31377353a90a" + "reference": "f347f223a7235178f056f34dc104557095998614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b1165b76fe8d451783d63ac99e3e31377353a90a", - "reference": "b1165b76fe8d451783d63ac99e3e31377353a90a", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f347f223a7235178f056f34dc104557095998614", + "reference": "f347f223a7235178f056f34dc104557095998614", "shasum": "" }, "require": { @@ -1458,7 +1458,7 @@ "type": "github" } ], - "time": "2024-09-24T12:23:49+00:00" + "time": "2024-09-30T19:33:02+00:00" }, { "name": "phpstan/phpstan-strict-rules", @@ -1466,12 +1466,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "63956f7896780551ed1ab29e75a6a645d8a0919c" + "reference": "e208c9311872047b903511e2e03cb0df795014b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/63956f7896780551ed1ab29e75a6a645d8a0919c", - "reference": "63956f7896780551ed1ab29e75a6a645d8a0919c", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/e208c9311872047b903511e2e03cb0df795014b0", + "reference": "e208c9311872047b903511e2e03cb0df795014b0", "shasum": "" }, "require": { @@ -1507,7 +1507,7 @@ "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" }, - "time": "2024-09-24T15:32:27+00:00" + "time": "2024-09-30T19:35:25+00:00" }, { "name": "psr/cache", From 1b1da3e2ce3acf10dde03d9656638cda4f7389a4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:40:28 +0200 Subject: [PATCH 317/508] Config option `exceptions.check.tooWideThrowType` made true by default --- conf/config.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/config.neon b/conf/config.neon index 5ab30e7e53..d627237282 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -19,7 +19,7 @@ parameters: checkedExceptionClasses: [] check: missingCheckedExceptionInThrows: false - tooWideThrowType: false + tooWideThrowType: true featureToggles: bleedingEdge: false skipCheckGenericClasses: [] From d7798d7f2c47f426efe91c566e6cafd5a4e2410c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:42:26 +0200 Subject: [PATCH 318/508] Rules about tooWideThrowType moved to level 4 --- conf/config.level4.neon | 12 ++++++++++++ conf/config.neon | 10 ---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 5636417046..e77344de28 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -25,6 +25,12 @@ rules: - PHPStan\Rules\TooWideTypehints\TooWidePropertyTypeRule - PHPStan\Rules\Traits\NotAnalysedTraitRule +conditionalTags: + PHPStan\Rules\Exceptions\TooWideFunctionThrowTypeRule: + phpstan.rules.rule: %exceptions.check.tooWideThrowType% + PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule: + phpstan.rules.rule: %exceptions.check.tooWideThrowType% + parameters: checkAdvancedIsset: true @@ -228,6 +234,12 @@ services: tags: - phpstan.rules.rule + - + class: PHPStan\Rules\Exceptions\TooWideFunctionThrowTypeRule + + - + class: PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule + - class: PHPStan\Rules\TooWideTypehints\TooWideMethodReturnTypehintRule arguments: diff --git a/conf/config.neon b/conf/config.neon index d627237282..e5082b1ce4 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -205,10 +205,6 @@ conditionalTags: phpstan.rules.rule: %exceptions.check.missingCheckedExceptionInThrows% PHPStan\Rules\Exceptions\MissingCheckedExceptionInMethodThrowsRule: phpstan.rules.rule: %exceptions.check.missingCheckedExceptionInThrows% - PHPStan\Rules\Exceptions\TooWideFunctionThrowTypeRule: - phpstan.rules.rule: %exceptions.check.tooWideThrowType% - PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule: - phpstan.rules.rule: %exceptions.check.tooWideThrowType% services: - @@ -881,12 +877,6 @@ services: arguments: exceptionTypeResolver: @exceptionTypeResolver - - - class: PHPStan\Rules\Exceptions\TooWideFunctionThrowTypeRule - - - - class: PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule - - class: PHPStan\Rules\Exceptions\TooWideThrowTypeCheck From b0858332efc7aa2f2fde7544a2a821ba81bde13b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 30 Sep 2024 21:52:02 +0200 Subject: [PATCH 319/508] Printer is covered by BC promise --- src/Node/Printer/Printer.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Node/Printer/Printer.php b/src/Node/Printer/Printer.php index 78455184f0..131376d66d 100644 --- a/src/Node/Printer/Printer.php +++ b/src/Node/Printer/Printer.php @@ -19,6 +19,9 @@ use PHPStan\Type\VerbosityLevel; use function sprintf; +/** + * @api + */ final class Printer extends Standard { From 3b6d0612c2165286000a99c404136e2293344128 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Mon, 30 Sep 2024 19:56:55 +0000 Subject: [PATCH 320/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 8d69f8840b..6b268bb146 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.9", - "phpstan/php-8-stubs": "0.3.111", + "phpstan/php-8-stubs": "0.4.0", "phpstan/phpdoc-parser": "^2.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index 60fb2a048d..35ad14bc74 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "108d46d88ea46d66d8fab6acc4765c04", + "content-hash": "9485ba4e0af44d8602eb360c34f92b8d", "packages": [ { "name": "clue/ndjson-react", @@ -2250,16 +2250,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.3.111", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "0013252145df5d84112764d4ea57ed1c6f074018" + "reference": "693817d86d0d0de1d39b97a70bff4fa728384aa1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/0013252145df5d84112764d4ea57ed1c6f074018", - "reference": "0013252145df5d84112764d4ea57ed1c6f074018", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/693817d86d0d0de1d39b97a70bff4fa728384aa1", + "reference": "693817d86d0d0de1d39b97a70bff4fa728384aa1", "shasum": "" }, "type": "library", @@ -2276,9 +2276,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.3.111" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.0" }, - "time": "2024-09-29T00:21:10+00:00" + "time": "2024-09-30T19:56:21+00:00" }, { "name": "phpstan/phpdoc-parser", From 1d3f4313955dc6fa5c6ce60fa58afe765964e5b0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 09:19:43 +0200 Subject: [PATCH 321/508] Collected PHP errors cannot be ignored --- src/Analyser/FileAnalyser.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Analyser/FileAnalyser.php b/src/Analyser/FileAnalyser.php index 8d8cf59016..570c637092 100644 --- a/src/Analyser/FileAnalyser.php +++ b/src/Analyser/FileAnalyser.php @@ -31,6 +31,7 @@ use const E_NOTICE; use const E_PARSE; use const E_STRICT; +use const E_USER_DEPRECATED; use const E_USER_ERROR; use const E_USER_NOTICE; use const E_USER_WARNING; @@ -322,7 +323,7 @@ private function collectErrors(array $analysedFiles): void $errorMessage = sprintf('%s: %s', $this->getErrorLabel($errno), $errstr); - $this->allPhpErrors[] = (new Error($errorMessage, $errfile, $errline, true))->withIdentifier('phpstan.php'); + $this->allPhpErrors[] = (new Error($errorMessage, $errfile, $errline, false))->withIdentifier('phpstan.php'); if ($errno === E_DEPRECATED) { return true; @@ -332,7 +333,7 @@ private function collectErrors(array $analysedFiles): void return true; } - $this->filteredPhpErrors[] = (new Error($errorMessage, $errfile, $errline, true))->withIdentifier('phpstan.php'); + $this->filteredPhpErrors[] = (new Error($errorMessage, $errfile, $errline, $errno === E_USER_DEPRECATED))->withIdentifier('phpstan.php'); return true; }); @@ -354,12 +355,16 @@ private function getErrorLabel(int $errno): string return 'Parse error'; case E_NOTICE: return 'Notice'; + case E_DEPRECATED: + return 'Deprecated'; case E_USER_ERROR: return 'User error (E_USER_ERROR)'; case E_USER_WARNING: return 'User warning (E_USER_WARNING)'; case E_USER_NOTICE: return 'User notice (E_USER_NOTICE)'; + case E_USER_DEPRECATED: + return 'Deprecated (E_USER_DEPRECATED)'; case E_STRICT: return 'Strict error (E_STRICT)'; } From d899a429adc44779751b23c99a4c359f6cd9b775 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 09:25:58 +0200 Subject: [PATCH 322/508] Move UselessFunctionReturnValueRule to level 4 --- changelog-2.0.md | 2 +- conf/config.level0.neon | 1 - conf/config.level4.neon | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index d9fe72d6c9..3b76ab1766 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -32,7 +32,7 @@ Major new features 🚀 * MagicConstantContextRule (level 0) ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * MissingMagicSerializationMethodsRule (level 0) ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! * Check vprintf/vsprintf arguments against placeholder count (level 0) ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! -* Report useless return values of function calls like `var_export` without `$return=true` (level 0) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! +* Report useless return values of function calls like `var_export` without `$return=true` (level 4) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! * Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! * Report useless `array_filter()` calls (level 5) ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! * Report useless `array_values()` calls (level 5) ([#2917](https://github.com/phpstan/phpstan-src/pull/2917)), thanks @kamil-zacek! diff --git a/conf/config.level0.neon b/conf/config.level0.neon index d8b1b775cc..30d798cdaa 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -67,7 +67,6 @@ rules: - PHPStan\Rules\Functions\PrintfParametersRule - PHPStan\Rules\Functions\RedefinedParametersRule - PHPStan\Rules\Functions\ReturnNullsafeByRefRule - - PHPStan\Rules\Functions\UselessFunctionReturnValueRule - PHPStan\Rules\Ignore\IgnoreParseErrorRule - PHPStan\Rules\Functions\VariadicParametersDeclarationRule - PHPStan\Rules\Keywords\ContinueBreakInLoopRule diff --git a/conf/config.level4.neon b/conf/config.level4.neon index e77344de28..bda46632c2 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -13,6 +13,7 @@ rules: - PHPStan\Rules\DeadCode\UnusedPrivateMethodRule - PHPStan\Rules\Exceptions\OverwrittenExitPointByFinallyRule - PHPStan\Rules\Functions\CallToFunctionStatementWithoutSideEffectsRule + - PHPStan\Rules\Functions\UselessFunctionReturnValueRule - PHPStan\Rules\Methods\CallToConstructorStatementWithoutSideEffectsRule - PHPStan\Rules\Methods\CallToMethodStatementWithoutSideEffectsRule - PHPStan\Rules\Methods\CallToStaticMethodStatementWithoutSideEffectsRule From 4b974a4698f9477a6530c4a9a78f906278d24419 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 09:28:25 +0200 Subject: [PATCH 323/508] Moved RegularExpressionQuotingRule to level 5 --- changelog-2.0.md | 2 +- conf/config.level0.neon | 1 - conf/config.level5.neon | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 3b76ab1766..9243a74288 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -28,7 +28,7 @@ Major new features 🚀 * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! * LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 * Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) -* Check preg_quote delimiter sanity (level 0) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! +* Check preg_quote delimiter sanity (level 5) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! * MagicConstantContextRule (level 0) ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! * MissingMagicSerializationMethodsRule (level 0) ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! * Check vprintf/vsprintf arguments against placeholder count (level 0) ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 30d798cdaa..fbad323697 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -98,7 +98,6 @@ rules: - PHPStan\Rules\Properties\ReadOnlyPropertyRule - PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyRule - PHPStan\Rules\Regexp\RegularExpressionPatternRule - - PHPStan\Rules\Regexp\RegularExpressionQuotingRule - PHPStan\Rules\Traits\ConflictingTraitConstantsRule - PHPStan\Rules\Traits\ConstantsInTraitsRule - PHPStan\Rules\Types\InvalidTypesInUnionRule diff --git a/conf/config.level5.neon b/conf/config.level5.neon index 0cbccea5d6..b89a6dbddf 100644 --- a/conf/config.level5.neon +++ b/conf/config.level5.neon @@ -11,6 +11,7 @@ rules: - PHPStan\Rules\Functions\ParameterCastableToStringRule - PHPStan\Rules\Functions\ImplodeParameterCastableToStringRule - PHPStan\Rules\Functions\SortParameterCastableToStringRule + - PHPStan\Rules\Regexp\RegularExpressionQuotingRule services: - From a0e688c1d1e4c5e82f989b26485eb9162f47aa97 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 09:35:21 +0200 Subject: [PATCH 324/508] Use `implicitThrows` to only look for explicit throw points in too-wide `@throws` rules when set to `false` --- conf/config.neon | 2 ++ .../Exceptions/TooWideThrowTypeCheck.php | 8 +++-- .../TooWideFunctionThrowTypeRuleTest.php | 4 ++- .../TooWideMethodThrowTypeRuleTest.php | 31 ++++++++++++++++++- .../data/too-wide-throws-explicit.php | 22 +++++++++++++ 5 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 tests/PHPStan/Rules/Exceptions/data/too-wide-throws-explicit.php diff --git a/conf/config.neon b/conf/config.neon index e5082b1ce4..08a5c8c099 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -879,6 +879,8 @@ services: - class: PHPStan\Rules\Exceptions\TooWideThrowTypeCheck + arguments: + implicitThrows: %exceptions.implicitThrows% - class: PHPStan\Rules\FunctionCallParametersCheck diff --git a/src/Rules/Exceptions/TooWideThrowTypeCheck.php b/src/Rules/Exceptions/TooWideThrowTypeCheck.php index 830d0f9a62..5c5e33c803 100644 --- a/src/Rules/Exceptions/TooWideThrowTypeCheck.php +++ b/src/Rules/Exceptions/TooWideThrowTypeCheck.php @@ -13,6 +13,10 @@ final class TooWideThrowTypeCheck { + public function __construct(private bool $implicitThrows) + { + } + /** * @param ThrowPoint[] $throwPoints * @return string[] @@ -23,8 +27,8 @@ public function check(Type $throwType, array $throwPoints): array return []; } - $throwPointType = TypeCombinator::union(...array_map(static function (ThrowPoint $throwPoint): Type { - if (!$throwPoint->isExplicit()) { + $throwPointType = TypeCombinator::union(...array_map(function (ThrowPoint $throwPoint): Type { + if (!$this->implicitThrows && !$throwPoint->isExplicit()) { return new NeverType(); } diff --git a/tests/PHPStan/Rules/Exceptions/TooWideFunctionThrowTypeRuleTest.php b/tests/PHPStan/Rules/Exceptions/TooWideFunctionThrowTypeRuleTest.php index 82871e6145..affb0fc679 100644 --- a/tests/PHPStan/Rules/Exceptions/TooWideFunctionThrowTypeRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/TooWideFunctionThrowTypeRuleTest.php @@ -11,9 +11,11 @@ class TooWideFunctionThrowTypeRuleTest extends RuleTestCase { + private bool $implicitThrows = true; + protected function getRule(): Rule { - return new TooWideFunctionThrowTypeRule(new TooWideThrowTypeCheck()); + return new TooWideFunctionThrowTypeRule(new TooWideThrowTypeCheck($this->implicitThrows)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php b/tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php index 5a32351986..1ebd091d9d 100644 --- a/tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/TooWideMethodThrowTypeRuleTest.php @@ -13,9 +13,11 @@ class TooWideMethodThrowTypeRuleTest extends RuleTestCase { + private bool $implicitThrows = true; + protected function getRule(): Rule { - return new TooWideMethodThrowTypeRule(self::getContainer()->getByType(FileTypeMapper::class), new TooWideThrowTypeCheck()); + return new TooWideMethodThrowTypeRule(self::getContainer()->getByType(FileTypeMapper::class), new TooWideThrowTypeCheck($this->implicitThrows)); } public function testRule(): void @@ -72,4 +74,31 @@ public function testFirstClassCallable(): void $this->analyse([__DIR__ . '/data/immediately-called-fcc.php'], []); } + public static function dataRuleLookOnlyForExplicitThrowPoints(): iterable + { + yield [ + true, + [], + ]; + yield [ + false, + [ + [ + 'Method TooWideThrowsExplicit\Foo::doFoo() has Exception in PHPDoc @throws tag but it\'s not thrown.', + 11, + ], + ], + ]; + } + + /** + * @dataProvider dataRuleLookOnlyForExplicitThrowPoints + * @param list $errors + */ + public function testRuleLookOnlyForExplicitThrowPoints(bool $implicitThrows, array $errors): void + { + $this->implicitThrows = $implicitThrows; + $this->analyse([__DIR__ . '/data/too-wide-throws-explicit.php'], $errors); + } + } diff --git a/tests/PHPStan/Rules/Exceptions/data/too-wide-throws-explicit.php b/tests/PHPStan/Rules/Exceptions/data/too-wide-throws-explicit.php new file mode 100644 index 0000000000..834df2b1f0 --- /dev/null +++ b/tests/PHPStan/Rules/Exceptions/data/too-wide-throws-explicit.php @@ -0,0 +1,22 @@ +doBar(); + } + + public function doBar(): void + { + + } + +} From 7ba8abcba1e9687c7c5eee38571e2fae09e5edd8 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 09:55:29 +0200 Subject: [PATCH 325/508] [BCB] `acceptsWithReason` renamed to `accepts` --- UPGRADING.md | 3 ++ .../ValueAssignedToClassConstantRule.php | 4 +-- src/Rules/FunctionCallParametersCheck.php | 2 +- src/Rules/FunctionReturnTypeCheck.php | 2 +- ...eArrowFunctionDefaultParameterTypeRule.php | 2 +- ...patibleClosureDefaultParameterTypeRule.php | 2 +- .../IncompatibleDefaultParameterTypeRule.php | 2 +- src/Rules/Generators/YieldFromTypeRule.php | 4 +-- src/Rules/Generators/YieldTypeRule.php | 4 +-- .../IncompatibleDefaultParameterTypeRule.php | 2 +- ...aultValueTypesAssignedToPropertiesRule.php | 2 +- .../TypesAssignedToPropertiesRule.php | 2 +- src/Rules/RuleLevelHelper.php | 11 ++----- src/Rules/RuleLevelHelperAcceptsResult.php | 3 ++ src/Type/Accessory/AccessoryArrayListType.php | 16 ++-------- .../Accessory/AccessoryLiteralStringType.php | 16 ++-------- .../AccessoryLowercaseStringType.php | 16 ++-------- .../Accessory/AccessoryNonEmptyStringType.php | 16 ++-------- .../Accessory/AccessoryNonFalsyStringType.php | 16 ++-------- .../Accessory/AccessoryNumericStringType.php | 16 ++-------- src/Type/Accessory/HasMethodType.php | 16 ++-------- src/Type/Accessory/HasOffsetType.php | 16 ++-------- src/Type/Accessory/HasOffsetValueType.php | 18 +++-------- src/Type/Accessory/HasPropertyType.php | 16 ++-------- src/Type/Accessory/NonEmptyArrayType.php | 16 ++-------- src/Type/Accessory/OversizedArrayType.php | 16 ++-------- src/Type/ArrayType.php | 17 ++++------ src/Type/BenevolentUnionType.php | 9 ++---- src/Type/CallableType.php | 16 ++-------- src/Type/CallableTypeHelper.php | 4 +-- src/Type/ClassStringType.php | 9 ++---- src/Type/ClosureType.php | 11 ++----- src/Type/CompoundType.php | 4 +-- src/Type/Constant/ConstantArrayType.php | 11 ++----- src/Type/Enum/EnumCaseObjectType.php | 7 +---- src/Type/FloatType.php | 9 ++---- src/Type/Generic/GenericClassStringType.php | 6 ++-- src/Type/Generic/GenericObjectType.php | 13 +++----- src/Type/Generic/TemplateMixedType.php | 7 +---- src/Type/Generic/TemplateStrictMixedType.php | 7 +---- src/Type/Generic/TemplateType.php | 5 +-- .../Generic/TemplateTypeArgumentStrategy.php | 4 +-- .../Generic/TemplateTypeParameterStrategy.php | 4 +-- src/Type/Generic/TemplateTypeTrait.php | 31 +++++-------------- src/Type/Generic/TemplateTypeVariance.php | 10 ++---- src/Type/IntegerRangeType.php | 16 ++-------- src/Type/IntersectionType.php | 18 +++-------- src/Type/IterableType.php | 20 +++--------- src/Type/JustNullableTypeTrait.php | 9 ++---- src/Type/MixedType.php | 14 ++------- src/Type/NeverType.php | 14 ++------- src/Type/NonAcceptingNeverType.php | 2 +- src/Type/NullType.php | 9 ++---- src/Type/ObjectShapeType.php | 11 ++----- src/Type/ObjectType.php | 9 ++---- src/Type/ObjectWithoutClassType.php | 9 ++---- src/Type/StaticType.php | 11 ++----- src/Type/StrictMixedType.php | 14 ++------- ...gAlwaysAcceptingObjectWithToStringType.php | 4 +-- src/Type/StringType.php | 9 ++---- src/Type/Traits/ConstantScalarTypeTrait.php | 11 ++----- src/Type/Traits/LateResolvableTypeTrait.php | 18 +++-------- src/Type/Type.php | 4 +-- src/Type/UnionType.php | 24 +++++--------- src/Type/VoidType.php | 9 ++---- tests/PHPStan/Type/ArrayTypeTest.php | 2 +- tests/PHPStan/Type/BooleanTypeTest.php | 2 +- tests/PHPStan/Type/CallableTypeTest.php | 2 +- tests/PHPStan/Type/ClassStringTypeTest.php | 2 +- .../Type/Constant/ConstantArrayTypeTest.php | 2 +- .../Type/Constant/ConstantIntegerTypeTest.php | 2 +- .../Type/Enum/EnumCaseObjectTypeTest.php | 2 +- tests/PHPStan/Type/FloatTypeTest.php | 2 +- .../Generic/GenericClassStringTypeTest.php | 2 +- .../Type/Generic/GenericObjectTypeTest.php | 2 +- .../Type/Generic/TemplateTypeVarianceTest.php | 5 +-- tests/PHPStan/Type/IntegerTypeTest.php | 2 +- tests/PHPStan/Type/IntersectionTypeTest.php | 2 +- tests/PHPStan/Type/IterableTypeTest.php | 2 +- tests/PHPStan/Type/ObjectTypeTest.php | 2 +- tests/PHPStan/Type/StringTypeTest.php | 2 +- tests/PHPStan/Type/TemplateTypeTest.php | 4 +-- tests/PHPStan/Type/UnionTypeTest.php | 2 +- 83 files changed, 184 insertions(+), 515 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 679ada1d75..cdaad24fcf 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -290,3 +290,6 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `tempResultCachePath` config parameter, use `resultCachePath` instead * `LevelsTestCase::dataTopics()` data provider made static * `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint +* Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) +* Remove `CompoundType::isAcceptedWithReasonBy()`, `CompoundType::isAcceptedBy()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) +* `RuleLevelHelper::accepts()` return type changed from `bool` to [`RuleLevelHelperAcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) diff --git a/src/Rules/Constants/ValueAssignedToClassConstantRule.php b/src/Rules/Constants/ValueAssignedToClassConstantRule.php index afdbf2c5e7..728b5a039f 100644 --- a/src/Rules/Constants/ValueAssignedToClassConstantRule.php +++ b/src/Rules/Constants/ValueAssignedToClassConstantRule.php @@ -63,7 +63,7 @@ private function processSingleConstant(ClassReflection $classReflection, string return []; } - $accepts = $nativeType->acceptsWithReason($valueExprType, true); + $accepts = $nativeType->accepts($valueExprType, true); if ($accepts->yes()) { return []; } @@ -107,7 +107,7 @@ private function processSingleConstant(ClassReflection $classReflection, string } $type = $constantReflection->getValueType(); - $accepts = $type->acceptsWithReason($valueExprType, true); + $accepts = $type->accepts($valueExprType, true); if ($accepts->yes()) { return []; } diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 787d6136da..aa8b9f356a 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -312,7 +312,7 @@ public function check( $parameterType = TypeUtils::resolveLateResolvableTypes($parameter->getType()); if (!$parameter->passedByReference()->createsNewVariable() || !$isBuiltin) { - $accepts = $this->ruleLevelHelper->acceptsWithReason($parameterType, $argumentValueType, $scope->isDeclareStrictTypes()); + $accepts = $this->ruleLevelHelper->accepts($parameterType, $argumentValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $argumentValueType); diff --git a/src/Rules/FunctionReturnTypeCheck.php b/src/Rules/FunctionReturnTypeCheck.php index be2eb86b1a..994b3943f2 100644 --- a/src/Rules/FunctionReturnTypeCheck.php +++ b/src/Rules/FunctionReturnTypeCheck.php @@ -90,7 +90,7 @@ public function checkReturnType( ]; } - $accepts = $this->ruleLevelHelper->acceptsWithReason($returnType, $returnValueType, $scope->isDeclareStrictTypes()); + $accepts = $this->ruleLevelHelper->accepts($returnType, $returnValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { return [ RuleErrorBuilder::message(sprintf( diff --git a/src/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRule.php b/src/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRule.php index 7d5967fb2b..80ab58e8bb 100644 --- a/src/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRule.php +++ b/src/Rules/Functions/IncompatibleArrowFunctionDefaultParameterTypeRule.php @@ -44,7 +44,7 @@ public function processNode(Node $node, Scope $scope): array $parameterType = $parameters[$paramI]->getType(); $parameterType = TemplateTypeHelper::resolveToBounds($parameterType); - $accepts = $parameterType->acceptsWithReason($defaultValueType, true); + $accepts = $parameterType->accepts($defaultValueType, true); if ($accepts->yes()) { continue; } diff --git a/src/Rules/Functions/IncompatibleClosureDefaultParameterTypeRule.php b/src/Rules/Functions/IncompatibleClosureDefaultParameterTypeRule.php index ab3565a612..f4d3965026 100644 --- a/src/Rules/Functions/IncompatibleClosureDefaultParameterTypeRule.php +++ b/src/Rules/Functions/IncompatibleClosureDefaultParameterTypeRule.php @@ -44,7 +44,7 @@ public function processNode(Node $node, Scope $scope): array $parameterType = $parameters[$paramI]->getType(); $parameterType = TemplateTypeHelper::resolveToBounds($parameterType); - $accepts = $parameterType->acceptsWithReason($defaultValueType, true); + $accepts = $parameterType->accepts($defaultValueType, true); if ($accepts->yes()) { continue; } diff --git a/src/Rules/Functions/IncompatibleDefaultParameterTypeRule.php b/src/Rules/Functions/IncompatibleDefaultParameterTypeRule.php index af9d403b34..68f9fffc6d 100644 --- a/src/Rules/Functions/IncompatibleDefaultParameterTypeRule.php +++ b/src/Rules/Functions/IncompatibleDefaultParameterTypeRule.php @@ -43,7 +43,7 @@ public function processNode(Node $node, Scope $scope): array $parameterType = $function->getParameters()[$paramI]->getType(); $parameterType = TemplateTypeHelper::resolveToBounds($parameterType); - $accepts = $parameterType->acceptsWithReason($defaultValueType, true); + $accepts = $parameterType->accepts($defaultValueType, true); if ($accepts->yes()) { continue; } diff --git a/src/Rules/Generators/YieldFromTypeRule.php b/src/Rules/Generators/YieldFromTypeRule.php index b73b5a3509..5bac445f13 100644 --- a/src/Rules/Generators/YieldFromTypeRule.php +++ b/src/Rules/Generators/YieldFromTypeRule.php @@ -78,7 +78,7 @@ public function processNode(Node $node, Scope $scope): array } $messages = []; - $acceptsKey = $this->ruleLevelHelper->acceptsWithReason($returnType->getIterableKeyType(), $exprType->getIterableKeyType(), $scope->isDeclareStrictTypes()); + $acceptsKey = $this->ruleLevelHelper->accepts($returnType->getIterableKeyType(), $exprType->getIterableKeyType(), $scope->isDeclareStrictTypes()); if (!$acceptsKey->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType->getIterableKeyType(), $exprType->getIterableKeyType()); $messages[] = RuleErrorBuilder::message(sprintf( @@ -92,7 +92,7 @@ public function processNode(Node $node, Scope $scope): array ->build(); } - $acceptsValue = $this->ruleLevelHelper->acceptsWithReason($returnType->getIterableValueType(), $exprType->getIterableValueType(), $scope->isDeclareStrictTypes()); + $acceptsValue = $this->ruleLevelHelper->accepts($returnType->getIterableValueType(), $exprType->getIterableValueType(), $scope->isDeclareStrictTypes()); if (!$acceptsValue->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType->getIterableValueType(), $exprType->getIterableValueType()); $messages[] = RuleErrorBuilder::message(sprintf( diff --git a/src/Rules/Generators/YieldTypeRule.php b/src/Rules/Generators/YieldTypeRule.php index c8475e23a8..eccc960d2a 100644 --- a/src/Rules/Generators/YieldTypeRule.php +++ b/src/Rules/Generators/YieldTypeRule.php @@ -53,7 +53,7 @@ public function processNode(Node $node, Scope $scope): array } $messages = []; - $acceptsKey = $this->ruleLevelHelper->acceptsWithReason($returnType->getIterableKeyType(), $keyType, $scope->isDeclareStrictTypes()); + $acceptsKey = $this->ruleLevelHelper->accepts($returnType->getIterableKeyType(), $keyType, $scope->isDeclareStrictTypes()); if (!$acceptsKey->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType->getIterableKeyType(), $keyType); $messages[] = RuleErrorBuilder::message(sprintf( @@ -72,7 +72,7 @@ public function processNode(Node $node, Scope $scope): array $valueType = $scope->getType($node->value); } - $acceptsValue = $this->ruleLevelHelper->acceptsWithReason($returnType->getIterableValueType(), $valueType, $scope->isDeclareStrictTypes()); + $acceptsValue = $this->ruleLevelHelper->accepts($returnType->getIterableValueType(), $valueType, $scope->isDeclareStrictTypes()); if (!$acceptsValue->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType->getIterableValueType(), $valueType); $messages[] = RuleErrorBuilder::message(sprintf( diff --git a/src/Rules/Methods/IncompatibleDefaultParameterTypeRule.php b/src/Rules/Methods/IncompatibleDefaultParameterTypeRule.php index d8814af601..85059abcac 100644 --- a/src/Rules/Methods/IncompatibleDefaultParameterTypeRule.php +++ b/src/Rules/Methods/IncompatibleDefaultParameterTypeRule.php @@ -44,7 +44,7 @@ public function processNode(Node $node, Scope $scope): array $parameterType = $parameter->getType(); $parameterType = TemplateTypeHelper::resolveToBounds($parameterType); - $accepts = $parameterType->acceptsWithReason($defaultValueType, true); + $accepts = $parameterType->accepts($defaultValueType, true); if ($accepts->yes()) { continue; } diff --git a/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php b/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php index 3076d2d3d8..63cd185b7a 100644 --- a/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php +++ b/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php @@ -44,7 +44,7 @@ public function processNode(Node $node, Scope $scope): array } } $defaultValueType = $scope->getType($default); - $accepts = $this->ruleLevelHelper->acceptsWithReason($propertyType, $defaultValueType, true); + $accepts = $this->ruleLevelHelper->accepts($propertyType, $defaultValueType, true); if ($accepts->result) { return []; } diff --git a/src/Rules/Properties/TypesAssignedToPropertiesRule.php b/src/Rules/Properties/TypesAssignedToPropertiesRule.php index bb2c2e83c0..f043cf3c3e 100644 --- a/src/Rules/Properties/TypesAssignedToPropertiesRule.php +++ b/src/Rules/Properties/TypesAssignedToPropertiesRule.php @@ -63,7 +63,7 @@ private function processSingleProperty( $scope = $propertyReflection->getScope(); $assignedValueType = $scope->getType($assignedExpr); - $accepts = $this->ruleLevelHelper->acceptsWithReason($propertyType, $assignedValueType, $scope->isDeclareStrictTypes()); + $accepts = $this->ruleLevelHelper->accepts($propertyType, $assignedValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { $propertyDescription = $this->describePropertyByName($propertyReflection, $propertyReflection->getName()); $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($propertyType, $assignedValueType); diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php index 1fe931aca5..94e1c914b2 100644 --- a/src/Rules/RuleLevelHelper.php +++ b/src/Rules/RuleLevelHelper.php @@ -46,12 +46,6 @@ public function isThis(Expr $expression): bool return $expression instanceof Expr\Variable && $expression->name === 'this'; } - /** @api */ - public function accepts(Type $acceptingType, Type $acceptedType, bool $strictTypes): bool - { - return $this->acceptsWithReason($acceptingType, $acceptedType, $strictTypes)->result; - } - private function transformCommonType(Type $type): Type { if (!$this->checkExplicitMixed && !$this->checkImplicitMixed) { @@ -144,12 +138,13 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType): return [$acceptedType, $checkForUnion]; } - public function acceptsWithReason(Type $acceptingType, Type $acceptedType, bool $strictTypes): RuleLevelHelperAcceptsResult + /** @api */ + public function accepts(Type $acceptingType, Type $acceptedType, bool $strictTypes): RuleLevelHelperAcceptsResult { [$acceptedType, $checkForUnion] = $this->transformAcceptedType($acceptingType, $acceptedType); $acceptingType = $this->transformCommonType($acceptingType); - $accepts = $acceptingType->acceptsWithReason($acceptedType, $strictTypes); + $accepts = $acceptingType->accepts($acceptedType, $strictTypes); return new RuleLevelHelperAcceptsResult( $checkForUnion ? $accepts->yes() : !$accepts->no(), diff --git a/src/Rules/RuleLevelHelperAcceptsResult.php b/src/Rules/RuleLevelHelperAcceptsResult.php index e33db8f0da..1b421c60a4 100644 --- a/src/Rules/RuleLevelHelperAcceptsResult.php +++ b/src/Rules/RuleLevelHelperAcceptsResult.php @@ -4,6 +4,9 @@ use function array_merge; +/** + * @api + */ final class RuleLevelHelperAcceptsResult { diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index d41d3c510f..637b8e75b0 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -74,15 +74,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } $isArray = $type->isArray(); @@ -116,12 +111,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/AccessoryLiteralStringType.php b/src/Type/Accessory/AccessoryLiteralStringType.php index 5f8705cfc5..52c2eeba10 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.php @@ -67,18 +67,13 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof MixedType) { return AcceptsResult::createNo(); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isLiteralString(), []); @@ -107,12 +102,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/AccessoryLowercaseStringType.php b/src/Type/Accessory/AccessoryLowercaseStringType.php index 48bb4b3179..2e4c9406fc 100644 --- a/src/Type/Accessory/AccessoryLowercaseStringType.php +++ b/src/Type/Accessory/AccessoryLowercaseStringType.php @@ -66,15 +66,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isLowercaseString(), []); @@ -103,12 +98,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/AccessoryNonEmptyStringType.php b/src/Type/Accessory/AccessoryNonEmptyStringType.php index 9815225062..61b9b60107 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -68,15 +68,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isNonEmptyString(), []); @@ -109,12 +104,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/AccessoryNonFalsyStringType.php b/src/Type/Accessory/AccessoryNonFalsyStringType.php index 6dca5f0514..e2a08f54e0 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.php @@ -68,15 +68,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isNonFalsyString(), []); @@ -109,12 +104,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/AccessoryNumericStringType.php b/src/Type/Accessory/AccessoryNumericStringType.php index ae15b4623e..b319a340fd 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.php @@ -67,15 +67,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isNumericString(), []); @@ -104,12 +99,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { if ($acceptingType->isNonFalsyString()->yes()) { return AcceptsResult::createMaybe(); diff --git a/src/Type/Accessory/HasMethodType.php b/src/Type/Accessory/HasMethodType.php index a28497912d..f556022dca 100644 --- a/src/Type/Accessory/HasMethodType.php +++ b/src/Type/Accessory/HasMethodType.php @@ -61,15 +61,10 @@ private function getCanonicalMethodName(): string return strtolower($this->methodName); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createFromBoolean($this->equals($type)); @@ -99,12 +94,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic return $limit->and($otherType->hasMethod($this->methodName)); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/HasOffsetType.php b/src/Type/Accessory/HasOffsetType.php index 132ae28edd..0903b3e877 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -77,15 +77,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); @@ -111,12 +106,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/HasOffsetValueType.php b/src/Type/Accessory/HasOffsetValueType.php index ec3a9908d1..a762290d5b 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -78,21 +78,16 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult( $type->isOffsetAccessible() ->and($type->hasOffsetValueType($this->offsetType)) - ->and($this->valueType->accepts($type->getOffsetValueType($this->offsetType), $strictTypes)), + ->and($this->valueType->accepts($type->getOffsetValueType($this->offsetType), $strictTypes)->result), [], ); } @@ -119,12 +114,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/HasPropertyType.php b/src/Type/Accessory/HasPropertyType.php index fdbc9b0bcc..f65b2bbe48 100644 --- a/src/Type/Accessory/HasPropertyType.php +++ b/src/Type/Accessory/HasPropertyType.php @@ -63,15 +63,10 @@ public function getPropertyName(): string return $this->propertyName; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createFromBoolean($this->equals($type)); @@ -97,12 +92,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic return $limit->and($otherType->hasProperty($this->propertyName)); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/NonEmptyArrayType.php b/src/Type/Accessory/NonEmptyArrayType.php index 50ccdb308e..2afc15de79 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -72,15 +72,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } $isArray = $type->isArray(); @@ -114,12 +109,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Accessory/OversizedArrayType.php b/src/Type/Accessory/OversizedArrayType.php index 113d0eb689..0d49eaf6cb 100644 --- a/src/Type/Accessory/OversizedArrayType.php +++ b/src/Type/Accessory/OversizedArrayType.php @@ -71,15 +71,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isArray()->and($type->isIterableAtLeastOnce()), []); @@ -110,12 +105,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 93d0094378..97ebb9a196 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -80,15 +80,10 @@ public function getConstantArrays(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } if ($type instanceof ConstantArrayType) { @@ -97,8 +92,8 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult $itemType = $this->getItemType(); foreach ($type->getKeyTypes() as $i => $keyType) { $valueType = $type->getValueTypes()[$i]; - $acceptsKey = $thisKeyType->acceptsWithReason($keyType, $strictTypes); - $acceptsValue = $itemType->acceptsWithReason($valueType, $strictTypes); + $acceptsKey = $thisKeyType->accepts($keyType, $strictTypes); + $acceptsValue = $itemType->accepts($valueType, $strictTypes); $result = $result->and($acceptsKey)->and($acceptsValue); } @@ -106,8 +101,8 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult } if ($type instanceof ArrayType) { - return $this->getItemType()->acceptsWithReason($type->getItemType(), $strictTypes) - ->and($this->keyType->acceptsWithReason($type->keyType, $strictTypes)); + return $this->getItemType()->accepts($type->getItemType(), $strictTypes) + ->and($this->keyType->accepts($type->keyType, $strictTypes)); } return AcceptsResult::createNo(); diff --git a/src/Type/BenevolentUnionType.php b/src/Type/BenevolentUnionType.php index c27a3d6cd0..b4ed647e25 100644 --- a/src/Type/BenevolentUnionType.php +++ b/src/Type/BenevolentUnionType.php @@ -87,16 +87,11 @@ protected function unionResults(callable $getResult): TrinaryLogic return TrinaryLogic::createNo()->lazyOr($this->getTypes(), $getResult); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { $result = AcceptsResult::createNo(); foreach ($this->getTypes() as $innerType) { - $result = $result->or($acceptingType->acceptsWithReason($innerType, $strictTypes)); + $result = $result->or($acceptingType->accepts($innerType, $strictTypes)); } return $result; diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 0f733ca60a..325a195d27 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -129,15 +129,10 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType && !$type instanceof self) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return $this->isSuperTypeOfInternal($type, true); @@ -204,12 +199,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/CallableTypeHelper.php b/src/Type/CallableTypeHelper.php index 29f416d3aa..e8253d1bfb 100644 --- a/src/Type/CallableTypeHelper.php +++ b/src/Type/CallableTypeHelper.php @@ -72,7 +72,7 @@ public static function isParametersAcceptorSuperTypeOf( } if ($treatMixedAsAny) { - $isSuperType = $theirParameter->getType()->acceptsWithReason($ourParameterType, true); + $isSuperType = $theirParameter->getType()->accepts($ourParameterType, true); } else { $isSuperType = new AcceptsResult($theirParameter->getType()->isSuperTypeOf($ourParameterType), []); } @@ -98,7 +98,7 @@ public static function isParametersAcceptorSuperTypeOf( $theirReturnType = $theirs->getReturnType(); if ($treatMixedAsAny) { - $isReturnTypeSuperType = $ours->getReturnType()->acceptsWithReason($theirReturnType, true); + $isReturnTypeSuperType = $ours->getReturnType()->accepts($theirReturnType, true); } else { $isReturnTypeSuperType = new AcceptsResult($ours->getReturnType()->isSuperTypeOf($theirReturnType), []); } diff --git a/src/Type/ClassStringType.php b/src/Type/ClassStringType.php index 4a74ec015a..41a9d16c74 100644 --- a/src/Type/ClassStringType.php +++ b/src/Type/ClassStringType.php @@ -21,15 +21,10 @@ public function describe(VerbosityLevel $level): string return 'class-string'; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isClassString(), []); diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index 90bef92255..ccd6c6cccb 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -188,19 +188,14 @@ public function getObjectClassReflections(): array return $this->objectType->getObjectClassReflections(); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } if (!$type instanceof ClosureType) { - return $this->objectType->acceptsWithReason($type, $strictTypes); + return $this->objectType->accepts($type, $strictTypes); } return $this->isSuperTypeOfInternal($type, true); diff --git a/src/Type/CompoundType.php b/src/Type/CompoundType.php index 775a4eb50f..8c6d8fd00d 100644 --- a/src/Type/CompoundType.php +++ b/src/Type/CompoundType.php @@ -11,9 +11,7 @@ interface CompoundType extends Type public function isSubTypeOf(Type $otherType): TrinaryLogic; - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic; - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult; + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult; public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic; diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 0d8d254eff..de72286489 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -297,15 +297,10 @@ public function isOptionalKey(int $i): bool return in_array($i, $this->optionalKeys, true); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType && !$type instanceof IntersectionType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } if ($type instanceof self && count($this->keyTypes) === 0) { @@ -333,7 +328,7 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult $result = $result->and($hasOffset); $otherValueType = $type->getOffsetValueType($keyType); $verbosity = VerbosityLevel::getRecommendedLevelByType($valueType, $otherValueType); - $acceptsValue = $valueType->acceptsWithReason($otherValueType, $strictTypes)->decorateReasons( + $acceptsValue = $valueType->accepts($otherValueType, $strictTypes)->decorateReasons( static fn (string $reason) => sprintf( 'Offset %s (%s) does not accept type %s: %s', $keyType->describe(VerbosityLevel::precise()), diff --git a/src/Type/Enum/EnumCaseObjectType.php b/src/Type/Enum/EnumCaseObjectType.php index 5bb5d0b5b7..cad4e394d1 100644 --- a/src/Type/Enum/EnumCaseObjectType.php +++ b/src/Type/Enum/EnumCaseObjectType.php @@ -59,12 +59,7 @@ public function equals(Type $type): bool $this->getClassName() === $type->getClassName(); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSuperTypeOf($type), []); } diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index 21d0a96904..a9bea4a070 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -64,19 +64,14 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof self || $type->isInteger()->yes()) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createNo(); diff --git a/src/Type/Generic/GenericClassStringType.php b/src/Type/Generic/GenericClassStringType.php index f7ecec9d86..ea2f583d8f 100644 --- a/src/Type/Generic/GenericClassStringType.php +++ b/src/Type/Generic/GenericClassStringType.php @@ -60,10 +60,10 @@ public function describe(VerbosityLevel $level): string return sprintf('%s<%s>', parent::describe($level), $this->type->describe($level)); } - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } if ($type instanceof ConstantStringType) { @@ -82,7 +82,7 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createNo(); } - return $this->type->acceptsWithReason($objectType, $strictTypes); + return $this->type->accepts($objectType, $strictTypes); } public function isSuperTypeOf(Type $type): TrinaryLogic diff --git a/src/Type/Generic/GenericObjectType.php b/src/Type/Generic/GenericObjectType.php index f13d52d4e3..b73a7efc94 100644 --- a/src/Type/Generic/GenericObjectType.php +++ b/src/Type/Generic/GenericObjectType.php @@ -118,15 +118,10 @@ public function getVariances(): array return $this->variances; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return $this->isSuperTypeOfInternal($type, true); @@ -192,9 +187,9 @@ private function isSuperTypeOfInternal(Type $type, bool $acceptsContext): Accept $thisVariance = $this->variances[$i] ?? TemplateTypeVariance::createInvariant(); $ancestorVariance = $ancestor->variances[$i] ?? TemplateTypeVariance::createInvariant(); if (!$thisVariance->invariant()) { - $results[] = $thisVariance->isValidVarianceWithReason($templateType, $this->types[$i], $ancestor->types[$i]); + $results[] = $thisVariance->isValidVariance($templateType, $this->types[$i], $ancestor->types[$i]); } else { - $results[] = $templateType->isValidVarianceWithReason($this->types[$i], $ancestor->types[$i]); + $results[] = $templateType->isValidVariance($this->types[$i], $ancestor->types[$i]); } $results[] = AcceptsResult::createFromBoolean($thisVariance->validPosition($ancestorVariance)); diff --git a/src/Type/Generic/TemplateMixedType.php b/src/Type/Generic/TemplateMixedType.php index 3363818673..e0c579074c 100644 --- a/src/Type/Generic/TemplateMixedType.php +++ b/src/Type/Generic/TemplateMixedType.php @@ -40,12 +40,7 @@ public function isSuperTypeOfMixed(MixedType $type): TrinaryLogic return $this->isSuperTypeOf($type); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { $isSuperType = new AcceptsResult($this->isSuperTypeOf($acceptingType), []); if ($isSuperType->no()) { diff --git a/src/Type/Generic/TemplateStrictMixedType.php b/src/Type/Generic/TemplateStrictMixedType.php index 6ae56cc228..897fb71524 100644 --- a/src/Type/Generic/TemplateStrictMixedType.php +++ b/src/Type/Generic/TemplateStrictMixedType.php @@ -38,12 +38,7 @@ public function isSuperTypeOfMixed(MixedType $type): TrinaryLogic return $this->isSuperTypeOf($type); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/Generic/TemplateType.php b/src/Type/Generic/TemplateType.php index 7661078ca1..367c94e709 100644 --- a/src/Type/Generic/TemplateType.php +++ b/src/Type/Generic/TemplateType.php @@ -2,7 +2,6 @@ namespace PHPStan\Type\Generic; -use PHPStan\TrinaryLogic; use PHPStan\Type\AcceptsResult; use PHPStan\Type\CompoundType; use PHPStan\Type\Type; @@ -22,9 +21,7 @@ public function toArgument(): TemplateType; public function isArgument(): bool; - public function isValidVariance(Type $a, Type $b): TrinaryLogic; - - public function isValidVarianceWithReason(Type $a, Type $b): AcceptsResult; + public function isValidVariance(Type $a, Type $b): AcceptsResult; public function getVariance(): TemplateTypeVariance; diff --git a/src/Type/Generic/TemplateTypeArgumentStrategy.php b/src/Type/Generic/TemplateTypeArgumentStrategy.php index 8c98baaacc..0e8f59cf5e 100644 --- a/src/Type/Generic/TemplateTypeArgumentStrategy.php +++ b/src/Type/Generic/TemplateTypeArgumentStrategy.php @@ -18,9 +18,9 @@ final class TemplateTypeArgumentStrategy implements TemplateTypeStrategy public function accepts(TemplateType $left, Type $right, bool $strictTypes): AcceptsResult { if ($right instanceof CompoundType) { - $accepts = $right->isAcceptedWithReasonBy($left, $strictTypes); + $accepts = $right->isAcceptedBy($left, $strictTypes); } else { - $accepts = $left->getBound()->acceptsWithReason($right, $strictTypes) + $accepts = $left->getBound()->accepts($right, $strictTypes) ->and(AcceptsResult::createMaybe()); if ($accepts->maybe()) { $verbosity = VerbosityLevel::getRecommendedLevelByType($left, $right); diff --git a/src/Type/Generic/TemplateTypeParameterStrategy.php b/src/Type/Generic/TemplateTypeParameterStrategy.php index 949f3bfa52..3e18bccf2d 100644 --- a/src/Type/Generic/TemplateTypeParameterStrategy.php +++ b/src/Type/Generic/TemplateTypeParameterStrategy.php @@ -15,10 +15,10 @@ final class TemplateTypeParameterStrategy implements TemplateTypeStrategy public function accepts(TemplateType $left, Type $right, bool $strictTypes): AcceptsResult { if ($right instanceof CompoundType) { - return $right->isAcceptedWithReasonBy($left, $strictTypes); + return $right->isAcceptedBy($left, $strictTypes); } - return $left->getBound()->acceptsWithReason($right, $strictTypes); + return $left->getBound()->accepts($right, $strictTypes); } public function isArgument(): bool diff --git a/src/Type/Generic/TemplateTypeTrait.php b/src/Type/Generic/TemplateTypeTrait.php index e1a170a57d..979867b458 100644 --- a/src/Type/Generic/TemplateTypeTrait.php +++ b/src/Type/Generic/TemplateTypeTrait.php @@ -91,14 +91,9 @@ public function toArgument(): TemplateType ); } - public function isValidVariance(Type $a, Type $b): TrinaryLogic + public function isValidVariance(Type $a, Type $b): AcceptsResult { - return $this->isValidVarianceWithReason($a, $b)->result; - } - - public function isValidVarianceWithReason(Type $a, Type $b): AcceptsResult - { - return $this->variance->isValidVarianceWithReason($this, $a, $b); + return $this->variance->isValidVariance($this, $a, $b); } public function subtract(Type $typeToRemove): Type @@ -163,12 +158,7 @@ public function equals(Type $type): bool && $this->bound->equals($type->bound); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { /** @var TBound $bound */ $bound = $this->getBound(); @@ -178,27 +168,22 @@ public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): && !$acceptingType instanceof TemplateType && ($acceptingType instanceof UnionType || $acceptingType instanceof IntersectionType) ) { - return $acceptingType->acceptsWithReason($this, $strictTypes); + return $acceptingType->accepts($this, $strictTypes); } if (!$acceptingType instanceof TemplateType) { - return $acceptingType->acceptsWithReason($this->getBound(), $strictTypes); + return $acceptingType->accepts($this->getBound(), $strictTypes); } if ($this->getScope()->equals($acceptingType->getScope()) && $this->getName() === $acceptingType->getName()) { - return $acceptingType->getBound()->acceptsWithReason($this->getBound(), $strictTypes); + return $acceptingType->getBound()->accepts($this->getBound(), $strictTypes); } - return $acceptingType->getBound()->acceptsWithReason($this->getBound(), $strictTypes) + return $acceptingType->getBound()->accepts($this->getBound(), $strictTypes) ->and(new AcceptsResult(TrinaryLogic::createMaybe(), [])); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { return $this->strategy->accepts($this, $type, $strictTypes); } diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index 24f8fe2927..4f4c704aa0 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -126,12 +126,7 @@ public function compose(self $other): self return $other; } - public function isValidVariance(Type $a, Type $b): TrinaryLogic - { - return $this->isValidVarianceWithReason(null, $a, $b)->result; - } - - public function isValidVarianceWithReason(?TemplateType $templateType, Type $a, Type $b): AcceptsResult + public function isValidVariance(TemplateType $templateType, Type $a, Type $b): AcceptsResult { if ($b instanceof NeverType) { return AcceptsResult::createYes(); @@ -162,8 +157,7 @@ public function isValidVarianceWithReason(?TemplateType $templateType, Type $a, $reasons = []; if (!$result) { if ( - $templateType !== null - && $templateType->getScope()->getClassName() !== null + $templateType->getScope()->getClassName() !== null && $a->isSuperTypeOf($b)->yes() ) { $reasons[] = sprintf( diff --git a/src/Type/IntegerRangeType.php b/src/Type/IntegerRangeType.php index e957bee8ea..8c0031ca10 100644 --- a/src/Type/IntegerRangeType.php +++ b/src/Type/IntegerRangeType.php @@ -201,19 +201,14 @@ public function shift(int $amount): Type return self::fromInterval($min, $max); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof parent) { return new AcceptsResult($this->isSuperTypeOf($type), []); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createNo(); @@ -288,12 +283,7 @@ private function isSubTypeOfUnion(UnionType $otherType): TrinaryLogic return TrinaryLogic::createNo()->lazyOr($otherType->getTypes(), fn (Type $innerType) => $this->isSubTypeOf($innerType)); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index 3c193d15f5..0117d14999 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -179,16 +179,11 @@ public function getConstantStrings(): array return $strings; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $otherType, bool $strictTypes): AcceptsResult + public function accepts(Type $otherType, bool $strictTypes): AcceptsResult { $result = AcceptsResult::createYes(); foreach ($this->types as $type) { - $result = $result->and($type->acceptsWithReason($otherType, $strictTypes)); + $result = $result->and($type->accepts($otherType, $strictTypes)); } if (!$result->yes()) { @@ -249,14 +244,9 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic return $result; } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - $result = AcceptsResult::maxMin(...array_map(static fn (Type $innerType) => $acceptingType->acceptsWithReason($innerType, $strictTypes), $this->types)); + $result = AcceptsResult::maxMin(...array_map(static fn (Type $innerType) => $acceptingType->accepts($innerType, $strictTypes), $this->types)); if ($this->isOversizedArray()->yes()) { if (!$result->no()) { return AcceptsResult::createYes(); diff --git a/src/Type/IterableType.php b/src/Type/IterableType.php index b1dcbec2fe..512f88ac7a 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -78,23 +78,18 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()) { return AcceptsResult::createYes(); } if ($type->isIterable()->yes()) { - return $this->getIterableValueType()->acceptsWithReason($type->getIterableValueType(), $strictTypes) - ->and($this->getIterableKeyType()->acceptsWithReason($type->getIterableKeyType(), $strictTypes)); + return $this->getIterableValueType()->accepts($type->getIterableValueType(), $strictTypes) + ->and($this->getIterableKeyType()->accepts($type->getIterableKeyType(), $strictTypes)); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createNo(); @@ -168,12 +163,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic ); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/JustNullableTypeTrait.php b/src/Type/JustNullableTypeTrait.php index 912dd68499..481e9fb3ac 100644 --- a/src/Type/JustNullableTypeTrait.php +++ b/src/Type/JustNullableTypeTrait.php @@ -26,19 +26,14 @@ public function getObjectClassReflections(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof static) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createNo(); diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index 08f7f0f205..43814c3643 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -94,12 +94,7 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { return AcceptsResult::createYes(); } @@ -332,12 +327,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { $isSuperType = new AcceptsResult($this->isSuperTypeOf($acceptingType), []); if ($isSuperType->no()) { diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index 66193ded71..50266db06b 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -72,12 +72,7 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { return AcceptsResult::createYes(); } @@ -101,12 +96,7 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic return TrinaryLogic::createYes(); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { return new AcceptsResult($this->isSubTypeOf($acceptingType), []); } diff --git a/src/Type/NonAcceptingNeverType.php b/src/Type/NonAcceptingNeverType.php index 3eaddf53cb..3424c664e5 100644 --- a/src/Type/NonAcceptingNeverType.php +++ b/src/Type/NonAcceptingNeverType.php @@ -26,7 +26,7 @@ public function isSuperTypeOf(Type $type): TrinaryLogic return TrinaryLogic::createNo(); } - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof NeverType) { return AcceptsResult::createYes(); diff --git a/src/Type/NullType.php b/src/Type/NullType.php index 753dccc5d8..b8ba6be336 100644 --- a/src/Type/NullType.php +++ b/src/Type/NullType.php @@ -72,19 +72,14 @@ public function generalize(GeneralizePrecision $precision): Type return $this; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof self) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createNo(); diff --git a/src/Type/ObjectShapeType.php b/src/Type/ObjectShapeType.php index 6878401ef0..946fb597d1 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -122,15 +122,10 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember ); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } $reflectionProvider = ReflectionProviderStaticAccessor::getInstance(); @@ -207,7 +202,7 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult $otherPropertyType = $otherProperty->getReadableType(); $verbosity = VerbosityLevel::getRecommendedLevelByType($propertyType, $otherPropertyType); - $acceptsValue = $propertyType->acceptsWithReason($otherPropertyType, $strictTypes)->decorateReasons( + $acceptsValue = $propertyType->accepts($otherPropertyType, $strictTypes)->decorateReasons( static fn (string $reason) => sprintf( 'Property ($%s) type %s does not accept type %s: %s', $propertyName, diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 2026e447f0..30f8be4640 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -278,19 +278,14 @@ public function getObjectClassReflections(): array return [$classReflection]; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof StaticType) { return $this->checkSubclassAcceptability($type->getClassName()); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } if ($type instanceof ClosureType) { diff --git a/src/Type/ObjectWithoutClassType.php b/src/Type/ObjectWithoutClassType.php index 5b388ba712..e9cd001bdc 100644 --- a/src/Type/ObjectWithoutClassType.php +++ b/src/Type/ObjectWithoutClassType.php @@ -52,15 +52,10 @@ public function getObjectClassReflections(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return AcceptsResult::createFromBoolean( diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index ab8fc9d1a0..9c720b5e52 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -132,22 +132,17 @@ public function getConstantStrings(): array return $this->getStaticObjectType()->getConstantStrings(); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } if (!$type instanceof static) { return AcceptsResult::createNo(); } - return $this->getStaticObjectType()->acceptsWithReason($type->getStaticObjectType(), $strictTypes); + return $this->getStaticObjectType()->accepts($type->getStaticObjectType(), $strictTypes); } public function isSuperTypeOf(Type $type): TrinaryLogic diff --git a/src/Type/StrictMixedType.php b/src/Type/StrictMixedType.php index c5d76697c6..1a269cb65f 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -51,22 +51,12 @@ public function getConstantStrings(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { return AcceptsResult::createYes(); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { if ($acceptingType instanceof self) { return AcceptsResult::createYes(); diff --git a/src/Type/StringAlwaysAcceptingObjectWithToStringType.php b/src/Type/StringAlwaysAcceptingObjectWithToStringType.php index 0130d7e094..c393a956d8 100644 --- a/src/Type/StringAlwaysAcceptingObjectWithToStringType.php +++ b/src/Type/StringAlwaysAcceptingObjectWithToStringType.php @@ -33,11 +33,11 @@ public function isSuperTypeOf(Type $type): TrinaryLogic return $result; } - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { $thatClassNames = $type->getObjectClassNames(); if ($thatClassNames === []) { - return parent::acceptsWithReason($type, $strictTypes); + return parent::accepts($type, $strictTypes); } $result = AcceptsResult::createNo(); diff --git a/src/Type/StringType.php b/src/Type/StringType.php index 55fb28c2c1..d6e48cd851 100644 --- a/src/Type/StringType.php +++ b/src/Type/StringType.php @@ -109,19 +109,14 @@ public function unsetOffset(Type $offsetType): Type return new ErrorType(); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof self) { return AcceptsResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } $thatClassNames = $type->getObjectClassNames(); diff --git a/src/Type/Traits/ConstantScalarTypeTrait.php b/src/Type/Traits/ConstantScalarTypeTrait.php index 7452cd3c83..618b3b5494 100644 --- a/src/Type/Traits/ConstantScalarTypeTrait.php +++ b/src/Type/Traits/ConstantScalarTypeTrait.php @@ -16,22 +16,17 @@ trait ConstantScalarTypeTrait { - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof self) { return AcceptsResult::createFromBoolean($this->equals($type)); } if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } - return parent::acceptsWithReason($type, $strictTypes)->and(AcceptsResult::createMaybe()); + return parent::accepts($type, $strictTypes)->and(AcceptsResult::createMaybe()); } public function isSuperTypeOf(Type $type): TrinaryLogic diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index 03120df9f4..f5d2b1dce2 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -48,16 +48,11 @@ public function getConstantStrings(): array return $this->resolve()->getConstantStrings(); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic + public function accepts(Type $type, bool $strictTypes): AcceptsResult { return $this->resolve()->accepts($type, $strictTypes); } - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult - { - return $this->resolve()->acceptsWithReason($type, $strictTypes); - } - public function isSuperTypeOf(Type $type): TrinaryLogic { return $this->isSuperTypeOfDefault($type); @@ -528,20 +523,15 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic return $otherType->isSuperTypeOf($result); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { $result = $this->resolve(); if ($result instanceof CompoundType) { - return $result->isAcceptedWithReasonBy($acceptingType, $strictTypes); + return $result->isAcceptedBy($acceptingType, $strictTypes); } - return $acceptingType->acceptsWithReason($result, $strictTypes); + return $acceptingType->accepts($result, $strictTypes); } public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic diff --git a/src/Type/Type.php b/src/Type/Type.php index 0f89e01a93..21b15c221b 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -64,8 +64,6 @@ public function getConstantArrays(): array; /** @return list */ public function getConstantStrings(): array; - public function accepts(Type $type, bool $strictTypes): TrinaryLogic; - /** * This is like accepts() but gives reasons * why the type was not/might not be accepted in some non-intuitive scenarios. @@ -73,7 +71,7 @@ public function accepts(Type $type, bool $strictTypes): TrinaryLogic; * In PHPStan 2.0 this method will be removed and the return type of accepts() * will change to AcceptsResult. */ - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult; + public function accepts(Type $type, bool $strictTypes): AcceptsResult; public function isSuperTypeOf(Type $type): TrinaryLogic; diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 454f511c75..704bd421b2 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -161,12 +161,7 @@ public function getConstantStrings(): array ); } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ( $type->equals(new ObjectType(DateTimeInterface::class)) @@ -180,24 +175,24 @@ public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult $result = AcceptsResult::createNo(); foreach ($this->getSortedTypes() as $i => $innerType) { - $result = $result->or($innerType->acceptsWithReason($type, $strictTypes)->decorateReasons(static fn (string $reason) => sprintf('Type #%d from the union: %s', $i + 1, $reason))); + $result = $result->or($innerType->accepts($type, $strictTypes)->decorateReasons(static fn (string $reason) => sprintf('Type #%d from the union: %s', $i + 1, $reason))); } if ($result->yes()) { return $result; } if ($type instanceof CompoundType && !$type instanceof CallableType && !$type instanceof TemplateType && !$type instanceof IntersectionType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } if ($type instanceof TemplateUnionType) { - return $result->or($type->isAcceptedWithReasonBy($this, $strictTypes)); + return $result->or($type->isAcceptedBy($this, $strictTypes)); } if ($type->isEnum()->yes() && !$this->isEnum()->no()) { $enumCasesUnion = TypeCombinator::union(...$type->getEnumCases()); if (!$type->equals($enumCasesUnion)) { - return $this->acceptsWithReason($enumCasesUnion, $strictTypes); + return $this->accepts($enumCasesUnion, $strictTypes); } } @@ -234,14 +229,9 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic return TrinaryLogic::lazyExtremeIdentity($this->getTypes(), static fn (Type $innerType) => $otherType->isSuperTypeOf($innerType)); } - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic - { - return $this->isAcceptedWithReasonBy($acceptingType, $strictTypes)->result; - } - - public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult + public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return AcceptsResult::extremeIdentity(...array_map(static fn (Type $innerType) => $acceptingType->acceptsWithReason($innerType, $strictTypes), $this->types)); + return AcceptsResult::extremeIdentity(...array_map(static fn (Type $innerType) => $acceptingType->accepts($innerType, $strictTypes), $this->types)); } public function equals(Type $type): bool diff --git a/src/Type/VoidType.php b/src/Type/VoidType.php index 16bf203351..a49c642aca 100644 --- a/src/Type/VoidType.php +++ b/src/Type/VoidType.php @@ -55,15 +55,10 @@ public function getObjectClassReflections(): array return []; } - public function accepts(Type $type, bool $strictTypes): TrinaryLogic - { - return $this->acceptsWithReason($type, $strictTypes)->result; - } - - public function acceptsWithReason(Type $type, bool $strictTypes): AcceptsResult + public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof CompoundType) { - return $type->isAcceptedWithReasonBy($this, $strictTypes); + return $type->isAcceptedBy($this, $strictTypes); } return new AcceptsResult($type->isVoid()->or($type->isNull()), []); diff --git a/tests/PHPStan/Type/ArrayTypeTest.php b/tests/PHPStan/Type/ArrayTypeTest.php index cd8ddce5bf..98332b7031 100644 --- a/tests/PHPStan/Type/ArrayTypeTest.php +++ b/tests/PHPStan/Type/ArrayTypeTest.php @@ -145,7 +145,7 @@ public function testAccepts( TrinaryLogic $expectedResult, ): void { - $actualResult = $acceptingType->accepts($acceptedType, true); + $actualResult = $acceptingType->accepts($acceptedType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/BooleanTypeTest.php b/tests/PHPStan/Type/BooleanTypeTest.php index 375210eea2..f7552cba51 100644 --- a/tests/PHPStan/Type/BooleanTypeTest.php +++ b/tests/PHPStan/Type/BooleanTypeTest.php @@ -52,7 +52,7 @@ public function dataAccepts(): array */ public function testAccepts(BooleanType $type, Type $otherType, TrinaryLogic $expectedResult): void { - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/CallableTypeTest.php b/tests/PHPStan/Type/CallableTypeTest.php index 87d3bae274..a59308f40c 100644 --- a/tests/PHPStan/Type/CallableTypeTest.php +++ b/tests/PHPStan/Type/CallableTypeTest.php @@ -423,7 +423,7 @@ public function testAccepts( { $this->assertSame( $expectedResult->describe(), - $type->accepts($acceptedType, true)->describe(), + $type->accepts($acceptedType, true)->result->describe(), sprintf('%s -> accepts(%s)', $type->describe(VerbosityLevel::precise()), $acceptedType->describe(VerbosityLevel::precise())), ); } diff --git a/tests/PHPStan/Type/ClassStringTypeTest.php b/tests/PHPStan/Type/ClassStringTypeTest.php index 2d827f7271..f4d19a2760 100644 --- a/tests/PHPStan/Type/ClassStringTypeTest.php +++ b/tests/PHPStan/Type/ClassStringTypeTest.php @@ -108,7 +108,7 @@ public function dataAccepts(): iterable */ public function testAccepts(ClassStringType $type, Type $otherType, TrinaryLogic $expectedResult): void { - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php b/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php index 9e814dfaf8..f2ee31c44f 100644 --- a/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php +++ b/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php @@ -413,7 +413,7 @@ public function dataAccepts(): iterable */ public function testAccepts(Type $type, Type $otherType, TrinaryLogic $expectedResult): void { - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/Constant/ConstantIntegerTypeTest.php b/tests/PHPStan/Type/Constant/ConstantIntegerTypeTest.php index 1b39e5ff55..c33c33e5a6 100644 --- a/tests/PHPStan/Type/Constant/ConstantIntegerTypeTest.php +++ b/tests/PHPStan/Type/Constant/ConstantIntegerTypeTest.php @@ -38,7 +38,7 @@ public function dataAccepts(): iterable */ public function testAccepts(ConstantIntegerType $type, Type $otherType, TrinaryLogic $expectedResult): void { - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/Enum/EnumCaseObjectTypeTest.php b/tests/PHPStan/Type/Enum/EnumCaseObjectTypeTest.php index e700d67a3d..1bf9013c42 100644 --- a/tests/PHPStan/Type/Enum/EnumCaseObjectTypeTest.php +++ b/tests/PHPStan/Type/Enum/EnumCaseObjectTypeTest.php @@ -219,7 +219,7 @@ public function testAccepts( $this->assertSame( $expectedResult->describe(), - $type->accepts($acceptedType, true)->describe(), + $type->accepts($acceptedType, true)->result->describe(), sprintf('%s -> accepts(%s)', $type->describe(VerbosityLevel::precise()), $acceptedType->describe(VerbosityLevel::precise())), ); } diff --git a/tests/PHPStan/Type/FloatTypeTest.php b/tests/PHPStan/Type/FloatTypeTest.php index ef878bf6dd..04a9c270ca 100644 --- a/tests/PHPStan/Type/FloatTypeTest.php +++ b/tests/PHPStan/Type/FloatTypeTest.php @@ -66,7 +66,7 @@ public function dataAccepts(): array public function testAccepts(Type $otherType, TrinaryLogic $expectedResult): void { $type = new FloatType(); - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/Generic/GenericClassStringTypeTest.php b/tests/PHPStan/Type/Generic/GenericClassStringTypeTest.php index 3efd727f4c..ef6a0faf8d 100644 --- a/tests/PHPStan/Type/Generic/GenericClassStringTypeTest.php +++ b/tests/PHPStan/Type/Generic/GenericClassStringTypeTest.php @@ -284,7 +284,7 @@ public function testAccepts( TrinaryLogic $expectedResult, ): void { - $actualResult = $acceptingType->accepts($acceptedType, true); + $actualResult = $acceptingType->accepts($acceptedType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php b/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php index 273394c6b6..30539fae85 100644 --- a/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php +++ b/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php @@ -340,7 +340,7 @@ public function testAccepts( TrinaryLogic $expectedResult, ): void { - $actualResult = $acceptingType->accepts($acceptedType, true); + $actualResult = $acceptingType->accepts($acceptedType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/Generic/TemplateTypeVarianceTest.php b/tests/PHPStan/Type/Generic/TemplateTypeVarianceTest.php index 71a57dda6d..c5bd9ac0a6 100644 --- a/tests/PHPStan/Type/Generic/TemplateTypeVarianceTest.php +++ b/tests/PHPStan/Type/Generic/TemplateTypeVarianceTest.php @@ -87,14 +87,15 @@ public function testIsValidVariance( TrinaryLogic $expectedInversed, ): void { + $templateType = TemplateTypeFactory::create(TemplateTypeScope::createWithFunction('foo'), 'T', null, $variance); $this->assertSame( $expected->describe(), - $variance->isValidVariance($a, $b)->describe(), + $variance->isValidVariance($templateType, $a, $b)->result->describe(), sprintf('%s->isValidVariance(%s, %s)', $variance->describe(), $a->describe(VerbosityLevel::precise()), $b->describe(VerbosityLevel::precise())), ); $this->assertSame( $expectedInversed->describe(), - $variance->isValidVariance($b, $a)->describe(), + $variance->isValidVariance($templateType, $b, $a)->result->describe(), sprintf('%s->isValidVariance(%s, %s)', $variance->describe(), $b->describe(VerbosityLevel::precise()), $a->describe(VerbosityLevel::precise())), ); } diff --git a/tests/PHPStan/Type/IntegerTypeTest.php b/tests/PHPStan/Type/IntegerTypeTest.php index a1c83f7885..79c3ef9560 100644 --- a/tests/PHPStan/Type/IntegerTypeTest.php +++ b/tests/PHPStan/Type/IntegerTypeTest.php @@ -53,7 +53,7 @@ public function dataAccepts(): array */ public function testAccepts(IntegerType $type, Type $otherType, TrinaryLogic $expectedResult): void { - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/IntersectionTypeTest.php b/tests/PHPStan/Type/IntersectionTypeTest.php index b6fa0c0b4a..c5dbfc07ab 100644 --- a/tests/PHPStan/Type/IntersectionTypeTest.php +++ b/tests/PHPStan/Type/IntersectionTypeTest.php @@ -71,7 +71,7 @@ public function dataAccepts(): Iterator */ public function testAccepts(IntersectionType $type, Type $otherType, TrinaryLogic $expectedResult): void { - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/IterableTypeTest.php b/tests/PHPStan/Type/IterableTypeTest.php index 2094ebf589..013c0fd15c 100644 --- a/tests/PHPStan/Type/IterableTypeTest.php +++ b/tests/PHPStan/Type/IterableTypeTest.php @@ -329,7 +329,7 @@ public function dataAccepts(): array */ public function testAccepts(IterableType $iterableType, Type $otherType, TrinaryLogic $expectedResult): void { - $actualResult = $iterableType->accepts($otherType, true); + $actualResult = $iterableType->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/ObjectTypeTest.php b/tests/PHPStan/Type/ObjectTypeTest.php index 6d8cfb28ee..f17c18ea97 100644 --- a/tests/PHPStan/Type/ObjectTypeTest.php +++ b/tests/PHPStan/Type/ObjectTypeTest.php @@ -531,7 +531,7 @@ public function testAccepts( { $this->assertSame( $expectedResult->describe(), - $type->accepts($acceptedType, true)->describe(), + $type->accepts($acceptedType, true)->result->describe(), sprintf('%s -> accepts(%s)', $type->describe(VerbosityLevel::precise()), $acceptedType->describe(VerbosityLevel::precise())), ); } diff --git a/tests/PHPStan/Type/StringTypeTest.php b/tests/PHPStan/Type/StringTypeTest.php index 8f22550446..813349b91a 100644 --- a/tests/PHPStan/Type/StringTypeTest.php +++ b/tests/PHPStan/Type/StringTypeTest.php @@ -179,7 +179,7 @@ public function dataAccepts(): iterable */ public function testAccepts(StringType $type, Type $otherType, TrinaryLogic $expectedResult): void { - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedResult->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/TemplateTypeTest.php b/tests/PHPStan/Type/TemplateTypeTest.php index 3a17311989..6b184eef8a 100644 --- a/tests/PHPStan/Type/TemplateTypeTest.php +++ b/tests/PHPStan/Type/TemplateTypeTest.php @@ -108,7 +108,7 @@ public function testAccepts( { assert($type instanceof TemplateType); - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedAccept->describe(), $actualResult->describe(), @@ -117,7 +117,7 @@ public function testAccepts( $type = $type->toArgument(); - $actualResult = $type->accepts($otherType, true); + $actualResult = $type->accepts($otherType, true)->result; $this->assertSame( $expectedAcceptArg->describe(), $actualResult->describe(), diff --git a/tests/PHPStan/Type/UnionTypeTest.php b/tests/PHPStan/Type/UnionTypeTest.php index 83ec097e23..46b5803374 100644 --- a/tests/PHPStan/Type/UnionTypeTest.php +++ b/tests/PHPStan/Type/UnionTypeTest.php @@ -1305,7 +1305,7 @@ public function testAccepts( { $this->assertSame( $expectedResult->describe(), - $type->accepts($acceptedType, true)->describe(), + $type->accepts($acceptedType, true)->result->describe(), sprintf('%s -> accepts(%s)', $type->describe(VerbosityLevel::precise()), $acceptedType->describe(VerbosityLevel::precise())), ); } From c067207bdeed8134d054de63444c53083132ddac Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 10:11:13 +0200 Subject: [PATCH 326/508] Fix build --- tests/PHPStan/Levels/data/unreachable-0.json | 12 ------------ tests/PHPStan/Levels/data/unreachable-4.json | 10 ++++++++++ 2 files changed, 10 insertions(+), 12 deletions(-) delete mode 100644 tests/PHPStan/Levels/data/unreachable-0.json diff --git a/tests/PHPStan/Levels/data/unreachable-0.json b/tests/PHPStan/Levels/data/unreachable-0.json deleted file mode 100644 index 5091fec153..0000000000 --- a/tests/PHPStan/Levels/data/unreachable-0.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "message": "Return value of function print_r() is always true and the result is printed instead of being returned. Pass in true as parameter #2 $return to return the output instead.", - "line": 38, - "ignorable": true - }, - { - "message": "Return value of function print_r() is always true and the result is printed instead of being returned. Pass in true as parameter #2 $return to return the output instead.", - "line": 89, - "ignorable": true - } -] diff --git a/tests/PHPStan/Levels/data/unreachable-4.json b/tests/PHPStan/Levels/data/unreachable-4.json index 6f937312ae..4e6216b466 100644 --- a/tests/PHPStan/Levels/data/unreachable-4.json +++ b/tests/PHPStan/Levels/data/unreachable-4.json @@ -19,6 +19,11 @@ "line": 38, "ignorable": true }, + { + "message": "Return value of function print_r() is always true and the result is printed instead of being returned. Pass in true as parameter #2 $return to return the output instead.", + "line": 38, + "ignorable": true + }, { "message": "If condition is always true.", "line": 47, @@ -64,6 +69,11 @@ "line": 84, "ignorable": true }, + { + "message": "Return value of function print_r() is always true and the result is printed instead of being returned. Pass in true as parameter #2 $return to return the output instead.", + "line": 89, + "ignorable": true + }, { "message": "Ternary operator condition is always true.", "line": 89, From 41275dcaca934a0956a6a50af4bba6f0ee4356b7 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 10:15:59 +0200 Subject: [PATCH 327/508] [BCB] ConstantReflection --- UPGRADING.md | 5 + src/Analyser/MutatingScope.php | 6 +- src/Analyser/OutOfClassScope.php | 4 +- src/Analyser/Scope.php | 4 +- src/PhpDoc/PhpDocBlock.php | 4 +- .../BetterReflectionProvider.php | 6 +- src/Reflection/ClassConstantReflection.php | 135 +---------------- src/Reflection/ClassMemberAccessAnswerer.php | 2 +- src/Reflection/ClassReflection.php | 4 +- .../Constant/RuntimeConstantReflection.php | 4 +- src/Reflection/ConstantReflection.php | 17 ++- ...n.php => DummyClassConstantReflection.php} | 29 +++- src/Reflection/GlobalConstantReflection.php | 24 --- .../RealClassClassConstantReflection.php | 140 ++++++++++++++++++ src/Reflection/ReflectionProvider.php | 2 +- .../DummyReflectionProvider.php | 4 +- .../MemoizingReflectionProvider.php | 4 +- .../AlwaysUsedClassConstantsExtension.php | 4 +- .../Constants/OverridingConstantRule.php | 5 +- src/Type/ClosureType.php | 4 +- src/Type/Constant/ConstantStringType.php | 4 +- src/Type/IntersectionType.php | 4 +- src/Type/MixedType.php | 8 +- src/Type/NeverType.php | 4 +- src/Type/NonexistentParentClassType.php | 4 +- src/Type/ObjectType.php | 4 +- src/Type/StaticType.php | 4 +- src/Type/StrictMixedType.php | 4 +- src/Type/Traits/LateResolvableTypeTrait.php | 4 +- src/Type/Traits/MaybeObjectTypeTrait.php | 8 +- src/Type/Traits/NonObjectTypeTrait.php | 4 +- src/Type/Traits/ObjectTypeTrait.php | 8 +- src/Type/Type.php | 4 +- src/Type/UnionType.php | 6 +- .../data/class-implements-out-of-phpstan.php | 2 +- .../UnusedPrivateConstantRuleTest.php | 4 +- 36 files changed, 260 insertions(+), 223 deletions(-) rename src/Reflection/Dummy/{DummyConstantReflection.php => DummyClassConstantReflection.php} (75%) delete mode 100644 src/Reflection/GlobalConstantReflection.php create mode 100644 src/Reflection/RealClassClassConstantReflection.php diff --git a/UPGRADING.md b/UPGRADING.md index cdaad24fcf..dc6ac842e1 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -293,3 +293,8 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) * Remove `CompoundType::isAcceptedWithReasonBy()`, `CompoundType::isAcceptedBy()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) * `RuleLevelHelper::accepts()` return type changed from `bool` to [`RuleLevelHelperAcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) +* Changes around `ClassConstantReflection` + * Class `ClassConstantReflection` removed from BC promise, renamed to `RealClassConstantReflection` + * Interface `ConstantReflection` renamed to `ClassConstantReflection` + * Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection` + * Interface `GlobalConstantReflection` renamed to `ConstantReflection` diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 4317d5945a..5d11b826c6 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -52,9 +52,9 @@ use PHPStan\Reflection\Callables\CallableParametersAcceptor; use PHPStan\Reflection\Callables\SimpleImpurePoint; use PHPStan\Reflection\Callables\SimpleThrowPoint; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\Dummy\DummyConstructorReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; @@ -5326,7 +5326,7 @@ public function canCallMethod(MethodReflection $methodReflection): bool } /** @api */ - public function canAccessConstant(ConstantReflection $constantReflection): bool + public function canAccessConstant(ClassConstantReflection $constantReflection): bool { return $this->canAccessClassMember($constantReflection); } @@ -5690,7 +5690,7 @@ private function propertyFetchType(Type $fetchedOnType, string $propertyName, Ex return $propertyReflection->getReadableType(); } - public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ConstantReflection + public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ClassConstantReflection { if ($typeWithConstant instanceof UnionType) { $newTypes = []; diff --git a/src/Analyser/OutOfClassScope.php b/src/Analyser/OutOfClassScope.php index 42a85108c9..925e35a50e 100644 --- a/src/Analyser/OutOfClassScope.php +++ b/src/Analyser/OutOfClassScope.php @@ -2,9 +2,9 @@ namespace PHPStan\Analyser; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\PropertyReflection; @@ -36,7 +36,7 @@ public function canCallMethod(MethodReflection $methodReflection): bool return $methodReflection->isPublic(); } - public function canAccessConstant(ConstantReflection $constantReflection): bool + public function canAccessConstant(ClassConstantReflection $constantReflection): bool { return $constantReflection->isPublic(); } diff --git a/src/Analyser/Scope.php b/src/Analyser/Scope.php index 96859d4c5e..963a4e2194 100644 --- a/src/Analyser/Scope.php +++ b/src/Analyser/Scope.php @@ -6,9 +6,9 @@ use PhpParser\Node\Expr; use PhpParser\Node\Name; use PhpParser\Node\Param; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\FunctionReflection; @@ -73,7 +73,7 @@ public function getPropertyReflection(Type $typeWithProperty, string $propertyNa public function getMethodReflection(Type $typeWithMethod, string $methodName): ?ExtendedMethodReflection; - public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ConstantReflection; + public function getConstantReflection(Type $typeWithConstant, string $constantName): ?ClassConstantReflection; public function getIterableKeyType(Type $iteratee): Type; diff --git a/src/PhpDoc/PhpDocBlock.php b/src/PhpDoc/PhpDocBlock.php index fd75fa5306..c64a74cea2 100644 --- a/src/PhpDoc/PhpDocBlock.php +++ b/src/PhpDoc/PhpDocBlock.php @@ -3,8 +3,8 @@ namespace PHPStan\PhpDoc; use PHPStan\PhpDoc\Tag\AssertTagParameter; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\Php\PhpMethodReflection; use PHPStan\Reflection\Php\PhpPropertyReflection; @@ -334,7 +334,7 @@ private static function resolvePhpDocBlockFromClass( ): ?self { if ($classReflection->$hasMethodName($name)) { - /** @var PropertyReflection|MethodReflection|ConstantReflection $parentReflection */ + /** @var PropertyReflection|MethodReflection|ClassConstantReflection $parentReflection */ $parentReflection = $classReflection->$getMethodName($name); if ($parentReflection->isPrivate()) { return null; diff --git a/src/Reflection/BetterReflection/BetterReflectionProvider.php b/src/Reflection/BetterReflection/BetterReflectionProvider.php index 06e94ae718..7542e3ccdf 100644 --- a/src/Reflection/BetterReflection/BetterReflectionProvider.php +++ b/src/Reflection/BetterReflection/BetterReflectionProvider.php @@ -34,9 +34,9 @@ use PHPStan\Reflection\ClassNameHelper; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\Constant\RuntimeConstantReflection; +use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\FunctionReflectionFactory; -use PHPStan\Reflection\GlobalConstantReflection; use PHPStan\Reflection\InitializerExprContext; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\NamespaceAnswerer; @@ -71,7 +71,7 @@ final class BetterReflectionProvider implements ReflectionProvider /** @var ClassReflection[] */ private static array $anonymousClasses = []; - /** @var array */ + /** @var array */ private array $cachedConstants = []; /** @@ -389,7 +389,7 @@ public function hasConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAn return $this->resolveConstantName($nameNode, $namespaceAnswerer) !== null; } - public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): GlobalConstantReflection + public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ConstantReflection { $constantName = $this->resolveConstantName($nameNode, $namespaceAnswerer); if ($constantName === null) { diff --git a/src/Reflection/ClassConstantReflection.php b/src/Reflection/ClassConstantReflection.php index 7afcb0d9e2..cafc201341 100644 --- a/src/Reflection/ClassConstantReflection.php +++ b/src/Reflection/ClassConstantReflection.php @@ -3,141 +3,22 @@ namespace PHPStan\Reflection; use PhpParser\Node\Expr; -use PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant; -use PHPStan\TrinaryLogic; use PHPStan\Type\Type; -use PHPStan\Type\TypehintHelper; -/** - * @api - */ -final class ClassConstantReflection implements ConstantReflection +/** @api */ +interface ClassConstantReflection extends ClassMemberReflection, ConstantReflection { - private ?Type $valueType = null; + public function getValueExpr(): Expr; - public function __construct( - private InitializerExprTypeResolver $initializerExprTypeResolver, - private ClassReflection $declaringClass, - private ReflectionClassConstant $reflection, - private ?Type $nativeType, - private ?Type $phpDocType, - private ?string $deprecatedDescription, - private bool $isDeprecated, - private bool $isInternal, - ) - { - } + public function isFinal(): bool; - public function getName(): string - { - return $this->reflection->getName(); - } + public function hasPhpDocType(): bool; - public function getFileName(): ?string - { - return $this->declaringClass->getFileName(); - } + public function getPhpDocType(): ?Type; - public function getValueExpr(): Expr - { - return $this->reflection->getValueExpression(); - } + public function hasNativeType(): bool; - public function hasPhpDocType(): bool - { - return $this->phpDocType !== null; - } - - public function getPhpDocType(): ?Type - { - return $this->phpDocType; - } - - public function hasNativeType(): bool - { - return $this->nativeType !== null; - } - - public function getNativeType(): ?Type - { - return $this->nativeType; - } - - public function getValueType(): Type - { - if ($this->valueType === null) { - if ($this->phpDocType !== null) { - if ($this->nativeType !== null) { - return $this->valueType = TypehintHelper::decideType( - $this->nativeType, - $this->phpDocType, - ); - } - - return $this->phpDocType; - } elseif ($this->nativeType !== null) { - return $this->nativeType; - } - - $this->valueType = $this->initializerExprTypeResolver->getType($this->getValueExpr(), InitializerExprContext::fromClassReflection($this->declaringClass)); - } - - return $this->valueType; - } - - public function getDeclaringClass(): ClassReflection - { - return $this->declaringClass; - } - - public function isStatic(): bool - { - return true; - } - - public function isPrivate(): bool - { - return $this->reflection->isPrivate(); - } - - public function isPublic(): bool - { - return $this->reflection->isPublic(); - } - - public function isFinal(): bool - { - return $this->reflection->isFinal(); - } - - public function isDeprecated(): TrinaryLogic - { - return TrinaryLogic::createFromBoolean($this->isDeprecated); - } - - public function getDeprecatedDescription(): ?string - { - if ($this->isDeprecated) { - return $this->deprecatedDescription; - } - - return null; - } - - public function isInternal(): TrinaryLogic - { - return TrinaryLogic::createFromBoolean($this->isInternal); - } - - public function getDocComment(): ?string - { - $docComment = $this->reflection->getDocComment(); - if ($docComment === false) { - return null; - } - - return $docComment; - } + public function getNativeType(): ?Type; } diff --git a/src/Reflection/ClassMemberAccessAnswerer.php b/src/Reflection/ClassMemberAccessAnswerer.php index ed1803e786..e1c62c60ca 100644 --- a/src/Reflection/ClassMemberAccessAnswerer.php +++ b/src/Reflection/ClassMemberAccessAnswerer.php @@ -17,6 +17,6 @@ public function canAccessProperty(PropertyReflection $propertyReflection): bool; public function canCallMethod(MethodReflection $methodReflection): bool; - public function canAccessConstant(ConstantReflection $constantReflection): bool; + public function canAccessConstant(ClassConstantReflection $constantReflection): bool; } diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index 2e1e7ae611..7d966f83d5 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -81,7 +81,7 @@ final class ClassReflection /** @var ExtendedPropertyReflection[] */ private array $properties = []; - /** @var ClassConstantReflection[] */ + /** @var RealClassClassConstantReflection[] */ private array $constants = []; /** @var EnumCaseReflection[]|null */ @@ -1082,7 +1082,7 @@ public function getConstant(string $name): ClassConstantReflection $nativeType = $this->signatureMapProvider->getClassConstantMetadata($declaringClass->getName(), $name)['nativeType']; } - $this->constants[$name] = new ClassConstantReflection( + $this->constants[$name] = new RealClassClassConstantReflection( $this->initializerExprTypeResolver, $declaringClass, $reflectionConstant, diff --git a/src/Reflection/Constant/RuntimeConstantReflection.php b/src/Reflection/Constant/RuntimeConstantReflection.php index 9940b28505..4b31de502d 100644 --- a/src/Reflection/Constant/RuntimeConstantReflection.php +++ b/src/Reflection/Constant/RuntimeConstantReflection.php @@ -2,11 +2,11 @@ namespace PHPStan\Reflection\Constant; -use PHPStan\Reflection\GlobalConstantReflection; +use PHPStan\Reflection\ConstantReflection; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; -final class RuntimeConstantReflection implements GlobalConstantReflection +final class RuntimeConstantReflection implements ConstantReflection { public function __construct( diff --git a/src/Reflection/ConstantReflection.php b/src/Reflection/ConstantReflection.php index 6a13877990..ebae755849 100644 --- a/src/Reflection/ConstantReflection.php +++ b/src/Reflection/ConstantReflection.php @@ -2,12 +2,23 @@ namespace PHPStan\Reflection; -use PhpParser\Node\Expr; +use PHPStan\TrinaryLogic; +use PHPStan\Type\Type; /** @api */ -interface ConstantReflection extends ClassMemberReflection, GlobalConstantReflection +interface ConstantReflection { - public function getValueExpr(): Expr; + public function getName(): string; + + public function getValueType(): Type; + + public function isDeprecated(): TrinaryLogic; + + public function getDeprecatedDescription(): ?string; + + public function isInternal(): TrinaryLogic; + + public function getFileName(): ?string; } diff --git a/src/Reflection/Dummy/DummyConstantReflection.php b/src/Reflection/Dummy/DummyClassConstantReflection.php similarity index 75% rename from src/Reflection/Dummy/DummyConstantReflection.php rename to src/Reflection/Dummy/DummyClassConstantReflection.php index b7d563a615..e38a8740dc 100644 --- a/src/Reflection/Dummy/DummyConstantReflection.php +++ b/src/Reflection/Dummy/DummyClassConstantReflection.php @@ -4,15 +4,15 @@ use PhpParser\Node\Expr; use PHPStan\Node\Expr\TypeExpr; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\TrinaryLogic; use PHPStan\Type\MixedType; use PHPStan\Type\Type; use stdClass; -final class DummyConstantReflection implements ConstantReflection +final class DummyClassConstantReflection implements ClassConstantReflection { public function __construct(private string $name) @@ -26,6 +26,11 @@ public function getDeclaringClass(): ClassReflection return $reflectionProvider->getClass(stdClass::class); } + public function isFinal(): bool + { + return false; + } + public function getFileName(): ?string { return null; @@ -81,4 +86,24 @@ public function getDocComment(): ?string return null; } + public function hasPhpDocType(): bool + { + return false; + } + + public function getPhpDocType(): ?Type + { + return null; + } + + public function hasNativeType(): bool + { + return false; + } + + public function getNativeType(): ?Type + { + return null; + } + } diff --git a/src/Reflection/GlobalConstantReflection.php b/src/Reflection/GlobalConstantReflection.php deleted file mode 100644 index 6483e72e86..0000000000 --- a/src/Reflection/GlobalConstantReflection.php +++ /dev/null @@ -1,24 +0,0 @@ -reflection->getName(); + } + + public function getFileName(): ?string + { + return $this->declaringClass->getFileName(); + } + + public function getValueExpr(): Expr + { + return $this->reflection->getValueExpression(); + } + + public function hasPhpDocType(): bool + { + return $this->phpDocType !== null; + } + + public function getPhpDocType(): ?Type + { + return $this->phpDocType; + } + + public function hasNativeType(): bool + { + return $this->nativeType !== null; + } + + public function getNativeType(): ?Type + { + return $this->nativeType; + } + + public function getValueType(): Type + { + if ($this->valueType === null) { + if ($this->phpDocType !== null) { + if ($this->nativeType !== null) { + return $this->valueType = TypehintHelper::decideType( + $this->nativeType, + $this->phpDocType, + ); + } + + return $this->phpDocType; + } elseif ($this->nativeType !== null) { + return $this->nativeType; + } + + $this->valueType = $this->initializerExprTypeResolver->getType($this->getValueExpr(), InitializerExprContext::fromClassReflection($this->declaringClass)); + } + + return $this->valueType; + } + + public function getDeclaringClass(): ClassReflection + { + return $this->declaringClass; + } + + public function isStatic(): bool + { + return true; + } + + public function isPrivate(): bool + { + return $this->reflection->isPrivate(); + } + + public function isPublic(): bool + { + return $this->reflection->isPublic(); + } + + public function isFinal(): bool + { + return $this->reflection->isFinal(); + } + + public function isDeprecated(): TrinaryLogic + { + return TrinaryLogic::createFromBoolean($this->isDeprecated); + } + + public function getDeprecatedDescription(): ?string + { + if ($this->isDeprecated) { + return $this->deprecatedDescription; + } + + return null; + } + + public function isInternal(): TrinaryLogic + { + return TrinaryLogic::createFromBoolean($this->isInternal); + } + + public function getDocComment(): ?string + { + $docComment = $this->reflection->getDocComment(); + if ($docComment === false) { + return null; + } + + return $docComment; + } + +} diff --git a/src/Reflection/ReflectionProvider.php b/src/Reflection/ReflectionProvider.php index 2e0cc7ee20..3b7387f85a 100644 --- a/src/Reflection/ReflectionProvider.php +++ b/src/Reflection/ReflectionProvider.php @@ -32,7 +32,7 @@ public function resolveFunctionName(Node\Name $nameNode, ?NamespaceAnswerer $nam public function hasConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): bool; - public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): GlobalConstantReflection; + public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ConstantReflection; public function resolveConstantName(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ?string; diff --git a/src/Reflection/ReflectionProvider/DummyReflectionProvider.php b/src/Reflection/ReflectionProvider/DummyReflectionProvider.php index 2f96b7016f..7d18639f8c 100644 --- a/src/Reflection/ReflectionProvider/DummyReflectionProvider.php +++ b/src/Reflection/ReflectionProvider/DummyReflectionProvider.php @@ -5,8 +5,8 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\GlobalConstantReflection; use PHPStan\Reflection\NamespaceAnswerer; use PHPStan\Reflection\ReflectionProvider; use PHPStan\ShouldNotHappenException; @@ -59,7 +59,7 @@ public function hasConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAn return false; } - public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): GlobalConstantReflection + public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ConstantReflection { throw new ShouldNotHappenException(); } diff --git a/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php b/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php index 48060fdfbd..00f4301c7e 100644 --- a/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php +++ b/src/Reflection/ReflectionProvider/MemoizingReflectionProvider.php @@ -5,8 +5,8 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\GlobalConstantReflection; use PHPStan\Reflection\NamespaceAnswerer; use PHPStan\Reflection\ReflectionProvider; use function strtolower; @@ -86,7 +86,7 @@ public function hasConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAn return $this->provider->hasConstant($nameNode, $namespaceAnswerer); } - public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): GlobalConstantReflection + public function getConstant(Node\Name $nameNode, ?NamespaceAnswerer $namespaceAnswerer): ConstantReflection { return $this->provider->getConstant($nameNode, $namespaceAnswerer); } diff --git a/src/Rules/Constants/AlwaysUsedClassConstantsExtension.php b/src/Rules/Constants/AlwaysUsedClassConstantsExtension.php index 4e3bdcc92d..977bac234b 100644 --- a/src/Rules/Constants/AlwaysUsedClassConstantsExtension.php +++ b/src/Rules/Constants/AlwaysUsedClassConstantsExtension.php @@ -2,7 +2,7 @@ namespace PHPStan\Rules\Constants; -use PHPStan\Reflection\ConstantReflection; +use PHPStan\Reflection\ClassConstantReflection; /** * This is the extension interface to implement if you want to describe @@ -25,6 +25,6 @@ interface AlwaysUsedClassConstantsExtension { - public function isAlwaysUsed(ConstantReflection $constant): bool; + public function isAlwaysUsed(ClassConstantReflection $constant): bool; } diff --git a/src/Rules/Constants/OverridingConstantRule.php b/src/Rules/Constants/OverridingConstantRule.php index ca1a822f99..2b3fa162d1 100644 --- a/src/Rules/Constants/OverridingConstantRule.php +++ b/src/Rules/Constants/OverridingConstantRule.php @@ -6,7 +6,6 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -53,7 +52,7 @@ public function processNode(Node $node, Scope $scope): array private function processSingleConstant(ClassReflection $classReflection, string $constantName): array { $prototype = $this->findPrototype($classReflection, $constantName); - if (!$prototype instanceof ClassConstantReflection) { + if ($prototype === null) { return []; } @@ -145,7 +144,7 @@ private function processSingleConstant(ClassReflection $classReflection, string return $errors; } - private function findPrototype(ClassReflection $classReflection, string $constantName): ?ConstantReflection + private function findPrototype(ClassReflection $classReflection, string $constantName): ?ClassConstantReflection { foreach ($classReflection->getImmediateInterfaces() as $immediateInterface) { if ($immediateInterface->hasConstant($constantName)) { diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index ccd6c6cccb..46101a4bfe 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -16,9 +16,9 @@ use PHPStan\Reflection\Callables\CallableParametersAcceptor; use PHPStan\Reflection\Callables\SimpleImpurePoint; use PHPStan\Reflection\Callables\SimpleThrowPoint; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Native\NativeParameterReflection; @@ -349,7 +349,7 @@ public function hasConstant(string $constantName): TrinaryLogic return $this->objectType->hasConstant($constantName); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { return $this->objectType->getConstant($constantName); } diff --git a/src/Type/Constant/ConstantStringType.php b/src/Type/Constant/ConstantStringType.php index a6fda677b7..6d2e32c4a0 100644 --- a/src/Type/Constant/ConstantStringType.php +++ b/src/Type/Constant/ConstantStringType.php @@ -11,8 +11,8 @@ use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\Callables\FunctionCallableVariant; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\InaccessibleMethod; use PHPStan\Reflection\PhpVersionStaticAccessor; use PHPStan\Reflection\ReflectionProviderStaticAccessor; @@ -534,7 +534,7 @@ public function hasConstant(string $constantName): TrinaryLogic return $this->getObjectType()->hasConstant($constantName); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { return $this->getObjectType()->getConstant($constantName); } diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index 0117d14999..c6c6d6b644 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -7,8 +7,8 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\InitializerExprTypeResolver; @@ -532,7 +532,7 @@ public function hasConstant(string $constantName): TrinaryLogic return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->hasConstant($constantName)); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { foreach ($this->types as $type) { if ($type->hasConstant($constantName)->yes()) { diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index 43814c3643..5353a10290 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -6,9 +6,9 @@ use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; -use PHPStan\Reflection\Dummy\DummyConstantReflection; +use PHPStan\Reflection\Dummy\DummyClassConstantReflection; use PHPStan\Reflection\Dummy\DummyMethodReflection; use PHPStan\Reflection\Dummy\DummyPropertyReflection; use PHPStan\Reflection\ExtendedMethodReflection; @@ -423,9 +423,9 @@ public function hasConstant(string $constantName): TrinaryLogic return TrinaryLogic::createYes(); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { - return new DummyConstantReflection($constantName); + return new DummyClassConstantReflection($constantName); } public function isCloneable(): TrinaryLogic diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index 50266db06b..21f58c0c29 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -5,8 +5,8 @@ use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -171,7 +171,7 @@ public function hasConstant(string $constantName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { throw new ShouldNotHappenException(); } diff --git a/src/Type/NonexistentParentClassType.php b/src/Type/NonexistentParentClassType.php index 29ae4f752c..f52c5ea8de 100644 --- a/src/Type/NonexistentParentClassType.php +++ b/src/Type/NonexistentParentClassType.php @@ -5,8 +5,8 @@ use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -107,7 +107,7 @@ public function hasConstant(string $constantName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { throw new ShouldNotHappenException(); } diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 30f8be4640..804147910e 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -19,9 +19,9 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\Callables\CallableParametersAcceptor; use PHPStan\Reflection\Callables\FunctionCallableVariant; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension; @@ -791,7 +791,7 @@ public function hasConstant(string $constantName): TrinaryLogic ); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { $class = $this->getClassReflection(); if ($class === null) { diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index 9c720b5e52..7d73571c4f 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -5,9 +5,9 @@ use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\CallbackUnresolvedMethodPrototypeReflection; @@ -309,7 +309,7 @@ public function hasConstant(string $constantName): TrinaryLogic return $this->getStaticObjectType()->hasConstant($constantName); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { return $this->getStaticObjectType()->getConstant($constantName); } diff --git a/src/Type/StrictMixedType.php b/src/Type/StrictMixedType.php index 1a269cb65f..2e426b2e66 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -5,8 +5,8 @@ use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -165,7 +165,7 @@ public function hasConstant(string $constantName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { throw new ShouldNotHappenException(); } diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index f5d2b1dce2..34785fb3f3 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -3,8 +3,8 @@ namespace PHPStan\Type\Traits; use PHPStan\Php\PhpVersion; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -142,7 +142,7 @@ public function hasConstant(string $constantName): TrinaryLogic return $this->resolve()->hasConstant($constantName); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { return $this->resolve()->getConstant($constantName); } diff --git a/src/Type/Traits/MaybeObjectTypeTrait.php b/src/Type/Traits/MaybeObjectTypeTrait.php index cc13c23a99..ff50c721d3 100644 --- a/src/Type/Traits/MaybeObjectTypeTrait.php +++ b/src/Type/Traits/MaybeObjectTypeTrait.php @@ -2,9 +2,9 @@ namespace PHPStan\Type\Traits; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; -use PHPStan\Reflection\Dummy\DummyConstantReflection; +use PHPStan\Reflection\Dummy\DummyClassConstantReflection; use PHPStan\Reflection\Dummy\DummyMethodReflection; use PHPStan\Reflection\Dummy\DummyPropertyReflection; use PHPStan\Reflection\ExtendedMethodReflection; @@ -97,9 +97,9 @@ public function hasConstant(string $constantName): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { - return new DummyConstantReflection($constantName); + return new DummyClassConstantReflection($constantName); } public function isCloneable(): TrinaryLogic diff --git a/src/Type/Traits/NonObjectTypeTrait.php b/src/Type/Traits/NonObjectTypeTrait.php index 048ef5fb33..d16b86c9b1 100644 --- a/src/Type/Traits/NonObjectTypeTrait.php +++ b/src/Type/Traits/NonObjectTypeTrait.php @@ -2,8 +2,8 @@ namespace PHPStan\Type\Traits; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -76,7 +76,7 @@ public function hasConstant(string $constantName): TrinaryLogic return TrinaryLogic::createNo(); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { throw new ShouldNotHappenException(); } diff --git a/src/Type/Traits/ObjectTypeTrait.php b/src/Type/Traits/ObjectTypeTrait.php index 174a6a2509..5a98ade9c4 100644 --- a/src/Type/Traits/ObjectTypeTrait.php +++ b/src/Type/Traits/ObjectTypeTrait.php @@ -3,9 +3,9 @@ namespace PHPStan\Type\Traits; use PHPStan\Php\PhpVersion; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; -use PHPStan\Reflection\Dummy\DummyConstantReflection; +use PHPStan\Reflection\Dummy\DummyClassConstantReflection; use PHPStan\Reflection\Dummy\DummyMethodReflection; use PHPStan\Reflection\Dummy\DummyPropertyReflection; use PHPStan\Reflection\ExtendedMethodReflection; @@ -108,9 +108,9 @@ public function hasConstant(string $constantName): TrinaryLogic return TrinaryLogic::createMaybe(); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { - return new DummyConstantReflection($constantName); + return new DummyClassConstantReflection($constantName); } public function getConstantStrings(): array diff --git a/src/Type/Type.php b/src/Type/Type.php index 21b15c221b..398bc0d4f2 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -5,9 +5,9 @@ use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\Callables\CallableParametersAcceptor; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassReflection; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; @@ -99,7 +99,7 @@ public function canAccessConstants(): TrinaryLogic; public function hasConstant(string $constantName): TrinaryLogic; - public function getConstant(string $constantName): ConstantReflection; + public function getConstant(string $constantName): ClassConstantReflection; public function isIterable(): TrinaryLogic; diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 704bd421b2..4e38c38566 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -8,8 +8,8 @@ use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; -use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\InitializerExprTypeResolver; @@ -504,11 +504,11 @@ public function hasConstant(string $constantName): TrinaryLogic ); } - public function getConstant(string $constantName): ConstantReflection + public function getConstant(string $constantName): ClassConstantReflection { return $this->getInternal( static fn (Type $type): TrinaryLogic => $type->hasConstant($constantName), - static fn (Type $type): ConstantReflection => $type->getConstant($constantName), + static fn (Type $type): ClassConstantReflection => $type->getConstant($constantName), ); } diff --git a/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php b/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php index ca38d7ec38..6ded7325fb 100644 --- a/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php +++ b/tests/PHPStan/Rules/Api/data/class-implements-out-of-phpstan.php @@ -128,7 +128,7 @@ public function hasConstant(string $constantName): \PHPStan\TrinaryLogic // TODO: Implement hasConstant() method. } - public function getConstant(string $constantName): \PHPStan\Reflection\ConstantReflection + public function getConstant(string $constantName): \PHPStan\Reflection\ClassConstantReflection { // TODO: Implement getConstant() method. } diff --git a/tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php b/tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php index 24bde42de8..9ef9924063 100644 --- a/tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php +++ b/tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php @@ -2,7 +2,7 @@ namespace PHPStan\Rules\DeadCode; -use PHPStan\Reflection\ConstantReflection; +use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Rules\Constants\AlwaysUsedClassConstantsExtension; use PHPStan\Rules\Constants\DirectAlwaysUsedClassConstantsExtensionProvider; use PHPStan\Rules\Rule; @@ -22,7 +22,7 @@ protected function getRule(): Rule new DirectAlwaysUsedClassConstantsExtensionProvider([ new class() implements AlwaysUsedClassConstantsExtension { - public function isAlwaysUsed(ConstantReflection $constant): bool + public function isAlwaysUsed(ClassConstantReflection $constant): bool { return $constant->getDeclaringClass()->getName() === TestExtension::class && $constant->getName() === 'USED'; From 778af2ed74ba59bfb2a69fd5b45821ccdb1107c9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 10:28:58 +0200 Subject: [PATCH 328/508] More interfaces that are not supposed to be implemented in userland --- src/Rules/Api/BcUncoveredInterface.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Rules/Api/BcUncoveredInterface.php b/src/Rules/Api/BcUncoveredInterface.php index 5b508c2e07..80a48f9808 100644 --- a/src/Rules/Api/BcUncoveredInterface.php +++ b/src/Rules/Api/BcUncoveredInterface.php @@ -5,6 +5,9 @@ use PHPStan\Analyser\Scope; use PHPStan\Command\Output; use PHPStan\Reflection\Callables\CallableParametersAcceptor; +use PHPStan\Reflection\ClassConstantReflection; +use PHPStan\Reflection\ClassMemberReflection; +use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\FunctionReflection; @@ -41,6 +44,9 @@ final class BcUncoveredInterface RuleError::class, TipRuleError::class, Output::class, + ClassMemberReflection::class, + ConstantReflection::class, + ClassConstantReflection::class, ]; } From cb6ab5544a016c52f931fc390bcdf9c627819d8f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 10:39:28 +0200 Subject: [PATCH 329/508] Even more interfaces that are not supposed to be implemented --- src/Rules/Api/BcUncoveredInterface.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Rules/Api/BcUncoveredInterface.php b/src/Rules/Api/BcUncoveredInterface.php index 80a48f9808..ccaf001a14 100644 --- a/src/Rules/Api/BcUncoveredInterface.php +++ b/src/Rules/Api/BcUncoveredInterface.php @@ -4,13 +4,20 @@ use PHPStan\Analyser\Scope; use PHPStan\Command\Output; +use PHPStan\Command\OutputStyle; +use PHPStan\DependencyInjection\Container; +use PHPStan\Node\ReturnStatementsNode; +use PHPStan\Node\VirtualNode; +use PHPStan\PhpDoc\Tag\TypedTag; use PHPStan\Reflection\Callables\CallableParametersAcceptor; use PHPStan\Reflection\ClassConstantReflection; +use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\FunctionReflection; +use PHPStan\Reflection\NamespaceAnswerer; use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\ReflectionProvider; @@ -21,13 +28,21 @@ use PHPStan\Rules\NonIgnorableRuleError; use PHPStan\Rules\RuleError; use PHPStan\Rules\TipRuleError; +use PHPStan\Type\CompoundType; +use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\Type; +use PHPStan\Type\TypeWithClassName; final class BcUncoveredInterface { public const CLASSES = [ Type::class, + CompoundType::class, + TemplateType::class, + TypedTag::class, + TypeWithClassName::class, + VirtualNode::class, ReflectionProvider::class, Scope::class, FunctionReflection::class, @@ -47,6 +62,11 @@ final class BcUncoveredInterface ClassMemberReflection::class, ConstantReflection::class, ClassConstantReflection::class, + ClassMemberAccessAnswerer::class, + NamespaceAnswerer::class, + Container::class, + OutputStyle::class, + ReturnStatementsNode::class, ]; } From 5eacc66a6eee59bf87748c9f0b1bb9c52f816724 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 10:45:59 +0200 Subject: [PATCH 330/508] [BCB] From `*WithPhpDocs` to `Extended*` --- UPGRADING.md | 1 + build/PHPStan/Build/FinalClassRule.php | 4 +- src/Analyser/MutatingScope.php | 6 +- src/Analyser/NodeScopeResolver.php | 18 +++--- src/Analyser/TypeSpecifier.php | 10 ++-- src/Dependency/DependencyResolver.php | 8 +-- .../AnnotationMethodReflection.php | 10 ++-- .../AnnotationsMethodParameterReflection.php | 4 +- .../Callables/FunctionCallableVariant.php | 14 ++--- .../Dummy/ChangedTypeMethodReflection.php | 8 +-- .../Dummy/DummyConstructorReflection.php | 8 +-- .../Dummy/DummyMethodReflection.php | 4 +- ...hp => ExtendedCallableFunctionVariant.php} | 4 +- ...hpDocs.php => ExtendedFunctionVariant.php} | 8 +-- src/Reflection/ExtendedMethodReflection.php | 6 +- ...cs.php => ExtendedParameterReflection.php} | 2 +- ...ocs.php => ExtendedParametersAcceptor.php} | 4 +- src/Reflection/FunctionReflection.php | 6 +- .../GenericParametersAcceptorResolver.php | 10 ++-- ... => ExtendedNativeParameterReflection.php} | 4 +- .../Native/NativeFunctionReflection.php | 8 +-- .../Native/NativeMethodReflection.php | 8 +-- src/Reflection/ParametersAcceptorSelector.php | 58 +++++++++---------- .../Php/ClosureCallMethodReflection.php | 12 ++-- .../Php/EnumCasesMethodReflection.php | 8 +-- src/Reflection/Php/ExitFunctionReflection.php | 12 ++-- ...PhpDocs.php => ExtendedDummyParameter.php} | 4 +- .../Php/PhpClassReflectionExtension.php | 10 ++-- .../PhpFunctionFromParserNodeReflection.php | 18 +++--- src/Reflection/Php/PhpFunctionReflection.php | 16 ++--- src/Reflection/Php/PhpMethodReflection.php | 16 ++--- .../PhpParameterFromParserNodeReflection.php | 4 +- src/Reflection/Php/PhpParameterReflection.php | 4 +- src/Reflection/ResolvedFunctionVariant.php | 2 +- .../ResolvedFunctionVariantWithOriginal.php | 10 ++-- src/Reflection/ResolvedMethodReflection.php | 8 +-- .../NativeFunctionReflectionProvider.php | 10 ++-- src/Reflection/TrivialParametersAcceptor.php | 2 +- ...ackUnresolvedMethodPrototypeReflection.php | 12 ++-- ...ypeUnresolvedMethodPrototypeReflection.php | 12 ++-- .../Type/IntersectionTypeMethodReflection.php | 8 +-- .../Type/UnionTypeMethodReflection.php | 4 +- .../WrappedExtendedMethodReflection.php | 10 ++-- src/Rules/Api/BcUncoveredInterface.php | 8 +-- src/Rules/FunctionCallParametersCheck.php | 4 +- src/Rules/FunctionDefinitionCheck.php | 10 ++-- src/Rules/Generics/VarianceCheck.php | 4 +- src/Rules/Methods/MethodSignatureRule.php | 12 ++-- src/Rules/Methods/OverridingMethodRule.php | 4 +- .../ConditionalReturnTypeRuleHelper.php | 4 +- src/Rules/Pure/FunctionPurityCheck.php | 4 +- .../TooWideParameterOutTypeCheck.php | 6 +- .../ParameterOutExecutionEndTypeRule.php | 4 +- ...FromCallableDynamicReturnTypeExtension.php | 4 +- .../ReflectionProviderGoldenTest.php | 2 +- 55 files changed, 231 insertions(+), 230 deletions(-) rename src/Reflection/{CallableFunctionVariantWithPhpDocs.php => ExtendedCallableFunctionVariant.php} (90%) rename src/Reflection/{FunctionVariantWithPhpDocs.php => ExtendedFunctionVariant.php} (77%) rename src/Reflection/{ParameterReflectionWithPhpDocs.php => ExtendedParameterReflection.php} (84%) rename src/Reflection/{ParametersAcceptorWithPhpDocs.php => ExtendedParametersAcceptor.php} (75%) rename src/Reflection/Native/{NativeParameterWithPhpDocsReflection.php => ExtendedNativeParameterReflection.php} (90%) rename src/Reflection/Php/{DummyParameterWithPhpDocs.php => ExtendedDummyParameter.php} (86%) diff --git a/UPGRADING.md b/UPGRADING.md index dc6ac842e1..7859c5f267 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -298,3 +298,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Interface `ConstantReflection` renamed to `ClassConstantReflection` * Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection` * Interface `GlobalConstantReflection` renamed to `ConstantReflection` +* Renamed interfaces and classes from `*WithPhpDocs` to `Extended*` diff --git a/build/PHPStan/Build/FinalClassRule.php b/build/PHPStan/Build/FinalClassRule.php index 5918003a71..a4758648c6 100644 --- a/build/PHPStan/Build/FinalClassRule.php +++ b/build/PHPStan/Build/FinalClassRule.php @@ -7,7 +7,7 @@ use PHPStan\File\FileHelper; use PHPStan\Node\InClassNode; use PHPStan\Reflection\FunctionVariant; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\Php\DummyParameter; use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; use PHPStan\Rules\Rule; @@ -51,7 +51,7 @@ public function processNode(Node $node, Scope $scope): array // exceptions if (in_array($classReflection->getName(), [ FunctionVariant::class, - FunctionVariantWithPhpDocs::class, + ExtendedFunctionVariant::class, DummyParameter::class, PhpFunctionFromParserNodeReflection::class, ], true)) { diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 5d11b826c6..ae1c02dca8 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -57,6 +57,7 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\Dummy\DummyConstructorReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\InitializerExprContext; @@ -66,7 +67,6 @@ use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ParametersAcceptorSelector; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\PassedByReference; use PHPStan\Reflection\Php\DummyParameter; use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; @@ -2503,7 +2503,7 @@ private function createFirstClassCallable( foreach ($variants as $variant) { $returnType = $variant->getReturnType(); - if ($variant instanceof ParametersAcceptorWithPhpDocs) { + if ($variant instanceof ExtendedParametersAcceptor) { $returnType = $this->nativeTypesPromoted ? $variant->getNativeReturnType() : $returnType; } @@ -2560,7 +2560,7 @@ private function createFirstClassCallable( $variant->isVariadic(), $variant->getTemplateTypeMap(), $variant->getResolvedTemplateTypeMap(), - $variant instanceof ParametersAcceptorWithPhpDocs ? $variant->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $variant instanceof ExtendedParametersAcceptor ? $variant->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), $templateTags, $throwPoints, $impurePoints, diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 74f2c58c71..ec807de6fa 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -130,16 +130,16 @@ use PHPStan\Reflection\Callables\SimpleThrowPoint; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\Native\NativeMethodReflection; use PHPStan\Reflection\Native\NativeParameterReflection; use PHPStan\Reflection\ParameterReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ParametersAcceptorSelector; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection; use PHPStan\Reflection\Php\PhpMethodReflection; @@ -2649,7 +2649,7 @@ static function (): void { TemplateTypeHelper::resolveTemplateTypes( $selfOutType, $parametersAcceptor->getResolvedTemplateTypeMap(), - $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createCovariant(), ), $scope->getNativeType($expr->var), @@ -4545,7 +4545,7 @@ private function processArgs( $assignByReference = $parameters[$i]->passedByReference()->createsNewVariable(); $parameterType = $parameters[$i]->getType(); - if ($parameters[$i] instanceof ParameterReflectionWithPhpDocs) { + if ($parameters[$i] instanceof ExtendedParameterReflection) { $parameterNativeType = $parameters[$i]->getNativeType(); } $parameter = $parameters[$i]; @@ -4554,7 +4554,7 @@ private function processArgs( $assignByReference = $lastParameter->passedByReference()->createsNewVariable(); $parameterType = $lastParameter->getType(); - if ($lastParameter instanceof ParameterReflectionWithPhpDocs) { + if ($lastParameter instanceof ExtendedParameterReflection) { $parameterNativeType = $lastParameter->getNativeType(); } $parameter = $lastParameter; @@ -4591,7 +4591,7 @@ private function processArgs( $scopeToPass = $closureBindScope; } - if ($parameter instanceof ParameterReflectionWithPhpDocs) { + if ($parameter instanceof ExtendedParameterReflection) { $parameterCallImmediately = $parameter->isImmediatelyInvokedCallable(); if ($parameterCallImmediately->maybe()) { $callCallbackImmediately = $calleeReflection instanceof FunctionReflection; @@ -4605,7 +4605,7 @@ private function processArgs( $restoreThisScope = null; if ( $closureBindScope === null - && $parameter instanceof ParameterReflectionWithPhpDocs + && $parameter instanceof ExtendedParameterReflection && $parameter->getClosureThisType() !== null && !$arg->value->static ) { @@ -4658,7 +4658,7 @@ private function processArgs( } elseif ($arg->value instanceof Expr\ArrowFunction) { if ( $closureBindScope === null - && $parameter instanceof ParameterReflectionWithPhpDocs + && $parameter instanceof ExtendedParameterReflection && $parameter->getClosureThisType() !== null && !$arg->value->static ) { @@ -4734,7 +4734,7 @@ private function processArgs( if ($currentParameter !== null) { $assignByReference = $currentParameter->passedByReference()->createsNewVariable(); if ($assignByReference) { - if ($currentParameter instanceof ParameterReflectionWithPhpDocs && $currentParameter->getOutType() !== null) { + if ($currentParameter instanceof ExtendedParameterReflection && $currentParameter->getOutType() !== null) { $byRefType = $currentParameter->getOutType(); } elseif ( $calleeReflection instanceof MethodReflection diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 5affae3a6f..1006f33633 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -24,9 +24,9 @@ use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Php\PhpVersion; use PHPStan\Reflection\Assertions; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ParametersAcceptorSelector; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Reflection\ResolvedFunctionVariant; use PHPStan\Rules\Arrays\AllowedArrayKeysTypes; @@ -485,7 +485,7 @@ public function specifyTypesInCondition( $asserts = $assertions->mapTypes(static fn (Type $type) => TemplateTypeHelper::resolveTemplateTypes( $type, $parametersAcceptor->getResolvedTemplateTypeMap(), - $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant(), )); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); @@ -533,7 +533,7 @@ public function specifyTypesInCondition( $asserts = $assertions->mapTypes(static fn (Type $type) => TemplateTypeHelper::resolveTemplateTypes( $type, $parametersAcceptor->getResolvedTemplateTypeMap(), - $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant(), )); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); @@ -586,7 +586,7 @@ public function specifyTypesInCondition( $asserts = $assertions->mapTypes(static fn (Type $type) => TemplateTypeHelper::resolveTemplateTypes( $type, $parametersAcceptor->getResolvedTemplateTypeMap(), - $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant(), )); $specifiedTypes = $this->specifyTypesFromAsserts($context, $expr, $asserts, $parametersAcceptor, $scope); @@ -935,7 +935,7 @@ public function specifyTypesInCondition( $asserts = $asserts->mapTypes(static fn (Type $type) => TemplateTypeHelper::resolveTemplateTypes( $type, $parametersAcceptor->getResolvedTemplateTypeMap(), - $parametersAcceptor instanceof ParametersAcceptorWithPhpDocs ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $parametersAcceptor instanceof ExtendedParametersAcceptor ? $parametersAcceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), TemplateTypeVariance::createInvariant(), )); diff --git a/src/Dependency/DependencyResolver.php b/src/Dependency/DependencyResolver.php index 12635a0913..9fde7ef34f 100644 --- a/src/Dependency/DependencyResolver.php +++ b/src/Dependency/DependencyResolver.php @@ -16,9 +16,9 @@ use PHPStan\Node\InClassMethodNode; use PHPStan\Node\InFunctionNode; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ClosureType; use PHPStan\Type\FileTypeMapper; @@ -171,7 +171,7 @@ public function resolveDependencies(Node $node, Scope $scope): NodeDependencies } foreach ($variant->getParameters() as $parameter) { - if (!$parameter instanceof ParameterReflectionWithPhpDocs) { + if (!$parameter instanceof ExtendedParameterReflection) { continue; } if ($parameter->getOutType() !== null) { @@ -615,7 +615,7 @@ private function getFunctionReflection(Node\Name $nameNode, ?Scope $scope): Func * @param array $dependenciesReflections */ private function extractFromParametersAcceptor( - ParametersAcceptorWithPhpDocs $parametersAcceptor, + ExtendedParametersAcceptor $parametersAcceptor, array &$dependenciesReflections, ): void { diff --git a/src/Reflection/Annotations/AnnotationMethodReflection.php b/src/Reflection/Annotations/AnnotationMethodReflection.php index 6b2ff2afdb..847a444eb5 100644 --- a/src/Reflection/Annotations/AnnotationMethodReflection.php +++ b/src/Reflection/Annotations/AnnotationMethodReflection.php @@ -5,9 +5,9 @@ use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\MixedType; @@ -17,7 +17,7 @@ final class AnnotationMethodReflection implements ExtendedMethodReflection { - /** @var FunctionVariantWithPhpDocs[]|null */ + /** @var ExtendedFunctionVariant[]|null */ private ?array $variants = null; /** @@ -70,7 +70,7 @@ public function getVariants(): array { if ($this->variants === null) { $this->variants = [ - new FunctionVariantWithPhpDocs( + new ExtendedFunctionVariant( $this->templateTypeMap, null, $this->parameters, @@ -84,7 +84,7 @@ public function getVariants(): array return $this->variants; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } diff --git a/src/Reflection/Annotations/AnnotationsMethodParameterReflection.php b/src/Reflection/Annotations/AnnotationsMethodParameterReflection.php index cb86e0fec4..51bddcaabe 100644 --- a/src/Reflection/Annotations/AnnotationsMethodParameterReflection.php +++ b/src/Reflection/Annotations/AnnotationsMethodParameterReflection.php @@ -2,13 +2,13 @@ namespace PHPStan\Reflection\Annotations; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\PassedByReference; use PHPStan\TrinaryLogic; use PHPStan\Type\MixedType; use PHPStan\Type\Type; -final class AnnotationsMethodParameterReflection implements ParameterReflectionWithPhpDocs +final class AnnotationsMethodParameterReflection implements ExtendedParameterReflection { public function __construct(private string $name, private Type $type, private PassedByReference $passedByReference, private bool $isOptional, private bool $isVariadic, private ?Type $defaultValue) diff --git a/src/Reflection/Callables/FunctionCallableVariant.php b/src/Reflection/Callables/FunctionCallableVariant.php index 82eb478fc3..66bd629a3e 100644 --- a/src/Reflection/Callables/FunctionCallableVariant.php +++ b/src/Reflection/Callables/FunctionCallableVariant.php @@ -3,9 +3,9 @@ namespace PHPStan\Reflection\Callables; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\Generic\TemplateTypeVarianceMap; @@ -16,7 +16,7 @@ use function array_map; use function count; -final class FunctionCallableVariant implements CallableParametersAcceptor, ParametersAcceptorWithPhpDocs +final class FunctionCallableVariant implements CallableParametersAcceptor, ExtendedParametersAcceptor { /** @var SimpleThrowPoint[]|null */ @@ -27,18 +27,18 @@ final class FunctionCallableVariant implements CallableParametersAcceptor, Param public function __construct( private FunctionReflection|ExtendedMethodReflection $function, - private ParametersAcceptorWithPhpDocs $variant, + private ExtendedParametersAcceptor $variant, ) { } /** - * @param ParametersAcceptorWithPhpDocs[] $variants + * @param ExtendedParametersAcceptor[] $variants * @return self[] */ public static function createFromVariants(FunctionReflection|ExtendedMethodReflection $function, array $variants): array { - return array_map(static fn (ParametersAcceptorWithPhpDocs $variant) => new self($function, $variant), $variants); + return array_map(static fn (ExtendedParametersAcceptor $variant) => new self($function, $variant), $variants); } public function getTemplateTypeMap(): TemplateTypeMap @@ -52,7 +52,7 @@ public function getResolvedTemplateTypeMap(): TemplateTypeMap } /** - * @return array + * @return array */ public function getParameters(): array { diff --git a/src/Reflection/Dummy/ChangedTypeMethodReflection.php b/src/Reflection/Dummy/ChangedTypeMethodReflection.php index 3dc1cd56b0..bc0a557157 100644 --- a/src/Reflection/Dummy/ChangedTypeMethodReflection.php +++ b/src/Reflection/Dummy/ChangedTypeMethodReflection.php @@ -6,7 +6,7 @@ use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; @@ -17,8 +17,8 @@ final class ChangedTypeMethodReflection implements ExtendedMethodReflection { /** - * @param ParametersAcceptorWithPhpDocs[] $variants - * @param ParametersAcceptorWithPhpDocs[]|null $namedArgumentsVariants + * @param ExtendedParametersAcceptor[] $variants + * @param ExtendedParametersAcceptor[]|null $namedArgumentsVariants */ public function __construct(private ClassReflection $declaringClass, private ExtendedMethodReflection $reflection, private array $variants, private ?array $namedArgumentsVariants) { @@ -64,7 +64,7 @@ public function getVariants(): array return $this->variants; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { $variants = $this->getVariants(); if (count($variants) !== 1) { diff --git a/src/Reflection/Dummy/DummyConstructorReflection.php b/src/Reflection/Dummy/DummyConstructorReflection.php index 36b143ed12..e3dff92c38 100644 --- a/src/Reflection/Dummy/DummyConstructorReflection.php +++ b/src/Reflection/Dummy/DummyConstructorReflection.php @@ -5,9 +5,9 @@ use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\MixedType; @@ -54,7 +54,7 @@ public function getPrototype(): ClassMemberReflection public function getVariants(): array { return [ - new FunctionVariantWithPhpDocs( + new ExtendedFunctionVariant( TemplateTypeMap::createEmpty(), null, [], @@ -67,7 +67,7 @@ public function getVariants(): array ]; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } diff --git a/src/Reflection/Dummy/DummyMethodReflection.php b/src/Reflection/Dummy/DummyMethodReflection.php index c6157c17db..c02b5ea370 100644 --- a/src/Reflection/Dummy/DummyMethodReflection.php +++ b/src/Reflection/Dummy/DummyMethodReflection.php @@ -6,7 +6,7 @@ use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\Reflection\TrivialParametersAcceptor; use PHPStan\TrinaryLogic; @@ -59,7 +59,7 @@ public function getVariants(): array ]; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } diff --git a/src/Reflection/CallableFunctionVariantWithPhpDocs.php b/src/Reflection/ExtendedCallableFunctionVariant.php similarity index 90% rename from src/Reflection/CallableFunctionVariantWithPhpDocs.php rename to src/Reflection/ExtendedCallableFunctionVariant.php index fd6c62afd5..5b67d210cc 100644 --- a/src/Reflection/CallableFunctionVariantWithPhpDocs.php +++ b/src/Reflection/ExtendedCallableFunctionVariant.php @@ -11,11 +11,11 @@ use PHPStan\Type\Generic\TemplateTypeVarianceMap; use PHPStan\Type\Type; -final class CallableFunctionVariantWithPhpDocs extends FunctionVariantWithPhpDocs implements CallableParametersAcceptor +final class ExtendedCallableFunctionVariant extends ExtendedFunctionVariant implements CallableParametersAcceptor { /** - * @param array $parameters + * @param array $parameters * @param SimpleThrowPoint[] $throwPoints * @param SimpleImpurePoint[] $impurePoints * @param InvalidateExprNode[] $invalidateExpressions diff --git a/src/Reflection/FunctionVariantWithPhpDocs.php b/src/Reflection/ExtendedFunctionVariant.php similarity index 77% rename from src/Reflection/FunctionVariantWithPhpDocs.php rename to src/Reflection/ExtendedFunctionVariant.php index 0b047b08b5..33c8e72c00 100644 --- a/src/Reflection/FunctionVariantWithPhpDocs.php +++ b/src/Reflection/ExtendedFunctionVariant.php @@ -9,12 +9,12 @@ /** * @api */ -class FunctionVariantWithPhpDocs extends FunctionVariant implements ParametersAcceptorWithPhpDocs +class ExtendedFunctionVariant extends FunctionVariant implements ExtendedParametersAcceptor { /** + * @param array $parameters * @api - * @param array $parameters */ public function __construct( TemplateTypeMap $templateTypeMap, @@ -38,11 +38,11 @@ public function __construct( } /** - * @return array + * @return array */ public function getParameters(): array { - /** @var array $parameters */ + /** @var array $parameters */ $parameters = parent::getParameters(); return $parameters; diff --git a/src/Reflection/ExtendedMethodReflection.php b/src/Reflection/ExtendedMethodReflection.php index 43f27903f9..e8a65b00b6 100644 --- a/src/Reflection/ExtendedMethodReflection.php +++ b/src/Reflection/ExtendedMethodReflection.php @@ -23,17 +23,17 @@ interface ExtendedMethodReflection extends MethodReflection { /** - * @return ParametersAcceptorWithPhpDocs[] + * @return ExtendedParametersAcceptor[] */ public function getVariants(): array; /** * @internal */ - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs; + public function getOnlyVariant(): ExtendedParametersAcceptor; /** - * @return ParametersAcceptorWithPhpDocs[]|null + * @return ExtendedParametersAcceptor[]|null */ public function getNamedArgumentsVariants(): ?array; diff --git a/src/Reflection/ParameterReflectionWithPhpDocs.php b/src/Reflection/ExtendedParameterReflection.php similarity index 84% rename from src/Reflection/ParameterReflectionWithPhpDocs.php rename to src/Reflection/ExtendedParameterReflection.php index 943338a493..db8df05ab8 100644 --- a/src/Reflection/ParameterReflectionWithPhpDocs.php +++ b/src/Reflection/ExtendedParameterReflection.php @@ -6,7 +6,7 @@ use PHPStan\Type\Type; /** @api */ -interface ParameterReflectionWithPhpDocs extends ParameterReflection +interface ExtendedParameterReflection extends ParameterReflection { public function getPhpDocType(): Type; diff --git a/src/Reflection/ParametersAcceptorWithPhpDocs.php b/src/Reflection/ExtendedParametersAcceptor.php similarity index 75% rename from src/Reflection/ParametersAcceptorWithPhpDocs.php rename to src/Reflection/ExtendedParametersAcceptor.php index f8ae03e477..002a8a930d 100644 --- a/src/Reflection/ParametersAcceptorWithPhpDocs.php +++ b/src/Reflection/ExtendedParametersAcceptor.php @@ -6,11 +6,11 @@ use PHPStan\Type\Type; /** @api */ -interface ParametersAcceptorWithPhpDocs extends ParametersAcceptor +interface ExtendedParametersAcceptor extends ParametersAcceptor { /** - * @return array + * @return array */ public function getParameters(): array; diff --git a/src/Reflection/FunctionReflection.php b/src/Reflection/FunctionReflection.php index 09232a4d8a..e6770e08a5 100644 --- a/src/Reflection/FunctionReflection.php +++ b/src/Reflection/FunctionReflection.php @@ -14,17 +14,17 @@ public function getName(): string; public function getFileName(): ?string; /** - * @return ParametersAcceptorWithPhpDocs[] + * @return ExtendedParametersAcceptor[] */ public function getVariants(): array; /** * @internal */ - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs; + public function getOnlyVariant(): ExtendedParametersAcceptor; /** - * @return ParametersAcceptorWithPhpDocs[]|null + * @return ExtendedParametersAcceptor[]|null */ public function getNamedArgumentsVariants(): ?array; diff --git a/src/Reflection/GenericParametersAcceptorResolver.php b/src/Reflection/GenericParametersAcceptorResolver.php index 5aa65587de..e680908c32 100644 --- a/src/Reflection/GenericParametersAcceptorResolver.php +++ b/src/Reflection/GenericParametersAcceptorResolver.php @@ -3,7 +3,7 @@ namespace PHPStan\Reflection; use PHPStan\Reflection\Callables\CallableParametersAcceptor; -use PHPStan\Reflection\Php\DummyParameterWithPhpDocs; +use PHPStan\Reflection\Php\ExtendedDummyParameter; use PHPStan\TrinaryLogic; use PHPStan\Type\ConditionalTypeForParameter; use PHPStan\Type\ErrorType; @@ -25,7 +25,7 @@ final class GenericParametersAcceptorResolver * @api * @param array $argTypes */ - public static function resolve(array $argTypes, ParametersAcceptor $parametersAcceptor): ParametersAcceptorWithPhpDocs + public static function resolve(array $argTypes, ParametersAcceptor $parametersAcceptor): ExtendedParametersAcceptor { $typeMap = TemplateTypeMap::createEmpty(); $passedArgs = []; @@ -87,11 +87,11 @@ public static function resolve(array $argTypes, ParametersAcceptor $parametersAc $originalParametersAcceptor = $parametersAcceptor; - if (!$parametersAcceptor instanceof ParametersAcceptorWithPhpDocs) { - $parametersAcceptor = new FunctionVariantWithPhpDocs( + if (!$parametersAcceptor instanceof ExtendedParametersAcceptor) { + $parametersAcceptor = new ExtendedFunctionVariant( $parametersAcceptor->getTemplateTypeMap(), $parametersAcceptor->getResolvedTemplateTypeMap(), - array_map(static fn (ParameterReflection $parameter): ParameterReflectionWithPhpDocs => new DummyParameterWithPhpDocs( + array_map(static fn (ParameterReflection $parameter): ExtendedParameterReflection => new ExtendedDummyParameter( $parameter->getName(), $parameter->getType(), $parameter->isOptional(), diff --git a/src/Reflection/Native/NativeParameterWithPhpDocsReflection.php b/src/Reflection/Native/ExtendedNativeParameterReflection.php similarity index 90% rename from src/Reflection/Native/NativeParameterWithPhpDocsReflection.php rename to src/Reflection/Native/ExtendedNativeParameterReflection.php index 64aa593067..7e1388bf5a 100644 --- a/src/Reflection/Native/NativeParameterWithPhpDocsReflection.php +++ b/src/Reflection/Native/ExtendedNativeParameterReflection.php @@ -2,12 +2,12 @@ namespace PHPStan\Reflection\Native; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\PassedByReference; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; -final class NativeParameterWithPhpDocsReflection implements ParameterReflectionWithPhpDocs +final class ExtendedNativeParameterReflection implements ExtendedParameterReflection { public function __construct( diff --git a/src/Reflection/Native/NativeFunctionReflection.php b/src/Reflection/Native/NativeFunctionReflection.php index 529bd5fbbf..852392d750 100644 --- a/src/Reflection/Native/NativeFunctionReflection.php +++ b/src/Reflection/Native/NativeFunctionReflection.php @@ -3,8 +3,8 @@ namespace PHPStan\Reflection\Native; use PHPStan\Reflection\Assertions; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; @@ -18,8 +18,8 @@ final class NativeFunctionReflection implements FunctionReflection private TrinaryLogic $returnsByReference; /** - * @param ParametersAcceptorWithPhpDocs[] $variants - * @param ParametersAcceptorWithPhpDocs[]|null $namedArgumentsVariants + * @param ExtendedParametersAcceptor[] $variants + * @param ExtendedParametersAcceptor[]|null $namedArgumentsVariants */ public function __construct( private string $name, @@ -53,7 +53,7 @@ public function getVariants(): array return $this->variants; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { $variants = $this->getVariants(); if (count($variants) !== 1) { diff --git a/src/Reflection/Native/NativeMethodReflection.php b/src/Reflection/Native/NativeMethodReflection.php index 1671c55aab..b167f1223f 100644 --- a/src/Reflection/Native/NativeMethodReflection.php +++ b/src/Reflection/Native/NativeMethodReflection.php @@ -7,8 +7,8 @@ use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\MethodPrototypeReflection; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\ReflectionProvider; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; @@ -22,8 +22,8 @@ final class NativeMethodReflection implements ExtendedMethodReflection { /** - * @param ParametersAcceptorWithPhpDocs[] $variants - * @param ParametersAcceptorWithPhpDocs[]|null $namedArgumentsVariants + * @param ExtendedParametersAcceptor[] $variants + * @param ExtendedParametersAcceptor[]|null $namedArgumentsVariants */ public function __construct( private ReflectionProvider $reflectionProvider, @@ -111,7 +111,7 @@ public function getVariants(): array return $this->variants; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { $variants = $this->getVariants(); if (count($variants) !== 1) { diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index 93db8e9834..57609ab0c7 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -17,7 +17,7 @@ use PHPStan\Reflection\Callables\CallableParametersAcceptor; use PHPStan\Reflection\Native\NativeParameterReflection; use PHPStan\Reflection\Php\DummyParameter; -use PHPStan\Reflection\Php\DummyParameterWithPhpDocs; +use PHPStan\Reflection\Php\ExtendedDummyParameter; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; @@ -116,7 +116,7 @@ public static function selectFromArgs( $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), - $acceptor instanceof ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), ), ]; } @@ -146,7 +146,7 @@ public static function selectFromArgs( $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), - $acceptor instanceof ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), ), ]; } @@ -196,7 +196,7 @@ public static function selectFromArgs( $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), - $acceptor instanceof ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), ), ]; } @@ -227,7 +227,7 @@ public static function selectFromArgs( $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), - $acceptor instanceof ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), ), ]; } @@ -269,7 +269,7 @@ public static function selectFromArgs( $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), - $acceptor instanceof ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), ), ]; } @@ -312,7 +312,7 @@ public static function selectFromArgs( $parameters, $acceptor->isVariadic(), $acceptor->getReturnType(), - $acceptor instanceof ParametersAcceptorWithPhpDocs ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), ), ]; } @@ -389,7 +389,7 @@ private static function hasAcceptorTemplateOrLateResolvableType(ParametersAccept foreach ($acceptor->getParameters() as $parameter) { if ( - $parameter instanceof ParameterReflectionWithPhpDocs + $parameter instanceof ExtendedParameterReflection && $parameter->getOutType() !== null && self::hasTemplateOrLateResolvableType($parameter->getOutType()) ) { @@ -397,7 +397,7 @@ private static function hasAcceptorTemplateOrLateResolvableType(ParametersAccept } if ( - $parameter instanceof ParameterReflectionWithPhpDocs + $parameter instanceof ExtendedParameterReflection && $parameter->getClosureThisType() !== null && self::hasTemplateOrLateResolvableType($parameter->getClosureThisType()) ) { @@ -541,7 +541,7 @@ public static function selectFromTypes( /** * @param ParametersAcceptor[] $acceptors */ - public static function combineAcceptors(array $acceptors): ParametersAcceptorWithPhpDocs + public static function combineAcceptors(array $acceptors): ExtendedParametersAcceptor { if (count($acceptors) === 0) { throw new ShouldNotHappenException( @@ -586,7 +586,7 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit foreach ($acceptors as $acceptor) { $returnTypes[] = $acceptor->getReturnType(); - if ($acceptor instanceof ParametersAcceptorWithPhpDocs) { + if ($acceptor instanceof ExtendedParametersAcceptor) { $phpDocReturnTypes[] = $acceptor->getPhpDocReturnType(); $nativeReturnTypes[] = $acceptor->getNativeReturnType(); } @@ -603,18 +603,18 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit foreach ($acceptor->getParameters() as $i => $parameter) { if (!isset($parameters[$i])) { - $parameters[$i] = new DummyParameterWithPhpDocs( + $parameters[$i] = new ExtendedDummyParameter( $parameter->getName(), $parameter->getType(), $i + 1 > $minimumNumberOfParameters, $parameter->passedByReference(), $parameter->isVariadic(), $parameter->getDefaultValue(), - $parameter instanceof ParameterReflectionWithPhpDocs ? $parameter->getNativeType() : new MixedType(), - $parameter instanceof ParameterReflectionWithPhpDocs ? $parameter->getPhpDocType() : new MixedType(), - $parameter instanceof ParameterReflectionWithPhpDocs ? $parameter->getOutType() : null, - $parameter instanceof ParameterReflectionWithPhpDocs ? $parameter->isImmediatelyInvokedCallable() : TrinaryLogic::createMaybe(), - $parameter instanceof ParameterReflectionWithPhpDocs ? $parameter->getClosureThisType() : null, + $parameter instanceof ExtendedParameterReflection ? $parameter->getNativeType() : new MixedType(), + $parameter instanceof ExtendedParameterReflection ? $parameter->getPhpDocType() : new MixedType(), + $parameter instanceof ExtendedParameterReflection ? $parameter->getOutType() : null, + $parameter instanceof ExtendedParameterReflection ? $parameter->isImmediatelyInvokedCallable() : TrinaryLogic::createMaybe(), + $parameter instanceof ExtendedParameterReflection ? $parameter->getClosureThisType() : null, ); continue; } @@ -634,7 +634,7 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit $outType = $parameters[$i]->getOutType(); $immediatelyInvokedCallable = $parameters[$i]->isImmediatelyInvokedCallable(); $closureThisType = $parameters[$i]->getClosureThisType(); - if ($parameter instanceof ParameterReflectionWithPhpDocs) { + if ($parameter instanceof ExtendedParameterReflection) { $nativeType = TypeCombinator::union($nativeType, $parameter->getNativeType()); $phpDocType = TypeCombinator::union($phpDocType, $parameter->getPhpDocType()); @@ -659,7 +659,7 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit $closureThisType = null; } - $parameters[$i] = new DummyParameterWithPhpDocs( + $parameters[$i] = new ExtendedDummyParameter( $parameters[$i]->getName() !== $parameter->getName() ? sprintf('%s|%s', $parameters[$i]->getName(), $parameter->getName()) : $parameter->getName(), $type, $i + 1 > $minimumNumberOfParameters, @@ -685,7 +685,7 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit $nativeReturnType = $nativeReturnTypes === [] ? null : TypeCombinator::union(...$nativeReturnTypes); if ($callableOccurred) { - return new CallableFunctionVariantWithPhpDocs( + return new ExtendedCallableFunctionVariant( TemplateTypeMap::createEmpty(), null, $parameters, @@ -703,7 +703,7 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit ); } - return new FunctionVariantWithPhpDocs( + return new ExtendedFunctionVariant( TemplateTypeMap::createEmpty(), null, $parameters, @@ -714,17 +714,17 @@ public static function combineAcceptors(array $acceptors): ParametersAcceptorWit ); } - private static function wrapAcceptor(ParametersAcceptor $acceptor): ParametersAcceptorWithPhpDocs + private static function wrapAcceptor(ParametersAcceptor $acceptor): ExtendedParametersAcceptor { - if ($acceptor instanceof ParametersAcceptorWithPhpDocs) { + if ($acceptor instanceof ExtendedParametersAcceptor) { return $acceptor; } if ($acceptor instanceof CallableParametersAcceptor) { - return new CallableFunctionVariantWithPhpDocs( + return new ExtendedCallableFunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), - array_map(static fn (ParameterReflection $parameter): ParameterReflectionWithPhpDocs => self::wrapParameter($parameter), $acceptor->getParameters()), + array_map(static fn (ParameterReflection $parameter): ExtendedParameterReflection => self::wrapParameter($parameter), $acceptor->getParameters()), $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor->getReturnType(), @@ -739,10 +739,10 @@ private static function wrapAcceptor(ParametersAcceptor $acceptor): ParametersAc ); } - return new FunctionVariantWithPhpDocs( + return new ExtendedFunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), - array_map(static fn (ParameterReflection $parameter): ParameterReflectionWithPhpDocs => self::wrapParameter($parameter), $acceptor->getParameters()), + array_map(static fn (ParameterReflection $parameter): ExtendedParameterReflection => self::wrapParameter($parameter), $acceptor->getParameters()), $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor->getReturnType(), @@ -751,9 +751,9 @@ private static function wrapAcceptor(ParametersAcceptor $acceptor): ParametersAc ); } - private static function wrapParameter(ParameterReflection $parameter): ParameterReflectionWithPhpDocs + private static function wrapParameter(ParameterReflection $parameter): ExtendedParameterReflection { - return $parameter instanceof ParameterReflectionWithPhpDocs ? $parameter : new DummyParameterWithPhpDocs( + return $parameter instanceof ExtendedParameterReflection ? $parameter : new ExtendedDummyParameter( $parameter->getName(), $parameter->getType(), $parameter->isOptional(), diff --git a/src/Reflection/Php/ClosureCallMethodReflection.php b/src/Reflection/Php/ClosureCallMethodReflection.php index 1bb9d201c8..e28f4cd259 100644 --- a/src/Reflection/Php/ClosureCallMethodReflection.php +++ b/src/Reflection/Php/ClosureCallMethodReflection.php @@ -5,12 +5,12 @@ use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\Native\NativeParameterReflection; use PHPStan\Reflection\ParameterReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\PassedByReference; use PHPStan\TrinaryLogic; use PHPStan\Type\ClosureType; @@ -81,10 +81,10 @@ public function getVariants(): array array_unshift($parameters, $newThis); return [ - new FunctionVariantWithPhpDocs( + new ExtendedFunctionVariant( $this->closureType->getTemplateTypeMap(), $this->closureType->getResolvedTemplateTypeMap(), - array_map(static fn (ParameterReflection $parameter): ParameterReflectionWithPhpDocs => new DummyParameterWithPhpDocs( + array_map(static fn (ParameterReflection $parameter): ExtendedParameterReflection => new ExtendedDummyParameter( $parameter->getName(), $parameter->getType(), $parameter->isOptional(), @@ -106,7 +106,7 @@ public function getVariants(): array ]; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } diff --git a/src/Reflection/Php/EnumCasesMethodReflection.php b/src/Reflection/Php/EnumCasesMethodReflection.php index bd706e7c98..2758c04c27 100644 --- a/src/Reflection/Php/EnumCasesMethodReflection.php +++ b/src/Reflection/Php/EnumCasesMethodReflection.php @@ -5,9 +5,9 @@ use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; @@ -64,7 +64,7 @@ public function getPrototype(): ClassMemberReflection public function getVariants(): array { return [ - new FunctionVariantWithPhpDocs( + new ExtendedFunctionVariant( TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [], @@ -76,7 +76,7 @@ public function getVariants(): array ]; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } diff --git a/src/Reflection/Php/ExitFunctionReflection.php b/src/Reflection/Php/ExitFunctionReflection.php index 331105aceb..12eb38927d 100644 --- a/src/Reflection/Php/ExitFunctionReflection.php +++ b/src/Reflection/Php/ExitFunctionReflection.php @@ -3,9 +3,9 @@ namespace PHPStan\Reflection\Php; use PHPStan\Reflection\Assertions; +use PHPStan\Reflection\ExtendedFunctionVariant; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\PassedByReference; use PHPStan\TrinaryLogic; use PHPStan\Type\Constant\ConstantIntegerType; @@ -42,11 +42,11 @@ public function getVariants(): array new IntegerType(), ]); return [ - new FunctionVariantWithPhpDocs( + new ExtendedFunctionVariant( TemplateTypeMap::createEmpty(), TemplateTypeMap::createEmpty(), [ - new DummyParameterWithPhpDocs( + new ExtendedDummyParameter( 'status', $parameterType, true, @@ -69,13 +69,13 @@ public function getVariants(): array ]; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } /** - * @return ParametersAcceptorWithPhpDocs[] + * @return ExtendedParametersAcceptor[] */ public function getNamedArgumentsVariants(): array { diff --git a/src/Reflection/Php/DummyParameterWithPhpDocs.php b/src/Reflection/Php/ExtendedDummyParameter.php similarity index 86% rename from src/Reflection/Php/DummyParameterWithPhpDocs.php rename to src/Reflection/Php/ExtendedDummyParameter.php index c7d8cc141c..91238c18b9 100644 --- a/src/Reflection/Php/DummyParameterWithPhpDocs.php +++ b/src/Reflection/Php/ExtendedDummyParameter.php @@ -2,12 +2,12 @@ namespace PHPStan\Reflection\Php; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\PassedByReference; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; -final class DummyParameterWithPhpDocs extends DummyParameter implements ParameterReflectionWithPhpDocs +final class ExtendedDummyParameter extends DummyParameter implements ExtendedParameterReflection { public function __construct( diff --git a/src/Reflection/Php/PhpClassReflectionExtension.php b/src/Reflection/Php/PhpClassReflectionExtension.php index 5a3606a66f..c42863737c 100644 --- a/src/Reflection/Php/PhpClassReflectionExtension.php +++ b/src/Reflection/Php/PhpClassReflectionExtension.php @@ -21,13 +21,13 @@ use PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; use PHPStan\Reflection\ExtendedPropertyReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\MethodsClassReflectionExtension; +use PHPStan\Reflection\Native\ExtendedNativeParameterReflection; use PHPStan\Reflection\Native\NativeMethodReflection; -use PHPStan\Reflection\Native\NativeParameterWithPhpDocsReflection; use PHPStan\Reflection\PropertiesClassReflectionExtension; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Reflection\SignatureMap\FunctionSignature; @@ -822,7 +822,7 @@ private function createNativeMethodVariant( array $stubClosureThisParameters, array $closureThisParameters, bool $usePhpDocParameterNames, - ): FunctionVariantWithPhpDocs + ): ExtendedFunctionVariant { $parameters = []; foreach ($methodSignature->getParameters() as $parameterSignature) { @@ -860,7 +860,7 @@ private function createNativeMethodVariant( $closureThisType = $closureThisParameters[$phpDocParameterName]; } - $parameters[] = new NativeParameterWithPhpDocsReflection( + $parameters[] = new ExtendedNativeParameterReflection( $usePhpDocParameterNames ? $phpDocParameterName : $parameterSignature->getName(), @@ -884,7 +884,7 @@ private function createNativeMethodVariant( $returnType = TypehintHelper::decideType($methodSignature->getReturnType(), $phpDocReturnType); } - return new FunctionVariantWithPhpDocs( + return new ExtendedFunctionVariant( TemplateTypeMap::createEmpty(), null, $parameters, diff --git a/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php b/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php index 227b23ddab..dc44c0d17d 100644 --- a/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php +++ b/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php @@ -8,10 +8,10 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; use PHPStan\Reflection\Assertions; +use PHPStan\Reflection\ExtendedFunctionVariant; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\PassedByReference; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; @@ -27,13 +27,13 @@ /** * @api */ -class PhpFunctionFromParserNodeReflection implements FunctionReflection, ParametersAcceptorWithPhpDocs +class PhpFunctionFromParserNodeReflection implements FunctionReflection, ExtendedParametersAcceptor { /** @var Function_|ClassMethod */ private Node\FunctionLike $functionLike; - /** @var FunctionVariantWithPhpDocs[]|null */ + /** @var ExtendedFunctionVariant[]|null */ private ?array $variants = null; /** @@ -94,13 +94,13 @@ public function getName(): string } /** - * @return ParametersAcceptorWithPhpDocs[] + * @return ExtendedParametersAcceptor[] */ public function getVariants(): array { if ($this->variants === null) { $this->variants = [ - new FunctionVariantWithPhpDocs( + new ExtendedFunctionVariant( $this->getTemplateTypeMap(), $this->getResolvedTemplateTypeMap(), $this->getParameters(), @@ -115,7 +115,7 @@ public function getVariants(): array return $this->variants; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this; } @@ -136,7 +136,7 @@ public function getResolvedTemplateTypeMap(): TemplateTypeMap } /** - * @return array + * @return array */ public function getParameters(): array { diff --git a/src/Reflection/Php/PhpFunctionReflection.php b/src/Reflection/Php/PhpFunctionReflection.php index 6aba725f1c..4669701c79 100644 --- a/src/Reflection/Php/PhpFunctionReflection.php +++ b/src/Reflection/Php/PhpFunctionReflection.php @@ -10,12 +10,12 @@ use PHPStan\Parser\FunctionCallStatementFinder; use PHPStan\Parser\Parser; use PHPStan\Reflection\Assertions; +use PHPStan\Reflection\ExtendedFunctionVariant; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; use PHPStan\Reflection\InitializerExprTypeResolver; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Reflection\ParametersAcceptor; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\MixedType; @@ -32,7 +32,7 @@ final class PhpFunctionReflection implements FunctionReflection { - /** @var FunctionVariantWithPhpDocs[]|null */ + /** @var ExtendedFunctionVariant[]|null */ private ?array $variants = null; /** @@ -86,13 +86,13 @@ public function getFileName(): ?string } /** - * @return ParametersAcceptorWithPhpDocs[] + * @return ExtendedParametersAcceptor[] */ public function getVariants(): array { if ($this->variants === null) { $this->variants = [ - new FunctionVariantWithPhpDocs( + new ExtendedFunctionVariant( $this->templateTypeMap, null, $this->getParameters(), @@ -107,7 +107,7 @@ public function getVariants(): array return $this->variants; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } @@ -118,7 +118,7 @@ public function getNamedArgumentsVariants(): ?array } /** - * @return ParameterReflectionWithPhpDocs[] + * @return ExtendedParameterReflection[] */ private function getParameters(): array { diff --git a/src/Reflection/Php/PhpMethodReflection.php b/src/Reflection/Php/PhpMethodReflection.php index d71fce1a4c..afa4f56a46 100644 --- a/src/Reflection/Php/PhpMethodReflection.php +++ b/src/Reflection/Php/PhpMethodReflection.php @@ -15,13 +15,13 @@ use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\MethodPrototypeReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Reflection\ParametersAcceptor; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\ReflectionProvider; use PHPStan\TrinaryLogic; use PHPStan\Type\ArrayType; @@ -59,7 +59,7 @@ final class PhpMethodReflection implements ExtendedMethodReflection private ?Type $nativeReturnType = null; - /** @var FunctionVariantWithPhpDocs[]|null */ + /** @var ExtendedFunctionVariant[]|null */ private ?array $variants = null; /** @@ -191,13 +191,13 @@ private function getMethodNameWithCorrectCase(string $lowercaseMethodName, strin } /** - * @return ParametersAcceptorWithPhpDocs[] + * @return ExtendedParametersAcceptor[] */ public function getVariants(): array { if ($this->variants === null) { $this->variants = [ - new FunctionVariantWithPhpDocs( + new ExtendedFunctionVariant( $this->templateTypeMap, null, $this->getParameters(), @@ -212,7 +212,7 @@ public function getVariants(): array return $this->variants; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } @@ -223,7 +223,7 @@ public function getNamedArgumentsVariants(): ?array } /** - * @return ParameterReflectionWithPhpDocs[] + * @return ExtendedParameterReflection[] */ private function getParameters(): array { diff --git a/src/Reflection/Php/PhpParameterFromParserNodeReflection.php b/src/Reflection/Php/PhpParameterFromParserNodeReflection.php index 61d1852c7d..8ebb272bfd 100644 --- a/src/Reflection/Php/PhpParameterFromParserNodeReflection.php +++ b/src/Reflection/Php/PhpParameterFromParserNodeReflection.php @@ -2,7 +2,7 @@ namespace PHPStan\Reflection\Php; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\PassedByReference; use PHPStan\TrinaryLogic; use PHPStan\Type\MixedType; @@ -10,7 +10,7 @@ use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypehintHelper; -final class PhpParameterFromParserNodeReflection implements ParameterReflectionWithPhpDocs +final class PhpParameterFromParserNodeReflection implements ExtendedParameterReflection { private ?Type $type = null; diff --git a/src/Reflection/Php/PhpParameterReflection.php b/src/Reflection/Php/PhpParameterReflection.php index 548d9bde47..40b28e9ff6 100644 --- a/src/Reflection/Php/PhpParameterReflection.php +++ b/src/Reflection/Php/PhpParameterReflection.php @@ -4,9 +4,9 @@ use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\InitializerExprContext; use PHPStan\Reflection\InitializerExprTypeResolver; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Reflection\PassedByReference; use PHPStan\TrinaryLogic; use PHPStan\Type\MixedType; @@ -14,7 +14,7 @@ use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypehintHelper; -final class PhpParameterReflection implements ParameterReflectionWithPhpDocs +final class PhpParameterReflection implements ExtendedParameterReflection { private ?Type $type = null; diff --git a/src/Reflection/ResolvedFunctionVariant.php b/src/Reflection/ResolvedFunctionVariant.php index a6139853fb..5b5cb6b4e6 100644 --- a/src/Reflection/ResolvedFunctionVariant.php +++ b/src/Reflection/ResolvedFunctionVariant.php @@ -4,7 +4,7 @@ use PHPStan\Type\Type; -interface ResolvedFunctionVariant extends ParametersAcceptorWithPhpDocs +interface ResolvedFunctionVariant extends ExtendedParametersAcceptor { public function getOriginalParametersAcceptor(): ParametersAcceptor; diff --git a/src/Reflection/ResolvedFunctionVariantWithOriginal.php b/src/Reflection/ResolvedFunctionVariantWithOriginal.php index ab5b182105..4dda7b8685 100644 --- a/src/Reflection/ResolvedFunctionVariantWithOriginal.php +++ b/src/Reflection/ResolvedFunctionVariantWithOriginal.php @@ -2,7 +2,7 @@ namespace PHPStan\Reflection; -use PHPStan\Reflection\Php\DummyParameterWithPhpDocs; +use PHPStan\Reflection\Php\ExtendedDummyParameter; use PHPStan\Type\ConditionalTypeForParameter; use PHPStan\Type\ErrorType; use PHPStan\Type\Generic\GenericObjectType; @@ -21,7 +21,7 @@ final class ResolvedFunctionVariantWithOriginal implements ResolvedFunctionVariant { - /** @var ParameterReflectionWithPhpDocs[]|null */ + /** @var ExtendedParameterReflection[]|null */ private ?array $parameters = null; private ?Type $returnTypeWithUnresolvableTemplateTypes = null; @@ -36,7 +36,7 @@ final class ResolvedFunctionVariantWithOriginal implements ResolvedFunctionVaria * @param array $passedArgs */ public function __construct( - private ParametersAcceptorWithPhpDocs $parametersAcceptor, + private ExtendedParametersAcceptor $parametersAcceptor, private TemplateTypeMap $resolvedTemplateTypeMap, private TemplateTypeVarianceMap $callSiteVarianceMap, private array $passedArgs, @@ -70,7 +70,7 @@ public function getParameters(): array if ($parameters === null) { $parameters = array_map( - function (ParameterReflectionWithPhpDocs $param): ParameterReflectionWithPhpDocs { + function (ExtendedParameterReflection $param): ExtendedParameterReflection { $paramType = TypeUtils::resolveLateResolvableTypes( TemplateTypeHelper::resolveTemplateTypes( $this->resolveConditionalTypesForParameter($param->getType()), @@ -107,7 +107,7 @@ function (ParameterReflectionWithPhpDocs $param): ParameterReflectionWithPhpDocs ); } - return new DummyParameterWithPhpDocs( + return new ExtendedDummyParameter( $param->getName(), $paramType, $param->isOptional(), diff --git a/src/Reflection/ResolvedMethodReflection.php b/src/Reflection/ResolvedMethodReflection.php index 1ce0c0dc71..b04803c13c 100644 --- a/src/Reflection/ResolvedMethodReflection.php +++ b/src/Reflection/ResolvedMethodReflection.php @@ -14,10 +14,10 @@ final class ResolvedMethodReflection implements ExtendedMethodReflection { - /** @var ParametersAcceptorWithPhpDocs[]|null */ + /** @var ExtendedParametersAcceptor[]|null */ private ?array $variants = null; - /** @var ParametersAcceptorWithPhpDocs[]|null */ + /** @var ExtendedParametersAcceptor[]|null */ private ?array $namedArgumentVariants = null; private ?Assertions $asserts = null; @@ -52,7 +52,7 @@ public function getVariants(): array return $this->variants = $this->resolveVariants($this->reflection->getVariants()); } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } @@ -73,7 +73,7 @@ public function getNamedArgumentsVariants(): ?array } /** - * @param ParametersAcceptorWithPhpDocs[] $variants + * @param ExtendedParametersAcceptor[] $variants * @return ResolvedFunctionVariant[] */ private function resolveVariants(array $variants): array diff --git a/src/Reflection/SignatureMap/NativeFunctionReflectionProvider.php b/src/Reflection/SignatureMap/NativeFunctionReflectionProvider.php index 32a484c3c9..2a94fc4da5 100644 --- a/src/Reflection/SignatureMap/NativeFunctionReflectionProvider.php +++ b/src/Reflection/SignatureMap/NativeFunctionReflectionProvider.php @@ -9,9 +9,9 @@ use PHPStan\PhpDoc\ResolvedPhpDocBlock; use PHPStan\PhpDoc\StubPhpDocProvider; use PHPStan\Reflection\Assertions; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; +use PHPStan\Reflection\ExtendedFunctionVariant; +use PHPStan\Reflection\Native\ExtendedNativeParameterReflection; use PHPStan\Reflection\Native\NativeFunctionReflection; -use PHPStan\Reflection\Native\NativeParameterWithPhpDocsReflection; use PHPStan\TrinaryLogic; use PHPStan\Type\FileTypeMapper; use PHPStan\Type\Generic\TemplateTypeMap; @@ -91,10 +91,10 @@ public function findFunctionReflection(string $functionName): ?NativeFunctionRef $variantsByType = ['positional' => []]; foreach ($functionSignaturesResult as $signatureType => $functionSignatures) { foreach ($functionSignatures ?? [] as $functionSignature) { - $variantsByType[$signatureType][] = new FunctionVariantWithPhpDocs( + $variantsByType[$signatureType][] = new ExtendedFunctionVariant( TemplateTypeMap::createEmpty(), null, - array_map(static function (ParameterSignature $parameterSignature) use ($phpDoc): NativeParameterWithPhpDocsReflection { + array_map(static function (ParameterSignature $parameterSignature) use ($phpDoc): ExtendedNativeParameterReflection { $type = $parameterSignature->getType(); $phpDocType = null; @@ -112,7 +112,7 @@ public function findFunctionReflection(string $functionName): ?NativeFunctionRef } } - return new NativeParameterWithPhpDocsReflection( + return new ExtendedNativeParameterReflection( $parameterSignature->getName(), $parameterSignature->isOptional(), TypehintHelper::decideType($type, $phpDocType), diff --git a/src/Reflection/TrivialParametersAcceptor.php b/src/Reflection/TrivialParametersAcceptor.php index 05a4888c27..ea6b278145 100644 --- a/src/Reflection/TrivialParametersAcceptor.php +++ b/src/Reflection/TrivialParametersAcceptor.php @@ -14,7 +14,7 @@ /** * @api */ -final class TrivialParametersAcceptor implements ParametersAcceptorWithPhpDocs, CallableParametersAcceptor +final class TrivialParametersAcceptor implements ExtendedParametersAcceptor, CallableParametersAcceptor { /** @api */ diff --git a/src/Reflection/Type/CallbackUnresolvedMethodPrototypeReflection.php b/src/Reflection/Type/CallbackUnresolvedMethodPrototypeReflection.php index 5fd19b3105..eaca01ec4c 100644 --- a/src/Reflection/Type/CallbackUnresolvedMethodPrototypeReflection.php +++ b/src/Reflection/Type/CallbackUnresolvedMethodPrototypeReflection.php @@ -4,11 +4,11 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\Dummy\ChangedTypeMethodReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; -use PHPStan\Reflection\Php\DummyParameterWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; +use PHPStan\Reflection\Php\ExtendedDummyParameter; use PHPStan\Reflection\ResolvedMethodReflection; use PHPStan\Type\Type; use function array_map; @@ -82,11 +82,11 @@ public function withCalledOnType(Type $type): UnresolvedMethodPrototypeReflectio private function transformMethodWithStaticType(ClassReflection $declaringClass, ExtendedMethodReflection $method): ExtendedMethodReflection { - $variantFn = fn (ParametersAcceptorWithPhpDocs $acceptor): ParametersAcceptorWithPhpDocs => new FunctionVariantWithPhpDocs( + $variantFn = fn (ExtendedParametersAcceptor $acceptor): ExtendedParametersAcceptor => new ExtendedFunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map( - fn (ParameterReflectionWithPhpDocs $parameter): ParameterReflectionWithPhpDocs => new DummyParameterWithPhpDocs( + fn (ExtendedParameterReflection $parameter): ExtendedParameterReflection => new ExtendedDummyParameter( $parameter->getName(), $this->transformStaticType($parameter->getType()), $parameter->isOptional(), diff --git a/src/Reflection/Type/CalledOnTypeUnresolvedMethodPrototypeReflection.php b/src/Reflection/Type/CalledOnTypeUnresolvedMethodPrototypeReflection.php index 607a08a37f..25f676b5ae 100644 --- a/src/Reflection/Type/CalledOnTypeUnresolvedMethodPrototypeReflection.php +++ b/src/Reflection/Type/CalledOnTypeUnresolvedMethodPrototypeReflection.php @@ -4,11 +4,11 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\Dummy\ChangedTypeMethodReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; -use PHPStan\Reflection\Php\DummyParameterWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; +use PHPStan\Reflection\Php\ExtendedDummyParameter; use PHPStan\Reflection\ResolvedMethodReflection; use PHPStan\Type\StaticType; use PHPStan\Type\Type; @@ -77,11 +77,11 @@ public function withCalledOnType(Type $type): UnresolvedMethodPrototypeReflectio private function transformMethodWithStaticType(ClassReflection $declaringClass, ExtendedMethodReflection $method): ExtendedMethodReflection { - $variantFn = fn (ParametersAcceptorWithPhpDocs $acceptor): ParametersAcceptorWithPhpDocs => new FunctionVariantWithPhpDocs( + $variantFn = fn (ExtendedParametersAcceptor $acceptor): ExtendedParametersAcceptor => new ExtendedFunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), array_map( - fn (ParameterReflectionWithPhpDocs $parameter): ParameterReflectionWithPhpDocs => new DummyParameterWithPhpDocs( + fn (ExtendedParameterReflection $parameter): ExtendedParameterReflection => new ExtendedDummyParameter( $parameter->getName(), $this->transformStaticType($parameter->getType()), $parameter->isOptional(), diff --git a/src/Reflection/Type/IntersectionTypeMethodReflection.php b/src/Reflection/Type/IntersectionTypeMethodReflection.php index d27576767f..c19986d71c 100644 --- a/src/Reflection/Type/IntersectionTypeMethodReflection.php +++ b/src/Reflection/Type/IntersectionTypeMethodReflection.php @@ -5,11 +5,11 @@ use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParametersAcceptor; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; @@ -83,7 +83,7 @@ public function getVariants(): array $phpDocReturnType = TypeCombinator::intersect(...array_map(static fn (MethodReflection $method): Type => TypeCombinator::intersect(...array_map(static fn (ParametersAcceptor $acceptor): Type => $acceptor->getPhpDocReturnType(), $method->getVariants())), $this->methods)); $nativeReturnType = TypeCombinator::intersect(...array_map(static fn (MethodReflection $method): Type => TypeCombinator::intersect(...array_map(static fn (ParametersAcceptor $acceptor): Type => $acceptor->getNativeReturnType(), $method->getVariants())), $this->methods)); - return array_map(static fn (ParametersAcceptorWithPhpDocs $acceptor): ParametersAcceptorWithPhpDocs => new FunctionVariantWithPhpDocs( + return array_map(static fn (ExtendedParametersAcceptor $acceptor): ExtendedParametersAcceptor => new ExtendedFunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), $acceptor->getParameters(), @@ -95,7 +95,7 @@ public function getVariants(): array ), $this->methods[0]->getVariants()); } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { $variants = $this->getVariants(); if (count($variants) !== 1) { diff --git a/src/Reflection/Type/UnionTypeMethodReflection.php b/src/Reflection/Type/UnionTypeMethodReflection.php index 140ce0bd2e..167493c0b8 100644 --- a/src/Reflection/Type/UnionTypeMethodReflection.php +++ b/src/Reflection/Type/UnionTypeMethodReflection.php @@ -6,9 +6,9 @@ use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParametersAcceptorSelector; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\TrinaryLogic; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -83,7 +83,7 @@ public function getVariants(): array return [ParametersAcceptorSelector::combineAcceptors($variants)]; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } diff --git a/src/Reflection/WrappedExtendedMethodReflection.php b/src/Reflection/WrappedExtendedMethodReflection.php index 2f348095ff..c14e51656e 100644 --- a/src/Reflection/WrappedExtendedMethodReflection.php +++ b/src/Reflection/WrappedExtendedMethodReflection.php @@ -2,7 +2,7 @@ namespace PHPStan\Reflection; -use PHPStan\Reflection\Php\DummyParameterWithPhpDocs; +use PHPStan\Reflection\Php\ExtendedDummyParameter; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeVarianceMap; use PHPStan\Type\MixedType; @@ -55,15 +55,15 @@ public function getVariants(): array { $variants = []; foreach ($this->method->getVariants() as $variant) { - if ($variant instanceof ParametersAcceptorWithPhpDocs) { + if ($variant instanceof ExtendedParametersAcceptor) { $variants[] = $variant; continue; } - $variants[] = new FunctionVariantWithPhpDocs( + $variants[] = new ExtendedFunctionVariant( $variant->getTemplateTypeMap(), $variant->getResolvedTemplateTypeMap(), - array_map(static fn (ParameterReflection $parameter): ParameterReflectionWithPhpDocs => $parameter instanceof ParameterReflectionWithPhpDocs ? $parameter : new DummyParameterWithPhpDocs( + array_map(static fn (ParameterReflection $parameter): ExtendedParameterReflection => $parameter instanceof ExtendedParameterReflection ? $parameter : new ExtendedDummyParameter( $parameter->getName(), $parameter->getType(), $parameter->isOptional(), @@ -87,7 +87,7 @@ public function getVariants(): array return $variants; } - public function getOnlyVariant(): ParametersAcceptorWithPhpDocs + public function getOnlyVariant(): ExtendedParametersAcceptor { return $this->getVariants()[0]; } diff --git a/src/Rules/Api/BcUncoveredInterface.php b/src/Rules/Api/BcUncoveredInterface.php index ccaf001a14..3bf9c0c61d 100644 --- a/src/Rules/Api/BcUncoveredInterface.php +++ b/src/Rules/Api/BcUncoveredInterface.php @@ -15,11 +15,11 @@ use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ConstantReflection; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\NamespaceAnswerer; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\FileRuleError; use PHPStan\Rules\IdentifierRuleError; @@ -48,8 +48,8 @@ final class BcUncoveredInterface FunctionReflection::class, ExtendedMethodReflection::class, ExtendedPropertyReflection::class, - ParametersAcceptorWithPhpDocs::class, - ParameterReflectionWithPhpDocs::class, + ExtendedParametersAcceptor::class, + ExtendedParameterReflection::class, CallableParametersAcceptor::class, FileRuleError::class, IdentifierRuleError::class, diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index aa8b9f356a..365ab626a1 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -7,8 +7,8 @@ use PHPStan\Analyser\MutatingScope; use PHPStan\Analyser\Scope; use PHPStan\Php\PhpVersion; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\ParameterReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ResolvedFunctionVariant; use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper; @@ -342,7 +342,7 @@ public function check( } if ( - $parameter instanceof ParameterReflectionWithPhpDocs + $parameter instanceof ExtendedParameterReflection && $parameter->getClosureThisType() !== null && ($argumentValue instanceof Expr\Closure || $argumentValue instanceof Expr\ArrowFunction) && $argumentValue->static diff --git a/src/Rules/FunctionDefinitionCheck.php b/src/Rules/FunctionDefinitionCheck.php index 8f91b45ec9..6874582743 100644 --- a/src/Rules/FunctionDefinitionCheck.php +++ b/src/Rules/FunctionDefinitionCheck.php @@ -18,10 +18,10 @@ use PHPStan\Analyser\Scope; use PHPStan\Node\Printer\NodeTypePrinter; use PHPStan\Php\PhpVersion; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\ParameterReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Reflection\ParametersAcceptor; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection; use PHPStan\Reflection\ReflectionProvider; @@ -368,7 +368,7 @@ private function checkParametersAcceptor( return $parameterNode; }; - if ($parameter instanceof ParameterReflectionWithPhpDocs) { + if ($parameter instanceof ExtendedParameterReflection) { $parameterVar = $parameterNodeCallback()->var; if (!$parameterVar instanceof Variable || !is_string($parameterVar->name)) { throw new ShouldNotHappenException(); @@ -630,7 +630,7 @@ private function getParameterNode( */ private function getParameterReferencedClasses(ParameterReflection $parameter): array { - if (!$parameter instanceof ParameterReflectionWithPhpDocs) { + if (!$parameter instanceof ExtendedParameterReflection) { return $parameter->getType()->getReferencedClasses(); } @@ -658,7 +658,7 @@ private function getParameterReferencedClasses(ParameterReflection $parameter): */ private function getReturnTypeReferencedClasses(ParametersAcceptor $parametersAcceptor): array { - if (!$parametersAcceptor instanceof ParametersAcceptorWithPhpDocs) { + if (!$parametersAcceptor instanceof ExtendedParametersAcceptor) { return $parametersAcceptor->getReturnType()->getReferencedClasses(); } diff --git a/src/Rules/Generics/VarianceCheck.php b/src/Rules/Generics/VarianceCheck.php index 95170eecb4..d01dbf75a3 100644 --- a/src/Rules/Generics/VarianceCheck.php +++ b/src/Rules/Generics/VarianceCheck.php @@ -2,7 +2,7 @@ namespace PHPStan\Rules\Generics; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\Generic\TemplateType; @@ -18,7 +18,7 @@ final class VarianceCheck * @return list */ public function checkParametersAcceptor( - ParametersAcceptorWithPhpDocs $parametersAcceptor, + ExtendedParametersAcceptor $parametersAcceptor, string $parameterTypeMessage, string $parameterOutTypeMessage, string $returnTypeMessage, diff --git a/src/Rules/Methods/MethodSignatureRule.php b/src/Rules/Methods/MethodSignatureRule.php index bac3f273ad..c3c04089ce 100644 --- a/src/Rules/Methods/MethodSignatureRule.php +++ b/src/Rules/Methods/MethodSignatureRule.php @@ -7,8 +7,8 @@ use PHPStan\Node\InClassMethodNode; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\Php\PhpClassReflectionExtension; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\Rule; @@ -196,8 +196,8 @@ private function collectParentMethods(string $methodName, ClassReflection $class */ private function checkReturnTypeCompatibility( ClassReflection $declaringClass, - ParametersAcceptorWithPhpDocs $currentVariant, - ParametersAcceptorWithPhpDocs $parentVariant, + ExtendedParametersAcceptor $currentVariant, + ExtendedParametersAcceptor $parentVariant, ): array { $returnType = TypehintHelper::decideType( @@ -226,8 +226,8 @@ private function checkReturnTypeCompatibility( } /** - * @param ParameterReflectionWithPhpDocs[] $parameters - * @param ParameterReflectionWithPhpDocs[] $parentParameters + * @param ExtendedParameterReflection[] $parameters + * @param ExtendedParameterReflection[] $parentParameters * @return array */ private function checkParameterTypeCompatibility( diff --git a/src/Rules/Methods/OverridingMethodRule.php b/src/Rules/Methods/OverridingMethodRule.php index 0a78f8d382..38c588f9db 100644 --- a/src/Rules/Methods/OverridingMethodRule.php +++ b/src/Rules/Methods/OverridingMethodRule.php @@ -7,8 +7,8 @@ use PHPStan\Node\InClassMethodNode; use PHPStan\Php\PhpVersion; use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedMethodReflection; -use PHPStan\Reflection\FunctionVariantWithPhpDocs; use PHPStan\Reflection\MethodPrototypeReflection; use PHPStan\Reflection\Native\NativeMethodReflection; use PHPStan\Reflection\Php\PhpClassReflectionExtension; @@ -230,7 +230,7 @@ public function processNode(Node $node, Scope $scope): array $messages = array_merge($messages, $this->methodParameterComparisonHelper->compare($prototype, $prototypeDeclaringClass, $method, false)); - if (!$prototypeVariant instanceof FunctionVariantWithPhpDocs) { + if (!$prototypeVariant instanceof ExtendedFunctionVariant) { return $this->addErrors($messages, $node, $scope); } diff --git a/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php b/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php index eee8ad3281..f48a8abc7a 100644 --- a/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php +++ b/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php @@ -2,7 +2,7 @@ namespace PHPStan\Rules\PhpDoc; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\ConditionalType; @@ -23,7 +23,7 @@ final class ConditionalReturnTypeRuleHelper /** * @return list */ - public function check(ParametersAcceptorWithPhpDocs $acceptor): array + public function check(ExtendedParametersAcceptor $acceptor): array { $conditionalTypes = []; $parametersByName = []; diff --git a/src/Rules/Pure/FunctionPurityCheck.php b/src/Rules/Pure/FunctionPurityCheck.php index e70d2eb292..13d0c1fc93 100644 --- a/src/Rules/Pure/FunctionPurityCheck.php +++ b/src/Rules/Pure/FunctionPurityCheck.php @@ -8,8 +8,8 @@ use PHPStan\Analyser\ImpurePoint; use PHPStan\Analyser\ThrowPoint; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Rules\Functions\CallToFunctionStatementWithoutSideEffectsRule; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\RuleErrorBuilder; @@ -25,7 +25,7 @@ final class FunctionPurityCheck /** * @param 'Function'|'Method' $identifier - * @param ParameterReflectionWithPhpDocs[] $parameters + * @param ExtendedParameterReflection[] $parameters * @param ImpurePoint[] $impurePoints * @param ThrowPoint[] $throwPoints * @param Stmt[] $statements diff --git a/src/Rules/TooWideTypehints/TooWideParameterOutTypeCheck.php b/src/Rules/TooWideTypehints/TooWideParameterOutTypeCheck.php index ceeb071238..e891b65fb6 100644 --- a/src/Rules/TooWideTypehints/TooWideParameterOutTypeCheck.php +++ b/src/Rules/TooWideTypehints/TooWideParameterOutTypeCheck.php @@ -6,7 +6,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Node\ExecutionEndNode; use PHPStan\Node\ReturnStatement; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\TypeUtils; @@ -20,7 +20,7 @@ final class TooWideParameterOutTypeCheck /** * @param list $executionEnds * @param list $returnStatements - * @param ParameterReflectionWithPhpDocs[] $parameters + * @param ExtendedParameterReflection[] $parameters * @return list */ public function check( @@ -74,7 +74,7 @@ public function check( private function processSingleParameter( Scope $scope, string $functionDescription, - ParameterReflectionWithPhpDocs $parameter, + ExtendedParameterReflection $parameter, ): array { $isParamOutType = true; diff --git a/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php b/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php index 4c380a67c3..d8337c97a0 100644 --- a/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php +++ b/src/Rules/Variables/ParameterOutExecutionEndTypeRule.php @@ -7,8 +7,8 @@ use PHPStan\Node\ExecutionEndNode; use PHPStan\Node\Expr\ParameterVariableOriginalValueExpr; use PHPStan\Reflection\ExtendedMethodReflection; +use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\FunctionReflection; -use PHPStan\Reflection\ParameterReflectionWithPhpDocs; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -78,7 +78,7 @@ public function processNode(Node $node, Scope $scope): array private function processSingleParameter( Scope $scope, FunctionReflection|ExtendedMethodReflection $inFunction, - ParameterReflectionWithPhpDocs $parameter, + ExtendedParameterReflection $parameter, ): array { $outType = $parameter->getOutType(); diff --git a/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php b/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php index d392b20500..d579157160 100644 --- a/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php +++ b/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php @@ -5,8 +5,8 @@ use Closure; use PhpParser\Node\Expr\StaticCall; use PHPStan\Analyser\Scope; +use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\MethodReflection; -use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Type\ClosureType; use PHPStan\Type\DynamicStaticMethodReturnTypeExtension; use PHPStan\Type\ErrorType; @@ -47,7 +47,7 @@ public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, $variant->isVariadic(), $variant->getTemplateTypeMap(), $variant->getResolvedTemplateTypeMap(), - $variant instanceof ParametersAcceptorWithPhpDocs ? $variant->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), + $variant instanceof ExtendedParametersAcceptor ? $variant->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), [], $variant->getThrowPoints(), $variant->getImpurePoints(), diff --git a/tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php b/tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php index bfafb5996e..870d185d59 100644 --- a/tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php +++ b/tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php @@ -364,7 +364,7 @@ private static function generateFunctionMethodBaseDescription($reflection): stri return $result; } - /** @param ParametersAcceptorWithPhpDocs[] $variants */ + /** @param ExtendedParametersAcceptor[] $variants */ private static function generateVariantsDescription(string $name, array $variants, bool $isNamedArguments): string { $variantCount = count($variants); From 9e7f39ed4ca63dc37941295a627958d517c6c8b4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 11:12:53 +0200 Subject: [PATCH 331/508] [BCB] `ClassPropertyNode::getNativeType()` return type changed from AST node to Type --- UPGRADING.md | 1 + src/Analyser/NodeScopeResolver.php | 7 ++- src/Dependency/DependencyResolver.php | 6 +- src/Node/ClassPropertyNode.php | 17 +++--- .../IncompatiblePropertyPhpDocTypeRule.php | 55 ++++++++++--------- .../Properties/OverridingPropertyRule.php | 9 ++- src/Rules/Types/InvalidTypesInUnionRule.php | 4 +- 7 files changed, 51 insertions(+), 48 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 7859c5f267..5f34052a8c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -299,3 +299,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection` * Interface `GlobalConstantReflection` renamed to `ConstantReflection` * Renamed interfaces and classes from `*WithPhpDocs` to `Extended*` +* `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index ec807de6fa..dfb1b6c1f4 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -170,6 +170,7 @@ use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; use PHPStan\Type\ObjectWithoutClassType; +use PHPStan\Type\ParserNodeTypeToPHPStanType; use PHPStan\Type\ResourceType; use PHPStan\Type\StaticType; use PHPStan\Type\StaticTypeFactory; @@ -648,7 +649,7 @@ private function processStmtNode( $nodeCallback(new ClassPropertyNode( $param->var->name, $param->flags, - $param->type, + $param->type !== null ? ParserNodeTypeToPHPStanType::resolve($param->type, $scope->getClassReflection()) : null, null, $phpDoc, $phpDocParameterTypes[$param->var->name] ?? null, @@ -899,13 +900,13 @@ private function processStmtNode( new ClassPropertyNode( $propertyName, $stmt->flags, - $stmt->type, + $stmt->type !== null ? ParserNodeTypeToPHPStanType::resolve($stmt->type, $scope->getClassReflection()) : null, $prop->default, $docComment, $phpDocType, false, false, - $prop, + $stmt, $isReadOnly, $scope->isInTrait(), $scope->getClassReflection()->isReadOnly(), diff --git a/src/Dependency/DependencyResolver.php b/src/Dependency/DependencyResolver.php index 9fde7ef34f..71fdb78b46 100644 --- a/src/Dependency/DependencyResolver.php +++ b/src/Dependency/DependencyResolver.php @@ -22,7 +22,6 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ClosureType; use PHPStan\Type\FileTypeMapper; -use PHPStan\Type\ParserNodeTypeToPHPStanType; use PHPStan\Type\Type; use function array_merge; use function count; @@ -85,9 +84,8 @@ public function resolveDependencies(Node $node, Scope $scope): NodeDependencies } } } elseif ($node instanceof ClassPropertyNode) { - $nativeTypeNode = $node->getNativeType(); - if ($nativeTypeNode !== null) { - $nativeType = ParserNodeTypeToPHPStanType::resolve($nativeTypeNode, $node->getClassReflection()); + $nativeType = $node->getNativeType(); + if ($nativeType !== null) { foreach ($nativeType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } diff --git a/src/Node/ClassPropertyNode.php b/src/Node/ClassPropertyNode.php index 571f8b34ed..3f500b62c1 100644 --- a/src/Node/ClassPropertyNode.php +++ b/src/Node/ClassPropertyNode.php @@ -5,8 +5,6 @@ use PhpParser\Modifiers; use PhpParser\Node; use PhpParser\Node\Expr; -use PhpParser\Node\Identifier; -use PhpParser\Node\Name; use PhpParser\NodeAbstract; use PHPStan\Reflection\ClassReflection; use PHPStan\Type\Type; @@ -20,13 +18,13 @@ final class ClassPropertyNode extends NodeAbstract implements VirtualNode public function __construct( private string $name, private int $flags, - private Identifier|Name|Node\ComplexType|null $type, + private ?Type $type, private ?Expr $default, private ?string $phpDoc, private ?Type $phpDocType, private bool $isPromoted, private bool $isPromotedFromTrait, - Node $originalNode, + private Node\Stmt\Property|Node\Param $originalNode, private bool $isReadonlyByPhpDoc, private bool $isDeclaredInTrait, private bool $isReadonlyClass, @@ -113,12 +111,17 @@ public function isAllowedPrivateMutation(): bool return $this->isAllowedPrivateMutation; } + public function getNativeType(): ?Type + { + return $this->type; + } + /** - * @return Identifier|Name|Node\ComplexType|null + * @return Node\Identifier|Node\Name|Node\ComplexType|null */ - public function getNativeType() + public function getNativeTypeNode() { - return $this->type; + return $this->originalNode->type; } public function getClassReflection(): ClassReflection diff --git a/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php b/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php index 184821b5a3..a202f67bcd 100644 --- a/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php +++ b/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php @@ -10,7 +10,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\Generic\TemplateType; -use PHPStan\Type\ParserNodeTypeToPHPStanType; use PHPStan\Type\VerbosityLevel; use function array_merge; use function sprintf; @@ -62,33 +61,35 @@ public function processNode(Node $node, Scope $scope): array ))->identifier('property.unresolvableType')->build(); } - $nativeType = ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection); - $isSuperType = $nativeType->isSuperTypeOf($phpDocType); - if ($isSuperType->no()) { - $messages[] = RuleErrorBuilder::message(sprintf( - '%s for property %s::$%s with type %s is incompatible with native type %s.', - $description, - $classReflection->getDisplayName(), - $propertyName, - $phpDocType->describe(VerbosityLevel::typeOnly()), - $nativeType->describe(VerbosityLevel::typeOnly()), - ))->identifier('property.phpDocType')->build(); - - } elseif ($isSuperType->maybe()) { - $errorBuilder = RuleErrorBuilder::message(sprintf( - '%s for property %s::$%s with type %s is not subtype of native type %s.', - $description, - $classReflection->getDisplayName(), - $propertyName, - $phpDocType->describe(VerbosityLevel::typeOnly()), - $nativeType->describe(VerbosityLevel::typeOnly()), - ))->identifier('property.phpDocType'); - - if ($phpDocType instanceof TemplateType) { - $errorBuilder->tip(sprintf('Write @template %s of %s to fix this.', $phpDocType->getName(), $nativeType->describe(VerbosityLevel::typeOnly()))); + $nativeType = $node->getNativeType(); + if ($nativeType !== null) { + $isSuperType = $nativeType->isSuperTypeOf($phpDocType); + if ($isSuperType->no()) { + $messages[] = RuleErrorBuilder::message(sprintf( + '%s for property %s::$%s with type %s is incompatible with native type %s.', + $description, + $classReflection->getDisplayName(), + $propertyName, + $phpDocType->describe(VerbosityLevel::typeOnly()), + $nativeType->describe(VerbosityLevel::typeOnly()), + ))->identifier('property.phpDocType')->build(); + + } elseif ($isSuperType->maybe()) { + $errorBuilder = RuleErrorBuilder::message(sprintf( + '%s for property %s::$%s with type %s is not subtype of native type %s.', + $description, + $classReflection->getDisplayName(), + $propertyName, + $phpDocType->describe(VerbosityLevel::typeOnly()), + $nativeType->describe(VerbosityLevel::typeOnly()), + ))->identifier('property.phpDocType'); + + if ($phpDocType instanceof TemplateType) { + $errorBuilder->tip(sprintf('Write @template %s of %s to fix this.', $phpDocType->getName(), $nativeType->describe(VerbosityLevel::typeOnly()))); + } + + $messages[] = $errorBuilder->build(); } - - $messages[] = $errorBuilder->build(); } $className = SprintfHelper::escapeFormatString($classReflection->getDisplayName()); diff --git a/src/Rules/Properties/OverridingPropertyRule.php b/src/Rules/Properties/OverridingPropertyRule.php index be6a9fca4f..5767635e27 100644 --- a/src/Rules/Properties/OverridingPropertyRule.php +++ b/src/Rules/Properties/OverridingPropertyRule.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\Php\PhpPropertyReflection; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\ParserNodeTypeToPHPStanType; use PHPStan\Type\VerbosityLevel; use function array_merge; use function count; @@ -104,8 +103,9 @@ public function processNode(Node $node, Scope $scope): array } $typeErrors = []; + $nativeType = $node->getNativeType(); if ($prototype->hasNativeType()) { - if ($node->getNativeType() === null) { + if ($nativeType === null) { $typeErrors[] = RuleErrorBuilder::message(sprintf( 'Property %s::$%s overriding property %s::$%s (%s) should also have native type %s.', $classReflection->getDisplayName(), @@ -116,7 +116,6 @@ public function processNode(Node $node, Scope $scope): array $prototype->getNativeType()->describe(VerbosityLevel::typeOnly()), ))->identifier('property.missingNativeType')->nonIgnorable()->build(); } else { - $nativeType = ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection); if (!$prototype->getNativeType()->equals($nativeType)) { $typeErrors[] = RuleErrorBuilder::message(sprintf( 'Type %s of property %s::$%s is not the same as type %s of overridden property %s::$%s.', @@ -129,12 +128,12 @@ public function processNode(Node $node, Scope $scope): array ))->identifier('property.nativeType')->nonIgnorable()->build(); } } - } elseif ($node->getNativeType() !== null) { + } elseif ($nativeType !== null) { $typeErrors[] = RuleErrorBuilder::message(sprintf( 'Property %s::$%s (%s) overriding property %s::$%s should not have a native type.', $classReflection->getDisplayName(), $node->getName(), - ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection)->describe(VerbosityLevel::typeOnly()), + $nativeType->describe(VerbosityLevel::typeOnly()), $prototype->getDeclaringClass()->getDisplayName(), $node->getName(), ))->identifier('property.extraNativeType')->nonIgnorable()->build(); diff --git a/src/Rules/Types/InvalidTypesInUnionRule.php b/src/Rules/Types/InvalidTypesInUnionRule.php index ba53111760..39379b6663 100644 --- a/src/Rules/Types/InvalidTypesInUnionRule.php +++ b/src/Rules/Types/InvalidTypesInUnionRule.php @@ -69,11 +69,11 @@ private function processFunctionLikeNode(Node\FunctionLike $functionLike): array */ private function processClassPropertyNode(ClassPropertyNode $classPropertyNode): array { - if (!$classPropertyNode->getNativeType() instanceof Node\ComplexType) { + if (!$classPropertyNode->getNativeTypeNode() instanceof Node\ComplexType) { return []; } - return $this->processComplexType($classPropertyNode->getNativeType()); + return $this->processComplexType($classPropertyNode->getNativeTypeNode()); } /** From f38addda2b151b6e41a746a37659c0bbe9e2293b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 11:22:50 +0200 Subject: [PATCH 332/508] Identifiers in the PHP baseline as real array keys --- .../BaselinePhpErrorFormatter.php | 29 ++++++++++--------- .../BaselinePhpErrorFormatterTest.php | 12 ++++++-- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php b/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php index 8107aba19b..fefb3175fd 100644 --- a/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php +++ b/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php @@ -8,7 +8,6 @@ use PHPStan\File\RelativePathHelper; use function array_keys; use function count; -use function implode; use function ksort; use function preg_quote; use function sort; @@ -74,22 +73,24 @@ public function formatErrors( foreach ($fileErrorsByMessage as $message => [$count, $identifiersInKeys]) { $identifiers = array_keys($identifiersInKeys); sort($identifiers); - $identifiersComment = ''; if (count($identifiers) > 0) { - if (count($identifiers) === 1) { - $identifiersComment = "\n\t// identifier: " . $identifiers[0]; - } else { - $identifiersComment = "\n\t// identifiers: " . implode(', ', $identifiers); + foreach ($identifiers as $identifier) { + $php .= sprintf( + "\$ignoreErrors[] = [\n\t'message' => %s,\n\t'identifier' => %s,\n\t'count' => %d,\n\t'path' => __DIR__ . %s,\n];\n", + var_export(Helpers::escape('#^' . preg_quote($message, '#') . '$#'), true), + var_export(Helpers::escape($identifier), true), + var_export($count, true), + var_export(Helpers::escape($file), true), + ); } + } else { + $php .= sprintf( + "\$ignoreErrors[] = [\n\t'message' => %s,\n\t'count' => %d,\n\t'path' => __DIR__ . %s,\n];\n", + var_export(Helpers::escape('#^' . preg_quote($message, '#') . '$#'), true), + var_export($count, true), + var_export(Helpers::escape($file), true), + ); } - - $php .= sprintf( - "\$ignoreErrors[] = [%s\n\t'message' => %s,\n\t'count' => %d,\n\t'path' => __DIR__ . %s,\n];\n", - $identifiersComment, - var_export(Helpers::escape('#^' . preg_quote($message, '#') . '$#'), true), - var_export($count, true), - var_export(Helpers::escape($file), true), - ); } } diff --git a/tests/PHPStan/Command/ErrorFormatter/BaselinePhpErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/BaselinePhpErrorFormatterTest.php index b49c717f22..4ba93f6805 100644 --- a/tests/PHPStan/Command/ErrorFormatter/BaselinePhpErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/BaselinePhpErrorFormatterTest.php @@ -80,8 +80,8 @@ public function dataFormatErrors(): iterable 'path' => __DIR__ . '/Foo.php', ]; \$ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Foo with identifier$#', + 'identifier' => 'argument.type', 'count' => 2, 'path' => __DIR__ . '/Foo.php', ]; @@ -127,14 +127,20 @@ public function dataFormatErrors(): iterable 'path' => __DIR__ . '/Foo.php', ]; \$ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Foo with another message$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__ . '/Foo.php', ]; \$ignoreErrors[] = [ - // identifiers: argument.byRef, argument.type 'message' => '#^Foo with same message, different identifier$#', + 'identifier' => 'argument.byRef', + 'count' => 2, + 'path' => __DIR__ . '/Foo.php', +]; +\$ignoreErrors[] = [ + 'message' => '#^Foo with same message, different identifier$#', + 'identifier' => 'argument.type', 'count' => 2, 'path' => __DIR__ . '/Foo.php', ]; From 710e09c41698efb1d8d3ae31791944077dbb9cc1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 1 Oct 2024 12:08:19 +0200 Subject: [PATCH 333/508] Refactored `FunctionCallParametersCheck::check()` parameters --- src/Rules/AttributesCheck.php | 32 ++++++------- src/Rules/Classes/InstantiationRule.php | 32 ++++++------- src/Rules/FunctionCallParametersCheck.php | 48 ++++++++++++------- src/Rules/Functions/CallCallablesRule.php | 32 ++++++------- .../CallToFunctionParametersRule.php | 32 ++++++------- src/Rules/Functions/CallUserFuncRule.php | 10 +++- src/Rules/Methods/CallMethodsRule.php | 32 ++++++------- src/Rules/Methods/CallStaticMethodsRule.php | 32 ++++++------- 8 files changed, 128 insertions(+), 122 deletions(-) diff --git a/src/Rules/AttributesCheck.php b/src/Rules/AttributesCheck.php index e04381033e..8633178d9f 100644 --- a/src/Rules/AttributesCheck.php +++ b/src/Rules/AttributesCheck.php @@ -136,25 +136,23 @@ public function check( $scope, $attributeConstructor->getDeclaringClass()->isBuiltin(), new New_($attribute->name, $attribute->args, $nodeAttributes), - [ - 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, %d required.', - 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, %d required.', - 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, at least %d required.', - 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, at least %d required.', - 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, %d-%d required.', - 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, %d-%d required.', - 'Parameter %s of attribute class ' . $attributeClassName . ' constructor expects %s, %s given.', - '', // constructor does not have a return type - 'Parameter %s of attribute class ' . $attributeClassName . ' constructor is passed by reference, so it expects variables only', - 'Unable to resolve the template type %s in instantiation of attribute class ' . $attributeClassName, - 'Missing parameter $%s in call to ' . $attributeClassName . ' constructor.', - 'Unknown parameter $%s in call to ' . $attributeClassName . ' constructor.', - 'Return type of call to ' . $attributeClassName . ' constructor contains unresolvable type.', - 'Parameter %s of attribute class ' . $attributeClassName . ' constructor contains unresolvable type.', - 'Attribute class ' . $attributeClassName . ' constructorinvoked with %s, but it\'s not allowed because of @no-named-arguments.', - ], 'attribute', $attributeConstructor->acceptsNamedArguments(), + 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, %d required.', + 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, %d required.', + 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, at least %d required.', + 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, at least %d required.', + 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, %d-%d required.', + 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, %d-%d required.', + 'Parameter %s of attribute class ' . $attributeClassName . ' constructor expects %s, %s given.', + '', // constructor does not have a return type + 'Parameter %s of attribute class ' . $attributeClassName . ' constructor is passed by reference, so it expects variables only', + 'Unable to resolve the template type %s in instantiation of attribute class ' . $attributeClassName, + 'Missing parameter $%s in call to ' . $attributeClassName . ' constructor.', + 'Unknown parameter $%s in call to ' . $attributeClassName . ' constructor.', + 'Return type of call to ' . $attributeClassName . ' constructor contains unresolvable type.', + 'Parameter %s of attribute class ' . $attributeClassName . ' constructor contains unresolvable type.', + 'Attribute class ' . $attributeClassName . ' constructorinvoked with %s, but it\'s not allowed because of @no-named-arguments.', ); foreach ($parameterErrors as $error) { diff --git a/src/Rules/Classes/InstantiationRule.php b/src/Rules/Classes/InstantiationRule.php index 8994a4754b..604038d1fa 100644 --- a/src/Rules/Classes/InstantiationRule.php +++ b/src/Rules/Classes/InstantiationRule.php @@ -201,25 +201,23 @@ private function checkClassName(string $class, bool $isName, Node $node, Scope $ $scope, $constructorReflection->getDeclaringClass()->isBuiltin(), $node, - [ - 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, %d required.', - 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, %d required.', - 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, at least %d required.', - 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, at least %d required.', - 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, %d-%d required.', - 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, %d-%d required.', - 'Parameter %s of class ' . $classDisplayName . ' constructor expects %s, %s given.', - '', // constructor does not have a return type - 'Parameter %s of class ' . $classDisplayName . ' constructor is passed by reference, so it expects variables only', - 'Unable to resolve the template type %s in instantiation of class ' . $classDisplayName, - 'Missing parameter $%s in call to ' . $classDisplayName . ' constructor.', - 'Unknown parameter $%s in call to ' . $classDisplayName . ' constructor.', - 'Return type of call to ' . $classDisplayName . ' constructor contains unresolvable type.', - 'Parameter %s of class ' . $classDisplayName . ' constructor contains unresolvable type.', - 'Class ' . $classDisplayName . ' constructor invoked with %s, but it\'s not allowed because of @no-named-arguments.', - ], 'new', $constructorReflection->acceptsNamedArguments(), + 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, %d required.', + 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, %d required.', + 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, at least %d required.', + 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, at least %d required.', + 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, %d-%d required.', + 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, %d-%d required.', + 'Parameter %s of class ' . $classDisplayName . ' constructor expects %s, %s given.', + '', // constructor does not have a return type + 'Parameter %s of class ' . $classDisplayName . ' constructor is passed by reference, so it expects variables only', + 'Unable to resolve the template type %s in instantiation of class ' . $classDisplayName, + 'Missing parameter $%s in call to ' . $classDisplayName . ' constructor.', + 'Unknown parameter $%s in call to ' . $classDisplayName . ' constructor.', + 'Return type of call to ' . $classDisplayName . ' constructor contains unresolvable type.', + 'Parameter %s of class ' . $classDisplayName . ' constructor contains unresolvable type.', + 'Class ' . $classDisplayName . ' constructor invoked with %s, but it\'s not allowed because of @no-named-arguments.', )); } diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 365ab626a1..1ad8773365 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -53,7 +53,6 @@ public function __construct( /** * @param Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $funcCall - * @param array{0: string, 1: string, 2: string, 3: string, 4: string, 5: string, 6: string, 7: string, 8: string, 9: string, 10: string, 11: string, 12: string, 13?: string, 14?: string} $messages * @param 'attribute'|'callable'|'method'|'staticMethod'|'function'|'new' $nodeType * @return list */ @@ -62,9 +61,23 @@ public function check( Scope $scope, bool $isBuiltin, $funcCall, - array $messages, string $nodeType, TrinaryLogic $acceptsNamedArguments, + string $singleInsufficientParameterMessage, + string $pluralInsufficientParametersMessage, + string $singleInsufficientParameterInVariadicFunctionMessage, + string $pluralInsufficientParametersInVariadicFunctionMessage, + string $singleInsufficientParameterWithOptionalParametersMessage, + string $pluralInsufficientParametersWithOptionalParametersMessage, + string $wrongArgumentTypeMessage, + string $voidReturnTypeUsed, + string $parameterPassedByReferenceMessage, + string $unresolvableTemplateTypeMessage, + string $missingParameterMessage, + string $unknownParameterMessage, + string $unresolvableReturnTypeMessage, + string $unresolvableParameterTypeMessage, + string $namedArgumentMessage, ): array { $functionParametersMinCount = 0; @@ -204,7 +217,7 @@ public function check( ) { if ($functionParametersMinCount === $functionParametersMaxCount) { $errors[] = RuleErrorBuilder::message(sprintf( - $invokedParametersCount === 1 ? $messages[0] : $messages[1], + $invokedParametersCount === 1 ? $singleInsufficientParameterMessage : $pluralInsufficientParametersMessage, $invokedParametersCount, $functionParametersMinCount, )) @@ -213,7 +226,7 @@ public function check( ->build(); } elseif ($functionParametersMaxCount === -1 && $invokedParametersCount < $functionParametersMinCount) { $errors[] = RuleErrorBuilder::message(sprintf( - $invokedParametersCount === 1 ? $messages[2] : $messages[3], + $invokedParametersCount === 1 ? $singleInsufficientParameterInVariadicFunctionMessage : $pluralInsufficientParametersInVariadicFunctionMessage, $invokedParametersCount, $functionParametersMinCount, )) @@ -222,7 +235,7 @@ public function check( ->build(); } elseif ($functionParametersMaxCount !== -1) { $errors[] = RuleErrorBuilder::message(sprintf( - $invokedParametersCount === 1 ? $messages[4] : $messages[5], + $invokedParametersCount === 1 ? $singleInsufficientParameterWithOptionalParametersMessage : $pluralInsufficientParametersWithOptionalParametersMessage, $invokedParametersCount, $functionParametersMinCount, $functionParametersMaxCount, @@ -239,13 +252,13 @@ public function check( && !$scope->isInFirstLevelStatement() && $scope->getKeepVoidType($funcCall)->isVoid()->yes() ) { - $errors[] = RuleErrorBuilder::message($messages[7]) + $errors[] = RuleErrorBuilder::message($voidReturnTypeUsed) ->identifier(sprintf('%s.void', $nodeType)) ->line($funcCall->getStartLine()) ->build(); } - [$addedErrors, $argumentsWithParameters] = $this->processArguments($parametersAcceptor, $funcCall->getStartLine(), $isBuiltin, $arguments, $hasNamedArguments, $messages[10], $messages[11]); + [$addedErrors, $argumentsWithParameters] = $this->processArguments($parametersAcceptor, $funcCall->getStartLine(), $isBuiltin, $arguments, $hasNamedArguments, $missingParameterMessage, $unknownParameterMessage); foreach ($addedErrors as $error) { $errors[] = $error; } @@ -290,9 +303,9 @@ public function check( } } - if (!$acceptsNamedArguments->yes() && isset($messages[14])) { + if (!$acceptsNamedArguments->yes()) { if ($argumentName !== null) { - $errors[] = RuleErrorBuilder::message(sprintf($messages[14], sprintf('named argument $%s', $argumentName))) + $errors[] = RuleErrorBuilder::message(sprintf($namedArgumentMessage, sprintf('named argument $%s', $argumentName))) ->identifier('argument.named') ->line($argumentLine) ->build(); @@ -300,7 +313,7 @@ public function check( $unpackedArrayType = $scope->getType($argumentValue); $hasStringKey = $unpackedArrayType->getIterableKeyType()->isString(); if (!$hasStringKey->no()) { - $errors[] = RuleErrorBuilder::message(sprintf($messages[14], sprintf('unpacked array with %s', $hasStringKey->yes() ? 'string key' : 'possibly string key'))) + $errors[] = RuleErrorBuilder::message(sprintf($namedArgumentMessage, sprintf('unpacked array with %s', $hasStringKey->yes() ? 'string key' : 'possibly string key'))) ->identifier('argument.named') ->line($argumentLine) ->build(); @@ -317,7 +330,7 @@ public function check( if (!$accepts->result) { $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $argumentValueType); $errors[] = RuleErrorBuilder::message(sprintf( - $messages[6], + $wrongArgumentTypeMessage, $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), $parameterType->describe($verbosityLevel), $argumentValueType->describe($verbosityLevel), @@ -331,12 +344,11 @@ public function check( if ( $originalParameter !== null - && isset($messages[13]) && !$this->unresolvableTypeHelper->containsUnresolvableType($originalParameter->getType()) && $this->unresolvableTypeHelper->containsUnresolvableType($parameterType) ) { $errors[] = RuleErrorBuilder::message(sprintf( - $messages[13], + $unresolvableParameterTypeMessage, $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), ))->identifier('argument.unresolvableType')->line($argumentLine)->build(); } @@ -348,7 +360,7 @@ public function check( && $argumentValue->static ) { $errors[] = RuleErrorBuilder::message(sprintf( - $messages[6], + $wrongArgumentTypeMessage, $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), 'bindable closure', 'static closure', @@ -368,7 +380,7 @@ public function check( if ($this->nullsafeCheck->containsNullSafe($argumentValue)) { $errors[] = RuleErrorBuilder::message(sprintf( - $messages[8], + $parameterPassedByReferenceMessage, $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), )) ->identifier('argument.byRef') @@ -412,7 +424,7 @@ public function check( } $errors[] = RuleErrorBuilder::message(sprintf( - $messages[8], + $parameterPassedByReferenceMessage, $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), ))->identifier('argument.byRef')->line($argumentLine)->build(); } @@ -469,7 +481,7 @@ static function (Type $type, callable $traverse) use (&$returnTemplateTypes): Ty continue; } - $errors[] = RuleErrorBuilder::message(sprintf($messages[9], $name)) + $errors[] = RuleErrorBuilder::message(sprintf($unresolvableTemplateTypeMessage, $name)) ->identifier('argument.templateType') ->line($funcCall->getStartLine()) ->tip('See: https://phpstan.org/blog/solving-phpstan-error-unable-to-resolve-template-type') @@ -481,7 +493,7 @@ static function (Type $type, callable $traverse) use (&$returnTemplateTypes): Ty !$this->unresolvableTypeHelper->containsUnresolvableType($originalParametersAcceptor->getReturnType()) && $this->unresolvableTypeHelper->containsUnresolvableType($parametersAcceptor->getReturnType()) ) { - $errors[] = RuleErrorBuilder::message($messages[12]) + $errors[] = RuleErrorBuilder::message($unresolvableReturnTypeMessage) ->identifier(sprintf('%s.unresolvableReturnType', $nodeType)) ->line($funcCall->getStartLine()) ->build(); diff --git a/src/Rules/Functions/CallCallablesRule.php b/src/Rules/Functions/CallCallablesRule.php index 05cd89d0a7..15c0bfb9ca 100644 --- a/src/Rules/Functions/CallCallablesRule.php +++ b/src/Rules/Functions/CallCallablesRule.php @@ -118,25 +118,23 @@ public function processNode( $scope, false, $node, - [ - ucfirst($callableDescription) . ' invoked with %d parameter, %d required.', - ucfirst($callableDescription) . ' invoked with %d parameters, %d required.', - ucfirst($callableDescription) . ' invoked with %d parameter, at least %d required.', - ucfirst($callableDescription) . ' invoked with %d parameters, at least %d required.', - ucfirst($callableDescription) . ' invoked with %d parameter, %d-%d required.', - ucfirst($callableDescription) . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of ' . $callableDescription . ' expects %s, %s given.', - 'Result of ' . $callableDescription . ' (void) is used.', - 'Parameter %s of ' . $callableDescription . ' is passed by reference, so it expects variables only.', - 'Unable to resolve the template type %s in call to ' . $callableDescription, - 'Missing parameter $%s in call to ' . $callableDescription . '.', - 'Unknown parameter $%s in call to ' . $callableDescription . '.', - 'Return type of call to ' . $callableDescription . ' contains unresolvable type.', - 'Parameter %s of ' . $callableDescription . ' contains unresolvable type.', - ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', - ], 'callable', $acceptsNamedArguments, + ucfirst($callableDescription) . ' invoked with %d parameter, %d required.', + ucfirst($callableDescription) . ' invoked with %d parameters, %d required.', + ucfirst($callableDescription) . ' invoked with %d parameter, at least %d required.', + ucfirst($callableDescription) . ' invoked with %d parameters, at least %d required.', + ucfirst($callableDescription) . ' invoked with %d parameter, %d-%d required.', + ucfirst($callableDescription) . ' invoked with %d parameters, %d-%d required.', + 'Parameter %s of ' . $callableDescription . ' expects %s, %s given.', + 'Result of ' . $callableDescription . ' (void) is used.', + 'Parameter %s of ' . $callableDescription . ' is passed by reference, so it expects variables only.', + 'Unable to resolve the template type %s in call to ' . $callableDescription, + 'Missing parameter $%s in call to ' . $callableDescription . '.', + 'Unknown parameter $%s in call to ' . $callableDescription . '.', + 'Return type of call to ' . $callableDescription . ' contains unresolvable type.', + 'Parameter %s of ' . $callableDescription . ' contains unresolvable type.', + ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', ), ); } diff --git a/src/Rules/Functions/CallToFunctionParametersRule.php b/src/Rules/Functions/CallToFunctionParametersRule.php index d1ca216791..39b4ee650f 100644 --- a/src/Rules/Functions/CallToFunctionParametersRule.php +++ b/src/Rules/Functions/CallToFunctionParametersRule.php @@ -49,25 +49,23 @@ public function processNode(Node $node, Scope $scope): array $scope, $function->isBuiltin(), $node, - [ - 'Function ' . $functionName . ' invoked with %d parameter, %d required.', - 'Function ' . $functionName . ' invoked with %d parameters, %d required.', - 'Function ' . $functionName . ' invoked with %d parameter, at least %d required.', - 'Function ' . $functionName . ' invoked with %d parameters, at least %d required.', - 'Function ' . $functionName . ' invoked with %d parameter, %d-%d required.', - 'Function ' . $functionName . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of function ' . $functionName . ' expects %s, %s given.', - 'Result of function ' . $functionName . ' (void) is used.', - 'Parameter %s of function ' . $functionName . ' is passed by reference, so it expects variables only.', - 'Unable to resolve the template type %s in call to function ' . $functionName, - 'Missing parameter $%s in call to function ' . $functionName . '.', - 'Unknown parameter $%s in call to function ' . $functionName . '.', - 'Return type of call to function ' . $functionName . ' contains unresolvable type.', - 'Parameter %s of function ' . $functionName . ' contains unresolvable type.', - 'Function ' . $functionName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', - ], 'function', $function->acceptsNamedArguments(), + 'Function ' . $functionName . ' invoked with %d parameter, %d required.', + 'Function ' . $functionName . ' invoked with %d parameters, %d required.', + 'Function ' . $functionName . ' invoked with %d parameter, at least %d required.', + 'Function ' . $functionName . ' invoked with %d parameters, at least %d required.', + 'Function ' . $functionName . ' invoked with %d parameter, %d-%d required.', + 'Function ' . $functionName . ' invoked with %d parameters, %d-%d required.', + 'Parameter %s of function ' . $functionName . ' expects %s, %s given.', + 'Result of function ' . $functionName . ' (void) is used.', + 'Parameter %s of function ' . $functionName . ' is passed by reference, so it expects variables only.', + 'Unable to resolve the template type %s in call to function ' . $functionName, + 'Missing parameter $%s in call to function ' . $functionName . '.', + 'Unknown parameter $%s in call to function ' . $functionName . '.', + 'Return type of call to function ' . $functionName . ' contains unresolvable type.', + 'Parameter %s of function ' . $functionName . ' contains unresolvable type.', + 'Function ' . $functionName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', ); } diff --git a/src/Rules/Functions/CallUserFuncRule.php b/src/Rules/Functions/CallUserFuncRule.php index c4030961cf..2ea1fb2777 100644 --- a/src/Rules/Functions/CallUserFuncRule.php +++ b/src/Rules/Functions/CallUserFuncRule.php @@ -60,7 +60,13 @@ public function processNode(Node $node, Scope $scope): array $callableDescription = 'callable passed to call_user_func()'; - return $this->check->check($parametersAcceptor, $scope, false, $funcCall, [ + return $this->check->check( + $parametersAcceptor, + $scope, + false, + $funcCall, + 'function', + $acceptsNamedArguments, ucfirst($callableDescription) . ' invoked with %d parameter, %d required.', ucfirst($callableDescription) . ' invoked with %d parameters, %d required.', ucfirst($callableDescription) . ' invoked with %d parameter, at least %d required.', @@ -76,7 +82,7 @@ public function processNode(Node $node, Scope $scope): array 'Return type of call to ' . $callableDescription . ' contains unresolvable type.', 'Parameter %s of ' . $callableDescription . ' contains unresolvable type.', ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', - ], 'function', $acceptsNamedArguments); + ); } } diff --git a/src/Rules/Methods/CallMethodsRule.php b/src/Rules/Methods/CallMethodsRule.php index 4f45dbf9fd..b0d522f439 100644 --- a/src/Rules/Methods/CallMethodsRule.php +++ b/src/Rules/Methods/CallMethodsRule.php @@ -55,25 +55,23 @@ public function processNode(Node $node, Scope $scope): array $scope, $declaringClass->isBuiltin(), $node, - [ - 'Method ' . $messagesMethodName . ' invoked with %d parameter, %d required.', - 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d required.', - 'Method ' . $messagesMethodName . ' invoked with %d parameter, at least %d required.', - 'Method ' . $messagesMethodName . ' invoked with %d parameters, at least %d required.', - 'Method ' . $messagesMethodName . ' invoked with %d parameter, %d-%d required.', - 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of method ' . $messagesMethodName . ' expects %s, %s given.', - 'Result of method ' . $messagesMethodName . ' (void) is used.', - 'Parameter %s of method ' . $messagesMethodName . ' is passed by reference, so it expects variables only.', - 'Unable to resolve the template type %s in call to method ' . $messagesMethodName, - 'Missing parameter $%s in call to method ' . $messagesMethodName . '.', - 'Unknown parameter $%s in call to method ' . $messagesMethodName . '.', - 'Return type of call to method ' . $messagesMethodName . ' contains unresolvable type.', - 'Parameter %s of method ' . $messagesMethodName . ' contains unresolvable type.', - 'Method ' . $messagesMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', - ], 'method', $methodReflection->acceptsNamedArguments(), + 'Method ' . $messagesMethodName . ' invoked with %d parameter, %d required.', + 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d required.', + 'Method ' . $messagesMethodName . ' invoked with %d parameter, at least %d required.', + 'Method ' . $messagesMethodName . ' invoked with %d parameters, at least %d required.', + 'Method ' . $messagesMethodName . ' invoked with %d parameter, %d-%d required.', + 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d-%d required.', + 'Parameter %s of method ' . $messagesMethodName . ' expects %s, %s given.', + 'Result of method ' . $messagesMethodName . ' (void) is used.', + 'Parameter %s of method ' . $messagesMethodName . ' is passed by reference, so it expects variables only.', + 'Unable to resolve the template type %s in call to method ' . $messagesMethodName, + 'Missing parameter $%s in call to method ' . $messagesMethodName . '.', + 'Unknown parameter $%s in call to method ' . $messagesMethodName . '.', + 'Return type of call to method ' . $messagesMethodName . ' contains unresolvable type.', + 'Parameter %s of method ' . $messagesMethodName . ' contains unresolvable type.', + 'Method ' . $messagesMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', )); } diff --git a/src/Rules/Methods/CallStaticMethodsRule.php b/src/Rules/Methods/CallStaticMethodsRule.php index 33612ff02c..0f98eca2d9 100644 --- a/src/Rules/Methods/CallStaticMethodsRule.php +++ b/src/Rules/Methods/CallStaticMethodsRule.php @@ -63,25 +63,23 @@ public function processNode(Node $node, Scope $scope): array $scope, $method->getDeclaringClass()->isBuiltin(), $node, - [ - $displayMethodName . ' invoked with %d parameter, %d required.', - $displayMethodName . ' invoked with %d parameters, %d required.', - $displayMethodName . ' invoked with %d parameter, at least %d required.', - $displayMethodName . ' invoked with %d parameters, at least %d required.', - $displayMethodName . ' invoked with %d parameter, %d-%d required.', - $displayMethodName . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of ' . $lowercasedMethodName . ' expects %s, %s given.', - 'Result of ' . $lowercasedMethodName . ' (void) is used.', - 'Parameter %s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.', - 'Unable to resolve the template type %s in call to method ' . $lowercasedMethodName, - 'Missing parameter $%s in call to ' . $lowercasedMethodName . '.', - 'Unknown parameter $%s in call to ' . $lowercasedMethodName . '.', - 'Return type of call to ' . $lowercasedMethodName . ' contains unresolvable type.', - 'Parameter %s of ' . $lowercasedMethodName . ' contains unresolvable type.', - $displayMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', - ], 'staticMethod', $method->acceptsNamedArguments(), + $displayMethodName . ' invoked with %d parameter, %d required.', + $displayMethodName . ' invoked with %d parameters, %d required.', + $displayMethodName . ' invoked with %d parameter, at least %d required.', + $displayMethodName . ' invoked with %d parameters, at least %d required.', + $displayMethodName . ' invoked with %d parameter, %d-%d required.', + $displayMethodName . ' invoked with %d parameters, %d-%d required.', + 'Parameter %s of ' . $lowercasedMethodName . ' expects %s, %s given.', + 'Result of ' . $lowercasedMethodName . ' (void) is used.', + 'Parameter %s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.', + 'Unable to resolve the template type %s in call to method ' . $lowercasedMethodName, + 'Missing parameter $%s in call to ' . $lowercasedMethodName . '.', + 'Unknown parameter $%s in call to ' . $lowercasedMethodName . '.', + 'Return type of call to ' . $lowercasedMethodName . ' contains unresolvable type.', + 'Parameter %s of ' . $lowercasedMethodName . ' contains unresolvable type.', + $displayMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', )); return $errors; From e95f79b2a3fff1f749cdd6dc9eaab2d2600def1a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 2 Oct 2024 10:10:30 +0200 Subject: [PATCH 334/508] Level 10 - checkImplicitMixed --- changelog-2.0.md | 1 + conf/config.level10.neon | 5 ++ conf/config.levelmax.neon | 2 +- src/Testing/LevelsTestCase.php | 2 +- tests/PHPStan/Levels/data/acceptTypes-10.json | 17 +++++ tests/PHPStan/Levels/data/arrayAccess-10.json | 7 +++ .../Levels/data/arrayDimFetches-10.json | 22 +++++++ .../Levels/data/callableCalls-10-missing.json | 12 ++++ .../PHPStan/Levels/data/clone-10-missing.json | 12 ++++ tests/PHPStan/Levels/data/coalesce-10.json | 12 ++++ .../data/constantAccesses-10-missing.json | 17 +++++ .../Levels/data/constantAccesses-10.json | 62 +++++++++++++++++++ .../Levels/data/constantAccesses83-10.json | 27 ++++++++ .../Levels/data/methodCalls-10-missing.json | 52 ++++++++++++++++ .../Levels/data/object-10-missing.json | 22 +++++++ tests/PHPStan/Levels/data/object-10.json | 32 ++++++++++ .../data/propertyAccesses-10-missing.json | 32 ++++++++++ .../Levels/data/propertyAccesses-10.json | 57 +++++++++++++++++ .../Levels/data/stringOffsetAccess-10.json | 32 ++++++++++ tests/PHPStan/Levels/data/variables-10.json | 7 +++ 20 files changed, 430 insertions(+), 2 deletions(-) create mode 100644 conf/config.level10.neon create mode 100644 tests/PHPStan/Levels/data/acceptTypes-10.json create mode 100644 tests/PHPStan/Levels/data/arrayAccess-10.json create mode 100644 tests/PHPStan/Levels/data/arrayDimFetches-10.json create mode 100644 tests/PHPStan/Levels/data/callableCalls-10-missing.json create mode 100644 tests/PHPStan/Levels/data/clone-10-missing.json create mode 100644 tests/PHPStan/Levels/data/coalesce-10.json create mode 100644 tests/PHPStan/Levels/data/constantAccesses-10-missing.json create mode 100644 tests/PHPStan/Levels/data/constantAccesses-10.json create mode 100644 tests/PHPStan/Levels/data/constantAccesses83-10.json create mode 100644 tests/PHPStan/Levels/data/methodCalls-10-missing.json create mode 100644 tests/PHPStan/Levels/data/object-10-missing.json create mode 100644 tests/PHPStan/Levels/data/object-10.json create mode 100644 tests/PHPStan/Levels/data/propertyAccesses-10-missing.json create mode 100644 tests/PHPStan/Levels/data/propertyAccesses-10.json create mode 100644 tests/PHPStan/Levels/data/stringOffsetAccess-10.json create mode 100644 tests/PHPStan/Levels/data/variables-10.json diff --git a/changelog-2.0.md b/changelog-2.0.md index 9243a74288..84559ebb67 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -5,6 +5,7 @@ When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](h Major new features 🚀 ===================== +* **Level 10** - level 9 on steroids, treats all `mixed` types strictly, not just explicit `mixed` * **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! * Lists are arrays with sequential integer keys starting at 0 * **Validate inline PHPDoc `@var` tag** type against native type (level 2) (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) diff --git a/conf/config.level10.neon b/conf/config.level10.neon new file mode 100644 index 0000000000..5d052692c9 --- /dev/null +++ b/conf/config.level10.neon @@ -0,0 +1,5 @@ +includes: + - config.level9.neon + +parameters: + checkImplicitMixed: true diff --git a/conf/config.levelmax.neon b/conf/config.levelmax.neon index da48578fe3..ce4c43f2f7 100644 --- a/conf/config.levelmax.neon +++ b/conf/config.levelmax.neon @@ -1,2 +1,2 @@ includes: - - config.level9.neon + - config.level10.neon diff --git a/src/Testing/LevelsTestCase.php b/src/Testing/LevelsTestCase.php index 9946e97c05..499277dc8b 100644 --- a/src/Testing/LevelsTestCase.php +++ b/src/Testing/LevelsTestCase.php @@ -71,7 +71,7 @@ public function testLevels( putenv('__PHPSTAN_FORCE_VALIDATE_STUB_FILES=1'); - foreach (range(0, 9) as $level) { + foreach (range(0, 10) as $level) { unset($outputLines); exec(sprintf('%s %s analyse --no-progress --error-format=prettyJson --level=%d %s %s %s', escapeshellarg(PHP_BINARY), $command, $level, $configPath !== null ? '--configuration ' . escapeshellarg($configPath) : '', $this->shouldAutoloadAnalysedFile() ? sprintf('--autoload-file %s', escapeshellarg($file)) : '', escapeshellarg($file)), $outputLines); diff --git a/tests/PHPStan/Levels/data/acceptTypes-10.json b/tests/PHPStan/Levels/data/acceptTypes-10.json new file mode 100644 index 0000000000..8a1b7a3992 --- /dev/null +++ b/tests/PHPStan/Levels/data/acceptTypes-10.json @@ -0,0 +1,17 @@ +[ + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 170, + "ignorable": true + }, + { + "message": "Parameter #1 $closure of method Levels\\AcceptTypes\\ClosureAccepts::doBar() expects Closure(Levels\\AcceptTypes\\FooInterface, int): Levels\\AcceptTypes\\FooInterface, Closure(mixed): mixed given.", + "line": 325, + "ignorable": true + }, + { + "message": "Parameter #1 $callable of method Levels\\AcceptTypes\\ClosureAccepts::doBaz() expects callable(Levels\\AcceptTypes\\FooInterface, int): Levels\\AcceptTypes\\FooInterface, Closure(mixed): mixed given.", + "line": 326, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/arrayAccess-10.json b/tests/PHPStan/Levels/data/arrayAccess-10.json new file mode 100644 index 0000000000..9dc3ca3eb9 --- /dev/null +++ b/tests/PHPStan/Levels/data/arrayAccess-10.json @@ -0,0 +1,7 @@ +[ + { + "message": "Cannot assign offset mixed to SplObjectStorage.", + "line": 43, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/arrayDimFetches-10.json b/tests/PHPStan/Levels/data/arrayDimFetches-10.json new file mode 100644 index 0000000000..900a4ee636 --- /dev/null +++ b/tests/PHPStan/Levels/data/arrayDimFetches-10.json @@ -0,0 +1,22 @@ +[ + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 14, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 21, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 27, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 28, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/callableCalls-10-missing.json b/tests/PHPStan/Levels/data/callableCalls-10-missing.json new file mode 100644 index 0000000000..5c7f12b38d --- /dev/null +++ b/tests/PHPStan/Levels/data/callableCalls-10-missing.json @@ -0,0 +1,12 @@ +[ + { + "message": "Closure invoked with 0 parameters, 1 required.", + "line": 37, + "ignorable": true + }, + { + "message": "Trying to invoke int but it's not a callable.", + "line": 43, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/clone-10-missing.json b/tests/PHPStan/Levels/data/clone-10-missing.json new file mode 100644 index 0000000000..40e1203120 --- /dev/null +++ b/tests/PHPStan/Levels/data/clone-10-missing.json @@ -0,0 +1,12 @@ +[ + { + "message": "Cannot clone non-object variable $nullableInt of type int.", + "line": 34, + "ignorable": true + }, + { + "message": "Cannot clone non-object variable $nullableUnion of type int|Levels\\Cloning\\Foo.", + "line": 35, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/coalesce-10.json b/tests/PHPStan/Levels/data/coalesce-10.json new file mode 100644 index 0000000000..e74887cb13 --- /dev/null +++ b/tests/PHPStan/Levels/data/coalesce-10.json @@ -0,0 +1,12 @@ +[ + { + "message": "Cannot access property $bar on mixed.", + "line": 6, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 11, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/constantAccesses-10-missing.json b/tests/PHPStan/Levels/data/constantAccesses-10-missing.json new file mode 100644 index 0000000000..0cc5a3f5d4 --- /dev/null +++ b/tests/PHPStan/Levels/data/constantAccesses-10-missing.json @@ -0,0 +1,17 @@ +[ + { + "message": "Access to undefined constant Levels\\ConstantAccesses\\Foo::BAR_CONSTANT.", + "line": 53, + "ignorable": true + }, + { + "message": "Access to undefined constant Levels\\ConstantAccesses\\Bar|Levels\\ConstantAccesses\\Foo::BAR_CONSTANT.", + "line": 56, + "ignorable": true + }, + { + "message": "Access to undefined constant Levels\\ConstantAccesses\\Bar|Levels\\ConstantAccesses\\Foo::FOO_CONSTANT.", + "line": 55, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/constantAccesses-10.json b/tests/PHPStan/Levels/data/constantAccesses-10.json new file mode 100644 index 0000000000..cf84dbb4c6 --- /dev/null +++ b/tests/PHPStan/Levels/data/constantAccesses-10.json @@ -0,0 +1,62 @@ +[ + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 6, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 17, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 18, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 20, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 23, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 49, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 50, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 52, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 53, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 55, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 56, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 58, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/constantAccesses83-10.json b/tests/PHPStan/Levels/data/constantAccesses83-10.json new file mode 100644 index 0000000000..7d5fcb38d3 --- /dev/null +++ b/tests/PHPStan/Levels/data/constantAccesses83-10.json @@ -0,0 +1,27 @@ +[ + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 15, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 16, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 18, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 19, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 20, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/methodCalls-10-missing.json b/tests/PHPStan/Levels/data/methodCalls-10-missing.json new file mode 100644 index 0000000000..47cdcab769 --- /dev/null +++ b/tests/PHPStan/Levels/data/methodCalls-10-missing.json @@ -0,0 +1,52 @@ +[ + { + "message": "Method Levels\\MethodCalls\\Foo::doFoo() invoked with 0 parameters, 1 required.", + "line": 53, + "ignorable": true + }, + { + "message": "Method Levels\\MethodCalls\\Foo::doFoo() invoked with 0 parameters, 1 required.", + "line": 56, + "ignorable": true + }, + { + "message": "Method Levels\\MethodCalls\\Foo::doFoo() invoked with 0 parameters, 1 required.", + "line": 59, + "ignorable": true + }, + { + "message": "Method Levels\\MethodCalls\\Foo::doFoo() invoked with 0 parameters, 1 required.", + "line": 162, + "ignorable": true + }, + { + "message": "Method Levels\\MethodCalls\\Foo::doFoo() invoked with 0 parameters, 1 required.", + "line": 166, + "ignorable": true + }, + { + "message": "Method Levels\\MethodCalls\\Foo::doFoo() invoked with 0 parameters, 1 required.", + "line": 170, + "ignorable": true + }, + { + "message": "Call to an undefined method Levels\\MethodCalls\\Bar|Levels\\MethodCalls\\Foo::doFoo().", + "line": 59, + "ignorable": true + }, + { + "message": "Call to an undefined method Levels\\MethodCalls\\Bar|Levels\\MethodCalls\\Foo::doFoo().", + "line": 60, + "ignorable": true + }, + { + "message": "Call to an undefined method Levels\\MethodCalls\\Bar|Levels\\MethodCalls\\Foo::doFoo().", + "line": 170, + "ignorable": true + }, + { + "message": "Call to an undefined method Levels\\MethodCalls\\Bar|Levels\\MethodCalls\\Foo::doFoo().", + "line": 171, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/object-10-missing.json b/tests/PHPStan/Levels/data/object-10-missing.json new file mode 100644 index 0000000000..4d1f2153ba --- /dev/null +++ b/tests/PHPStan/Levels/data/object-10-missing.json @@ -0,0 +1,22 @@ +[ + { + "message": "Call to an undefined method object::foo().", + "line": 25, + "ignorable": true + }, + { + "message": "Access to an undefined property object::$bar.", + "line": 26, + "ignorable": true + }, + { + "message": "Call to an undefined static method object::baz().", + "line": 28, + "ignorable": true + }, + { + "message": "Access to an undefined static property object::$dolor.", + "line": 29, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/object-10.json b/tests/PHPStan/Levels/data/object-10.json new file mode 100644 index 0000000000..57f727da24 --- /dev/null +++ b/tests/PHPStan/Levels/data/object-10.json @@ -0,0 +1,32 @@ +[ + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 14, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 17, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 26, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 29, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 38, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 41, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/propertyAccesses-10-missing.json b/tests/PHPStan/Levels/data/propertyAccesses-10-missing.json new file mode 100644 index 0000000000..1a8bc8b4b7 --- /dev/null +++ b/tests/PHPStan/Levels/data/propertyAccesses-10-missing.json @@ -0,0 +1,32 @@ +[ + { + "message": "Access to an undefined property Levels\\PropertyAccesses\\Foo::$bar.", + "line": 61, + "ignorable": true + }, + { + "message": "Access to an undefined property Levels\\PropertyAccesses\\Foo::$bar.", + "line": 166, + "ignorable": true + }, + { + "message": "Access to an undefined property Levels\\PropertyAccesses\\Bar|Levels\\PropertyAccesses\\Foo::$foo.", + "line": 63, + "ignorable": true + }, + { + "message": "Access to an undefined property Levels\\PropertyAccesses\\Bar|Levels\\PropertyAccesses\\Foo::$bar.", + "line": 64, + "ignorable": true + }, + { + "message": "Access to an undefined property Levels\\PropertyAccesses\\Bar|Levels\\PropertyAccesses\\Foo::$foo.", + "line": 169, + "ignorable": true + }, + { + "message": "Access to an undefined property Levels\\PropertyAccesses\\Bar|Levels\\PropertyAccesses\\Foo::$bar.", + "line": 170, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/propertyAccesses-10.json b/tests/PHPStan/Levels/data/propertyAccesses-10.json new file mode 100644 index 0000000000..9581e25ad9 --- /dev/null +++ b/tests/PHPStan/Levels/data/propertyAccesses-10.json @@ -0,0 +1,57 @@ +[ + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 14, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 18, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 32, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 36, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 95, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 186, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 187, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 188, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 198, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 199, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 200, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/stringOffsetAccess-10.json b/tests/PHPStan/Levels/data/stringOffsetAccess-10.json new file mode 100644 index 0000000000..cc773c1e06 --- /dev/null +++ b/tests/PHPStan/Levels/data/stringOffsetAccess-10.json @@ -0,0 +1,32 @@ +[ + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 13, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 16, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 23, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 27, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 31, + "ignorable": true + }, + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 35, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/PHPStan/Levels/data/variables-10.json b/tests/PHPStan/Levels/data/variables-10.json new file mode 100644 index 0000000000..fd397067b9 --- /dev/null +++ b/tests/PHPStan/Levels/data/variables-10.json @@ -0,0 +1,7 @@ +[ + { + "message": "Parameter #1 (mixed) of echo cannot be converted to string.", + "line": 7, + "ignorable": true + } +] \ No newline at end of file From 04aa17f1f83c456ff688d8cfde19e69b193333af Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 2 Oct 2024 14:09:59 +0200 Subject: [PATCH 335/508] Added missing BC break --- UPGRADING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPGRADING.md b/UPGRADING.md index 5f34052a8c..96579f42c7 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -300,3 +300,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle * Interface `GlobalConstantReflection` renamed to `ConstantReflection` * Renamed interfaces and classes from `*WithPhpDocs` to `Extended*` * `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null +* Class `PHPStan\Node\ClassMethod` (accessible from `ClassMethodsNode`) is no longer an AST node From 7081a966c56074f163238a8d810970706b93fad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Mirtes?= Date: Wed, 2 Oct 2024 14:18:46 +0200 Subject: [PATCH 336/508] Added missing BC break --- UPGRADING.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 96579f42c7..bf3fee1b8a 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -233,6 +233,16 @@ Use [`PHPStan\Reflection\ReflectionProvider`](https://apiref.phpstan.org/2.0.x/P Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createReflectionProvider()`. +### List type is enabled for everyone + +Removed static methods from `AccessoryArrayListType` class: + +* `isListTypeEnabled()` +* `setListTypeEnabled()` +* `intersectWith()` + +Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::intersect($type, new AccessoryArrayListType())`. + ### Minor backward compatibility breaks * Classes that were previously `@final` were made `final` From 37cdfa3200a2cf1f1779324ff30790a0ab3c4b1e Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 3 Oct 2024 08:27:11 +0200 Subject: [PATCH 337/508] UPGRADING: fix missing syntax highlighting --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index bf3fee1b8a..474ecaf275 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -185,7 +185,7 @@ $returnType = ParametersAcceptorSelector::selectSingle($function->getVariants()) **After**: -``` +```php $returnType = $node->getFunctionReflection()->getReturnType(); ``` From 25cd191875697b3718f23799cec64df7e3f1d57d Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 3 Oct 2024 10:16:59 +0200 Subject: [PATCH 338/508] UPGRADING: fix typo --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index 474ecaf275..d66361a286 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -9,7 +9,7 @@ PHPStan now requires PHP 7.4 or newer to run. ## Upgrading guide for end users -The best way do get ready for upgrade to PHPStan 2.0 is to update to the **latest PHPStan 1.12 release** +The best way to get ready for upgrade to PHPStan 2.0 is to update to the **latest PHPStan 1.12 release** and enable [**Bleeding Edge**](https://phpstan.org/blog/what-is-bleeding-edge). This will enable the new rules and behaviours that 2.0 turns on for all users. Also make sure to install and enable [`phpstan/phpstan-deprecation-rules`](https://github.com/phpstan/phpstan-deprecation-rules). From b1d176ee45dd5050a84bd49da5477e102f28dba8 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 3 Oct 2024 10:43:40 +0200 Subject: [PATCH 339/508] UPGRADING: fix missing backticks --- UPGRADING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index d66361a286..cc0fd98bda 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -287,15 +287,15 @@ Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::i * Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead * Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead * Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead -* Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer bool -* Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list`, no longer int +* Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer `bool` +* Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list`, no longer `int` * Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead * `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool` * Remove `FunctionReflection::isFinal()` * [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html) * `additionalConfigFiles` config parameter must be a list * Remove `__set_state()` on objects that should not be serialized in cache -* Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts string +* Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts `string` * Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead * Remove `tempResultCachePath` config parameter, use `resultCachePath` instead * `LevelsTestCase::dataTopics()` data provider made static @@ -309,5 +309,5 @@ Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::i * Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection` * Interface `GlobalConstantReflection` renamed to `ConstantReflection` * Renamed interfaces and classes from `*WithPhpDocs` to `Extended*` -* `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null +* `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null` * Class `PHPStan\Node\ClassMethod` (accessible from `ClassMethodsNode`) is no longer an AST node From 58a5251f1b82b20e08a7d01d956bc8bf25909bc1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 3 Oct 2024 08:55:54 +0200 Subject: [PATCH 340/508] Upgrading note --- UPGRADING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPGRADING.md b/UPGRADING.md index cc0fd98bda..83e9631321 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -311,3 +311,4 @@ Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::i * Renamed interfaces and classes from `*WithPhpDocs` to `Extended*` * `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null` * Class `PHPStan\Node\ClassMethod` (accessible from `ClassMethodsNode`) is no longer an AST node + * Call `PHPStan\Node\ClassMethod::getNode()` to access the original AST node From 46a2477ae79ad958a29db073fe95c7de8a96d09e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 3 Oct 2024 09:00:30 +0200 Subject: [PATCH 341/508] Upgrading note --- UPGRADING.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 83e9631321..161a09499b 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -309,6 +309,9 @@ Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::i * Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection` * Interface `GlobalConstantReflection` renamed to `ConstantReflection` * Renamed interfaces and classes from `*WithPhpDocs` to `Extended*` + * `ParametersAcceptorWithPhpDocs` -> `ExtendedParametersAcceptor` + * `ParameterReflectionWithPhpDocs` -> `ExtendedParameterReflection` + * `FunctionVariantWithPhpDocs` -> `ExtendedFunctionVariant` * `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null` * Class `PHPStan\Node\ClassMethod` (accessible from `ClassMethodsNode`) is no longer an AST node * Call `PHPStan\Node\ClassMethod::getNode()` to access the original AST node From 0715ab942a6d2081044890fb900401e03d05e684 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 3 Oct 2024 10:47:53 +0200 Subject: [PATCH 342/508] Upgrading note --- UPGRADING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 161a09499b..c1ed243017 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -109,6 +109,10 @@ Tags without a PHP version are no longer published - `nightly`, `2`, `latest` ar ## Upgrading guide for extension developers +> [!NOTE] +> Please switch to PHPStan 2.0 in a new major version of your extension. It's not feasible to try to support both PHPStan 1.x and PHPStan 2.x with the same extension code. +> You can definitely get closer to supporting PHPStan 2.0 without increasing major version by solving reported deprecations and other issues by analysing your extension code with PHPStan & phpstan-deprecation-rules & Bleeding Edge, but the final leap and solving backward incompatibilities should be done by requiring `"phpstan/phpstan": "^2.0"` in your `composer.json`, and releasing a new major version. + ### PHPStan now uses nikic/php-parser v5 See [UPGRADING](https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md) guide for PHP-Parser. From b009a445bd3d96013d02746109d6ebd777275da4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 3 Oct 2024 10:49:01 +0200 Subject: [PATCH 343/508] Typo --- UPGRADING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPGRADING.md b/UPGRADING.md index c1ed243017..2ab208b5da 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -111,6 +111,7 @@ Tags without a PHP version are no longer published - `nightly`, `2`, `latest` ar > [!NOTE] > Please switch to PHPStan 2.0 in a new major version of your extension. It's not feasible to try to support both PHPStan 1.x and PHPStan 2.x with the same extension code. +> > You can definitely get closer to supporting PHPStan 2.0 without increasing major version by solving reported deprecations and other issues by analysing your extension code with PHPStan & phpstan-deprecation-rules & Bleeding Edge, but the final leap and solving backward incompatibilities should be done by requiring `"phpstan/phpstan": "^2.0"` in your `composer.json`, and releasing a new major version. ### PHPStan now uses nikic/php-parser v5 From 70a3e075008f6d2b216f4fa58cdefad685ef048d Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Thu, 3 Oct 2024 12:37:22 +0200 Subject: [PATCH 344/508] Spread list usages in Reflection, Scope, Type --- src/Analyser/MutatingScope.php | 4 ++-- src/Analyser/StatementResult.php | 4 ++-- src/PhpDoc/TypeNodeResolver.php | 7 ++++--- .../AnnotationMethodReflection.php | 4 ++-- .../Callables/FunctionCallableVariant.php | 2 +- src/Reflection/ClassReflection.php | 20 +++++++++---------- .../Dummy/ChangedTypeMethodReflection.php | 4 ++-- .../ExtendedCallableFunctionVariant.php | 2 +- src/Reflection/ExtendedFunctionVariant.php | 6 +++--- src/Reflection/ExtendedMethodReflection.php | 4 ++-- src/Reflection/ExtendedParametersAcceptor.php | 2 +- src/Reflection/FunctionReflection.php | 4 ++-- src/Reflection/FunctionVariant.php | 4 ++-- src/Reflection/InaccessibleMethod.php | 3 --- src/Reflection/MethodReflection.php | 2 +- .../Native/NativeFunctionReflection.php | 4 ++-- .../Native/NativeMethodReflection.php | 4 ++-- src/Reflection/ParametersAcceptor.php | 2 +- src/Reflection/ParametersAcceptorSelector.php | 13 ++++++------ src/Reflection/Php/ExitFunctionReflection.php | 2 +- .../PhpFunctionFromParserNodeReflection.php | 7 ++----- src/Reflection/Php/PhpFunctionReflection.php | 7 ++----- src/Reflection/Php/PhpMethodReflection.php | 8 ++++---- .../ResolvedFunctionVariantWithOriginal.php | 2 +- src/Reflection/ResolvedMethodReflection.php | 6 +++--- .../SignatureMap/FunctionSignature.php | 4 ++-- .../SignatureMap/SignatureMapParser.php | 2 +- src/Type/Accessory/HasPropertyType.php | 3 --- src/Type/ArrayType.php | 3 --- src/Type/CallableType.php | 9 +++------ src/Type/ClosureType.php | 9 +++------ src/Type/FloatType.php | 3 --- src/Type/Generic/GenericObjectType.php | 3 --- src/Type/IterableType.php | 3 --- src/Type/JustNullableTypeTrait.php | 3 --- src/Type/MixedType.php | 3 --- src/Type/NeverType.php | 3 --- src/Type/NullType.php | 3 --- src/Type/ObjectType.php | 3 --- src/Type/ObjectWithoutClassType.php | 3 --- src/Type/StaticType.php | 3 --- src/Type/Type.php | 4 ++-- src/Type/TypeUtils.php | 6 +++--- src/Type/UnionType.php | 3 --- src/Type/VoidType.php | 3 --- 45 files changed, 74 insertions(+), 129 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 461ab91c4f..b145afa082 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -552,7 +552,7 @@ public function getVariableType(string $variableName): Type /** * @api - * @return array + * @return list */ public function getDefinedVariables(): array { @@ -573,7 +573,7 @@ public function getDefinedVariables(): array /** * @api - * @return array + * @return list */ public function getMaybeDefinedVariables(): array { diff --git a/src/Analyser/StatementResult.php b/src/Analyser/StatementResult.php index 71f0ddc740..dad528dc18 100644 --- a/src/Analyser/StatementResult.php +++ b/src/Analyser/StatementResult.php @@ -81,7 +81,7 @@ public function getExitPoints(): array /** * @param class-string|class-string $stmtClass - * @return StatementExitPoint[] + * @return list */ public function getExitPointsByType(string $stmtClass): array { @@ -115,7 +115,7 @@ public function getExitPointsByType(string $stmtClass): array } /** - * @return StatementExitPoint[] + * @return list */ public function getExitPointsForOuterLoop(): array { diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php index ee7ef34786..6dd4f821b9 100644 --- a/src/PhpDoc/TypeNodeResolver.php +++ b/src/PhpDoc/TypeNodeResolver.php @@ -107,6 +107,7 @@ use Traversable; use function array_key_exists; use function array_map; +use function array_values; use function count; use function explode; use function get_class; @@ -927,7 +928,7 @@ private function resolveCallableTypeNode(CallableTypeNode $typeNode, NameScope $ $mainType = $this->resolve($typeNode->identifier, $nameScope); $isVariadic = false; - $parameters = array_map( + $parameters = array_values(array_map( function (CallableTypeParameterNode $parameterNode) use ($nameScope, &$isVariadic): NativeParameterReflection { $isVariadic = $isVariadic || $parameterNode->isVariadic; $parameterName = $parameterNode->parameterName; @@ -945,7 +946,7 @@ function (CallableTypeParameterNode $parameterNode) use ($nameScope, &$isVariadi ); }, $typeNode->parameters, - ); + )); $returnType = $this->resolve($typeNode->returnType, $nameScope); @@ -1196,7 +1197,7 @@ private function expandIntMaskToType(Type $type): ?Type /** * @api * @param TypeNode[] $typeNodes - * @return Type[] + * @return list */ public function resolveMultiple(array $typeNodes, NameScope $nameScope): array { diff --git a/src/Reflection/Annotations/AnnotationMethodReflection.php b/src/Reflection/Annotations/AnnotationMethodReflection.php index 847a444eb5..865abdbe04 100644 --- a/src/Reflection/Annotations/AnnotationMethodReflection.php +++ b/src/Reflection/Annotations/AnnotationMethodReflection.php @@ -17,11 +17,11 @@ final class AnnotationMethodReflection implements ExtendedMethodReflection { - /** @var ExtendedFunctionVariant[]|null */ + /** @var list|null */ private ?array $variants = null; /** - * @param AnnotationsMethodParameterReflection[] $parameters + * @param list $parameters */ public function __construct( private string $name, diff --git a/src/Reflection/Callables/FunctionCallableVariant.php b/src/Reflection/Callables/FunctionCallableVariant.php index 66bd629a3e..71ea905c52 100644 --- a/src/Reflection/Callables/FunctionCallableVariant.php +++ b/src/Reflection/Callables/FunctionCallableVariant.php @@ -52,7 +52,7 @@ public function getResolvedTemplateTypeMap(): TemplateTypeMap } /** - * @return array + * @return list */ public function getParameters(): array { diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index 7d966f83d5..a557218fd5 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -130,7 +130,7 @@ final class ClassReflection private false|ResolvedPhpDocBlock $traitContextResolvedPhpDocBlock = false; - /** @var ClassReflection[]|null */ + /** @var array|null */ private ?array $cachedInterfaces = null; private ClassReflection|false|null $cachedParentClass = false; @@ -360,7 +360,7 @@ public function getClassHierarchyDistances(): array } /** - * @return ReflectionClass[] + * @return list */ private function collectTraits(ReflectionClass|ReflectionEnum $class): array { @@ -845,7 +845,7 @@ public function implementsInterface(string $className): bool } /** - * @return ClassReflection[] + * @return list */ public function getParents(): array { @@ -860,7 +860,7 @@ public function getParents(): array } /** - * @return ClassReflection[] + * @return array */ public function getInterfaces(): array { @@ -894,7 +894,7 @@ public function getInterfaces(): array } /** - * @return ClassReflection[] + * @return array */ private function collectInterfaces(ClassReflection $interface): array { @@ -910,7 +910,7 @@ private function collectInterfaces(ClassReflection $interface): array } /** - * @return ClassReflection[] + * @return array */ public function getImmediateInterfaces(): array { @@ -1102,7 +1102,7 @@ public function hasTraitUse(string $traitName): bool } /** - * @return string[] + * @return list */ private function getTraitNames(): array { @@ -1459,7 +1459,7 @@ public function varianceMapFromList(array $variances): TemplateTypeVarianceMap return new TemplateTypeVarianceMap($map); } - /** @return array */ + /** @return list */ public function typeMapToList(TemplateTypeMap $typeMap): array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); @@ -1475,7 +1475,7 @@ public function typeMapToList(TemplateTypeMap $typeMap): array return $list; } - /** @return array */ + /** @return list */ public function varianceMapToList(TemplateTypeVarianceMap $varianceMap): array { $resolvedPhpDoc = $this->getResolvedPhpDoc(); @@ -1775,7 +1775,7 @@ public function getMethodTags(): array } /** - * @return array + * @return list */ public function getResolvedMixinTypes(): array { diff --git a/src/Reflection/Dummy/ChangedTypeMethodReflection.php b/src/Reflection/Dummy/ChangedTypeMethodReflection.php index bc0a557157..3b3279596a 100644 --- a/src/Reflection/Dummy/ChangedTypeMethodReflection.php +++ b/src/Reflection/Dummy/ChangedTypeMethodReflection.php @@ -17,8 +17,8 @@ final class ChangedTypeMethodReflection implements ExtendedMethodReflection { /** - * @param ExtendedParametersAcceptor[] $variants - * @param ExtendedParametersAcceptor[]|null $namedArgumentsVariants + * @param list $variants + * @param list|null $namedArgumentsVariants */ public function __construct(private ClassReflection $declaringClass, private ExtendedMethodReflection $reflection, private array $variants, private ?array $namedArgumentsVariants) { diff --git a/src/Reflection/ExtendedCallableFunctionVariant.php b/src/Reflection/ExtendedCallableFunctionVariant.php index 5b67d210cc..5e2d3a9c10 100644 --- a/src/Reflection/ExtendedCallableFunctionVariant.php +++ b/src/Reflection/ExtendedCallableFunctionVariant.php @@ -15,7 +15,7 @@ final class ExtendedCallableFunctionVariant extends ExtendedFunctionVariant impl { /** - * @param array $parameters + * @param list $parameters * @param SimpleThrowPoint[] $throwPoints * @param SimpleImpurePoint[] $impurePoints * @param InvalidateExprNode[] $invalidateExpressions diff --git a/src/Reflection/ExtendedFunctionVariant.php b/src/Reflection/ExtendedFunctionVariant.php index 33c8e72c00..e45f402bb0 100644 --- a/src/Reflection/ExtendedFunctionVariant.php +++ b/src/Reflection/ExtendedFunctionVariant.php @@ -13,7 +13,7 @@ class ExtendedFunctionVariant extends FunctionVariant implements ExtendedParamet { /** - * @param array $parameters + * @param list $parameters * @api */ public function __construct( @@ -38,11 +38,11 @@ public function __construct( } /** - * @return array + * @return list */ public function getParameters(): array { - /** @var array $parameters */ + /** @var list $parameters */ $parameters = parent::getParameters(); return $parameters; diff --git a/src/Reflection/ExtendedMethodReflection.php b/src/Reflection/ExtendedMethodReflection.php index e8a65b00b6..b49a71bb1a 100644 --- a/src/Reflection/ExtendedMethodReflection.php +++ b/src/Reflection/ExtendedMethodReflection.php @@ -23,7 +23,7 @@ interface ExtendedMethodReflection extends MethodReflection { /** - * @return ExtendedParametersAcceptor[] + * @return list */ public function getVariants(): array; @@ -33,7 +33,7 @@ public function getVariants(): array; public function getOnlyVariant(): ExtendedParametersAcceptor; /** - * @return ExtendedParametersAcceptor[]|null + * @return list|null */ public function getNamedArgumentsVariants(): ?array; diff --git a/src/Reflection/ExtendedParametersAcceptor.php b/src/Reflection/ExtendedParametersAcceptor.php index 002a8a930d..77fb213b49 100644 --- a/src/Reflection/ExtendedParametersAcceptor.php +++ b/src/Reflection/ExtendedParametersAcceptor.php @@ -10,7 +10,7 @@ interface ExtendedParametersAcceptor extends ParametersAcceptor { /** - * @return array + * @return list */ public function getParameters(): array; diff --git a/src/Reflection/FunctionReflection.php b/src/Reflection/FunctionReflection.php index e6770e08a5..33b355b844 100644 --- a/src/Reflection/FunctionReflection.php +++ b/src/Reflection/FunctionReflection.php @@ -14,7 +14,7 @@ public function getName(): string; public function getFileName(): ?string; /** - * @return ExtendedParametersAcceptor[] + * @return list */ public function getVariants(): array; @@ -24,7 +24,7 @@ public function getVariants(): array; public function getOnlyVariant(): ExtendedParametersAcceptor; /** - * @return ExtendedParametersAcceptor[]|null + * @return list|null */ public function getNamedArgumentsVariants(): ?array; diff --git a/src/Reflection/FunctionVariant.php b/src/Reflection/FunctionVariant.php index b6023cae16..7c69274ef0 100644 --- a/src/Reflection/FunctionVariant.php +++ b/src/Reflection/FunctionVariant.php @@ -16,7 +16,7 @@ class FunctionVariant implements ParametersAcceptor /** * @api - * @param array $parameters + * @param list $parameters */ public function __construct( private TemplateTypeMap $templateTypeMap, @@ -46,7 +46,7 @@ public function getCallSiteVarianceMap(): TemplateTypeVarianceMap } /** - * @return array + * @return list */ public function getParameters(): array { diff --git a/src/Reflection/InaccessibleMethod.php b/src/Reflection/InaccessibleMethod.php index fef9716d6c..037f4e8137 100644 --- a/src/Reflection/InaccessibleMethod.php +++ b/src/Reflection/InaccessibleMethod.php @@ -37,9 +37,6 @@ public function getCallSiteVarianceMap(): TemplateTypeVarianceMap return TemplateTypeVarianceMap::createEmpty(); } - /** - * @return array - */ public function getParameters(): array { return []; diff --git a/src/Reflection/MethodReflection.php b/src/Reflection/MethodReflection.php index 8d601e9471..529a5011dd 100644 --- a/src/Reflection/MethodReflection.php +++ b/src/Reflection/MethodReflection.php @@ -14,7 +14,7 @@ public function getName(): string; public function getPrototype(): ClassMemberReflection; /** - * @return ParametersAcceptor[] + * @return list */ public function getVariants(): array; diff --git a/src/Reflection/Native/NativeFunctionReflection.php b/src/Reflection/Native/NativeFunctionReflection.php index 852392d750..730f8c61e9 100644 --- a/src/Reflection/Native/NativeFunctionReflection.php +++ b/src/Reflection/Native/NativeFunctionReflection.php @@ -18,8 +18,8 @@ final class NativeFunctionReflection implements FunctionReflection private TrinaryLogic $returnsByReference; /** - * @param ExtendedParametersAcceptor[] $variants - * @param ExtendedParametersAcceptor[]|null $namedArgumentsVariants + * @param list $variants + * @param list|null $namedArgumentsVariants */ public function __construct( private string $name, diff --git a/src/Reflection/Native/NativeMethodReflection.php b/src/Reflection/Native/NativeMethodReflection.php index b167f1223f..8f1e21d7c9 100644 --- a/src/Reflection/Native/NativeMethodReflection.php +++ b/src/Reflection/Native/NativeMethodReflection.php @@ -22,8 +22,8 @@ final class NativeMethodReflection implements ExtendedMethodReflection { /** - * @param ExtendedParametersAcceptor[] $variants - * @param ExtendedParametersAcceptor[]|null $namedArgumentsVariants + * @param list $variants + * @param list|null $namedArgumentsVariants */ public function __construct( private ReflectionProvider $reflectionProvider, diff --git a/src/Reflection/ParametersAcceptor.php b/src/Reflection/ParametersAcceptor.php index f4c2d4f1c0..b5fa5f1a2d 100644 --- a/src/Reflection/ParametersAcceptor.php +++ b/src/Reflection/ParametersAcceptor.php @@ -20,7 +20,7 @@ public function getTemplateTypeMap(): TemplateTypeMap; public function getResolvedTemplateTypeMap(): TemplateTypeMap; /** - * @return array + * @return list */ public function getParameters(): array; diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index 57609ab0c7..cc36c1d951 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -44,6 +44,7 @@ use function array_map; use function array_merge; use function array_slice; +use function array_values; use function constant; use function count; use function defined; @@ -143,7 +144,7 @@ public static function selectFromArgs( new FunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), - $parameters, + array_values($parameters), $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), @@ -193,7 +194,7 @@ public static function selectFromArgs( new FunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), - $parameters, + array_values($parameters), $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), @@ -224,7 +225,7 @@ public static function selectFromArgs( new FunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), - $parameters, + array_values($parameters), $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), @@ -309,7 +310,7 @@ public static function selectFromArgs( new FunctionVariant( $acceptor->getTemplateTypeMap(), $acceptor->getResolvedTemplateTypeMap(), - $parameters, + array_values($parameters), $acceptor->isVariadic(), $acceptor->getReturnType(), $acceptor instanceof ExtendedParametersAcceptor ? $acceptor->getCallSiteVarianceMap() : TemplateTypeVarianceMap::createEmpty(), @@ -688,7 +689,7 @@ public static function combineAcceptors(array $acceptors): ExtendedParametersAcc return new ExtendedCallableFunctionVariant( TemplateTypeMap::createEmpty(), null, - $parameters, + array_values($parameters), $isVariadic, $returnType, $phpDocReturnType ?? $returnType, @@ -706,7 +707,7 @@ public static function combineAcceptors(array $acceptors): ExtendedParametersAcc return new ExtendedFunctionVariant( TemplateTypeMap::createEmpty(), null, - $parameters, + array_values($parameters), $isVariadic, $returnType, $phpDocReturnType ?? $returnType, diff --git a/src/Reflection/Php/ExitFunctionReflection.php b/src/Reflection/Php/ExitFunctionReflection.php index 12eb38927d..76c8e7cf7a 100644 --- a/src/Reflection/Php/ExitFunctionReflection.php +++ b/src/Reflection/Php/ExitFunctionReflection.php @@ -75,7 +75,7 @@ public function getOnlyVariant(): ExtendedParametersAcceptor } /** - * @return ExtendedParametersAcceptor[] + * @return list */ public function getNamedArgumentsVariants(): array { diff --git a/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php b/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php index dc44c0d17d..1d157476df 100644 --- a/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php +++ b/src/Reflection/Php/PhpFunctionFromParserNodeReflection.php @@ -33,7 +33,7 @@ class PhpFunctionFromParserNodeReflection implements FunctionReflection, Extende /** @var Function_|ClassMethod */ private Node\FunctionLike $functionLike; - /** @var ExtendedFunctionVariant[]|null */ + /** @var list|null */ private ?array $variants = null; /** @@ -93,9 +93,6 @@ public function getName(): string return (string) $this->functionLike->namespacedName; } - /** - * @return ExtendedParametersAcceptor[] - */ public function getVariants(): array { if ($this->variants === null) { @@ -136,7 +133,7 @@ public function getResolvedTemplateTypeMap(): TemplateTypeMap } /** - * @return array + * @return list */ public function getParameters(): array { diff --git a/src/Reflection/Php/PhpFunctionReflection.php b/src/Reflection/Php/PhpFunctionReflection.php index 4669701c79..6209323f77 100644 --- a/src/Reflection/Php/PhpFunctionReflection.php +++ b/src/Reflection/Php/PhpFunctionReflection.php @@ -32,7 +32,7 @@ final class PhpFunctionReflection implements FunctionReflection { - /** @var ExtendedFunctionVariant[]|null */ + /** @var list|null */ private ?array $variants = null; /** @@ -85,9 +85,6 @@ public function getFileName(): ?string return $this->filename; } - /** - * @return ExtendedParametersAcceptor[] - */ public function getVariants(): array { if ($this->variants === null) { @@ -118,7 +115,7 @@ public function getNamedArgumentsVariants(): ?array } /** - * @return ExtendedParameterReflection[] + * @return list */ private function getParameters(): array { diff --git a/src/Reflection/Php/PhpMethodReflection.php b/src/Reflection/Php/PhpMethodReflection.php index afa4f56a46..d0e008a7ed 100644 --- a/src/Reflection/Php/PhpMethodReflection.php +++ b/src/Reflection/Php/PhpMethodReflection.php @@ -52,14 +52,14 @@ final class PhpMethodReflection implements ExtendedMethodReflection { - /** @var PhpParameterReflection[]|null */ + /** @var list|null */ private ?array $parameters = null; private ?Type $returnType = null; private ?Type $nativeReturnType = null; - /** @var ExtendedFunctionVariant[]|null */ + /** @var list|null */ private ?array $variants = null; /** @@ -191,7 +191,7 @@ private function getMethodNameWithCorrectCase(string $lowercaseMethodName, strin } /** - * @return ExtendedParametersAcceptor[] + * @return list */ public function getVariants(): array { @@ -223,7 +223,7 @@ public function getNamedArgumentsVariants(): ?array } /** - * @return ExtendedParameterReflection[] + * @return list */ private function getParameters(): array { diff --git a/src/Reflection/ResolvedFunctionVariantWithOriginal.php b/src/Reflection/ResolvedFunctionVariantWithOriginal.php index 4dda7b8685..dcf68ca1ef 100644 --- a/src/Reflection/ResolvedFunctionVariantWithOriginal.php +++ b/src/Reflection/ResolvedFunctionVariantWithOriginal.php @@ -21,7 +21,7 @@ final class ResolvedFunctionVariantWithOriginal implements ResolvedFunctionVariant { - /** @var ExtendedParameterReflection[]|null */ + /** @var list|null */ private ?array $parameters = null; private ?Type $returnTypeWithUnresolvableTemplateTypes = null; diff --git a/src/Reflection/ResolvedMethodReflection.php b/src/Reflection/ResolvedMethodReflection.php index b04803c13c..33b70bafe4 100644 --- a/src/Reflection/ResolvedMethodReflection.php +++ b/src/Reflection/ResolvedMethodReflection.php @@ -14,10 +14,10 @@ final class ResolvedMethodReflection implements ExtendedMethodReflection { - /** @var ExtendedParametersAcceptor[]|null */ + /** @var list|null */ private ?array $variants = null; - /** @var ExtendedParametersAcceptor[]|null */ + /** @var list|null */ private ?array $namedArgumentVariants = null; private ?Assertions $asserts = null; @@ -74,7 +74,7 @@ public function getNamedArgumentsVariants(): ?array /** * @param ExtendedParametersAcceptor[] $variants - * @return ResolvedFunctionVariant[] + * @return list */ private function resolveVariants(array $variants): array { diff --git a/src/Reflection/SignatureMap/FunctionSignature.php b/src/Reflection/SignatureMap/FunctionSignature.php index 07886541f8..f9107d4b23 100644 --- a/src/Reflection/SignatureMap/FunctionSignature.php +++ b/src/Reflection/SignatureMap/FunctionSignature.php @@ -8,7 +8,7 @@ final class FunctionSignature { /** - * @param array $parameters + * @param list $parameters */ public function __construct( private array $parameters, @@ -20,7 +20,7 @@ public function __construct( } /** - * @return array + * @return list */ public function getParameters(): array { diff --git a/src/Reflection/SignatureMap/SignatureMapParser.php b/src/Reflection/SignatureMap/SignatureMapParser.php index 0652b11383..e60cede66d 100644 --- a/src/Reflection/SignatureMap/SignatureMapParser.php +++ b/src/Reflection/SignatureMap/SignatureMapParser.php @@ -57,7 +57,7 @@ private function getTypeFromString(string $typeString, ?string $className): Type /** * @param array $parameterMap - * @return array + * @return list */ private function getParameters(array $parameterMap): array { diff --git a/src/Type/Accessory/HasPropertyType.php b/src/Type/Accessory/HasPropertyType.php index f65b2bbe48..759230b2cd 100644 --- a/src/Type/Accessory/HasPropertyType.php +++ b/src/Type/Accessory/HasPropertyType.php @@ -35,9 +35,6 @@ public function __construct(private string $propertyName) { } - /** - * @return string[] - */ public function getReferencedClasses(): array { return []; diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 97ebb9a196..11304c9edd 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -64,9 +64,6 @@ public function getItemType(): Type return $this->itemType; } - /** - * @return string[] - */ public function getReferencedClasses(): array { return array_merge( diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 325a195d27..353b5622ea 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -52,7 +52,7 @@ class CallableType implements CompoundType, CallableParametersAcceptor use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; - /** @var array */ + /** @var list */ private array $parameters; private Type $returnType; @@ -67,7 +67,7 @@ class CallableType implements CompoundType, CallableParametersAcceptor /** * @api - * @param array|null $parameters + * @param list|null $parameters * @param array $templateTags */ public function __construct( @@ -101,9 +101,6 @@ public function isPure(): TrinaryLogic return $this->isPure; } - /** - * @return string[] - */ public function getReferencedClasses(): array { $classes = []; @@ -345,7 +342,7 @@ public function getCallSiteVarianceMap(): TemplateTypeVarianceMap } /** - * @return array + * @return list */ public function getParameters(): array { diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index 46101a4bfe..f4e50f8089 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -59,7 +59,7 @@ class ClosureType implements TypeWithClassName, CallableParametersAcceptor use NonRemoveableTypeTrait; use NonGeneralizableTypeTrait; - /** @var array */ + /** @var list */ private array $parameters; private Type $returnType; @@ -81,7 +81,7 @@ class ClosureType implements TypeWithClassName, CallableParametersAcceptor /** * @api - * @param array|null $parameters + * @param list|null $parameters * @param array $templateTags * @param SimpleThrowPoint[] $throwPoints * @param ?SimpleImpurePoint[] $impurePoints @@ -165,9 +165,6 @@ public function getAncestorWithClassName(string $className): ?TypeWithClassName return $this->objectType->getAncestorWithClassName($className); } - /** - * @return string[] - */ public function getReferencedClasses(): array { $classes = $this->objectType->getReferencedClasses(); @@ -481,7 +478,7 @@ public function getCallSiteVarianceMap(): TemplateTypeVarianceMap } /** - * @return array + * @return list */ public function getParameters(): array { diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index a9bea4a070..829f1cb8ed 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -41,9 +41,6 @@ public function __construct() { } - /** - * @return string[] - */ public function getReferencedClasses(): array { return []; diff --git a/src/Type/Generic/GenericObjectType.php b/src/Type/Generic/GenericObjectType.php index b73a7efc94..f7c18de70b 100644 --- a/src/Type/Generic/GenericObjectType.php +++ b/src/Type/Generic/GenericObjectType.php @@ -91,9 +91,6 @@ public function equals(Type $type): bool return true; } - /** - * @return string[] - */ public function getReferencedClasses(): array { $classes = parent::getReferencedClasses(); diff --git a/src/Type/IterableType.php b/src/Type/IterableType.php index 512f88ac7a..6d375c7e2c 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -52,9 +52,6 @@ public function getItemType(): Type return $this->itemType; } - /** - * @return string[] - */ public function getReferencedClasses(): array { return array_merge( diff --git a/src/Type/JustNullableTypeTrait.php b/src/Type/JustNullableTypeTrait.php index 481e9fb3ac..24f2974ae4 100644 --- a/src/Type/JustNullableTypeTrait.php +++ b/src/Type/JustNullableTypeTrait.php @@ -8,9 +8,6 @@ trait JustNullableTypeTrait { - /** - * @return string[] - */ public function getReferencedClasses(): array { return []; diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index 5353a10290..8ffc633771 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -61,9 +61,6 @@ public function __construct( $this->subtractedType = $subtractedType; } - /** - * @return string[] - */ public function getReferencedClasses(): array { return []; diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index 21f58c0c29..5e2291a38b 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -39,9 +39,6 @@ public function isExplicit(): bool return $this->isExplicit; } - /** - * @return string[] - */ public function getReferencedClasses(): array { return []; diff --git a/src/Type/NullType.php b/src/Type/NullType.php index b8ba6be336..f9296f32ff 100644 --- a/src/Type/NullType.php +++ b/src/Type/NullType.php @@ -36,9 +36,6 @@ public function __construct() { } - /** - * @return string[] - */ public function getReferencedClasses(): array { return []; diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 804147910e..c08fc0af10 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -252,9 +252,6 @@ public function getPropertyWithoutTransformingStatic(string $propertyName, Class return $classReflection->getProperty($propertyName, $scope); } - /** - * @return string[] - */ public function getReferencedClasses(): array { return [$this->className]; diff --git a/src/Type/ObjectWithoutClassType.php b/src/Type/ObjectWithoutClassType.php index e9cd001bdc..69f10e8dba 100644 --- a/src/Type/ObjectWithoutClassType.php +++ b/src/Type/ObjectWithoutClassType.php @@ -34,9 +34,6 @@ public function __construct( $this->subtractedType = $subtractedType; } - /** - * @return string[] - */ public function getReferencedClasses(): array { return []; diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index 7d73571c4f..cb3a135431 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -99,9 +99,6 @@ public function getStaticObjectType(): ObjectType return $this->staticObjectType; } - /** - * @return string[] - */ public function getReferencedClasses(): array { return $this->getStaticObjectType()->getReferencedClasses(); diff --git a/src/Type/Type.php b/src/Type/Type.php index 398bc0d4f2..2e0557ba0c 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -28,7 +28,7 @@ interface Type { /** - * @return string[] + * @return list */ public function getReferencedClasses(): array; @@ -313,7 +313,7 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap; * which the receiver type was * found. * - * @return TemplateTypeReference[] + * @return list */ public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array; diff --git a/src/Type/TypeUtils.php b/src/Type/TypeUtils.php index c00c7602ec..65268fba79 100644 --- a/src/Type/TypeUtils.php +++ b/src/Type/TypeUtils.php @@ -18,7 +18,7 @@ final class TypeUtils { /** - * @return ConstantIntegerType[] + * @return list */ public static function getConstantIntegers(Type $type): array { @@ -26,7 +26,7 @@ public static function getConstantIntegers(Type $type): array } /** - * @return IntegerRangeType[] + * @return list */ public static function getIntegerRanges(Type $type): array { @@ -34,7 +34,7 @@ public static function getIntegerRanges(Type $type): array } /** - * @return mixed[] + * @return list */ private static function map( string $typeClass, diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 4e38c38566..3c8b9ef1ff 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -106,9 +106,6 @@ protected function getSortedTypes(): array return $this->types; } - /** - * @return string[] - */ public function getReferencedClasses(): array { $classes = []; diff --git a/src/Type/VoidType.php b/src/Type/VoidType.php index a49c642aca..5895449145 100644 --- a/src/Type/VoidType.php +++ b/src/Type/VoidType.php @@ -37,9 +37,6 @@ public function __construct() { } - /** - * @return string[] - */ public function getReferencedClasses(): array { return []; From 1249a20d4c287e92e9360802be859c54c4fbf9f9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 3 Oct 2024 14:03:49 +0200 Subject: [PATCH 345/508] Report old PHP-Parser v4 class names in PHPStan-related code --- conf/config.level0.neon | 1 + src/Rules/Api/OldPhpParser4ClassRule.php | 79 +++++++++++++++++++ .../Rules/Api/OldPhpParser4ClassRuleTest.php | 29 +++++++ .../Rules/Api/data/old-php-parser-4-class.php | 32 ++++++++ 4 files changed, 141 insertions(+) create mode 100644 src/Rules/Api/OldPhpParser4ClassRule.php create mode 100644 tests/PHPStan/Rules/Api/OldPhpParser4ClassRuleTest.php create mode 100644 tests/PHPStan/Rules/Api/data/old-php-parser-4-class.php diff --git a/conf/config.level0.neon b/conf/config.level0.neon index fbad323697..d4927a56c4 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -18,6 +18,7 @@ rules: - PHPStan\Rules\Api\ApiTraitUseRule - PHPStan\Rules\Api\GetTemplateTypeRule - PHPStan\Rules\Api\NodeConnectingVisitorAttributesRule + - PHPStan\Rules\Api\OldPhpParser4ClassRule - PHPStan\Rules\Api\PhpStanNamespaceIn3rdPartyPackageRule - PHPStan\Rules\Api\RuntimeReflectionInstantiationRule - PHPStan\Rules\Api\RuntimeReflectionFunctionRule diff --git a/src/Rules/Api/OldPhpParser4ClassRule.php b/src/Rules/Api/OldPhpParser4ClassRule.php new file mode 100644 index 0000000000..8c86e3c713 --- /dev/null +++ b/src/Rules/Api/OldPhpParser4ClassRule.php @@ -0,0 +1,79 @@ + + */ +final class OldPhpParser4ClassRule implements Rule +{ + + private const NAME_MAPPING = [ + // from https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md#renamed-nodes + 'PhpParser\Node\Scalar\LNumber' => Node\Scalar\Int_::class, + 'PhpParser\Node\Scalar\DNumber' => Node\Scalar\Float_::class, + 'PhpParser\Node\Scalar\Encapsed' => Node\Scalar\InterpolatedString::class, + 'PhpParser\Node\Scalar\EncapsedStringPart' => Node\InterpolatedStringPart::class, + 'PhpParser\Node\Expr\ArrayItem' => Node\ArrayItem::class, + 'PhpParser\Node\Expr\ClosureUse' => Node\ClosureUse::class, + 'PhpParser\Node\Stmt\DeclareDeclare' => Node\DeclareItem::class, + 'PhpParser\Node\Stmt\PropertyProperty' => Node\PropertyItem::class, + 'PhpParser\Node\Stmt\StaticVar' => Node\StaticVar::class, + 'PhpParser\Node\Stmt\UseUse' => Node\UseItem::class, + ]; + + public function getNodeType(): string + { + return Name::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $nameMapping = array_change_key_case(self::NAME_MAPPING); + $lowerName = $node->toLowerString(); + if (!array_key_exists($lowerName, $nameMapping)) { + return []; + } + + $newName = $nameMapping[$lowerName]; + + if (!$scope->isInClass()) { + return []; + } + + $classReflection = $scope->getClassReflection(); + $hasPhpStanInterface = false; + foreach (array_keys($classReflection->getInterfaces()) as $interfaceName) { + if (!str_starts_with($interfaceName, 'PHPStan\\')) { + continue; + } + + $hasPhpStanInterface = true; + } + + if (!$hasPhpStanInterface) { + return []; + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Class %s not found. It has been renamed to %s in PHP-Parser v5.', + $node->toString(), + $newName, + ))->identifier('phpParser.classRenamed') + ->build(), + ]; + } + +} diff --git a/tests/PHPStan/Rules/Api/OldPhpParser4ClassRuleTest.php b/tests/PHPStan/Rules/Api/OldPhpParser4ClassRuleTest.php new file mode 100644 index 0000000000..23892389dd --- /dev/null +++ b/tests/PHPStan/Rules/Api/OldPhpParser4ClassRuleTest.php @@ -0,0 +1,29 @@ + + */ +class OldPhpParser4ClassRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new OldPhpParser4ClassRule(); + } + + public function testRule(): void + { + $this->analyse([__DIR__ . '/data/old-php-parser-4-class.php'], [ + [ + 'Class PhpParser\Node\Expr\ArrayItem not found. It has been renamed to PhpParser\Node\ArrayItem in PHP-Parser v5.', + 24, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Api/data/old-php-parser-4-class.php b/tests/PHPStan/Rules/Api/data/old-php-parser-4-class.php new file mode 100644 index 0000000000..f9f017054f --- /dev/null +++ b/tests/PHPStan/Rules/Api/data/old-php-parser-4-class.php @@ -0,0 +1,32 @@ + Date: Thu, 3 Oct 2024 17:24:57 +0200 Subject: [PATCH 346/508] Fix PHP baseline count --- .../BaselinePhpErrorFormatter.php | 26 +++++++++++-------- .../BaselinePhpErrorFormatterTest.php | 4 +-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php b/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php index fefb3175fd..65cafffb9f 100644 --- a/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php +++ b/src/Command/ErrorFormatter/BaselinePhpErrorFormatter.php @@ -6,11 +6,9 @@ use PHPStan\Command\AnalysisResult; use PHPStan\Command\Output; use PHPStan\File\RelativePathHelper; -use function array_keys; use function count; use function ksort; use function preg_quote; -use function sort; use function sprintf; use function var_export; use const SORT_STRING; @@ -53,33 +51,39 @@ public function formatErrors( $fileErrorsByMessage = []; foreach ($errors as $error) { $errorMessage = $error->getMessage(); + $identifier = $error->getIdentifier(); if (!isset($fileErrorsByMessage[$errorMessage])) { $fileErrorsByMessage[$errorMessage] = [ 1, - $error->getIdentifier() !== null ? [$error->getIdentifier() => true] : [], + $identifier !== null ? [$identifier => 1] : [], ]; continue; } $fileErrorsByMessage[$errorMessage][0]++; - if ($error->getIdentifier() === null) { + if ($identifier === null) { continue; } - $fileErrorsByMessage[$errorMessage][1][$error->getIdentifier()] = true; + + if (!isset($fileErrorsByMessage[$errorMessage][1][$identifier])) { + $fileErrorsByMessage[$errorMessage][1][$identifier] = 1; + continue; + } + + $fileErrorsByMessage[$errorMessage][1][$identifier]++; } ksort($fileErrorsByMessage, SORT_STRING); - foreach ($fileErrorsByMessage as $message => [$count, $identifiersInKeys]) { - $identifiers = array_keys($identifiersInKeys); - sort($identifiers); + foreach ($fileErrorsByMessage as $message => [$totalCount, $identifiers]) { + ksort($identifiers, SORT_STRING); if (count($identifiers) > 0) { - foreach ($identifiers as $identifier) { + foreach ($identifiers as $identifier => $identifierCount) { $php .= sprintf( "\$ignoreErrors[] = [\n\t'message' => %s,\n\t'identifier' => %s,\n\t'count' => %d,\n\t'path' => __DIR__ . %s,\n];\n", var_export(Helpers::escape('#^' . preg_quote($message, '#') . '$#'), true), var_export(Helpers::escape($identifier), true), - var_export($count, true), + var_export($identifierCount, true), var_export(Helpers::escape($file), true), ); } @@ -87,7 +91,7 @@ public function formatErrors( $php .= sprintf( "\$ignoreErrors[] = [\n\t'message' => %s,\n\t'count' => %d,\n\t'path' => __DIR__ . %s,\n];\n", var_export(Helpers::escape('#^' . preg_quote($message, '#') . '$#'), true), - var_export($count, true), + var_export($totalCount, true), var_export(Helpers::escape($file), true), ); } diff --git a/tests/PHPStan/Command/ErrorFormatter/BaselinePhpErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/BaselinePhpErrorFormatterTest.php index 4ba93f6805..e9590e9402 100644 --- a/tests/PHPStan/Command/ErrorFormatter/BaselinePhpErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/BaselinePhpErrorFormatterTest.php @@ -135,13 +135,13 @@ public function dataFormatErrors(): iterable \$ignoreErrors[] = [ 'message' => '#^Foo with same message, different identifier$#', 'identifier' => 'argument.byRef', - 'count' => 2, + 'count' => 1, 'path' => __DIR__ . '/Foo.php', ]; \$ignoreErrors[] = [ 'message' => '#^Foo with same message, different identifier$#', 'identifier' => 'argument.type', - 'count' => 2, + 'count' => 1, 'path' => __DIR__ . '/Foo.php', ]; From c8b7ea9e8f51c8bbc38dfa6b04f9a0172f5cfea0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 3 Oct 2024 17:11:05 +0200 Subject: [PATCH 347/508] Neon baseline - add identifier key --- phpstan-baseline.neon | 322 ++++++++++++++++++ .../BaselineNeonErrorFormatter.php | 59 +++- .../BaselineNeonErrorFormatterTest.php | 133 ++++++++ 3 files changed, 499 insertions(+), 15 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index b1010cff7b..22970c5201 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -2,1610 +2,1932 @@ parameters: ignoreErrors: - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php - message: "#^Method PHPStan\\\\Analyser\\\\AnalyserResultFinalizer\\:\\:finalize\\(\\) throws checked exception Throwable but it's missing from the PHPDoc @throws tag\\.$#" + identifier: missingType.checkedException count: 1 path: src/Analyser/AnalyserResultFinalizer.php - message: "#^Cannot assign offset 'realCount' to array\\|string\\.$#" + identifier: offsetAssign.dimType count: 1 path: src/Analyser/Ignore/IgnoredErrorHelperResult.php - message: "#^Casting to string something that's already string\\.$#" + identifier: cast.useless count: 3 path: src/Analyser/MutatingScope.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Analyser/MutatingScope.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Analyser/MutatingScope.php - message: "#^Only numeric types are allowed in pre\\-increment, float\\|int\\|string\\|null given\\.$#" + identifier: preInc.nonNumeric count: 1 path: src/Analyser/MutatingScope.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Analyser/NodeScopeResolver.php - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + identifier: argument.type count: 1 path: src/Analyser/NodeScopeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Analyser/TypeSpecifier.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 5 path: src/Analyser/TypeSpecifier.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Analyser/TypeSpecifier.php - message: "#^Template type TNodeType is declared as covariant, but occurs in contravariant position in parameter node of method PHPStan\\\\Collectors\\\\Collector\\:\\:processNode\\(\\)\\.$#" + identifier: generics.variance count: 1 path: src/Collectors/Collector.php - message: "#^Method PHPStan\\\\Collectors\\\\Registry\\:\\:__construct\\(\\) has parameter \\$collectors with generic interface PHPStan\\\\Collectors\\\\Collector but does not specify its types\\: TNodeType, TValue$#" + identifier: missingType.generics count: 1 path: src/Collectors/Registry.php - message: "#^Property PHPStan\\\\Collectors\\\\Registry\\:\\:\\$cache with generic interface PHPStan\\\\Collectors\\\\Collector does not specify its types\\: TNodeType, TValue$#" + identifier: missingType.generics count: 1 path: src/Collectors/Registry.php - message: "#^Property PHPStan\\\\Collectors\\\\Registry\\:\\:\\$collectors with generic interface PHPStan\\\\Collectors\\\\Collector does not specify its types\\: TNodeType, TValue$#" + identifier: missingType.generics count: 1 path: src/Collectors/Registry.php - message: "#^Anonymous function has an unused use \\$container\\.$#" + identifier: closure.unusedUse count: 1 path: src/Command/CommandHelper.php - message: "#^Parameter \\#1 \\$path of function dirname expects string, string\\|false given\\.$#" + identifier: argument.type count: 1 path: src/Command/CommandHelper.php - message: "#^Static property PHPStan\\\\Command\\\\CommandHelper\\:\\:\\$reservedMemory is never read, only written\\.$#" + identifier: property.onlyWritten count: 1 path: src/Command/CommandHelper.php - message: "#^Parameter \\#1 \\$headers \\(array\\\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$headers \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\StyleInterface\\:\\:table\\(\\)$#" + identifier: method.childParameterType count: 1 path: src/Command/ErrorsConsoleStyle.php - message: "#^Parameter \\#1 \\$headers \\(array\\\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$headers \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\SymfonyStyle\\:\\:table\\(\\)$#" + identifier: method.childParameterType count: 1 path: src/Command/ErrorsConsoleStyle.php - message: "#^Parameter \\#2 \\$rows \\(array\\\\>\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$rows \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\StyleInterface\\:\\:table\\(\\)$#" + identifier: method.childParameterType count: 1 path: src/Command/ErrorsConsoleStyle.php - message: "#^Parameter \\#2 \\$rows \\(array\\\\>\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$rows \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\SymfonyStyle\\:\\:table\\(\\)$#" + identifier: method.childParameterType count: 1 path: src/Command/ErrorsConsoleStyle.php - message: "#^Variable method call on Nette\\\\Schema\\\\Elements\\\\AnyOf\\|Nette\\\\Schema\\\\Elements\\\\Structure\\|Nette\\\\Schema\\\\Elements\\\\Type\\.$#" + identifier: method.dynamicName count: 1 path: src/DependencyInjection/ContainerFactory.php - message: "#^Variable static method call on Nette\\\\Schema\\\\Expect\\.$#" + identifier: staticMethod.dynamicName count: 1 path: src/DependencyInjection/ContainerFactory.php - message: "#^Fetching class constant PREVENT_MERGING of deprecated class Nette\\\\DI\\\\Config\\\\Helpers\\.$#" + identifier: classConstant.deprecatedClass count: 1 path: src/DependencyInjection/NeonAdapter.php - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - message: "#^Parameter \\#1 \\$path of function dirname expects string, string\\|false given\\.$#" + identifier: argument.type count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - message: "#^Variable method call on PHPStan\\\\Reflection\\\\ClassReflection\\.$#" + identifier: method.dynamicName count: 2 path: src/PhpDoc/PhpDocBlock.php - message: "#^Variable static method call on PHPStan\\\\PhpDoc\\\\PhpDocBlock\\.$#" + identifier: staticMethod.dynamicName count: 1 path: src/PhpDoc/PhpDocBlock.php - message: "#^Call to function method_exists\\(\\) with PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\PhpDocNode and 'getParamOutTypeTagV…' will always evaluate to true\\.$#" + identifier: function.alreadyNarrowedType count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - message: "#^Call to function method_exists\\(\\) with PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\PhpDocNode and 'getSelfOutTypeTagVa…' will always evaluate to true\\.$#" + identifier: function.alreadyNarrowedType count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - message: "#^Method PHPStan\\\\PhpDoc\\\\ResolvedPhpDocBlock\\:\\:getNameScope\\(\\) should return PHPStan\\\\Analyser\\\\NameScope but returns PHPStan\\\\Analyser\\\\NameScope\\|null\\.$#" + identifier: return.type count: 1 path: src/PhpDoc/ResolvedPhpDocBlock.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/PhpDoc/TypeNodeResolver.php - message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\Identifier\\\\Exception\\\\InvalidIdentifierName is never thrown in the try block\\.$#" + identifier: catch.neverThrown count: 3 path: src/Reflection/BetterReflection/BetterReflectionProvider.php - message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\NodeCompiler\\\\Exception\\\\UnableToCompileNode is never thrown in the try block\\.$#" + identifier: catch.neverThrown count: 1 path: src/Reflection/BetterReflection/BetterReflectionProvider.php - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - message: "#^Creating new ReflectionFunction is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + identifier: argument.type count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - message: "#^Method PHPStan\\\\Reflection\\\\BetterReflection\\\\SourceLocator\\\\FileReadTrapStreamWrapper\\:\\:invokeWithRealFileStreamWrapper\\(\\) has parameter \\$cb with no signature specified for callable\\.$#" + identifier: missingType.callable count: 1 path: src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" + identifier: argument.type count: 1 path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + identifier: argument.type count: 2 path: src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/ReflectionClassSourceLocator.php - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.php - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Reflection/ClassReflection.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Reflection/ClassReflection.php - message: "#^Method PHPStan\\\\Reflection\\\\ClassReflection\\:\\:getCacheKey\\(\\) should return string but returns string\\|null\\.$#" + identifier: return.type count: 1 path: src/Reflection/ClassReflection.php - message: "#^Binary operation \"&\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Binary operation \"\\*\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Binary operation \"\\+\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Binary operation \"\\-\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Binary operation \"\\^\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Binary operation \"\\|\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 22 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 10 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" + identifier: varTag.nativeType count: 1 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^PHPDoc tag @var with type float\\|int is not subtype of type int\\.$#" + identifier: varTag.type count: 4 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^PHPDoc tag @var with type float\\|int\\|null is not subtype of type int\\|null\\.$#" + identifier: varTag.type count: 6 path: src/Reflection/InitializerExprTypeResolver.php - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + identifier: phpstanApi.constructor count: 1 path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Api/NodeConnectingVisitorAttributesRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Classes/ImpossibleInstanceOfRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Classes/RequireExtendsRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Classes/RequireImplementsRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 6 path: src/Rules/Comparison/BooleanAndConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/BooleanNotConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 6 path: src/Rules/Comparison/BooleanOrConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/ConstantLooseComparisonRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/DoWhileLoopConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/ElseIfConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/IfConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Rules/Comparison/LogicalXorConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Rules/Comparison/MatchExpressionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/NumberComparisonOperatorsConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/TernaryOperatorConstantConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Comparison/WhileLoopAlwaysFalseConditionRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php - message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Rules/DirectRegistry.php - message: "#^Function class_parents\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Rules/DirectRegistry.php - message: "#^Method PHPStan\\\\Rules\\\\DirectRegistry\\:\\:__construct\\(\\) has parameter \\$rules with generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: src/Rules/DirectRegistry.php - message: "#^Property PHPStan\\\\Rules\\\\DirectRegistry\\:\\:\\$cache with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: src/Rules/DirectRegistry.php - message: "#^Property PHPStan\\\\Rules\\\\DirectRegistry\\:\\:\\$rules with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: src/Rules/DirectRegistry.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Generics/GenericAncestorsCheck.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Generics/TemplateTypeCheck.php - message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Rules/LazyRegistry.php - message: "#^Function class_parents\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + identifier: phpstanApi.runtimeReflection count: 1 path: src/Rules/LazyRegistry.php - message: "#^Method PHPStan\\\\Rules\\\\LazyRegistry\\:\\:getRulesFromContainer\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: src/Rules/LazyRegistry.php - message: "#^Property PHPStan\\\\Rules\\\\LazyRegistry\\:\\:\\$cache with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: src/Rules/LazyRegistry.php - message: "#^Property PHPStan\\\\Rules\\\\LazyRegistry\\:\\:\\$rules with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: src/Rules/LazyRegistry.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Methods/StaticMethodCallCheck.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/PhpDoc/RequireExtendsCheck.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/PhpDoc/VarTagTypeRuleHelper.php - message: "#^Access to an undefined property T of PHPStan\\\\Rules\\\\RuleError\\:\\:\\$tip\\.$#" + identifier: property.notFound count: 2 path: src/Rules/RuleErrorBuilder.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/RuleLevelHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/UnusedFunctionParametersCheck.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Variables/CompactVariablesRule.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Variables/CompactVariablesRule.php - message: "#^Anonymous function has an unused use \\$container\\.$#" + identifier: closure.unusedUse count: 1 path: src/Testing/PHPStanTestCase.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Testing/TypeInferenceTestCase.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryArrayListType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryLiteralStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryLowercaseStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNonEmptyStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNonEmptyStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNonFalsyStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNumericStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNumericStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasMethodType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasOffsetType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Accessory/HasOffsetValueType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Accessory/HasOffsetValueType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasOffsetValueType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasPropertyType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/NonEmptyArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/OversizedArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/ArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/ArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/ArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/ArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/BooleanType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/BooleanType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/CallableType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/CallableType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/ClosureType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Constant/ConstantArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 7 path: src/Type/Constant/ConstantArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Constant/ConstantArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Constant/ConstantArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Type is always PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType\\|PHPStan\\\\Type\\\\Constant\\\\ConstantStringType but it's error\\-prone and dangerous\\.$#" + identifier: phpstanApi.varTagAssumption count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" + identifier: varTag.nativeType count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - message: "#^PHPDoc tag @var with type float\\|int is not subtype of type int\\.$#" + identifier: varTag.type count: 1 path: src/Type/Constant/ConstantArrayTypeBuilder.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantBooleanType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantBooleanType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Constant/ConstantBooleanType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantFloatType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantFloatType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantIntegerType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantIntegerType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantStringType.php - message: "#^PHPDoc tag @var with type int\\|string is not subtype of type string\\.$#" + identifier: varTag.type count: 1 path: src/Type/Constant/ConstantStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/OversizedArrayBuilder.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Enum/EnumCaseObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/ExponentiateHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/FileTypeMapper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/FloatType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/GenericClassStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Generic/GenericClassStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Generic/GenericClassStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/GenericClassStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Generic/GenericClassStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/GenericObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/GenericObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/GenericObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Generic/GenericObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateBenevolentUnionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateBooleanType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateConstantArrayType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateConstantIntegerType.php - message: "#^Method PHPStan\\\\Type\\\\Generic\\\\TemplateConstantIntegerType\\:\\:toPhpDocNode\\(\\) should return PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\ConstTypeNode but returns PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\IdentifierTypeNode\\.$#" + identifier: return.type count: 1 path: src/Type/Generic/TemplateConstantIntegerType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateConstantStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateFloatType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateGenericObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateIntegerType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateIntersectionType.php - message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\IntersectionType will always evaluate to false\\.$#" + identifier: instanceof.alwaysFalse count: 2 path: src/Type/Generic/TemplateIntersectionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateKeyOfType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Generic/TemplateMixedType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateObjectShapeType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateObjectWithoutClassType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Generic/TemplateStrictMixedType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateStringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateUnionType.php - message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\UnionType will always evaluate to false\\.$#" + identifier: instanceof.alwaysFalse count: 2 path: src/Type/Generic/TemplateUnionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/IntegerRangeType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/IntegerRangeType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/IntegerRangeType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/IntegerType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/IntersectionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/IntersectionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/IntersectionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/IntersectionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/IterableType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/IterableType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/NullType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/NullType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/ObjectShapeType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/ObjectShapeType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/ObjectShapeType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/ObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/ObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 6 path: src/Type/ObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/ObjectType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/ObjectWithoutClassType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/ObjectWithoutClassType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 16 path: src/Type/Php/BcMathStringOrNullReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/CompactFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/CompactFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/DefineConstantTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/DefinedConstantTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/DsMapDynamicReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/FilterFunctionReturnTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/FilterFunctionReturnTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ImplodeFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/IsAFunctionTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/LtrimFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/MbStrlenFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/MethodExistsTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/PropertyExistsTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/RangeFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php - message: "#^Cannot access offset int\\<0, max\\> on \\(float\\|int\\)\\.$#" + identifier: offsetAccess.nonOffsetAccessible count: 2 path: src/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/StrRepeatFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/StrlenFunctionReturnTypeExtension.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/StaticType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/StaticType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/StringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/StringType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 5 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 14 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 5 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 8 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - message: "#^Instanceof between PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType and PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType will always evaluate to true\\.$#" + identifier: instanceof.alwaysTrue count: 1 path: src/Type/TypeCombinator.php - message: "#^Result of \\|\\| is always true\\.$#" + identifier: booleanOr.alwaysTrue count: 1 path: src/Type/TypeCombinator.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/TypeUtils.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/TypeUtils.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/TypehintHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/TypehintHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypehintHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/UnionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 1 path: src/Type/UnionType.php - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Type is always PHPStan\\\\Type\\\\BooleanType but it's error\\-prone and dangerous\\.$#" + identifier: phpstanApi.varTagAssumption count: 1 path: src/Type/UnionType.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + identifier: phpstanApi.instanceofType count: 3 path: src/Type/UnionTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 4 path: src/Type/UnionTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - message: "#^Doing instanceof PHPStan\\\\Type\\\\VoidType is error\\-prone and deprecated\\. Use Type\\:\\:isVoid\\(\\) instead\\.$#" + identifier: phpstanApi.instanceofType count: 2 path: src/Type/VoidType.php - message: "#^Unreachable statement \\- code above always terminates\\.$#" + identifier: deadCode.unreachable count: 1 path: tests/PHPStan/Analyser/AnalyserTest.php - message: "#^Class PHPStan\\\\Analyser\\\\AnonymousClassNameRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + identifier: missingType.generics count: 1 path: tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php - message: "#^Method PHPStan\\\\Analyser\\\\AnonymousClassNameRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php - message: "#^Class PHPStan\\\\Analyser\\\\EvaluationOrderTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + identifier: missingType.generics count: 1 path: tests/PHPStan/Analyser/EvaluationOrderTest.php - message: "#^Method PHPStan\\\\Analyser\\\\EvaluationOrderTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: tests/PHPStan/Analyser/EvaluationOrderTest.php - message: "#^Constant SOME_CONSTANT_IN_AUTOLOAD_FILE not found\\.$#" + identifier: constant.notFound count: 1 path: tests/PHPStan/Command/AnalyseCommandTest.php - message: "#^Class PHPStan\\\\Node\\\\FileNodeTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + identifier: missingType.generics count: 1 path: tests/PHPStan/Node/FileNodeTest.php - message: "#^Method PHPStan\\\\Node\\\\FileNodeTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + identifier: missingType.generics count: 1 path: tests/PHPStan/Node/FileNodeTest.php - message: "#^PHPDoc tag @var with type string is not subtype of type class\\-string\\.$#" + identifier: varTag.type count: 1 path: tests/PHPStan/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorTest.php - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + identifier: phpstanApi.constructor count: 1 path: tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + identifier: phpstanApi.constructor count: 1 path: tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" + identifier: phpstanApi.varTagAssumption count: 1 path: tests/PHPStan/Type/IterableTypeTest.php diff --git a/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php b/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php index b6dd1e2c2f..ac02e1f9e1 100644 --- a/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php +++ b/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php @@ -9,6 +9,7 @@ use PHPStan\Command\Output; use PHPStan\File\RelativePathHelper; use PHPStan\ShouldNotHappenException; +use function count; use function ksort; use function preg_quote; use function substr; @@ -37,29 +38,57 @@ public function formatErrors( if (!$fileSpecificError->canBeIgnored()) { continue; } - $fileErrors[$this->relativePathHelper->getRelativePath($fileSpecificError->getFilePath())][] = $fileSpecificError->getMessage(); + $fileErrors[$this->relativePathHelper->getRelativePath($fileSpecificError->getFilePath())][] = $fileSpecificError; } ksort($fileErrors, SORT_STRING); $errorsToOutput = []; - foreach ($fileErrors as $file => $errorMessages) { - $fileErrorsCounts = []; - foreach ($errorMessages as $errorMessage) { - if (!isset($fileErrorsCounts[$errorMessage])) { - $fileErrorsCounts[$errorMessage] = 1; + foreach ($fileErrors as $file => $errors) { + $fileErrorsByMessage = []; + foreach ($errors as $error) { + $errorMessage = $error->getMessage(); + $identifier = $error->getIdentifier(); + if (!isset($fileErrorsByMessage[$errorMessage])) { + $fileErrorsByMessage[$errorMessage] = [ + 1, + $identifier !== null ? [$identifier => 1] : [], + ]; continue; } - $fileErrorsCounts[$errorMessage]++; + $fileErrorsByMessage[$errorMessage][0]++; + + if ($identifier === null) { + continue; + } + + if (!isset($fileErrorsByMessage[$errorMessage][1][$identifier])) { + $fileErrorsByMessage[$errorMessage][1][$identifier] = 1; + continue; + } + + $fileErrorsByMessage[$errorMessage][1][$identifier]++; } - ksort($fileErrorsCounts, SORT_STRING); - - foreach ($fileErrorsCounts as $message => $count) { - $errorsToOutput[] = [ - 'message' => Helpers::escape('#^' . preg_quote($message, '#') . '$#'), - 'count' => $count, - 'path' => Helpers::escape($file), - ]; + ksort($fileErrorsByMessage, SORT_STRING); + + foreach ($fileErrorsByMessage as $message => [$totalCount, $identifiers]) { + ksort($identifiers, SORT_STRING); + if (count($identifiers) > 0) { + foreach ($identifiers as $identifier => $identifierCount) { + $errorsToOutput[] = [ + 'message' => Helpers::escape('#^' . preg_quote($message, '#') . '$#'), + 'identifier' => $identifier, + 'count' => $identifierCount, + 'path' => Helpers::escape($file), + ]; + } + } else { + $errorsToOutput[] = [ + 'message' => Helpers::escape('#^' . preg_quote($message, '#') . '$#'), + 'count' => $totalCount, + 'path' => Helpers::escape($file), + ]; + } } } diff --git a/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php index ac972f04a9..ace5a21c5b 100644 --- a/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php @@ -448,4 +448,137 @@ public function testEndOfFileNewlines( Assert::assertNotSame("\n", substr($content, -($expectedNewlinesCount + 1), 1)); } + public function dataFormatErrorsWithIdentifiers(): iterable + { + yield [ + [ + new Error( + 'Foo', + __DIR__ . '/Foo.php', + 5, + ), + new Error( + 'Foo', + __DIR__ . '/Foo.php', + 5, + ), + (new Error( + 'Foo with identifier', + __DIR__ . '/Foo.php', + 5, + ))->withIdentifier('argument.type'), + (new Error( + 'Foo with identifier', + __DIR__ . '/Foo.php', + 6, + ))->withIdentifier('argument.type'), + ], + [ + 'parameters' => [ + 'ignoreErrors' => [ + [ + 'message' => '#^Foo$#', + 'count' => 2, + 'path' => 'Foo.php', + ], + [ + 'message' => '#^Foo with identifier$#', + 'identifier' => 'argument.type', + 'count' => 2, + 'path' => 'Foo.php', + ], + ], + ], + ], + ]; + + yield [ + [ + new Error( + 'Foo', + __DIR__ . '/Foo.php', + 5, + ), + new Error( + 'Foo', + __DIR__ . '/Foo.php', + 5, + ), + (new Error( + 'Foo with same message, different identifier', + __DIR__ . '/Foo.php', + 5, + ))->withIdentifier('argument.type'), + (new Error( + 'Foo with same message, different identifier', + __DIR__ . '/Foo.php', + 6, + ))->withIdentifier('argument.byRef'), + (new Error( + 'Foo with another message', + __DIR__ . '/Foo.php', + 5, + ))->withIdentifier('argument.type'), + ], + [ + 'parameters' => [ + 'ignoreErrors' => [ + [ + 'message' => '#^Foo$#', + 'count' => 2, + 'path' => 'Foo.php', + ], + [ + 'message' => '#^Foo with another message$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => 'Foo.php', + ], + [ + 'message' => '#^Foo with same message, different identifier$#', + 'identifier' => 'argument.byRef', + 'count' => 1, + 'path' => 'Foo.php', + ], + [ + 'message' => '#^Foo with same message, different identifier$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => 'Foo.php', + ], + ], + ], + ], + ]; + } + + /** + * @dataProvider dataFormatErrorsWithIdentifiers + * @param list $errors + * @param mixed[] $expectedOutput + */ + public function testFormatErrorsWithIdentifiers(array $errors, array $expectedOutput): void + { + $formatter = new BaselineNeonErrorFormatter(new SimpleRelativePathHelper(__DIR__)); + $formatter->formatErrors( + new AnalysisResult( + $errors, + [], + [], + [], + [], + false, + null, + true, + 0, + true, + [], + ), + $this->getOutput(), + '', + ); + + $this->assertSame($expectedOutput, Neon::decode($this->getOutputContent())); + } + } From c0a430c3189610cb3e62b38d097ac751fb7cd3d5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 09:23:06 +0200 Subject: [PATCH 348/508] Upgrading note --- UPGRADING.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 2ab208b5da..af436a4ec1 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -36,6 +36,12 @@ After changing your `composer.json`, run `composer update 'phpstan/*' -W`. It's up to you whether you go through the new reported errors or if you just put them all to the [baseline](https://phpstan.org/user-guide/baseline) ;) Everyone who's on PHPStan 1.12 should be able to upgrade to PHPStan 2.0. +### Noteworthy changes to code analysis + +* [**Enhancements in handling parameters passed by reference**](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) +* [**Validate inline PHPDoc `@var` tag type**](https://phpstan.org/blog/phpstan-1-10-comes-with-lie-detector#validate-inline-phpdoc-%40var-tag-type) +* **Always `true` conditions always reported**: previously reported only with phpstan-strict-rules, this is now always reported. + ### Removed option `checkMissingIterableValueType` It's strongly recommended to add the missing array typehints. From f1853a8df867368015d81d5d571a394f04afd922 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 09:26:44 +0200 Subject: [PATCH 349/508] Upgrading note --- UPGRADING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPGRADING.md b/UPGRADING.md index af436a4ec1..d23ee8f530 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -40,6 +40,7 @@ It's up to you whether you go through the new reported errors or if you just put * [**Enhancements in handling parameters passed by reference**](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [**Validate inline PHPDoc `@var` tag type**](https://phpstan.org/blog/phpstan-1-10-comes-with-lie-detector#validate-inline-phpdoc-%40var-tag-type) +* [**List type enforced**](https://phpstan.org/blog/phpstan-1-9-0-with-phpdoc-asserts-list-type#list-type) * **Always `true` conditions always reported**: previously reported only with phpstan-strict-rules, this is now always reported. ### Removed option `checkMissingIterableValueType` From d598545fe96c5e6ab26e36e2ee6afc5760126ec3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 09:46:51 +0200 Subject: [PATCH 350/508] Move upgrading notes --- UPGRADING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index d23ee8f530..68769233aa 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -113,6 +113,9 @@ Tags without a PHP version are no longer published - `nightly`, `2`, `latest` ar * Removed unused config parameter `memoryLimitFile` * Removed unused feature toggle `disableRuntimeReflectionProvider` * Removed unused config parameter `staticReflectionClassNamePatterns` +* Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead +* Remove `tempResultCachePath` config parameter, use `resultCachePath` instead +* `additionalConfigFiles` config parameter must be a list ## Upgrading guide for extension developers @@ -305,11 +308,8 @@ Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::i * `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool` * Remove `FunctionReflection::isFinal()` * [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html) -* `additionalConfigFiles` config parameter must be a list * Remove `__set_state()` on objects that should not be serialized in cache * Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts `string` -* Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead -* Remove `tempResultCachePath` config parameter, use `resultCachePath` instead * `LevelsTestCase::dataTopics()` data provider made static * `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint * Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) From bf19914cac1682d0eab8bf65a874ba368522311c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 09:51:05 +0200 Subject: [PATCH 351/508] Added missing rules to StubValidator --- src/PhpDoc/StubValidator.php | 20 ++++++++++++++++++++ stubs/ReflectionClass.stub | 5 ----- stubs/ext-ds.stub | 10 ---------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/PhpDoc/StubValidator.php b/src/PhpDoc/StubValidator.php index a0539b7168..39ebcf09b3 100644 --- a/src/PhpDoc/StubValidator.php +++ b/src/PhpDoc/StubValidator.php @@ -47,6 +47,8 @@ use PHPStan\Rules\Generics\ClassAncestorsRule; use PHPStan\Rules\Generics\ClassTemplateTypeRule; use PHPStan\Rules\Generics\CrossCheckInterfacesHelper; +use PHPStan\Rules\Generics\EnumAncestorsRule; +use PHPStan\Rules\Generics\EnumTemplateTypeRule; use PHPStan\Rules\Generics\FunctionSignatureVarianceRule; use PHPStan\Rules\Generics\FunctionTemplateTypeRule; use PHPStan\Rules\Generics\GenericAncestorsCheck; @@ -58,8 +60,10 @@ use PHPStan\Rules\Generics\MethodTagTemplateTypeRule; use PHPStan\Rules\Generics\MethodTagTemplateTypeTraitRule; use PHPStan\Rules\Generics\MethodTemplateTypeRule; +use PHPStan\Rules\Generics\PropertyVarianceRule; use PHPStan\Rules\Generics\TemplateTypeCheck; use PHPStan\Rules\Generics\TraitTemplateTypeRule; +use PHPStan\Rules\Generics\UsedTraitsRule; use PHPStan\Rules\Generics\VarianceCheck; use PHPStan\Rules\Methods\ExistingClassesInTypehintsRule; use PHPStan\Rules\Methods\MethodParameterComparisonHelper; @@ -69,6 +73,10 @@ use PHPStan\Rules\Methods\MissingMethodSelfOutTypeRule; use PHPStan\Rules\Methods\OverridingMethodRule; use PHPStan\Rules\MissingTypehintCheck; +use PHPStan\Rules\PhpDoc\AssertRuleHelper; +use PHPStan\Rules\PhpDoc\ConditionalReturnTypeRuleHelper; +use PHPStan\Rules\PhpDoc\FunctionAssertRule; +use PHPStan\Rules\PhpDoc\FunctionConditionalReturnTypeRule; use PHPStan\Rules\PhpDoc\GenericCallableRuleHelper; use PHPStan\Rules\PhpDoc\IncompatibleClassConstantPhpDocTypeRule; use PHPStan\Rules\PhpDoc\IncompatibleParamImmediatelyInvokedCallableRule; @@ -78,6 +86,8 @@ use PHPStan\Rules\PhpDoc\InvalidPhpDocTagValueRule; use PHPStan\Rules\PhpDoc\InvalidPHPStanDocTagRule; use PHPStan\Rules\PhpDoc\InvalidThrowsPhpDocValueRule; +use PHPStan\Rules\PhpDoc\MethodAssertRule; +use PHPStan\Rules\PhpDoc\MethodConditionalReturnTypeRule; use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper; use PHPStan\Rules\Properties\ExistingClassesInPropertiesRule; use PHPStan\Rules\Properties\MissingPropertyTypehintRule; @@ -186,6 +196,8 @@ private function getRuleRegistry(Container $container): RuleRegistry $propertyTagCheck = new PropertyTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true); $reflector = $container->getService('stubReflector'); $relativePathHelper = $container->getService('simpleRelativePathHelper'); + $assertRuleHelper = $container->getByType(AssertRuleHelper::class); + $conditionalReturnTypeRuleHelper = $container->getByType(ConditionalReturnTypeRuleHelper::class); $rules = [ // level 0 @@ -237,6 +249,14 @@ private function getRuleRegistry(Container $container): RuleRegistry new PropertyTagRule($propertyTagCheck), new PropertyTagTraitRule($propertyTagCheck, $reflectionProvider), new PropertyTagTraitUseRule($propertyTagCheck), + new EnumAncestorsRule($genericAncestorsCheck, $crossCheckInterfacesHelper), + new EnumTemplateTypeRule(), + new PropertyVarianceRule($varianceCheck), + new UsedTraitsRule($fileTypeMapper, $genericAncestorsCheck), + new FunctionAssertRule($assertRuleHelper), + new MethodAssertRule($assertRuleHelper), + new FunctionConditionalReturnTypeRule($conditionalReturnTypeRuleHelper), + new MethodConditionalReturnTypeRule($conditionalReturnTypeRuleHelper), // level 6 new MissingFunctionParameterTypehintRule($missingTypehintCheck), diff --git a/stubs/ReflectionClass.stub b/stubs/ReflectionClass.stub index f47d5d89a1..3f6ce4bddf 100644 --- a/stubs/ReflectionClass.stub +++ b/stubs/ReflectionClass.stub @@ -6,11 +6,6 @@ class ReflectionClass { - /** - * @var class-string - */ - public $name; - /** * @param T|class-string $argument * @throws ReflectionException diff --git a/stubs/ext-ds.stub b/stubs/ext-ds.stub index ba72a0d584..f0b45a47b7 100644 --- a/stubs/ext-ds.stub +++ b/stubs/ext-ds.stub @@ -353,16 +353,6 @@ final class Map implements Collection, ArrayAccess */ final class Pair implements JsonSerializable { - /** - * @var TKey - */ - public $key; - - /** - * @var TValue - */ - public $value; - /** * @param TKey $key * @param TValue $value From ce3c89360b10a7927b6c95f722fb4608ec08282a Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Fri, 27 Sep 2024 12:42:28 +0200 Subject: [PATCH 352/508] Report precise offsets in errors Fixes phpstan/phpstan#11760 --- src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php | 5 +++-- src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php | 3 ++- .../Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php index 8f78c9023b..5b81f82f1a 100644 --- a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php +++ b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchCheck.php @@ -14,6 +14,7 @@ use PHPStan\Type\TypeUtils; use PHPStan\Type\UnionType; use PHPStan\Type\VerbosityLevel; +use function count; use function sprintf; final class NonexistentOffsetInArrayDimFetchCheck @@ -55,7 +56,7 @@ public function check( if ($type->hasOffsetValueType($dimType)->no()) { return [ - RuleErrorBuilder::message(sprintf('Offset %s does not exist on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value()))) + RuleErrorBuilder::message(sprintf('Offset %s does not exist on %s.', $dimType->describe(count($dimType->getConstantStrings()) > 0 ? VerbosityLevel::precise() : VerbosityLevel::value()), $type->describe(VerbosityLevel::value()))) ->identifier('offsetAccess.notFound') ->build(), ]; @@ -104,7 +105,7 @@ public function check( if ($report) { return [ - RuleErrorBuilder::message(sprintf('Offset %s might not exist on %s.', $dimType->describe(VerbosityLevel::value()), $type->describe(VerbosityLevel::value()))) + RuleErrorBuilder::message(sprintf('Offset %s might not exist on %s.', $dimType->describe(count($dimType->getConstantStrings()) > 0 ? VerbosityLevel::precise() : VerbosityLevel::value()), $type->describe(VerbosityLevel::value()))) ->identifier('offsetAccess.notFound') ->build(), ]; diff --git a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php index 3cb1b93328..d3ef021189 100644 --- a/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php +++ b/src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php @@ -12,6 +12,7 @@ use PHPStan\Type\ErrorType; use PHPStan\Type\Type; use PHPStan\Type\VerbosityLevel; +use function count; use function sprintf; /** @@ -74,7 +75,7 @@ public function processNode(Node $node, Scope $scope): array return [ RuleErrorBuilder::message(sprintf( 'Cannot access offset %s on %s.', - $dimType->describe(VerbosityLevel::value()), + $dimType->describe(count($dimType->getConstantStrings()) > 0 ? VerbosityLevel::precise() : VerbosityLevel::value()), $isOffsetAccessibleType->describe(VerbosityLevel::value()), ))->identifier('offsetAccess.nonOffsetAccessible')->build(), ]; diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index 3862059b02..b45c120089 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -162,7 +162,7 @@ public function testRule(): void 443, ], [ - 'Offset \'feature_pretty…\' might not exist on array{version: non-falsy-string, commit: string|null, pretty_version: string|null, feature_version: non-falsy-string, feature_pretty_version?: string|null}.', + 'Offset \'feature_pretty_version\' might not exist on array{version: non-falsy-string, commit: string|null, pretty_version: string|null, feature_version: non-falsy-string, feature_pretty_version?: string|null}.', 504, ], [ From 8f55339fa525386da6e4182156d342951e14b990 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 11:04:04 +0200 Subject: [PATCH 353/508] Fix build --- conf/config.neon | 1 - src/Rules/PhpDoc/AssertRuleHelper.php | 29 +++++++------------ .../Rules/PhpDoc/FunctionAssertRuleTest.php | 3 +- .../Rules/PhpDoc/MethodAssertRuleTest.php | 3 +- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index 7b84bf2705..6a8f4d6897 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -975,7 +975,6 @@ services: arguments: checkMissingTypehints: %checkMissingTypehints% checkClassCaseSensitivity: %checkClassCaseSensitivity% - absentTypeChecks: %featureToggles.absentTypeChecks% - class: PHPStan\Rules\PhpDoc\UnresolvableTypeHelper diff --git a/src/Rules/PhpDoc/AssertRuleHelper.php b/src/Rules/PhpDoc/AssertRuleHelper.php index 073d131922..091da8aa2a 100644 --- a/src/Rules/PhpDoc/AssertRuleHelper.php +++ b/src/Rules/PhpDoc/AssertRuleHelper.php @@ -37,7 +37,6 @@ public function __construct( private ClassNameCheck $classCheck, private MissingTypehintCheck $missingTypehintCheck, private GenericObjectTypeCheck $genericObjectTypeCheck, - private bool $absentTypeChecks, private bool $checkClassCaseSensitivity, private bool $checkMissingTypehints, ) @@ -83,11 +82,9 @@ public function check( $assertedExprType = $this->initializerExprTypeResolver->getType($assertedExpr, $context); $assertedExprString = $assert->getParameter()->describe(); if ($assertedExprType instanceof ErrorType) { - if ($this->absentTypeChecks) { - $errors[] = RuleErrorBuilder::message(sprintf('Assert references unknown %s.', $assertedExprString)) - ->identifier('assert.unknownExpr') - ->build(); - } + $errors[] = RuleErrorBuilder::message(sprintf('Assert references unknown %s.', $assertedExprString)) + ->identifier('assert.unknownExpr') + ->build(); continue; } @@ -99,15 +96,13 @@ public function check( AssertTag::IF_FALSE => '@phpstan-assert-if-false', ][$assert->getIf()]; - if ($this->absentTypeChecks) { - if ($this->unresolvableTypeHelper->containsUnresolvableType($assertedType)) { - $errors[] = RuleErrorBuilder::message(sprintf( - 'PHPDoc tag %s for %s contains unresolvable type.', - $tagName, - $assertedExprString, - ))->identifier('assert.unresolvableType')->build(); - continue; - } + if ($this->unresolvableTypeHelper->containsUnresolvableType($assertedType)) { + $errors[] = RuleErrorBuilder::message(sprintf( + 'PHPDoc tag %s for %s contains unresolvable type.', + $tagName, + $assertedExprString, + ))->identifier('assert.unresolvableType')->build(); + continue; } $isSuperType = $assertedType->isSuperTypeOf($assertedExprType); @@ -131,10 +126,6 @@ public function check( } } - if (!$this->absentTypeChecks) { - continue; - } - foreach ($assertedType->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = RuleErrorBuilder::message(sprintf( diff --git a/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php b/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php index 7c63ae9d67..72c49cc286 100644 --- a/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php @@ -26,11 +26,10 @@ protected function getRule(): Rule $reflectionProvider, new UnresolvableTypeHelper(), new ClassNameCheck(new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer())), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, []), new GenericObjectTypeCheck(), true, true, - true, )); } diff --git a/tests/PHPStan/Rules/PhpDoc/MethodAssertRuleTest.php b/tests/PHPStan/Rules/PhpDoc/MethodAssertRuleTest.php index 84474ea49a..c038a01891 100644 --- a/tests/PHPStan/Rules/PhpDoc/MethodAssertRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/MethodAssertRuleTest.php @@ -26,11 +26,10 @@ protected function getRule(): Rule $reflectionProvider, new UnresolvableTypeHelper(), new ClassNameCheck(new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer())), - new MissingTypehintCheck(true, true, true, true, []), + new MissingTypehintCheck(true, []), new GenericObjectTypeCheck(), true, true, - true, )); } From efcf36898f0bb8eb5d8ab7268637b9c5678b2a6e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 11:08:43 +0200 Subject: [PATCH 354/508] Update changelog --- UPGRADING.md | 2 -- changelog-2.0.md | 2 -- 2 files changed, 4 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 68769233aa..57adbd1012 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,5 +1,3 @@ -This document is a work in progress. - Upgrading from PHPStan 1.x to 2.0 ================================= diff --git a/changelog-2.0.md b/changelog-2.0.md index 84559ebb67..2a7a46631a 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -1,5 +1,3 @@ -This document is a work in progress. - When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](https://github.com/phpstan/phpstan/releases) + a separate [UPGRADING](./UPGRADING.md) document. Major new features 🚀 From 40c4505f00fc2dfad604c238497aa98b03db7fa8 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 11:43:24 +0200 Subject: [PATCH 355/508] Finish changelog --- changelog-2.0.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/changelog-2.0.md b/changelog-2.0.md index 2a7a46631a..f0abba38de 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -19,6 +19,7 @@ Major new features 🚀 * Always report always true conditions, except for last elseif and match arm (https://github.com/phpstan/phpstan-src/commit/565fb0f6da9cdc58e8686598015561a848693972) * Remove "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule * Because "always true" is always reported, these are no longer needed +* New option: `polluteScopeWithBlock` (defaults to `true`, `false` in `phpstan-strict-rules`) (https://github.com/phpstan/phpstan-src/commit/946cf180c960930c2c42075d0f28ff9090507272) * Checking truthiness of `@phpstan-pure` above functions and methods * Check `new`/function call/method call/static method call on a separate line without any side effects even without `@phpstan-pure` PHPDoc tag on the declaration side * https://github.com/phpstan/phpstan-src/commit/281a87d1ab61809076ecfa6dfc2cc86e3babe235 @@ -76,6 +77,11 @@ Major new features 🚀 Improvements 🔧 ===================== +* TableErrorFormatter - always output identifiers (https://github.com/phpstan/phpstan-src/commit/fc66c24113e9fe88c3155703224eb03768846fdd) +* Config option `exceptions.check.tooWideThrowType` made true by default (https://github.com/phpstan/phpstan-src/commit/1b1da3e2ce3acf10dde03d9656638cda4f7389a4) +* Use `implicitThrows` to only look for explicit throw points in too-wide `@throws` rules when set to `false` (https://github.com/phpstan/phpstan-src/commit/a0e688c1d1e4c5e82f989b26485eb9162f47aa97) +* Rules about tooWideThrowType moved to level 4 (https://github.com/phpstan/phpstan-src/commit/d7798d7f2c47f426efe91c566e6cafd5a4e2410c) +* Both .php and .neon baselines now include error identifiers (https://github.com/phpstan/phpstan-src/commit/f38addda2b151b6e41a746a37659c0bbe9e2293b, https://github.com/phpstan/phpstan-src/commit/c8b7ea9e8f51c8bbc38dfa6b04f9a0172f5cfea0) * PHPDoc parser: Require whitespace before description with limited start tokens (https://github.com/phpstan/phpdoc-parser/pull/128), https://github.com/phpstan/phpdoc-parser/issues/125, thanks @rvanvelzen! * Unescape strings in PHPDoc parser (https://github.com/phpstan/phpstan-src/commit/97786ed8376b478ec541ea9df1c450c1fbfe7461) * PHPDoc parser: add config for lines in its AST & enable ignoring errors within PHPDocs ([#2807](https://github.com/phpstan/phpstan-src/pull/2807)), thanks @janedbal! @@ -118,6 +124,14 @@ Improvements 🔧 * Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) * InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) * CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) +* ContainerFactory - always check duplicate files (https://github.com/phpstan/phpstan-src/commit/939a715a0636ed05752659dbe7646c1f1a574765) +* Display parent class name for anonymous class like native PHP does ([#3362](https://github.com/phpstan/phpstan-src/pull/3362)), thanks @mvorisek! +* Always report static property fetch in `isset()`, not just on PHP 8.2+ ([#3476](https://github.com/phpstan/phpstan-src/pull/3476)), thanks @ondrejmirtes! +* Revert "Dumb down parameter types in some recently added stubs" (https://github.com/phpstan/phpstan-src/commit/950a491485c46068074ca3f4f6dc5b970d41465a) +* Do not apply heuristics of `Collection<...>|Foo[]` being resolved to Collection of Foo (https://github.com/phpstan/phpstan-src/commit/fff8f095988a66f298aa4037fe8e6ba98266063c) +* Collected PHP errors cannot be ignored (https://github.com/phpstan/phpstan-src/commit/1d3f4313955dc6fa5c6ce60fa58afe765964e5b0) +* Added missing rules to StubValidator (https://github.com/phpstan/phpstan-src/commit/bf19914cac1682d0eab8bf65a874ba368522311c) +* Report precise offsets in errors ([#3504](https://github.com/phpstan/phpstan-src/pull/3504)), thanks @ruudk! Bugfixes 🐛 @@ -150,5 +164,31 @@ Function signature fixes 🤖 * Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3!* Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! * Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! + Internals 🔍 ===================== + +* Tool to make optional parameters required across the codebase (https://github.com/phpstan/phpstan-src/commit/7e366e08f96e2e4095b3f02b5487e8f9531f37bf) +* A few more MutatingScope method parameters made required (https://github.com/phpstan/phpstan-src/commit/2c4c0cde75e637ac323e81def57d4a2ace952429) +* CommandHelper::begin() parameters made required (https://github.com/phpstan/phpstan-src/commit/f17cf9ec43111cb29dd50d620fb6259c0ab0d373) +* MethodTag - constructor parameter `$templateTags` is required (https://github.com/phpstan/phpstan-src/commit/5b58f83e6d8b5044d742caed9729d00178c4a9de) +* InitializerExprTypeResolver - constructor parameter `$usePathConstantsAsConstantString` made required (https://github.com/phpstan/phpstan-src/commit/f88d9ba7f56ef6c3b783aee1c909a3422c0ef3c3) +* `PhpMethodReflectionFactory::create()` - all parameters are required (https://github.com/phpstan/phpstan-src/commit/8bfbf8f254a68e4f1b15419eb950ea677fc2916e) +* FunctionCallParametersCheck - parameters `$nodeType` and `$acceptsNamedArguments` made required (https://github.com/phpstan/phpstan-src/commit/493752737c32eb878de4dfb91817761b952348e4) +* MethodParameterComparisonHelper - parameter `$ignorable` of `compare()` method made required (https://github.com/phpstan/phpstan-src/commit/f85a500288b0b8ef9a19d405c0e3d99ab57ce797) +* Parameter `$dateTimeClass` of DateTimeModifyReturnTypeExtension constructor made required (https://github.com/phpstan/phpstan-src/commit/a8cd423e842deaa7d924580665207a4b1a373115) +* NativeFunctionReflection construct parameters made required (https://github.com/phpstan/phpstan-src/commit/64ff598cd42268d2178d02efd208afe637060978) +* Cover AccessoryArrayListType constructor with BC promise (https://github.com/phpstan/phpstan-src/commit/51de9032c6e98bff2d6eb0e5b7295720ec0276b9) +* Add `PhpVersion` parameter to various `Type` methods ([#3478](https://github.com/phpstan/phpstan-src/pull/3478)), thanks @VincentLanglet! +* Move ContainerDynamicReturnTypeExtension to build/PHPStan (https://github.com/phpstan/phpstan-src/commit/5651bec661582b2d62de1b4ae9d5f27e69e3c524) +* Renamed NewOptimizedDirectorySourceLocator to OptimizedDirectorySourceLocator (https://github.com/phpstan/phpstan-src/commit/db02a30ca11c7b9839c30e0321ed403dd14f6c73) +* Remove unneded abstraction (https://github.com/phpstan/phpstan-src/commit/f302c9069274afa63ec1b4f313ca72340699e9d8) +* Introduce native return types thanks to PHP 7.4 return type covariance (https://github.com/phpstan/phpstan-src/commit/392f090066bfc9946b4ad524ffecf3d420c23114) +* ReadWritePropertiesExtension - use ExtendedPropertyReflection in parameter type (https://github.com/phpstan/phpstan-src/commit/f0a629685de2202687b9f92bd0e1a516daf2443e) +* Declare more precise `getClass()` return types in extension interfaces ([#1754](https://github.com/phpstan/phpstan-src/pull/1754)), thanks @staabm! +* (https://github.com/phpstan/phpstan-src/commit/38cb5a315e5573231d8695df343c8ee87a8c3b2e) +* HasOffsetType - put constructor parameter type natively (https://github.com/phpstan/phpstan-src/commit/b5accb3f6bbcffc8a44934539b88903e09b6a174) +* Printer is covered by BC promise (https://github.com/phpstan/phpstan-src/commit/b0858332efc7aa2f2fde7544a2a821ba81bde13b) +* More interfaces that are not supposed to be implemented in userland (https://github.com/phpstan/phpstan-src/commit/778af2ed74ba59bfb2a69fd5b45821ccdb1107c9, https://github.com/phpstan/phpstan-src/commit/cb6ab5544a016c52f931fc390bcdf9c627819d8f) +* Refactored `FunctionCallParametersCheck::check()` parameters (https://github.com/phpstan/phpstan-src/commit/710e09c41698efb1d8d3ae31791944077dbb9cc1) +* Spread list usages in Reflection, Scope, Type ([#3530](https://github.com/phpstan/phpstan-src/pull/3530)), thanks @janedbal! From 8051007f39905883f6ec36f9d64ad673bbaed355 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 13:23:43 +0200 Subject: [PATCH 356/508] Fix test --- tests/PHPStan/Analyser/nsrt/assert-docblock.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Analyser/nsrt/assert-docblock.php b/tests/PHPStan/Analyser/nsrt/assert-docblock.php index b6391d651a..8451a48ebd 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-docblock.php +++ b/tests/PHPStan/Analyser/nsrt/assert-docblock.php @@ -39,7 +39,7 @@ function validateStringOrIntArray(array $arr) : bool { * @param mixed[] $arr * @phpstan-assert-if-true =string[] $arr * @phpstan-assert-if-false =int[] $arr - * @phpstan-assert-if-false =non-empty-array $arr + * @phpstan-assert-if-false =non-empty-array $arr */ function validateStringOrNonEmptyIntArray(array $arr) : bool { return false; From 2b19dcfbc9b97ebdbfa3493fc032ceaf187e6a16 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 13:28:08 +0200 Subject: [PATCH 357/508] Cleanup --- build/baseline-lt-7.3.neon | 2 - build/enum-adapter-errors.neon | 151 --------------------------- build/ignore-by-php-version.neon.php | 9 -- phpstan-baseline.neon | 15 +++ 4 files changed, 15 insertions(+), 162 deletions(-) delete mode 100644 build/baseline-lt-7.3.neon delete mode 100644 build/enum-adapter-errors.neon diff --git a/build/baseline-lt-7.3.neon b/build/baseline-lt-7.3.neon deleted file mode 100644 index aab4991158..0000000000 --- a/build/baseline-lt-7.3.neon +++ /dev/null @@ -1,2 +0,0 @@ -parameters: - ignoreErrors: [] diff --git a/build/enum-adapter-errors.neon b/build/enum-adapter-errors.neon deleted file mode 100644 index 8acded5318..0000000000 --- a/build/enum-adapter-errors.neon +++ /dev/null @@ -1,151 +0,0 @@ -parameters: - ignoreErrors: - - - message: "#^Call to method getAttributes\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 2 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getBackingType\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getValueExpression\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnumBackedCase\\.$#" - count: 2 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getCase\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getCases\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getConstructor\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getDocComment\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 2 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getFileName\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getName\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getParentClass\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 4 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method getTraits\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method hasCase\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method implementsInterface\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isAbstract\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isBacked\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 2 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isEnum\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isFinal\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isInterface\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 2 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isInternal\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isReadOnly\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isSubclassOf\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Call to method isTrait\\(\\) on an unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum not found\\.$#" - count: 4 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnumBackedCase not found\\.$#" - count: 2 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Method PHPStan\\\\Reflection\\\\ClassReflection\\:\\:getNativeReflection\\(\\) has invalid return type PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Parameter \\$class of method PHPStan\\\\Reflection\\\\ClassReflection\\:\\:collectTraits\\(\\) has invalid type PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Parameter \\$reflection of method PHPStan\\\\Reflection\\\\ClassReflection\\:\\:__construct\\(\\) has invalid type PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Property PHPStan\\\\Reflection\\\\ClassReflection\\:\\:\\$reflection has unknown class PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum as its type\\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^PHPDoc tag @phpstan\-assert\-if\-true for \$this\-\>reflection contains unknown class PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionEnum\.$#" - count: 1 - path: ../src/Reflection/ClassReflection.php - - - - message: "#^Method PHPStan\\\\Reflection\\\\Php\\\\BuiltinMethodReflection\\:\\:getDeclaringClass\\(\\) has invalid return type PHPStan\\\\BetterReflection\\\\Reflection\\\\Adapter\\\\ReflectionEnum\\.$#" - count: 1 - path: ../src/Reflection/Php/BuiltinMethodReflection.php diff --git a/build/ignore-by-php-version.neon.php b/build/ignore-by-php-version.neon.php index 62de0070e5..2c808909bc 100644 --- a/build/ignore-by-php-version.neon.php +++ b/build/ignore-by-php-version.neon.php @@ -1,11 +1,6 @@ = 80000) { $includes[] = __DIR__ . '/baseline-8.0.neon'; } @@ -20,10 +15,6 @@ $includes[] = __DIR__ . '/ignore-gte-php7.4-errors.neon'; } -if (PHP_VERSION_ID < 70400) { - $includes[] = __DIR__ . '/enum-adapter-errors.neon'; -} - if (PHP_VERSION_ID < 80000) { $includes[] = __DIR__ . '/more-enum-adapter-errors.neon'; } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 22970c5201..63e2058a4c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -690,6 +690,21 @@ parameters: count: 1 path: src/Rules/Variables/CompactVariablesRule.php + - + message: """ + #^Call to deprecated method assertFileNotExists\\(\\) of class PHPUnit\\\\Framework\\\\Assert\\: + https\\://github\\.com/sebastianbergmann/phpunit/issues/4077$# + """ + identifier: staticMethod.deprecated + count: 1 + path: src/Testing/LevelsTestCase.php + + - + message: "#^Call to function method_exists\\(\\) with 'PHPUnit\\\\\\\\Framework\\\\\\\\TestCase' and 'assertFileDoesNotEx…' will always evaluate to true\\.$#" + identifier: function.alreadyNarrowedType + count: 1 + path: src/Testing/LevelsTestCase.php + - message: "#^Anonymous function has an unused use \\$container\\.$#" identifier: closure.unusedUse From 1326a795309000aab4fe929eeb10143d709a39aa Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 4 Oct 2024 14:03:38 +0200 Subject: [PATCH 358/508] Fix ClassPropertyNode line --- src/Analyser/NodeScopeResolver.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 65af41abc9..66da20eec9 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -896,6 +896,8 @@ private function processStmtNode( } elseif (isset($varTags[$propertyName])) { $phpDocType = $varTags[$propertyName]->getType(); } + $propStmt = clone $stmt; + $propStmt->setAttributes($prop->getAttributes()); $nodeCallback( new ClassPropertyNode( $propertyName, @@ -906,7 +908,7 @@ private function processStmtNode( $phpDocType, false, false, - $stmt, + $propStmt, $isReadOnly, $scope->isInTrait(), $scope->getClassReflection()->isReadOnly(), From 6cf6fff04b29119d9757fd9a231e4589083a20a2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 5 Oct 2024 09:51:04 +0200 Subject: [PATCH 359/508] Update nette/neon --- composer.json | 6 +---- composer.lock | 18 +++++++------- patches/NeonParser.patch | 11 --------- patches/NetteNeonStringNode.patch | 40 ------------------------------- 4 files changed, 10 insertions(+), 65 deletions(-) delete mode 100644 patches/NeonParser.patch delete mode 100644 patches/NetteNeonStringNode.patch diff --git a/composer.json b/composer.json index 6b268bb146..1b3a8bedf2 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "jetbrains/phpstorm-stubs": "dev-master#56f6b9e55f5885e651553843a1aaf9ec9c586c04", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", - "nette/neon": "3.3.3", + "nette/neon": "3.3.4", "nette/php-generator": "3.6.9", "nette/schema": "^1.2.2", "nette/utils": "^3.2.5", @@ -117,10 +117,6 @@ ], "nette/di": [ "patches/DependencyChecker.patch" - ], - "nette/neon": [ - "patches/NetteNeonStringNode.patch", - "patches/NeonParser.patch" ] } }, diff --git a/composer.lock b/composer.lock index 2a0883c500..660c3ad5ec 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9485ba4e0af44d8602eb360c34f92b8d", + "content-hash": "eb6f30bebe27d08d2b3b9e2c729ccf20", "packages": [ { "name": "clue/ndjson-react", @@ -1706,21 +1706,21 @@ }, { "name": "nette/neon", - "version": "v3.3.3", + "version": "v3.3.4", "source": { "type": "git", "url": "https://github.com/nette/neon.git", - "reference": "22e384da162fab42961d48eb06c06d3ad0c11b95" + "reference": "bb88bf3a54dd21bf4dbddb5cd525d7b0c61b7cda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/neon/zipball/22e384da162fab42961d48eb06c06d3ad0c11b95", - "reference": "22e384da162fab42961d48eb06c06d3ad0c11b95", + "url": "https://api.github.com/repos/nette/neon/zipball/bb88bf3a54dd21bf4dbddb5cd525d7b0c61b7cda", + "reference": "bb88bf3a54dd21bf4dbddb5cd525d7b0c61b7cda", "shasum": "" }, "require": { "ext-json": "*", - "php": ">=7.1" + "php": "7.1 - 8.4" }, "require-dev": { "nette/tester": "^2.0", @@ -1768,9 +1768,9 @@ ], "support": { "issues": "https://github.com/nette/neon/issues", - "source": "https://github.com/nette/neon/tree/v3.3.3" + "source": "https://github.com/nette/neon/tree/v3.3.4" }, - "time": "2022-03-10T02:04:26+00:00" + "time": "2024-10-04T22:17:24+00:00" }, { "name": "nette/php-generator", @@ -6453,7 +6453,7 @@ "php": "^8.1", "composer-runtime-api": "^2.0" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.1.99" }, diff --git a/patches/NeonParser.patch b/patches/NeonParser.patch deleted file mode 100644 index 9ff7a2b3de..0000000000 --- a/patches/NeonParser.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- src/Neon/Parser.php 2022-03-10 03:04:26 -+++ src/Neon/Parser.php 2024-08-26 21:57:02 -@@ -236,7 +236,7 @@ - } - - -- private function injectPos(Node $node, int $start = null, int $end = null): Node -+ private function injectPos(Node $node, ?int $start = null, ?int $end = null): Node - { - $node->startTokenPos = $start ?? $this->tokens->getPos(); - $node->startLine = $this->posToLine[$node->startTokenPos]; diff --git a/patches/NetteNeonStringNode.patch b/patches/NetteNeonStringNode.patch deleted file mode 100644 index ff7332693f..0000000000 --- a/patches/NetteNeonStringNode.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- src/Neon/Node/StringNode.php 2022-03-10 03:04:26 -+++ src/Neon/Node/StringNode.php 2024-08-26 14:53:45 -@@ -79,27 +79,18 @@ - - public function toString(): string - { -- if (strpos($this->value, "\n") === false) { -- return "'" . str_replace("'", "''", $this->value) . "'"; -+ $res = json_encode($this->value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); -+ if ($res === false) { -+ throw new Nette\Neon\Exception('Invalid UTF-8 sequence: ' . $this->value); -+ } - -- } elseif (preg_match('~\n[\t ]+\'{3}~', $this->value)) { -- $s = json_encode($this->value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); -- $s = preg_replace_callback( -- '#[^\\\\]|\\\\(.)#s', -- function ($m) { -- return ['n' => "\n", 't' => "\t", '"' => '"'][$m[1] ?? ''] ?? $m[0]; -- }, -- substr($s, 1, -1) -- ); -- $s = str_replace('"""', '""\"', $s); -- $delim = '"""'; -- -- } else { -- $s = $this->value; -- $delim = "'''"; -+ if (strpos($this->value, "\n") !== false) { -+ $res = preg_replace_callback('#[^\\\\]|\\\\(.)#s', function ($m) { -+ return ['n' => "\n\t", 't' => "\t", '"' => '"'][$m[1] ?? ''] ?? $m[0]; -+ }, $res); -+ $res = '"""' . "\n\t" . substr($res, 1, -1) . "\n" . '"""'; - } - -- $s = preg_replace('#^(?=.)#m', "\t", $s); -- return $delim . "\n" . $s . "\n" . $delim; -+ return $res; - } - } From bc81fe968607d7a773d0982617624956f79bb67f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 5 Oct 2024 09:54:43 +0200 Subject: [PATCH 360/508] Regenerate baseline --- phpstan-baseline.neon | 654 +++++++++++++++++++++--------------------- 1 file changed, 327 insertions(+), 327 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 63e2058a4c..370a77c831 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,1948 +1,1948 @@ parameters: ignoreErrors: - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: build/PHPStan/Build/ContainerDynamicReturnTypeExtension.php - - message: "#^Method PHPStan\\\\Analyser\\\\AnalyserResultFinalizer\\:\\:finalize\\(\\) throws checked exception Throwable but it's missing from the PHPDoc @throws tag\\.$#" + message: '#^Method PHPStan\\Analyser\\AnalyserResultFinalizer\:\:finalize\(\) throws checked exception Throwable but it''s missing from the PHPDoc @throws tag\.$#' identifier: missingType.checkedException count: 1 path: src/Analyser/AnalyserResultFinalizer.php - - message: "#^Cannot assign offset 'realCount' to array\\|string\\.$#" + message: '#^Cannot assign offset ''realCount'' to array\|string\.$#' identifier: offsetAssign.dimType count: 1 path: src/Analyser/Ignore/IgnoredErrorHelperResult.php - - message: "#^Casting to string something that's already string\\.$#" + message: '#^Casting to string something that''s already string\.$#' identifier: cast.useless count: 3 path: src/Analyser/MutatingScope.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Analyser/MutatingScope.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Analyser/MutatingScope.php - - message: "#^Only numeric types are allowed in pre\\-increment, float\\|int\\|string\\|null given\\.$#" + message: '#^Only numeric types are allowed in pre\-increment, float\|int\|string\|null given\.$#' identifier: preInc.nonNumeric count: 1 path: src/Analyser/MutatingScope.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Analyser/NodeScopeResolver.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' identifier: argument.type count: 1 path: src/Analyser/NodeScopeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Analyser/TypeSpecifier.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 5 path: src/Analyser/TypeSpecifier.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Analyser/TypeSpecifier.php - - message: "#^Template type TNodeType is declared as covariant, but occurs in contravariant position in parameter node of method PHPStan\\\\Collectors\\\\Collector\\:\\:processNode\\(\\)\\.$#" + message: '#^Template type TNodeType is declared as covariant, but occurs in contravariant position in parameter node of method PHPStan\\Collectors\\Collector\:\:processNode\(\)\.$#' identifier: generics.variance count: 1 path: src/Collectors/Collector.php - - message: "#^Method PHPStan\\\\Collectors\\\\Registry\\:\\:__construct\\(\\) has parameter \\$collectors with generic interface PHPStan\\\\Collectors\\\\Collector but does not specify its types\\: TNodeType, TValue$#" + message: '#^Method PHPStan\\Collectors\\Registry\:\:__construct\(\) has parameter \$collectors with generic interface PHPStan\\Collectors\\Collector but does not specify its types\: TNodeType, TValue$#' identifier: missingType.generics count: 1 path: src/Collectors/Registry.php - - message: "#^Property PHPStan\\\\Collectors\\\\Registry\\:\\:\\$cache with generic interface PHPStan\\\\Collectors\\\\Collector does not specify its types\\: TNodeType, TValue$#" + message: '#^Property PHPStan\\Collectors\\Registry\:\:\$cache with generic interface PHPStan\\Collectors\\Collector does not specify its types\: TNodeType, TValue$#' identifier: missingType.generics count: 1 path: src/Collectors/Registry.php - - message: "#^Property PHPStan\\\\Collectors\\\\Registry\\:\\:\\$collectors with generic interface PHPStan\\\\Collectors\\\\Collector does not specify its types\\: TNodeType, TValue$#" + message: '#^Property PHPStan\\Collectors\\Registry\:\:\$collectors with generic interface PHPStan\\Collectors\\Collector does not specify its types\: TNodeType, TValue$#' identifier: missingType.generics count: 1 path: src/Collectors/Registry.php - - message: "#^Anonymous function has an unused use \\$container\\.$#" + message: '#^Anonymous function has an unused use \$container\.$#' identifier: closure.unusedUse count: 1 path: src/Command/CommandHelper.php - - message: "#^Parameter \\#1 \\$path of function dirname expects string, string\\|false given\\.$#" + message: '#^Parameter \#1 \$path of function dirname expects string, string\|false given\.$#' identifier: argument.type count: 1 path: src/Command/CommandHelper.php - - message: "#^Static property PHPStan\\\\Command\\\\CommandHelper\\:\\:\\$reservedMemory is never read, only written\\.$#" + message: '#^Static property PHPStan\\Command\\CommandHelper\:\:\$reservedMemory is never read, only written\.$#' identifier: property.onlyWritten count: 1 path: src/Command/CommandHelper.php - - message: "#^Parameter \\#1 \\$headers \\(array\\\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$headers \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\StyleInterface\\:\\:table\\(\\)$#" + message: '#^Parameter \#1 \$headers \(array\\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$headers \(array\) of method Symfony\\Component\\Console\\Style\\StyleInterface\:\:table\(\)$#' identifier: method.childParameterType count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: "#^Parameter \\#1 \\$headers \\(array\\\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$headers \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\SymfonyStyle\\:\\:table\\(\\)$#" + message: '#^Parameter \#1 \$headers \(array\\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$headers \(array\) of method Symfony\\Component\\Console\\Style\\SymfonyStyle\:\:table\(\)$#' identifier: method.childParameterType count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: "#^Parameter \\#2 \\$rows \\(array\\\\>\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$rows \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\StyleInterface\\:\\:table\\(\\)$#" + message: '#^Parameter \#2 \$rows \(array\\>\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$rows \(array\) of method Symfony\\Component\\Console\\Style\\StyleInterface\:\:table\(\)$#' identifier: method.childParameterType count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: "#^Parameter \\#2 \\$rows \\(array\\\\>\\) of method PHPStan\\\\Command\\\\ErrorsConsoleStyle\\:\\:table\\(\\) should be contravariant with parameter \\$rows \\(array\\) of method Symfony\\\\Component\\\\Console\\\\Style\\\\SymfonyStyle\\:\\:table\\(\\)$#" + message: '#^Parameter \#2 \$rows \(array\\>\) of method PHPStan\\Command\\ErrorsConsoleStyle\:\:table\(\) should be contravariant with parameter \$rows \(array\) of method Symfony\\Component\\Console\\Style\\SymfonyStyle\:\:table\(\)$#' identifier: method.childParameterType count: 1 path: src/Command/ErrorsConsoleStyle.php - - message: "#^Variable method call on Nette\\\\Schema\\\\Elements\\\\AnyOf\\|Nette\\\\Schema\\\\Elements\\\\Structure\\|Nette\\\\Schema\\\\Elements\\\\Type\\.$#" + message: '#^Variable method call on Nette\\Schema\\Elements\\AnyOf\|Nette\\Schema\\Elements\\Structure\|Nette\\Schema\\Elements\\Type\.$#' identifier: method.dynamicName count: 1 path: src/DependencyInjection/ContainerFactory.php - - message: "#^Variable static method call on Nette\\\\Schema\\\\Expect\\.$#" + message: '#^Variable static method call on Nette\\Schema\\Expect\.$#' identifier: staticMethod.dynamicName count: 1 path: src/DependencyInjection/ContainerFactory.php - - message: "#^Fetching class constant PREVENT_MERGING of deprecated class Nette\\\\DI\\\\Config\\\\Helpers\\.$#" + message: '#^Fetching class constant PREVENT_MERGING of deprecated class Nette\\DI\\Config\\Helpers\.$#' identifier: classConstant.deprecatedClass count: 1 path: src/DependencyInjection/NeonAdapter.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - - message: "#^Parameter \\#1 \\$path of function dirname expects string, string\\|false given\\.$#" + message: '#^Parameter \#1 \$path of function dirname expects string, string\|false given\.$#' identifier: argument.type count: 1 path: src/Diagnose/PHPStanDiagnoseExtension.php - - message: "#^Variable method call on PHPStan\\\\Reflection\\\\ClassReflection\\.$#" + message: '#^Variable method call on PHPStan\\Reflection\\ClassReflection\.$#' identifier: method.dynamicName count: 2 path: src/PhpDoc/PhpDocBlock.php - - message: "#^Variable static method call on PHPStan\\\\PhpDoc\\\\PhpDocBlock\\.$#" + message: '#^Variable static method call on PHPStan\\PhpDoc\\PhpDocBlock\.$#' identifier: staticMethod.dynamicName count: 1 path: src/PhpDoc/PhpDocBlock.php - - message: "#^Call to function method_exists\\(\\) with PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\PhpDocNode and 'getParamOutTypeTagV…' will always evaluate to true\\.$#" + message: '#^Call to function method_exists\(\) with PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode and ''getParamOutTypeTagV…'' will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - - message: "#^Call to function method_exists\\(\\) with PHPStan\\\\PhpDocParser\\\\Ast\\\\PhpDoc\\\\PhpDocNode and 'getSelfOutTypeTagVa…' will always evaluate to true\\.$#" + message: '#^Call to function method_exists\(\) with PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode and ''getSelfOutTypeTagVa…'' will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: src/PhpDoc/PhpDocNodeResolver.php - - message: "#^Method PHPStan\\\\PhpDoc\\\\ResolvedPhpDocBlock\\:\\:getNameScope\\(\\) should return PHPStan\\\\Analyser\\\\NameScope but returns PHPStan\\\\Analyser\\\\NameScope\\|null\\.$#" + message: '#^Method PHPStan\\PhpDoc\\ResolvedPhpDocBlock\:\:getNameScope\(\) should return PHPStan\\Analyser\\NameScope but returns PHPStan\\Analyser\\NameScope\|null\.$#' identifier: return.type count: 1 path: src/PhpDoc/ResolvedPhpDocBlock.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/PhpDoc/TypeNodeResolver.php - - message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\Identifier\\\\Exception\\\\InvalidIdentifierName is never thrown in the try block\\.$#" + message: '#^Dead catch \- PHPStan\\BetterReflection\\Identifier\\Exception\\InvalidIdentifierName is never thrown in the try block\.$#' identifier: catch.neverThrown count: 3 path: src/Reflection/BetterReflection/BetterReflectionProvider.php - - message: "#^Dead catch \\- PHPStan\\\\BetterReflection\\\\NodeCompiler\\\\Exception\\\\UnableToCompileNode is never thrown in the try block\\.$#" + message: '#^Dead catch \- PHPStan\\BetterReflection\\NodeCompiler\\Exception\\UnableToCompileNode is never thrown in the try block\.$#' identifier: catch.neverThrown count: 1 path: src/Reflection/BetterReflection/BetterReflectionProvider.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: "#^Creating new ReflectionFunction is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionFunction is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' identifier: argument.type count: 1 path: src/Reflection/BetterReflection/SourceLocator/AutoloadSourceLocator.php - - message: "#^Method PHPStan\\\\Reflection\\\\BetterReflection\\\\SourceLocator\\\\FileReadTrapStreamWrapper\\:\\:invokeWithRealFileStreamWrapper\\(\\) has parameter \\$cb with no signature specified for callable\\.$#" + message: '#^Method PHPStan\\Reflection\\BetterReflection\\SourceLocator\\FileReadTrapStreamWrapper\:\:invokeWithRealFileStreamWrapper\(\) has parameter \$cb with no signature specified for callable\.$#' identifier: missingType.callable count: 1 path: src/Reflection/BetterReflection/SourceLocator/FileReadTrapStreamWrapper.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\ClassLike\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_ given\\.$#" + message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\ClassLike\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Function_ given\.$#' identifier: argument.type count: 1 path: src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php - - message: "#^Parameter \\#2 \\$node of method PHPStan\\\\BetterReflection\\\\SourceLocator\\\\Ast\\\\Strategy\\\\NodeToReflection\\:\\:__invoke\\(\\) expects PhpParser\\\\Node\\\\Expr\\\\ArrowFunction\\|PhpParser\\\\Node\\\\Expr\\\\Closure\\|PhpParser\\\\Node\\\\Expr\\\\FuncCall\\|PhpParser\\\\Node\\\\Stmt\\\\Class_\\|PhpParser\\\\Node\\\\Stmt\\\\Const_\\|PhpParser\\\\Node\\\\Stmt\\\\Enum_\\|PhpParser\\\\Node\\\\Stmt\\\\Function_\\|PhpParser\\\\Node\\\\Stmt\\\\Interface_\\|PhpParser\\\\Node\\\\Stmt\\\\Trait_, PhpParser\\\\Node\\\\Stmt\\\\ClassLike given\\.$#" + message: '#^Parameter \#2 \$node of method PHPStan\\BetterReflection\\SourceLocator\\Ast\\Strategy\\NodeToReflection\:\:__invoke\(\) expects PhpParser\\Node\\Expr\\ArrowFunction\|PhpParser\\Node\\Expr\\Closure\|PhpParser\\Node\\Expr\\FuncCall\|PhpParser\\Node\\Stmt\\Class_\|PhpParser\\Node\\Stmt\\Const_\|PhpParser\\Node\\Stmt\\Enum_\|PhpParser\\Node\\Stmt\\Function_\|PhpParser\\Node\\Stmt\\Interface_\|PhpParser\\Node\\Stmt\\Trait_, PhpParser\\Node\\Stmt\\ClassLike given\.$#' identifier: argument.type count: 2 path: src/Reflection/BetterReflection/SourceLocator/OptimizedSingleFileSourceLocator.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/ReflectionClassSourceLocator.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.php - - message: "#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Reflection/BetterReflection/SourceLocator/SkipClassAliasSourceLocator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Reflection/ClassReflection.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Reflection/ClassReflection.php - - message: "#^Method PHPStan\\\\Reflection\\\\ClassReflection\\:\\:getCacheKey\\(\\) should return string but returns string\\|null\\.$#" + message: '#^Method PHPStan\\Reflection\\ClassReflection\:\:getCacheKey\(\) should return string but returns string\|null\.$#' identifier: return.type count: 1 path: src/Reflection/ClassReflection.php - - message: "#^Binary operation \"&\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "&" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\*\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\*" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\+\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\+" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\-\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\-" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\^\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\^" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\|\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: '#^Binary operation "\|" between bool\|float\|int\|string\|null and bool\|float\|int\|string\|null results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 22 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 10 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" + message: '#^PHPDoc tag @var with type float\|int is not subtype of native type int\.$#' identifier: varTag.nativeType count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^PHPDoc tag @var with type float\\|int is not subtype of type int\\.$#" + message: '#^PHPDoc tag @var with type float\|int is not subtype of type int\.$#' identifier: varTag.type count: 4 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^PHPDoc tag @var with type float\\|int\\|null is not subtype of type int\\|null\\.$#" + message: '#^PHPDoc tag @var with type float\|int\|null is not subtype of type int\|null\.$#' identifier: varTag.type count: 6 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' identifier: phpstanApi.constructor count: 1 path: src/Reflection/SignatureMap/Php8SignatureMapProvider.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Api/NodeConnectingVisitorAttributesRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Classes/ImpossibleInstanceOfRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Classes/RequireExtendsRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Classes/RequireImplementsRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 6 path: src/Rules/Comparison/BooleanAndConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/BooleanNotConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 6 path: src/Rules/Comparison/BooleanOrConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/ConstantLooseComparisonRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/DoWhileLoopConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/ElseIfConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/IfConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Comparison/ImpossibleCheckTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Rules/Comparison/LogicalXorConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Rules/Comparison/MatchExpressionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/NumberComparisonOperatorsConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/StrictComparisonOfDifferentTypesRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Rules/Comparison/TernaryOperatorConstantConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Comparison/WhileLoopAlwaysFalseConditionRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Comparison/WhileLoopAlwaysTrueConditionRule.php - - message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Function class_implements\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Function class_parents\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Function class_parents\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Method PHPStan\\\\Rules\\\\DirectRegistry\\:\\:__construct\\(\\) has parameter \\$rules with generic interface PHPStan\\\\Rules\\\\Rule but does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Rules\\DirectRegistry\:\:__construct\(\) has parameter \$rules with generic interface PHPStan\\Rules\\Rule but does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Property PHPStan\\\\Rules\\\\DirectRegistry\\:\\:\\$cache with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Property PHPStan\\Rules\\DirectRegistry\:\:\$cache with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Property PHPStan\\\\Rules\\\\DirectRegistry\\:\\:\\$rules with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Property PHPStan\\Rules\\DirectRegistry\:\:\$rules with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: src/Rules/DirectRegistry.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Generics/GenericAncestorsCheck.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Generics/TemplateTypeCheck.php - - message: "#^Function class_implements\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Function class_implements\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Function class_parents\\(\\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\\. Use objects retrieved from ReflectionProvider instead\\.$#" + message: '#^Function class_parents\(\) is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#' identifier: phpstanApi.runtimeReflection count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Method PHPStan\\\\Rules\\\\LazyRegistry\\:\\:getRulesFromContainer\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Rules\\LazyRegistry\:\:getRulesFromContainer\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Property PHPStan\\\\Rules\\\\LazyRegistry\\:\\:\\$cache with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Property PHPStan\\Rules\\LazyRegistry\:\:\$cache with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Property PHPStan\\\\Rules\\\\LazyRegistry\\:\\:\\$rules with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Property PHPStan\\Rules\\LazyRegistry\:\:\$rules with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: src/Rules/LazyRegistry.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Methods/MethodParameterComparisonHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Methods/StaticMethodCallCheck.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/PhpDoc/RequireExtendsCheck.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/PhpDoc/RequireImplementsDefinitionTraitRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/PhpDoc/VarTagTypeRuleHelper.php - - message: "#^Access to an undefined property T of PHPStan\\\\Rules\\\\RuleError\\:\\:\\$tip\\.$#" + message: '#^Access to an undefined property T of PHPStan\\Rules\\RuleError\:\:\$tip\.$#' identifier: property.notFound count: 2 path: src/Rules/RuleErrorBuilder.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/RuleLevelHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/UnusedFunctionParametersCheck.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Variables/CompactVariablesRule.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Rules/Variables/CompactVariablesRule.php - - message: """ - #^Call to deprecated method assertFileNotExists\\(\\) of class PHPUnit\\\\Framework\\\\Assert\\: - https\\://github\\.com/sebastianbergmann/phpunit/issues/4077$# - """ + message: ''' + #^Call to deprecated method assertFileNotExists\(\) of class PHPUnit\\Framework\\Assert\: + https\://github\.com/sebastianbergmann/phpunit/issues/4077$# + ''' identifier: staticMethod.deprecated count: 1 path: src/Testing/LevelsTestCase.php - - message: "#^Call to function method_exists\\(\\) with 'PHPUnit\\\\\\\\Framework\\\\\\\\TestCase' and 'assertFileDoesNotEx…' will always evaluate to true\\.$#" + message: '#^Call to function method_exists\(\) with ''PHPUnit\\\\Framework\\\\TestCase'' and ''assertFileDoesNotEx…'' will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: src/Testing/LevelsTestCase.php - - message: "#^Anonymous function has an unused use \\$container\\.$#" + message: '#^Anonymous function has an unused use \$container\.$#' identifier: closure.unusedUse count: 1 path: src/Testing/PHPStanTestCase.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Testing/TypeInferenceTestCase.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryArrayListType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryLiteralStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryLowercaseStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNonEmptyStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNonEmptyStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNonFalsyStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNumericStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/AccessoryNumericStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasMethodType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasOffsetType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Accessory/HasOffsetValueType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Accessory/HasOffsetValueType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasOffsetValueType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasPropertyType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/NonEmptyArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/OversizedArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/ArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/ArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/ArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/ArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/BooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/BooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/CallableType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/CallableType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/ClosureType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 7 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Constant/ConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Type is always PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType\\|PHPStan\\\\Type\\\\Constant\\\\ConstantStringType but it's error\\-prone and dangerous\\.$#" + message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Type is always PHPStan\\Type\\Constant\\ConstantIntegerType\|PHPStan\\Type\\Constant\\ConstantStringType but it''s error\-prone and dangerous\.$#' identifier: phpstanApi.varTagAssumption count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: "#^PHPDoc tag @var with type float\\|int is not subtype of native type int\\.$#" + message: '#^PHPDoc tag @var with type float\|int is not subtype of native type int\.$#' identifier: varTag.nativeType count: 2 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: "#^PHPDoc tag @var with type float\\|int is not subtype of type int\\.$#" + message: '#^PHPDoc tag @var with type float\|int is not subtype of type int\.$#' identifier: varTag.type count: 1 path: src/Type/Constant/ConstantArrayTypeBuilder.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantBooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantBooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Constant/ConstantBooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantFloatType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantFloatType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantIntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantIntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/ConstantStringType.php - - message: "#^PHPDoc tag @var with type int\\|string is not subtype of type string\\.$#" + message: '#^PHPDoc tag @var with type int\|string is not subtype of type string\.$#' identifier: varTag.type count: 1 path: src/Type/Constant/ConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Constant/OversizedArrayBuilder.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Enum\\EnumCaseObjectType is error\-prone and deprecated\. Use Type\:\:getEnumCases\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Enum/EnumCaseObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/ExponentiateHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/FileTypeMapper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/FloatType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Generic/GenericClassStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Generic/GenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateBenevolentUnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateBooleanType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateConstantArrayType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateConstantIntegerType.php - - message: "#^Method PHPStan\\\\Type\\\\Generic\\\\TemplateConstantIntegerType\\:\\:toPhpDocNode\\(\\) should return PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\ConstTypeNode but returns PHPStan\\\\PhpDocParser\\\\Ast\\\\Type\\\\IdentifierTypeNode\\.$#" + message: '#^Method PHPStan\\Type\\Generic\\TemplateConstantIntegerType\:\:toPhpDocNode\(\) should return PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode but returns PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode\.$#' identifier: return.type count: 1 path: src/Type/Generic/TemplateConstantIntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateConstantStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateFloatType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateGenericObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateIntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateIntersectionType.php - - message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\IntersectionType will always evaluate to false\\.$#" + message: '#^Instanceof between PHPStan\\Type\\Type and PHPStan\\Type\\IntersectionType will always evaluate to false\.$#' identifier: instanceof.alwaysFalse count: 2 path: src/Type/Generic/TemplateIntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateKeyOfType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Generic/TemplateMixedType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateObjectWithoutClassType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Generic/TemplateStrictMixedType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Generic/TemplateTypeFactory.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/Generic/TemplateUnionType.php - - message: "#^Instanceof between PHPStan\\\\Type\\\\Type and PHPStan\\\\Type\\\\UnionType will always evaluate to false\\.$#" + message: '#^Instanceof between PHPStan\\Type\\Type and PHPStan\\Type\\UnionType will always evaluate to false\.$#' identifier: instanceof.alwaysFalse count: 2 path: src/Type/Generic/TemplateUnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/IntegerRangeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/IntegerRangeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/IntegerRangeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/IntegerType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/IntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/IntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/IntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/IntersectionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/IterableType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/IterableType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/NullType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/NullType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/ObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/ObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/ObjectShapeType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Enum\\\\EnumCaseObjectType is error\\-prone and deprecated\\. Use Type\\:\\:getEnumCases\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Enum\\EnumCaseObjectType is error\-prone and deprecated\. Use Type\:\:getEnumCases\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericObjectType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 6 path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/ObjectType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/ObjectWithoutClassType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/ObjectWithoutClassType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ArrayCombineFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ArrayFilterFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Php/ArrayMergeFunctionDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 16 path: src/Type/Php/BcMathStringOrNullReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/CompactFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/CompactFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/DefineConstantTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/DefinedConstantTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\TypeWithClassName is error\\-prone and deprecated\\. Use Type\\:\\:getObjectClassNames\\(\\) or Type\\:\\:getObjectClassReflections\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\TypeWithClassName is error\-prone and deprecated\. Use Type\:\:getObjectClassNames\(\) or Type\:\:getObjectClassReflections\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/DsMapDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/FilterFunctionReturnTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/FilterFunctionReturnTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ImplodeFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/IsAFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/LtrimFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/MbStrlenFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/MbSubstituteCharacterDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/MethodExistsTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/MinMaxFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/NumberFormatFunctionDynamicReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/PropertyExistsTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/Php/RangeFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ReflectionClassIsSubclassOfTypeSpecifyingExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/ReflectionMethodConstructorThrowTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/SscanfFunctionDynamicReturnTypeExtension.php - - message: "#^Cannot access offset int\\<0, max\\> on \\(float\\|int\\)\\.$#" + message: '#^Cannot access offset int\<0, max\> on \(float\|int\)\.$#' identifier: offsetAccess.nonOffsetAccessible count: 2 path: src/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/StrRepeatFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/Php/StrlenFunctionReturnTypeExtension.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) or Type\\:\\:getObjectClassNames\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/StaticType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectWithoutClassType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectWithoutClassType is error\-prone and deprecated\. Use Type\:\:isObject\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/StaticType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/StringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/StringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 5 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\BooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isBoolean\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 14 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 5 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\FloatType is error\\-prone and deprecated\\. Use Type\\:\\:isFloat\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\FloatType is error\-prone and deprecated\. Use Type\:\:isFloat\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 8 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ObjectShapeType is error\\-prone and deprecated\\. Use Type\\:\\:isObject\\(\\) and Type\\:\\:hasProperty\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\StringType is error\\-prone and deprecated\\. Use Type\\:\\:isString\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\StringType is error\-prone and deprecated\. Use Type\:\:isString\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypeCombinator.php - - message: "#^Instanceof between PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType and PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType will always evaluate to true\\.$#" + message: '#^Instanceof between PHPStan\\Type\\Constant\\ConstantIntegerType and PHPStan\\Type\\Constant\\ConstantIntegerType will always evaluate to true\.$#' identifier: instanceof.alwaysTrue count: 1 path: src/Type/TypeCombinator.php - - message: "#^Result of \\|\\| is always true\\.$#" + message: '#^Result of \|\| is always true\.$#' identifier: booleanOr.alwaysTrue count: 1 path: src/Type/TypeCombinator.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/TypeUtils.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/TypeUtils.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ArrayType is error\\-prone and deprecated\\. Use Type\\:\\:isArray\\(\\) or Type\\:\\:getArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/TypehintHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/TypehintHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/TypehintHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Generic\\\\GenericClassStringType is error\\-prone and deprecated\\. Use Type\\:\\:isClassStringType\\(\\) and Type\\:\\:getClassStringObjectType\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Generic\\GenericClassStringType is error\-prone and deprecated\. Use Type\:\:isClassStringType\(\) and Type\:\:getClassStringObjectType\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/UnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IterableType is error\\-prone and deprecated\\. Use Type\\:\\:isIterable\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 1 path: src/Type/UnionType.php - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Type is always PHPStan\\\\Type\\\\BooleanType but it's error\\-prone and dangerous\\.$#" + message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Type is always PHPStan\\Type\\BooleanType but it''s error\-prone and dangerous\.$#' identifier: phpstanApi.varTagAssumption count: 1 path: src/Type/UnionType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Accessory\\\\AccessoryType is error\\-prone and deprecated\\. Use methods on PHPStan\\\\Type\\\\Type instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Accessory\\AccessoryType is error\-prone and deprecated\. Use methods on PHPStan\\Type\\Type instead\.$#' identifier: phpstanApi.instanceofType count: 3 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\CallableType is error\\-prone and deprecated\\. Use Type\\:\\:isCallable\\(\\) and Type\\:\\:getCallableParametersAcceptors\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\CallableType is error\-prone and deprecated\. Use Type\:\:isCallable\(\) and Type\:\:getCallableParametersAcceptors\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\ConstantScalarType is error\\-prone and deprecated\\. Use Type\\:\\:isConstantScalarValue\\(\\) or Type\\:\\:getConstantScalarTypes\\(\\) or Type\\:\\:getConstantScalarValues\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\ConstantScalarType is error\-prone and deprecated\. Use Type\:\:isConstantScalarValue\(\) or Type\:\:getConstantScalarTypes\(\) or Type\:\:getConstantScalarValues\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 4 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantBooleanType is error\\-prone and deprecated\\. Use Type\\:\\:isTrue\\(\\) or Type\\:\\:isFalse\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantBooleanType is error\-prone and deprecated\. Use Type\:\:isTrue\(\) or Type\:\:isFalse\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantStringType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantStrings\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantStringType is error\-prone and deprecated\. Use Type\:\:getConstantStrings\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntegerType is error\\-prone and deprecated\\. Use Type\\:\\:isInteger\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntegerType is error\-prone and deprecated\. Use Type\:\:isInteger\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\NullType is error\\-prone and deprecated\\. Use Type\\:\\:isNull\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\NullType is error\-prone and deprecated\. Use Type\:\:isNull\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/UnionTypeHelper.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\VoidType is error\\-prone and deprecated\\. Use Type\\:\\:isVoid\\(\\) instead\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\VoidType is error\-prone and deprecated\. Use Type\:\:isVoid\(\) instead\.$#' identifier: phpstanApi.instanceofType count: 2 path: src/Type/VoidType.php - - message: "#^Unreachable statement \\- code above always terminates\\.$#" + message: '#^Unreachable statement \- code above always terminates\.$#' identifier: deadCode.unreachable count: 1 path: tests/PHPStan/Analyser/AnalyserTest.php - - message: "#^Class PHPStan\\\\Analyser\\\\AnonymousClassNameRuleTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + message: '#^Class PHPStan\\Analyser\\AnonymousClassNameRuleTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' identifier: missingType.generics count: 1 path: tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php - - message: "#^Method PHPStan\\\\Analyser\\\\AnonymousClassNameRuleTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Analyser\\AnonymousClassNameRuleTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: tests/PHPStan/Analyser/AnonymousClassNameRuleTest.php - - message: "#^Class PHPStan\\\\Analyser\\\\EvaluationOrderTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + message: '#^Class PHPStan\\Analyser\\EvaluationOrderTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' identifier: missingType.generics count: 1 path: tests/PHPStan/Analyser/EvaluationOrderTest.php - - message: "#^Method PHPStan\\\\Analyser\\\\EvaluationOrderTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Analyser\\EvaluationOrderTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: tests/PHPStan/Analyser/EvaluationOrderTest.php - - message: "#^Constant SOME_CONSTANT_IN_AUTOLOAD_FILE not found\\.$#" + message: '#^Constant SOME_CONSTANT_IN_AUTOLOAD_FILE not found\.$#' identifier: constant.notFound count: 1 path: tests/PHPStan/Command/AnalyseCommandTest.php - - message: "#^Class PHPStan\\\\Node\\\\FileNodeTest extends generic class PHPStan\\\\Testing\\\\RuleTestCase but does not specify its types\\: TRule$#" + message: '#^Class PHPStan\\Node\\FileNodeTest extends generic class PHPStan\\Testing\\RuleTestCase but does not specify its types\: TRule$#' identifier: missingType.generics count: 1 path: tests/PHPStan/Node/FileNodeTest.php - - message: "#^Method PHPStan\\\\Node\\\\FileNodeTest\\:\\:getRule\\(\\) return type with generic interface PHPStan\\\\Rules\\\\Rule does not specify its types\\: TNodeType$#" + message: '#^Method PHPStan\\Node\\FileNodeTest\:\:getRule\(\) return type with generic interface PHPStan\\Rules\\Rule does not specify its types\: TNodeType$#' identifier: missingType.generics count: 1 path: tests/PHPStan/Node/FileNodeTest.php - - message: "#^PHPDoc tag @var with type string is not subtype of type class\\-string\\.$#" + message: '#^PHPDoc tag @var with type string is not subtype of type class\-string\.$#' identifier: varTag.type count: 1 path: tests/PHPStan/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorTest.php - - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' identifier: phpstanApi.constructor count: 1 path: tests/PHPStan/Reflection/ReflectionProviderGoldenTest.php - - message: "#^Creating new PHPStan\\\\Php8StubsMap is not covered by backward compatibility promise\\. The class might change in a minor PHPStan version\\.$#" + message: '#^Creating new PHPStan\\Php8StubsMap is not covered by backward compatibility promise\. The class might change in a minor PHPStan version\.$#' identifier: phpstanApi.constructor count: 1 path: tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php - - message: "#^PHPDoc tag @var assumes the expression with type PHPStan\\\\Type\\\\Generic\\\\TemplateType is always PHPStan\\\\Type\\\\Generic\\\\TemplateMixedType but it's error\\-prone and dangerous\\.$#" + message: '#^PHPDoc tag @var assumes the expression with type PHPStan\\Type\\Generic\\TemplateType is always PHPStan\\Type\\Generic\\TemplateMixedType but it''s error\-prone and dangerous\.$#' identifier: phpstanApi.varTagAssumption count: 1 path: tests/PHPStan/Type/IterableTypeTest.php From 0210d458d7e2dfa2d800d2a3558667fd0c061002 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 5 Oct 2024 13:07:48 +0200 Subject: [PATCH 361/508] Fix `ConstantArrayType::isSuperTypeOf()` --- src/Type/Constant/ConstantArrayType.php | 2 +- .../WrongVariableNameInVarTagRuleTest.php | 4 -- tests/PHPStan/Type/ArrayTypeTest.php | 11 ++++++ .../Type/Constant/ConstantArrayTypeTest.php | 37 +++++++++++++++++++ 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index de72286489..46adbf9a73 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -405,7 +405,7 @@ public function isSuperTypeOf(Type $type): TrinaryLogic return TrinaryLogic::createNo(); } - return $result->and($isKeySuperType, $this->getIterableValueType()->isSuperTypeOf($type->getIterableKeyType())); + return $result->and($isKeySuperType, $this->getIterableValueType()->isSuperTypeOf($type->getIterableValueType())); } if ($type instanceof CompoundType) { diff --git a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php index f0c8cd0025..155c0d6ea4 100644 --- a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php @@ -140,10 +140,6 @@ public function testRule(): void 'PHPDoc tag @var above a function has no effect.', 313, ], - [ - "PHPDoc tag @var with type array is not subtype of native type array{: 'empty', 1: '1'}.", - 324, - ], ]); } diff --git a/tests/PHPStan/Type/ArrayTypeTest.php b/tests/PHPStan/Type/ArrayTypeTest.php index 98332b7031..e701997c6c 100644 --- a/tests/PHPStan/Type/ArrayTypeTest.php +++ b/tests/PHPStan/Type/ArrayTypeTest.php @@ -71,6 +71,17 @@ public function dataIsSuperTypeOf(): array new IntersectionType([new ArrayType(new IntegerType(), new StringType()), new OversizedArrayType()]), TrinaryLogic::createYes(), ], + [ + new ArrayType(new StringType(), new MixedType()), + new ConstantArrayType([ + new ConstantStringType('a'), + new ConstantStringType('b'), + ], [ + new IntegerType(), + new UnionType([new IntegerType(), new NullType()]), + ]), + TrinaryLogic::createYes(), + ], ]; } diff --git a/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php b/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php index f2ee31c44f..b047b86a69 100644 --- a/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php +++ b/tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php @@ -18,6 +18,7 @@ use PHPStan\Type\IterableType; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; +use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; use PHPStan\Type\StringType; use PHPStan\Type\Type; @@ -654,6 +655,42 @@ public function dataIsSuperTypeOf(): iterable ], [1], [0]), TrinaryLogic::createMaybe(), ]; + + yield [ + new ConstantArrayType([ + new ConstantStringType('a'), + new ConstantStringType('b'), + ], [ + new IntegerType(), + new UnionType([new IntegerType(), new NullType()]), + ]), + new ArrayType(new StringType(), new MixedType()), + TrinaryLogic::createMaybe(), + ]; + + yield [ + new ConstantArrayType([ + new ConstantStringType('a'), + new ConstantStringType('b'), + ], [ + new IntegerType(), + new UnionType([new IntegerType(), new NullType()]), + ]), + new ArrayType(new StringType(), new StringType()), + TrinaryLogic::createNo(), + ]; + + yield [ + new ConstantArrayType([ + new ConstantIntegerType(1), + new ConstantIntegerType(2), + ], [ + new IntegerType(), + new UnionType([new IntegerType(), new NullType()]), + ]), + new ArrayType(new StringType(), new MixedType()), + TrinaryLogic::createNo(), + ]; } /** From f680629bc92e4dd5d7acd3bc60c9539fb047452b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 6 Oct 2024 14:24:35 +0200 Subject: [PATCH 362/508] IntersectionType - always describe list as list --- phpstan-baseline.neon | 12 +++ src/Type/IntersectionType.php | 33 +++++++++ .../Analyser/AnalyserIntegrationTest.php | 4 +- tests/PHPStan/Analyser/nsrt/bug-4117.php | 2 +- .../nsrt/constant-array-optional-set.php | 6 +- tests/PHPStan/Analyser/nsrt/count-maybe.php | 30 ++++---- .../Arrays/IterableInForeachRuleTest.php | 2 +- ...plodeParameterCastableToStringRuleTest.php | 2 +- .../ParameterCastableToStringRuleTest.php | 2 +- .../Rules/Functions/ReturnTypeRuleTest.php | 2 +- .../SortParameterCastableToStringRuleTest.php | 30 ++++---- .../Rules/Methods/ReturnTypeRuleTest.php | 4 +- .../Rules/PhpDoc/FunctionAssertRuleTest.php | 2 +- tests/PHPStan/Type/IntersectionTypeTest.php | 73 +++++++++++++++++++ 14 files changed, 161 insertions(+), 43 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 370a77c831..246118a8d5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1311,6 +1311,12 @@ parameters: count: 3 path: src/Type/IntersectionType.php + - + message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' + identifier: phpstanApi.instanceofType + count: 1 + path: src/Type/IntersectionType.php + - message: '#^Doing instanceof PHPStan\\Type\\BooleanType is error\-prone and deprecated\. Use Type\:\:isBoolean\(\) instead\.$#' identifier: phpstanApi.instanceofType @@ -1323,6 +1329,12 @@ parameters: count: 2 path: src/Type/IntersectionType.php + - + message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' + identifier: phpstanApi.instanceofType + count: 1 + path: src/Type/IntersectionType.php + - message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' identifier: phpstanApi.instanceofType diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index c6c6d6b644..f3784184ba 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -27,6 +27,7 @@ use PHPStan\Type\Accessory\AccessoryNumericStringType; use PHPStan\Type\Accessory\AccessoryType; use PHPStan\Type\Accessory\NonEmptyArrayType; +use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\Generic\TemplateTypeMap; @@ -45,8 +46,10 @@ use function md5; use function sprintf; use function str_starts_with; +use function strcasecmp; use function strlen; use function substr; +use function usort; /** @api */ class IntersectionType implements CompoundType @@ -292,13 +295,43 @@ public function describe(VerbosityLevel $level): string return $level->handle( function () use ($level): string { $typeNames = []; + $isList = $this->isList()->yes(); + $valueType = null; foreach ($this->getSortedTypes() as $type) { + if ($isList) { + if ($type instanceof ArrayType || $type instanceof ConstantArrayType) { + $valueType = $type->getIterableValueType(); + continue; + } + if ($type instanceof NonEmptyArrayType) { + continue; + } + } if ($type instanceof AccessoryType) { continue; } $typeNames[] = $type->generalize(GeneralizePrecision::lessSpecific())->describe($level); } + if ($isList) { + $isMixedValueType = $valueType instanceof MixedType && $valueType->describe(VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); + $innerType = ''; + if ($valueType !== null && !$isMixedValueType) { + $innerType = sprintf('<%s>', $valueType->describe($level)); + } + + $typeNames[] = 'list' . $innerType; + } + + usort($typeNames, static function ($a, $b) { + $cmp = strcasecmp($a, $b); + if ($cmp !== 0) { + return $cmp; + } + + return $a <=> $b; + }); + return implode('&', $typeNames); }, fn (): string => $this->describeItself($level, true), diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 19b2783093..52791b8b95 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -843,7 +843,7 @@ public function testUnresolvableParameter(): void { $errors = $this->runAnalyse(__DIR__ . '/data/unresolvable-parameter.php'); $this->assertCount(3, $errors); - $this->assertSame('Parameter #2 $array of function array_map expects array, array|false given.', $errors[0]->getMessage()); + $this->assertSame('Parameter #2 $array of function array_map expects array, list|false given.', $errors[0]->getMessage()); $this->assertSame(18, $errors[0]->getLine()); $this->assertSame('Method UnresolvableParameter\Collection::pipeInto() has parameter $class with no type specified.', $errors[1]->getMessage()); $this->assertSame(30, $errors[1]->getLine()); @@ -892,7 +892,7 @@ public function testBug7554(): void $errors = $this->runAnalyse(__DIR__ . '/data/bug-7554.php'); $this->assertCount(2, $errors); - $this->assertSame(sprintf('Parameter #1 $%s of function count expects array|Countable, array>|false given.', PHP_VERSION_ID < 80000 ? 'var' : 'value'), $errors[0]->getMessage()); + $this->assertSame(sprintf('Parameter #1 $%s of function count expects array|Countable, list|string>>|false given.', PHP_VERSION_ID < 80000 ? 'var' : 'value'), $errors[0]->getMessage()); $this->assertSame(26, $errors[0]->getLine()); $this->assertSame('Cannot access offset int<1, max> on list}>|false.', $errors[1]->getMessage()); diff --git a/tests/PHPStan/Analyser/nsrt/bug-4117.php b/tests/PHPStan/Analyser/nsrt/bug-4117.php index f1f2f60f40..510df695f1 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-4117.php +++ b/tests/PHPStan/Analyser/nsrt/bug-4117.php @@ -34,7 +34,7 @@ public function broken(int $key) if ($item) { assertType("T of mixed~(0|0.0|''|'0'|array{}|false|null) (class Bug4117Types\GenericList, argument)", $item); } else { - assertType("(array{}&T of mixed~null (class Bug4117Types\GenericList, argument))|(0.0&T of mixed~null (class Bug4117Types\GenericList, argument))|(0&T of mixed~null (class Bug4117Types\GenericList, argument))|(''&T of mixed~null (class Bug4117Types\GenericList, argument))|('0'&T of mixed~null (class Bug4117Types\GenericList, argument))|(T of mixed~null (class Bug4117Types\GenericList, argument)&false)|null", $item); + assertType("(T of mixed~null (class Bug4117Types\GenericList, argument)&false)|(0.0&T of mixed~null (class Bug4117Types\GenericList, argument))|(0&T of mixed~null (class Bug4117Types\GenericList, argument))|(array{}&T of mixed~null (class Bug4117Types\GenericList, argument))|(''&T of mixed~null (class Bug4117Types\GenericList, argument))|('0'&T of mixed~null (class Bug4117Types\GenericList, argument))|null", $item); } assertType('T of mixed~null (class Bug4117Types\GenericList, argument)|null', $item); diff --git a/tests/PHPStan/Analyser/nsrt/constant-array-optional-set.php b/tests/PHPStan/Analyser/nsrt/constant-array-optional-set.php index 6faaa574c1..fe3512a45b 100644 --- a/tests/PHPStan/Analyser/nsrt/constant-array-optional-set.php +++ b/tests/PHPStan/Analyser/nsrt/constant-array-optional-set.php @@ -60,13 +60,13 @@ class Bar */ public function doFoo($nextAutoIndexes) { - assertType('non-empty-list|int', $nextAutoIndexes); + assertType('int|non-empty-list', $nextAutoIndexes); if (is_int($nextAutoIndexes)) { assertType('int', $nextAutoIndexes); } else { assertType('non-empty-list', $nextAutoIndexes); } - assertType('non-empty-list|int', $nextAutoIndexes); + assertType('int|non-empty-list', $nextAutoIndexes); } /** @@ -75,7 +75,7 @@ public function doFoo($nextAutoIndexes) */ public function doBar($nextAutoIndexes) { - assertType('non-empty-list|int', $nextAutoIndexes); + assertType('int|non-empty-list', $nextAutoIndexes); if (is_int($nextAutoIndexes)) { $nextAutoIndexes = [$nextAutoIndexes]; assertType('array{int}', $nextAutoIndexes); diff --git a/tests/PHPStan/Analyser/nsrt/count-maybe.php b/tests/PHPStan/Analyser/nsrt/count-maybe.php index 255c936d22..4be30d9f49 100644 --- a/tests/PHPStan/Analyser/nsrt/count-maybe.php +++ b/tests/PHPStan/Analyser/nsrt/count-maybe.php @@ -86,9 +86,9 @@ function doFoo4($maybeCountable, int $mode): void if (count($maybeCountable, $mode) > 0) { assertType('non-empty-list', $maybeCountable); } else { - assertType('list|float', $maybeCountable); + assertType('float|list', $maybeCountable); } - assertType('list|float', $maybeCountable); + assertType('float|list', $maybeCountable); } /** @@ -100,9 +100,9 @@ function doFoo5($maybeCountable, $maybeMode): void if (count($maybeCountable, $maybeMode) > 0) { assertType('non-empty-list', $maybeCountable); } else { - assertType('list|float', $maybeCountable); + assertType('float|list', $maybeCountable); } - assertType('list|float', $maybeCountable); + assertType('float|list', $maybeCountable); } /** @@ -113,9 +113,9 @@ function doFoo6($maybeCountable, float $invalidMode): void if (count($maybeCountable, $invalidMode) > 0) { assertType('non-empty-list', $maybeCountable); } else { - assertType('list|float', $maybeCountable); + assertType('float|list', $maybeCountable); } - assertType('list|float', $maybeCountable); + assertType('float|list', $maybeCountable); } /** @@ -124,11 +124,11 @@ function doFoo6($maybeCountable, float $invalidMode): void function doFoo7($maybeCountable, int $mode): void { if (count($maybeCountable, $mode) > 0) { - assertType('non-empty-list|Countable', $maybeCountable); + assertType('Countable|non-empty-list', $maybeCountable); } else { - assertType('list|Countable|float', $maybeCountable); + assertType('Countable|float|list', $maybeCountable); } - assertType('list|Countable|float', $maybeCountable); + assertType('Countable|float|list', $maybeCountable); } /** @@ -138,11 +138,11 @@ function doFoo7($maybeCountable, int $mode): void function doFoo8($maybeCountable, $maybeMode): void { if (count($maybeCountable, $maybeMode) > 0) { - assertType('non-empty-list|Countable', $maybeCountable); + assertType('Countable|non-empty-list', $maybeCountable); } else { - assertType('list|Countable|float', $maybeCountable); + assertType('Countable|float|list', $maybeCountable); } - assertType('list|Countable|float', $maybeCountable); + assertType('Countable|float|list', $maybeCountable); } /** @@ -151,11 +151,11 @@ function doFoo8($maybeCountable, $maybeMode): void function doFoo9($maybeCountable, float $invalidMode): void { if (count($maybeCountable, $invalidMode) > 0) { - assertType('non-empty-list|Countable', $maybeCountable); + assertType('Countable|non-empty-list', $maybeCountable); } else { - assertType('list|Countable|float', $maybeCountable); + assertType('Countable|float|list', $maybeCountable); } - assertType('list|Countable|float', $maybeCountable); + assertType('Countable|float|list', $maybeCountable); } function doFooBar1(array $countable, int $mode): void diff --git a/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php b/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php index c83001b6a8..43c6020744 100644 --- a/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php @@ -32,7 +32,7 @@ public function testCheckWithMaybes(): void 10, ], [ - 'Argument of an invalid type array|false supplied for foreach, only iterables are supported.', + 'Argument of an invalid type list|false supplied for foreach, only iterables are supported.', 19, ], [ diff --git a/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php index e5003028bc..8111e9a965 100644 --- a/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php @@ -64,7 +64,7 @@ public function testImplode(): void { $this->analyse([__DIR__ . '/data/implode.php'], [ [ - 'Parameter #2 $array of function implode expects array, array|string> given.', + 'Parameter #2 $array of function implode expects array, array|string> given.', 9, ], [ diff --git a/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php index e577240cb8..83b0f40567 100644 --- a/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php @@ -154,7 +154,7 @@ public function testBug3946(): void { $this->analyse([__DIR__ . '/data/bug-3946.php'], [ [ - 'Parameter #1 $keys of function array_combine expects an array of values castable to string, array|Bug3946\stdClass|float|int|string> given.', + 'Parameter #1 $keys of function array_combine expects an array of values castable to string, array|string> given.', 8, ], ]); diff --git a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php index bd993f3bca..14d161de9a 100644 --- a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php @@ -173,7 +173,7 @@ public function testListWithNullablesChecked(): void $this->checkNullables = true; $this->analyse([__DIR__ . '/data/return-list-nullables.php'], [ [ - 'Function ReturnListNullables\doFoo() should return array|null but returns array.', + 'Function ReturnListNullables\doFoo() should return array|null but returns list.', 16, ], ]); diff --git a/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php index f0350b5179..8c0105a424 100644 --- a/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php @@ -26,7 +26,7 @@ public function testRule(): void { $this->analyse([__DIR__ . '/data/sort-param-castable-to-string-functions.php'], $this->hackParameterNames([ [ - 'Parameter #1 $array of function array_unique expects an array of values castable to string, array> given.', + 'Parameter #1 $array of function array_unique expects an array of values castable to string, array> given.', 16, ], [ @@ -38,27 +38,27 @@ public function testRule(): void 20, ], [ - 'Parameter #1 $array of function rsort expects an array of values castable to string, array> given.', + 'Parameter #1 $array of function rsort expects an array of values castable to string, list> given.', 21, ], [ - 'Parameter #1 $array of function asort expects an array of values castable to string, array> given.', + 'Parameter #1 $array of function asort expects an array of values castable to string, list> given.', 22, ], [ - 'Parameter #1 $array of function arsort expects an array of values castable to string, array> given.', + 'Parameter #1 $array of function arsort expects an array of values castable to string, array> given.', 23, ], [ - 'Parameter #1 $array of function sort expects an array of values castable to string, array> given.', + 'Parameter #1 $array of function sort expects an array of values castable to string, array> given.', 25, ], [ - 'Parameter #1 $array of function rsort expects an array of values castable to string, array> given.', + 'Parameter #1 $array of function rsort expects an array of values castable to string, list> given.', 26, ], [ - 'Parameter #1 $array of function asort expects an array of values castable to string, array> given.', + 'Parameter #1 $array of function asort expects an array of values castable to string, list> given.', 27, ], [ @@ -70,11 +70,11 @@ public function testRule(): void 32, ], [ - 'Parameter #1 $array of function sort expects an array of values castable to string, array> given.', + 'Parameter #1 $array of function sort expects an array of values castable to string, array> given.', 33, ], [ - 'Parameter #1 $array of function sort expects an array of values castable to string and float, array> given.', + 'Parameter #1 $array of function sort expects an array of values castable to string and float, list> given.', 34, ], ])); @@ -88,7 +88,7 @@ public function testNamedArguments(): void $this->analyse([__DIR__ . '/data/sort-param-castable-to-string-functions-named-args.php'], [ [ - 'Parameter $array of function array_unique expects an array of values castable to string, array> given.', + 'Parameter $array of function array_unique expects an array of values castable to string, array> given.', 7, ], [ @@ -96,15 +96,15 @@ public function testNamedArguments(): void 9, ], [ - 'Parameter $array of function rsort expects an array of values castable to string, array> given.', + 'Parameter $array of function rsort expects an array of values castable to string, list> given.', 10, ], [ - 'Parameter $array of function asort expects an array of values castable to string, array> given.', + 'Parameter $array of function asort expects an array of values castable to string, list> given.', 11, ], [ - 'Parameter $array of function arsort expects an array of values castable to string, array> given.', + 'Parameter $array of function arsort expects an array of values castable to string, array> given.', 12, ], ]); @@ -126,11 +126,11 @@ public function testEnum(): void 14, ], [ - 'Parameter #1 $array of function rsort expects an array of values castable to string, array given.', + 'Parameter #1 $array of function rsort expects an array of values castable to string, list given.', 15, ], [ - 'Parameter #1 $array of function asort expects an array of values castable to string, array given.', + 'Parameter #1 $array of function asort expects an array of values castable to string, list given.', 16, ], [ diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index 150b170ca3..4c19971d5e 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -237,7 +237,7 @@ public function testReturnTypeRule(): void 759, ], [ - 'Method ReturnTypes\ArrayFillKeysIssue::getIPs2() should return array> but returns array>.', + 'Method ReturnTypes\ArrayFillKeysIssue::getIPs2() should return array> but returns array>.', 817, ], [ @@ -245,7 +245,7 @@ public function testReturnTypeRule(): void 840, ], [ - 'Method ReturnTypes\NestedArrayCheck::doFoo() should return array but returns array>.', + 'Method ReturnTypes\NestedArrayCheck::doFoo() should return array but returns array>.', 860, ], [ diff --git a/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php b/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php index 5af9a8aae4..8a69195287 100644 --- a/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/FunctionAssertRuleTest.php @@ -70,7 +70,7 @@ public function testRule(): void 70, ], [ - 'PHPDoc tag @phpstan-assert for $array has no value type specified in iterable type array.', + 'PHPDoc tag @phpstan-assert for $array has no value type specified in iterable type list.', 88, 'See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type', ], diff --git a/tests/PHPStan/Type/IntersectionTypeTest.php b/tests/PHPStan/Type/IntersectionTypeTest.php index c5dbfc07ab..7648a80ae9 100644 --- a/tests/PHPStan/Type/IntersectionTypeTest.php +++ b/tests/PHPStan/Type/IntersectionTypeTest.php @@ -7,6 +7,7 @@ use ObjectTypeEnums\FooEnum; use PHPStan\Testing\PHPStanTestCase; use PHPStan\TrinaryLogic; +use PHPStan\Type\Accessory\AccessoryArrayListType; use PHPStan\Type\Accessory\AccessoryLowercaseStringType; use PHPStan\Type\Accessory\HasPropertyType; use PHPStan\Type\Accessory\NonEmptyArrayType; @@ -418,6 +419,78 @@ public function dataDescribe(): iterable VerbosityLevel::precise(), 'lowercase-string', ]; + + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + VerbosityLevel::typeOnly(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-list', + ]; + + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new IntegerType()), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + VerbosityLevel::typeOnly(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new IntegerType()), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-list', + ]; + + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new NonEmptyArrayType(), + ]), + VerbosityLevel::typeOnly(), + 'array', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-array', + ]; + + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new IntegerType()), + new NonEmptyArrayType(), + ]), + VerbosityLevel::typeOnly(), + 'array', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new IntegerType()), + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-array', + ]; } /** From 069da3f0c6b7078620ee65fd322c593fcfa42e28 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 6 Oct 2024 16:15:48 +0200 Subject: [PATCH 363/508] TypeNodeResolver - more specific array key type for lists --- src/PhpDoc/TypeNodeResolver.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PhpDoc/TypeNodeResolver.php b/src/PhpDoc/TypeNodeResolver.php index 6dd4f821b9..f617b07693 100644 --- a/src/PhpDoc/TypeNodeResolver.php +++ b/src/PhpDoc/TypeNodeResolver.php @@ -420,10 +420,10 @@ private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameSco return new NonAcceptingNeverType(); case 'list': - return TypeCombinator::intersect(new ArrayType(new IntegerType(), new MixedType()), new AccessoryArrayListType()); + return TypeCombinator::intersect(new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), new AccessoryArrayListType()); case 'non-empty-list': return TypeCombinator::intersect( - new ArrayType(new IntegerType(), new MixedType()), + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), new NonEmptyArrayType(), new AccessoryArrayListType(), ); @@ -666,7 +666,7 @@ static function (string $variance): TemplateTypeVariance { return $arrayType; } elseif (in_array($mainTypeName, ['list', 'non-empty-list'], true)) { if (count($genericTypes) === 1) { // list - $listType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $genericTypes[0]), new AccessoryArrayListType()); + $listType = TypeCombinator::intersect(new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), $genericTypes[0]), new AccessoryArrayListType()); if ($mainTypeName === 'non-empty-list') { return TypeCombinator::intersect($listType, new NonEmptyArrayType()); } From 7717291e9e6b7783825c01aaa7b2330fa03979e3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 6 Oct 2024 16:45:43 +0200 Subject: [PATCH 364/508] [BCB] Remove `ConstantArrayType::slice()` --- UPGRADING.md | 1 + phpstan-baseline.neon | 2 +- src/Type/Constant/ConstantArrayType.php | 29 +------------------------ 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 57adbd1012..6cfb483e2a 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -289,6 +289,7 @@ Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::i * Remove `ConstantArrayType::removeFirst()`, use [`Type::shiftArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_shiftArray) instead * Remove `ConstantArrayType::reverse()`, use [`Type::reverseArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_reverseArray) instead * Remove `ConstantArrayType::chunk()`, use [`Type::chunkArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_chunkArray) instead +* Remove `ConstantArrayType::slice()`, use [`Type::sliceArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_sliceArray) instead * Made `TypeUtils` thinner by removing methods: * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 31b15792ed..246118a8d5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -882,7 +882,7 @@ parameters: - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType - count: 9 + count: 7 path: src/Type/Constant/ConstantArrayType.php - diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 8fa3cd05ff..ab0e41edc3 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -30,7 +30,6 @@ use PHPStan\Type\BooleanType; use PHPStan\Type\CompoundType; use PHPStan\Type\ConstantScalarType; -use PHPStan\Type\ConstantTypeHelper; use PHPStan\Type\ErrorType; use PHPStan\Type\GeneralizePrecision; use PHPStan\Type\Generic\TemplateTypeMap; @@ -39,10 +38,10 @@ use PHPStan\Type\IntersectionType; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; +use PHPStan\Type\NullType; use PHPStan\Type\Traits\ArrayTypeTrait; use PHPStan\Type\Traits\NonObjectTypeTrait; use PHPStan\Type\Traits\UndecidedComparisonTypeTrait; -use PHPStan\Type\NullType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\UnionType; @@ -1183,32 +1182,6 @@ private function removeFirstElements(int $length, bool $reindex = true): self return $array; } - /** @deprecated Use sliceArray() instead */ - public function slice(int $offset, ?int $limit, bool $preserveKeys = false): self - { - $array = $this->sliceArray( - ConstantTypeHelper::getTypeFromValue($offset), - ConstantTypeHelper::getTypeFromValue($limit), - TrinaryLogic::createFromBoolean($preserveKeys), - ); - if (!$array instanceof self) { - throw new ShouldNotHappenException(); - } - - return $array; - } - - /** @deprecated Use reverseArray() instead */ - public function reverse(bool $preserveKeys = false): self - { - $array = $this->reverseArray(TrinaryLogic::createFromBoolean($preserveKeys)); - if (!$array instanceof self) { - throw new ShouldNotHappenException(); - } - - return $array; - } - private function reindex(): self { $keyTypes = []; From bb19be5bf0878d17d302a89cdb4e749c764a65d5 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 3 Oct 2024 20:52:40 +0200 Subject: [PATCH 365/508] Remove $isFinal dead-code in PhpFunctionReflection --- src/Reflection/BetterReflection/BetterReflectionProvider.php | 3 --- src/Reflection/FunctionReflectionFactory.php | 1 - src/Reflection/Php/PhpFunctionReflection.php | 1 - 3 files changed, 5 deletions(-) diff --git a/src/Reflection/BetterReflection/BetterReflectionProvider.php b/src/Reflection/BetterReflection/BetterReflectionProvider.php index 7542e3ccdf..72f918f62b 100644 --- a/src/Reflection/BetterReflection/BetterReflectionProvider.php +++ b/src/Reflection/BetterReflection/BetterReflectionProvider.php @@ -304,7 +304,6 @@ private function getCustomFunction(string $functionName): PhpFunctionReflection $deprecatedTag = null; $isDeprecated = false; $isInternal = false; - $isFinal = false; $isPure = null; $asserts = Assertions::createEmpty(); $acceptsNamedArguments = true; @@ -327,7 +326,6 @@ private function getCustomFunction(string $functionName): PhpFunctionReflection $deprecatedTag = $resolvedPhpDoc->getDeprecatedTag(); $isDeprecated = $resolvedPhpDoc->isDeprecated(); $isInternal = $resolvedPhpDoc->isInternal(); - $isFinal = $resolvedPhpDoc->isFinal(); $isPure = $resolvedPhpDoc->isPure(); $asserts = Assertions::createFromResolvedPhpDocBlock($resolvedPhpDoc); if ($resolvedPhpDoc->hasPhpDocString()) { @@ -348,7 +346,6 @@ private function getCustomFunction(string $functionName): PhpFunctionReflection $deprecatedTag !== null ? $deprecatedTag->getMessage() : null, $isDeprecated, $isInternal, - $isFinal, $reflectionFunction->getFileName() !== false ? $reflectionFunction->getFileName() : null, $isPure, $asserts, diff --git a/src/Reflection/FunctionReflectionFactory.php b/src/Reflection/FunctionReflectionFactory.php index 4333954ff3..405eea46b1 100644 --- a/src/Reflection/FunctionReflectionFactory.php +++ b/src/Reflection/FunctionReflectionFactory.php @@ -25,7 +25,6 @@ public function create( ?string $deprecatedDescription, bool $isDeprecated, bool $isInternal, - bool $isFinal, ?string $filename, ?bool $isPure, Assertions $asserts, diff --git a/src/Reflection/Php/PhpFunctionReflection.php b/src/Reflection/Php/PhpFunctionReflection.php index 6209323f77..e28f19f879 100644 --- a/src/Reflection/Php/PhpFunctionReflection.php +++ b/src/Reflection/Php/PhpFunctionReflection.php @@ -54,7 +54,6 @@ public function __construct( private ?string $deprecatedDescription, private bool $isDeprecated, private bool $isInternal, - private bool $isFinal, private ?string $filename, private ?bool $isPure, private Assertions $asserts, From 544101bd8370ca434eb26b925e2a26f639491ac2 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 7 Oct 2024 08:59:17 +0200 Subject: [PATCH 366/508] Fix stubs --- stubs/ReflectionClass.stub | 6 ++++++ stubs/ext-ds.stub | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/stubs/ReflectionClass.stub b/stubs/ReflectionClass.stub index 3f6ce4bddf..889ab78f1b 100644 --- a/stubs/ReflectionClass.stub +++ b/stubs/ReflectionClass.stub @@ -6,6 +6,12 @@ class ReflectionClass { + /** + * @readonly + * @var class-string + */ + public $name; + /** * @param T|class-string $argument * @throws ReflectionException diff --git a/stubs/ext-ds.stub b/stubs/ext-ds.stub index f0b45a47b7..e05628d968 100644 --- a/stubs/ext-ds.stub +++ b/stubs/ext-ds.stub @@ -348,11 +348,21 @@ final class Map implements Collection, ArrayAccess } /** - * @template-covariant TKey - * @template-covariant TValue + * @template TKey + * @template TValue */ final class Pair implements JsonSerializable { + /** + * @var TKey + */ + public $key; + + /** + * @var TValue + */ + public $value; + /** * @param TKey $key * @param TValue $value From b256d502e7889454f5255b563afea936557612d9 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 7 Oct 2024 10:37:46 +0200 Subject: [PATCH 367/508] [BCB] Changed `TemplateType::isValidVariance()` return type to IsSuperTypeOfResult --- UPGRADING.md | 1 + src/Type/Generic/GenericObjectType.php | 6 ++---- src/Type/Generic/TemplateType.php | 4 ++-- src/Type/Generic/TemplateTypeTrait.php | 2 +- src/Type/Generic/TemplateTypeVariance.php | 21 ++++++++++----------- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 6cfb483e2a..c46f3e1742 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -313,6 +313,7 @@ Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::i * `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint * Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) * Remove `CompoundType::isAcceptedWithReasonBy()`, `CompoundType::isAcceptedBy()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) +* Remove `TemplateType::isValidVarianceWithReason()`, changed `TemplateType::isValidVariance()` return type to `IsSuperTypeOfResult` * `RuleLevelHelper::accepts()` return type changed from `bool` to [`RuleLevelHelperAcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) * Changes around `ClassConstantReflection` * Class `ClassConstantReflection` removed from BC promise, renamed to `RealClassConstantReflection` diff --git a/src/Type/Generic/GenericObjectType.php b/src/Type/Generic/GenericObjectType.php index b02995393b..779bfcc98d 100644 --- a/src/Type/Generic/GenericObjectType.php +++ b/src/Type/Generic/GenericObjectType.php @@ -190,11 +190,9 @@ private function isSuperTypeOfInternal(Type $type, bool $acceptsContext): IsSupe $thisVariance = $this->variances[$i] ?? TemplateTypeVariance::createInvariant(); $ancestorVariance = $ancestor->variances[$i] ?? TemplateTypeVariance::createInvariant(); if (!$thisVariance->invariant()) { - $result = $thisVariance->isValidVariance($templateType, $this->types[$i], $ancestor->types[$i]); - $results[] = new IsSuperTypeOfResult($result->result, $result->reasons); + $results[] = $thisVariance->isValidVariance($templateType, $this->types[$i], $ancestor->types[$i]); } else { - $result = $templateType->isValidVariance($this->types[$i], $ancestor->types[$i]); - $results[] = new IsSuperTypeOfResult($result->result, $result->reasons); + $results[] = $templateType->isValidVariance($this->types[$i], $ancestor->types[$i]); } $results[] = IsSuperTypeOfResult::createFromBoolean($thisVariance->validPosition($ancestorVariance)); diff --git a/src/Type/Generic/TemplateType.php b/src/Type/Generic/TemplateType.php index 367c94e709..4858d69242 100644 --- a/src/Type/Generic/TemplateType.php +++ b/src/Type/Generic/TemplateType.php @@ -2,8 +2,8 @@ namespace PHPStan\Type\Generic; -use PHPStan\Type\AcceptsResult; use PHPStan\Type\CompoundType; +use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\Type; /** @api */ @@ -21,7 +21,7 @@ public function toArgument(): TemplateType; public function isArgument(): bool; - public function isValidVariance(Type $a, Type $b): AcceptsResult; + public function isValidVariance(Type $a, Type $b): IsSuperTypeOfResult; public function getVariance(): TemplateTypeVariance; diff --git a/src/Type/Generic/TemplateTypeTrait.php b/src/Type/Generic/TemplateTypeTrait.php index 8e8df311f9..053bbf8160 100644 --- a/src/Type/Generic/TemplateTypeTrait.php +++ b/src/Type/Generic/TemplateTypeTrait.php @@ -92,7 +92,7 @@ public function toArgument(): TemplateType ); } - public function isValidVariance(Type $a, Type $b): AcceptsResult + public function isValidVariance(Type $a, Type $b): IsSuperTypeOfResult { return $this->variance->isValidVariance($this, $a, $b); } diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index bbd0790350..a2269616c9 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -5,7 +5,6 @@ use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; -use PHPStan\Type\AcceptsResult; use PHPStan\Type\BenevolentUnionType; use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\MixedType; @@ -127,30 +126,30 @@ public function compose(self $other): self return $other; } - public function isValidVariance(TemplateType $templateType, Type $a, Type $b): AcceptsResult + public function isValidVariance(TemplateType $templateType, Type $a, Type $b): IsSuperTypeOfResult { if ($b instanceof NeverType) { - return AcceptsResult::createYes(); + return IsSuperTypeOfResult::createYes(); } if ($a instanceof MixedType && !$a instanceof TemplateType) { - return AcceptsResult::createYes(); + return IsSuperTypeOfResult::createYes(); } if ($a instanceof BenevolentUnionType) { if (!$a->isSuperTypeOf($b)->no()) { - return AcceptsResult::createYes(); + return IsSuperTypeOfResult::createYes(); } } if ($b instanceof BenevolentUnionType) { if (!$b->isSuperTypeOf($a)->no()) { - return AcceptsResult::createYes(); + return IsSuperTypeOfResult::createYes(); } } if ($b instanceof MixedType && !$b instanceof TemplateType) { - return AcceptsResult::createYes(); + return IsSuperTypeOfResult::createYes(); } if ($this->invariant()) { @@ -169,19 +168,19 @@ public function isValidVariance(TemplateType $templateType, Type $a, Type $b): A } } - return new AcceptsResult(TrinaryLogic::createFromBoolean($result), $reasons); + return new IsSuperTypeOfResult(TrinaryLogic::createFromBoolean($result), $reasons); } if ($this->covariant()) { - return $a->isSuperTypeOfWithReason($b)->toAcceptsResult(); + return $a->isSuperTypeOfWithReason($b); } if ($this->contravariant()) { - return $b->isSuperTypeOfWithReason($a)->toAcceptsResult(); + return $b->isSuperTypeOfWithReason($a); } if ($this->bivariant()) { - return AcceptsResult::createYes(); + return IsSuperTypeOfResult::createYes(); } throw new ShouldNotHappenException(); From f81bc5d33a10b517bb8834bfe21ff85b26802193 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 7 Oct 2024 10:45:30 +0200 Subject: [PATCH 368/508] [BCB] Remove `Type::isSuperTypeOfWithReason()`, `Type::isSuperTypeOf()` return type changed to IsSuperTypeOfResult --- UPGRADING.md | 4 +- src/Analyser/TypeSpecifier.php | 4 +- src/Reflection/ParametersAcceptorSelector.php | 2 +- .../Comparison/ImpossibleCheckTypeHelper.php | 4 +- src/Rules/Methods/MethodSignatureRule.php | 4 +- src/Type/Accessory/AccessoryArrayListType.php | 22 +++------- .../Accessory/AccessoryLiteralStringType.php | 20 +++------- .../AccessoryLowercaseStringType.php | 20 +++------- .../Accessory/AccessoryNonEmptyStringType.php | 20 +++------- .../Accessory/AccessoryNonFalsyStringType.php | 20 +++------- .../Accessory/AccessoryNumericStringType.php | 20 +++------- src/Type/Accessory/HasMethodType.php | 18 ++------- src/Type/Accessory/HasOffsetType.php | 18 ++------- src/Type/Accessory/HasOffsetValueType.php | 22 +++------- src/Type/Accessory/HasPropertyType.php | 18 ++------- src/Type/Accessory/NonEmptyArrayType.php | 20 +++------- src/Type/Accessory/OversizedArrayType.php | 20 +++------- src/Type/ArrayType.php | 13 ++---- src/Type/CallableType.php | 20 +++------- src/Type/CallableTypeHelper.php | 4 +- src/Type/ClassStringType.php | 9 +---- src/Type/ClosureType.php | 11 ++--- src/Type/CompoundType.php | 11 +---- src/Type/ConditionalType.php | 12 ++---- src/Type/ConditionalTypeForParameter.php | 12 ++---- src/Type/Constant/ConstantArrayType.php | 15 +++---- src/Type/Constant/ConstantIntegerType.php | 10 +---- src/Type/Constant/ConstantStringType.php | 15 +++---- src/Type/Enum/EnumCaseObjectType.php | 15 +++---- src/Type/FloatType.php | 9 +---- src/Type/Generic/GenericClassStringType.php | 16 +++----- src/Type/Generic/GenericObjectType.php | 12 ++---- src/Type/Generic/TemplateMixedType.php | 6 +-- src/Type/Generic/TemplateStrictMixedType.php | 6 +-- src/Type/Generic/TemplateTypeTrait.php | 26 ++++-------- src/Type/Generic/TemplateTypeVariance.php | 4 +- src/Type/IntegerRangeType.php | 26 ++++-------- src/Type/IntersectionType.php | 20 +++------- src/Type/IsSuperTypeOfResult.php | 5 +++ src/Type/IterableType.php | 40 +++++++------------ src/Type/JustNullableTypeTrait.php | 9 +---- src/Type/MixedType.php | 40 +++++++------------ src/Type/NeverType.php | 16 ++------ src/Type/NonAcceptingNeverType.php | 9 +---- src/Type/NullType.php | 9 +---- src/Type/ObjectShapeType.php | 11 ++--- src/Type/ObjectType.php | 13 ++---- src/Type/ObjectWithoutClassType.php | 13 ++---- src/Type/StaticType.php | 13 ++---- src/Type/StrictMixedType.php | 14 +------ ...gAlwaysAcceptingObjectWithToStringType.php | 12 ++---- src/Type/ThisType.php | 14 ++----- src/Type/Traits/ConstantScalarTypeTrait.php | 9 +---- src/Type/Traits/LateResolvableTypeTrait.php | 20 +++------- src/Type/Type.php | 11 +---- src/Type/UnionType.php | 22 +++------- src/Type/VoidType.php | 9 +---- 57 files changed, 231 insertions(+), 586 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index c46f3e1742..5fe143b645 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -313,7 +313,9 @@ Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::i * `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint * Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) * Remove `CompoundType::isAcceptedWithReasonBy()`, `CompoundType::isAcceptedBy()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) -* Remove `TemplateType::isValidVarianceWithReason()`, changed `TemplateType::isValidVariance()` return type to `IsSuperTypeOfResult` +Remove `Type::isSuperTypeOfWithReason()`, `Type:isSuperTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) +* Remove `CompoundType::isSubTypeOfWithReasonBy()`, `CompoundType::isSubTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) +* Remove `TemplateType::isValidVarianceWithReason()`, changed `TemplateType::isValidVariance()` return type to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) * `RuleLevelHelper::accepts()` return type changed from `bool` to [`RuleLevelHelperAcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) * Changes around `ClassConstantReflection` * Class `ClassConstantReflection` removed from BC promise, renamed to `RealClassConstantReflection` diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 1006f33633..a78fc63cbc 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -963,7 +963,7 @@ private function narrowUnionByArraySize(FuncCall $countFuncCall, UnionType $argT $isNormalCount = TrinaryLogic::createYes(); } else { $mode = $scope->getType($countFuncCall->getArgs()[1]->value); - $isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->or($argType->getIterableValueType()->isArray()->negate()); + $isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->result->or($argType->getIterableValueType()->isArray()->negate()); } if ( @@ -1007,7 +1007,7 @@ private function turnListIntoConstantArray(FuncCall $countFuncCall, Type $type, $isNormalCount = TrinaryLogic::createYes(); } else { $mode = $scope->getType($countFuncCall->getArgs()[1]->value); - $isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->or($argType->getIterableValueType()->isArray()->negate()); + $isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->result->or($argType->getIterableValueType()->isArray()->negate()); } if ( diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index cc36c1d951..455e72a704 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -510,7 +510,7 @@ public static function selectFromTypes( if ($parameter->getType() instanceof MixedType) { $isSuperType = $isSuperType->and(TrinaryLogic::createMaybe()); } else { - $isSuperType = $isSuperType->and($parameter->getType()->isSuperTypeOf($type)); + $isSuperType = $isSuperType->and($parameter->getType()->isSuperTypeOf($type)->result); } } diff --git a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php index b61904f26b..48eea97d6f 100644 --- a/src/Rules/Comparison/ImpossibleCheckTypeHelper.php +++ b/src/Rules/Comparison/ImpossibleCheckTypeHelper.php @@ -282,7 +282,7 @@ public function findSpecifiedType( /** @var Type $resultType */ $resultType = $sureType[1]; - $results[] = $resultType->isSuperTypeOf($argumentType); + $results[] = $resultType->isSuperTypeOf($argumentType)->result; } foreach ($sureNotTypes as $sureNotType) { @@ -300,7 +300,7 @@ public function findSpecifiedType( /** @var Type $resultType */ $resultType = $sureNotType[1]; - $results[] = $resultType->isSuperTypeOf($argumentType)->negate(); + $results[] = $resultType->isSuperTypeOf($argumentType)->negate()->result; } if (count($results) === 0) { diff --git a/src/Rules/Methods/MethodSignatureRule.php b/src/Rules/Methods/MethodSignatureRule.php index c3c04089ce..86b4614133 100644 --- a/src/Rules/Methods/MethodSignatureRule.php +++ b/src/Rules/Methods/MethodSignatureRule.php @@ -219,7 +219,7 @@ private function checkReturnTypeCompatibility( return [TrinaryLogic::createYes(), $returnType, $parentReturnType]; } - return [$parentReturnType->isSuperTypeOf($returnType), TypehintHelper::decideType( + return [$parentReturnType->isSuperTypeOf($returnType)->result, TypehintHelper::decideType( $currentVariant->getNativeReturnType(), $currentVariant->getPhpDocReturnType(), ), $originalParentReturnType]; @@ -253,7 +253,7 @@ private function checkParameterTypeCompatibility( ); $parentParameterType = $this->transformStaticType($declaringClass, $originalParameterType); - $parameterResults[] = [$parameterType->isSuperTypeOf($parentParameterType), TypehintHelper::decideType( + $parameterResults[] = [$parameterType->isSuperTypeOf($parentParameterType)->result, TypehintHelper::decideType( $parameter->getNativeType(), $parameter->getPhpDocType(), ), $originalParameterType]; diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index 3e00d609d9..62e5205b8f 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -87,33 +87,23 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($isArray->and($isList), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isList()), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return (new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isList()), [])) @@ -122,7 +112,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool @@ -147,7 +137,7 @@ public function isOffsetAccessLegal(): TrinaryLogic public function hasOffsetValueType(Type $offsetType): TrinaryLogic { - return $this->getIterableKeyType()->isSuperTypeOf($offsetType)->and(TrinaryLogic::createMaybe()); + return $this->getIterableKeyType()->isSuperTypeOf($offsetType)->result->and(TrinaryLogic::createMaybe()); } public function getOffsetValueType(Type $offsetType): Type diff --git a/src/Type/Accessory/AccessoryLiteralStringType.php b/src/Type/Accessory/AccessoryLiteralStringType.php index a206842873..4c99637c60 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.php @@ -80,15 +80,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isLiteralString(), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($this->equals($type)) { @@ -98,15 +93,10 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return new IsSuperTypeOfResult($type->isLiteralString(), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return (new IsSuperTypeOfResult($otherType->isLiteralString(), [])) @@ -115,7 +105,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/AccessoryLowercaseStringType.php b/src/Type/Accessory/AccessoryLowercaseStringType.php index 0893a0e3df..a959dfbebf 100644 --- a/src/Type/Accessory/AccessoryLowercaseStringType.php +++ b/src/Type/Accessory/AccessoryLowercaseStringType.php @@ -76,15 +76,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isLowercaseString(), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($this->equals($type)) { @@ -94,15 +89,10 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return new IsSuperTypeOfResult($type->isLowercaseString(), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return (new IsSuperTypeOfResult($otherType->isLowercaseString(), [])) @@ -111,7 +101,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/AccessoryNonEmptyStringType.php b/src/Type/Accessory/AccessoryNonEmptyStringType.php index 1374071903..d3d4aa406c 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -78,15 +78,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isNonEmptyString(), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($this->equals($type)) { @@ -100,15 +95,10 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return new IsSuperTypeOfResult($type->isNonEmptyString(), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return (new IsSuperTypeOfResult($otherType->isNonEmptyString(), [])) @@ -117,7 +107,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/AccessoryNonFalsyStringType.php b/src/Type/Accessory/AccessoryNonFalsyStringType.php index ea97eebab1..871a3473fa 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.php @@ -78,15 +78,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isNonFalsyString(), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($this->equals($type)) { @@ -96,15 +91,10 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return new IsSuperTypeOfResult($type->isNonFalsyString(), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } if ($otherType instanceof AccessoryNonEmptyStringType) { @@ -117,7 +107,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/AccessoryNumericStringType.php b/src/Type/Accessory/AccessoryNumericStringType.php index 05da3126c5..78fde66dab 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.php @@ -77,15 +77,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isNumericString(), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($this->equals($type)) { @@ -95,15 +90,10 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return new IsSuperTypeOfResult($type->isNumericString(), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return (new IsSuperTypeOfResult($otherType->isNumericString(), [])) @@ -120,7 +110,7 @@ public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsRes return AcceptsResult::createYes(); } - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/HasMethodType.php b/src/Type/Accessory/HasMethodType.php index 04424d84f0..94364bb21f 100644 --- a/src/Type/Accessory/HasMethodType.php +++ b/src/Type/Accessory/HasMethodType.php @@ -71,25 +71,15 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createFromBoolean($this->equals($type)); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { return new IsSuperTypeOfResult($type->hasMethod($this->methodName), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } if ($this->isCallable()->yes() && $otherType->isCallable()->yes()) { @@ -107,7 +97,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/HasOffsetType.php b/src/Type/Accessory/HasOffsetType.php index 7401ee5629..10c3722dab 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -89,12 +89,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); @@ -102,15 +97,10 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return new IsSuperTypeOfResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } $result = new IsSuperTypeOfResult($otherType->isOffsetAccessible()->and($otherType->hasOffsetValueType($this->offsetType)), []); @@ -121,7 +111,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/HasOffsetValueType.php b/src/Type/Accessory/HasOffsetValueType.php index ef4a70adf3..c30f30e1c0 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -95,12 +95,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult ); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); @@ -109,30 +104,25 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult $result = new IsSuperTypeOfResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); return $result - ->and($this->valueType->isSuperTypeOfWithReason($type->getOffsetValueType($this->offsetType))); - } - - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; + ->and($this->valueType->isSuperTypeOf($type->getOffsetValueType($this->offsetType))); } - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } $result = new IsSuperTypeOfResult($otherType->isOffsetAccessible()->and($otherType->hasOffsetValueType($this->offsetType)), []); return $result - ->and($otherType->getOffsetValueType($this->offsetType)->isSuperTypeOfWithReason($this->valueType)) + ->and($otherType->getOffsetValueType($this->offsetType)->isSuperTypeOf($this->valueType)) ->and($otherType instanceof self ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createMaybe()); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/HasPropertyType.php b/src/Type/Accessory/HasPropertyType.php index 2b8a2d1d06..71b6b42759 100644 --- a/src/Type/Accessory/HasPropertyType.php +++ b/src/Type/Accessory/HasPropertyType.php @@ -70,25 +70,15 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createFromBoolean($this->equals($type)); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { return new IsSuperTypeOfResult($type->hasProperty($this->propertyName), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } if ($otherType instanceof self) { @@ -102,7 +92,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/NonEmptyArrayType.php b/src/Type/Accessory/NonEmptyArrayType.php index beaa20c06b..b7da64e0b8 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -85,33 +85,23 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($isArray->and($isIterableAtLeastOnce), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isIterableAtLeastOnce()), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return (new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isIterableAtLeastOnce()), [])) @@ -120,7 +110,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/Accessory/OversizedArrayType.php b/src/Type/Accessory/OversizedArrayType.php index ac9e45da1b..07f76e888a 100644 --- a/src/Type/Accessory/OversizedArrayType.php +++ b/src/Type/Accessory/OversizedArrayType.php @@ -81,33 +81,23 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isArray()->and($type->isIterableAtLeastOnce()), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->isArray()->and($type->isOversizedArray()), []); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof UnionType || $otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return (new IsSuperTypeOfResult($otherType->isArray()->and($otherType->isOversizedArray()), [])) @@ -116,7 +106,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 93ce993005..8fb1a219d5 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -105,20 +105,15 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createNo(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self || $type instanceof ConstantArrayType) { - return $this->getItemType()->isSuperTypeOfWithReason($type->getItemType()) - ->and($this->getIterableKeyType()->isSuperTypeOfWithReason($type->getIterableKeyType())); + return $this->getItemType()->isSuperTypeOf($type->getItemType()) + ->and($this->getIterableKeyType()->isSuperTypeOf($type->getIterableKeyType())); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 74d3b2cc49..c42961fce5 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -135,15 +135,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $this->isSuperTypeOfInternal($type, true)->toAcceptsResult(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType && !$type instanceof self) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return $this->isSuperTypeOfInternal($type, false); @@ -191,15 +186,10 @@ private function isSuperTypeOfInternal(Type $type, bool $treatMixedAsAny): IsSup return $isCallable->and($variantsResult); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof IntersectionType || $otherType instanceof UnionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return (new IsSuperTypeOfResult($otherType->isCallable(), [])) @@ -208,7 +198,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/CallableTypeHelper.php b/src/Type/CallableTypeHelper.php index 203e0d048e..4e99e94cc9 100644 --- a/src/Type/CallableTypeHelper.php +++ b/src/Type/CallableTypeHelper.php @@ -75,7 +75,7 @@ public static function isParametersAcceptorSuperTypeOf( $isSuperType = $theirParameter->getType()->accepts($ourParameterType, true); $isSuperType = new IsSuperTypeOfResult($isSuperType->result, $isSuperType->reasons); } else { - $isSuperType = $theirParameter->getType()->isSuperTypeOfWithReason($ourParameterType); + $isSuperType = $theirParameter->getType()->isSuperTypeOf($ourParameterType); } if ($isSuperType->maybe()) { @@ -102,7 +102,7 @@ public static function isParametersAcceptorSuperTypeOf( $isReturnTypeSuperType = $ours->getReturnType()->accepts($theirReturnType, true); $isReturnTypeSuperType = new IsSuperTypeOfResult($isReturnTypeSuperType->result, $isReturnTypeSuperType->reasons); } else { - $isReturnTypeSuperType = $ours->getReturnType()->isSuperTypeOfWithReason($theirReturnType); + $isReturnTypeSuperType = $ours->getReturnType()->isSuperTypeOf($theirReturnType); } $pure = $ours->isPure(); diff --git a/src/Type/ClassStringType.php b/src/Type/ClassStringType.php index 57d85316c7..b5b09e9e73 100644 --- a/src/Type/ClassStringType.php +++ b/src/Type/ClassStringType.php @@ -30,15 +30,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isClassString(), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return new IsSuperTypeOfResult($type->isClassString(), []); diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index 64defc1524..26063e2fa9 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -198,15 +198,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $this->isSuperTypeOfInternal($type, true)->toAcceptsResult(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return $this->isSuperTypeOfInternal($type, false); @@ -226,7 +221,7 @@ private function isSuperTypeOfInternal(Type $type, bool $treatMixedAsAny): IsSup return IsSuperTypeOfResult::createMaybe(); } - return $this->objectType->isSuperTypeOfWithReason($type); + return $this->objectType->isSuperTypeOf($type); } public function equals(Type $type): bool diff --git a/src/Type/CompoundType.php b/src/Type/CompoundType.php index 54637fd45b..f66e10c091 100644 --- a/src/Type/CompoundType.php +++ b/src/Type/CompoundType.php @@ -9,18 +9,9 @@ interface CompoundType extends Type { - public function isSubTypeOf(Type $otherType): TrinaryLogic; - public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult; - /** - * This is like isSubTypeOf() but gives reasons - * why the type was not/might not be accepted in some non-intuitive scenarios. - * - * In PHPStan 2.0 this method will be removed and the return type of isSubTypeOf() - * will change to IsSuperTypeOfResult. - */ - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult; + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult; public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic; diff --git a/src/Type/ConditionalType.php b/src/Type/ConditionalType.php index ab283f5e23..f154fb5368 100644 --- a/src/Type/ConditionalType.php +++ b/src/Type/ConditionalType.php @@ -4,7 +4,6 @@ use PHPStan\PhpDocParser\Ast\Type\ConditionalTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; -use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeVariance; use PHPStan\Type\Traits\LateResolvableTypeTrait; use PHPStan\Type\Traits\NonGeneralizableTypeTrait; @@ -61,16 +60,11 @@ public function isNegated(): bool return $this->negated; } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { - return $this->if->isSuperTypeOfWithReason($type->if) - ->and($this->else->isSuperTypeOfWithReason($type->else)); + return $this->if->isSuperTypeOf($type->if) + ->and($this->else->isSuperTypeOf($type->else)); } return $this->isSuperTypeOfDefault($type); diff --git a/src/Type/ConditionalTypeForParameter.php b/src/Type/ConditionalTypeForParameter.php index 89ae748982..0fd8cf4475 100644 --- a/src/Type/ConditionalTypeForParameter.php +++ b/src/Type/ConditionalTypeForParameter.php @@ -4,7 +4,6 @@ use PHPStan\PhpDocParser\Ast\Type\ConditionalTypeForParameterNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; -use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeVariance; use PHPStan\Type\Traits\LateResolvableTypeTrait; use PHPStan\Type\Traits\NonGeneralizableTypeTrait; @@ -75,16 +74,11 @@ public function toConditional(Type $subject): Type ); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { - return $this->if->isSuperTypeOfWithReason($type->if) - ->and($this->else->isSuperTypeOfWithReason($type->else)); + return $this->if->isSuperTypeOf($type->if) + ->and($this->else->isSuperTypeOf($type->else)); } return $this->isSuperTypeOfDefault($type); diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index b77802d759..46315a4eae 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -365,12 +365,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $result; } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { if (count($this->keyTypes) === 0) { @@ -391,7 +386,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult $results[] = IsSuperTypeOfResult::createMaybe(); } - $isValueSuperType = $this->valueTypes[$i]->isSuperTypeOfWithReason($type->getOffsetValueType($keyType)); + $isValueSuperType = $this->valueTypes[$i]->isSuperTypeOf($type->getOffsetValueType($keyType)); if ($isValueSuperType->no()) { return $isValueSuperType; } @@ -407,16 +402,16 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return $result; } - $isKeySuperType = $this->getKeyType()->isSuperTypeOfWithReason($type->getKeyType()); + $isKeySuperType = $this->getKeyType()->isSuperTypeOf($type->getKeyType()); if ($isKeySuperType->no()) { return $isKeySuperType; } - return $result->and($isKeySuperType, $this->getItemType()->isSuperTypeOfWithReason($type->getItemType())); + return $result->and($isKeySuperType, $this->getItemType()->isSuperTypeOf($type->getItemType())); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); diff --git a/src/Type/Constant/ConstantIntegerType.php b/src/Type/Constant/ConstantIntegerType.php index ce9d490116..52f29d37a2 100644 --- a/src/Type/Constant/ConstantIntegerType.php +++ b/src/Type/Constant/ConstantIntegerType.php @@ -5,7 +5,6 @@ use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode; use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; -use PHPStan\TrinaryLogic; use PHPStan\Type\CompoundType; use PHPStan\Type\ConstantScalarType; use PHPStan\Type\GeneralizePrecision; @@ -38,12 +37,7 @@ public function getValue(): int return $this->value; } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return $this->value === $type->value ? IsSuperTypeOfResult::createYes() : IsSuperTypeOfResult::createNo(); @@ -64,7 +58,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); diff --git a/src/Type/Constant/ConstantStringType.php b/src/Type/Constant/ConstantStringType.php index 2643ab810a..f2991857b7 100644 --- a/src/Type/Constant/ConstantStringType.php +++ b/src/Type/Constant/ConstantStringType.php @@ -139,12 +139,7 @@ private function export(string $value): string return "'" . addcslashes($value, '\\\'') . "'"; } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof GenericClassStringType) { $genericType = $type->getGenericType(); @@ -162,9 +157,9 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult // Do not use TemplateType's isSuperTypeOf handling directly because it takes ObjectType // uncertainty into account. if ($genericType instanceof TemplateType) { - $isSuperType = $genericType->getBound()->isSuperTypeOfWithReason($objectType); + $isSuperType = $genericType->getBound()->isSuperTypeOf($objectType); } else { - $isSuperType = $genericType->isSuperTypeOfWithReason($objectType); + $isSuperType = $genericType->isSuperTypeOf($objectType); } // Explicitly handle the uncertainty for Yes & Maybe. @@ -186,7 +181,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); @@ -351,7 +346,7 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic { if ($offsetType->isInteger()->yes()) { $strLenType = IntegerRangeType::fromInterval(0, strlen($this->value) - 1); - return $strLenType->isSuperTypeOf($offsetType); + return $strLenType->isSuperTypeOf($offsetType)->result; } return parent::hasOffsetValueType($offsetType); diff --git a/src/Type/Enum/EnumCaseObjectType.php b/src/Type/Enum/EnumCaseObjectType.php index 72ee1bf9d2..5e803a6af9 100644 --- a/src/Type/Enum/EnumCaseObjectType.php +++ b/src/Type/Enum/EnumCaseObjectType.php @@ -62,15 +62,10 @@ public function equals(Type $type): bool public function accepts(Type $type, bool $strictTypes): AcceptsResult { - return $this->isSuperTypeOfWithReason($type)->toAcceptsResult(); + return $this->isSuperTypeOf($type)->toAcceptsResult(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createFromBoolean( @@ -79,14 +74,14 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ( $type instanceof SubtractableType && $type->getSubtractedType() !== null ) { - $isSuperType = $type->getSubtractedType()->isSuperTypeOfWithReason($this); + $isSuperType = $type->getSubtractedType()->isSuperTypeOf($this); if ($isSuperType->yes()) { return IsSuperTypeOfResult::createNo(); } @@ -94,7 +89,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult $parent = new parent($this->getClassName(), $this->getSubtractedType(), $this->getClassReflection()); - return $parent->isSuperTypeOfWithReason($type)->and(IsSuperTypeOfResult::createMaybe()); + return $parent->isSuperTypeOf($type)->and(IsSuperTypeOfResult::createMaybe()); } public function subtract(Type $type): Type diff --git a/src/Type/FloatType.php b/src/Type/FloatType.php index d1a77c2f76..531b177af9 100644 --- a/src/Type/FloatType.php +++ b/src/Type/FloatType.php @@ -74,19 +74,14 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createNo(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); diff --git a/src/Type/Generic/GenericClassStringType.php b/src/Type/Generic/GenericClassStringType.php index 9fe2da3a79..4e04a9df28 100644 --- a/src/Type/Generic/GenericClassStringType.php +++ b/src/Type/Generic/GenericClassStringType.php @@ -6,7 +6,6 @@ use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\ReflectionProviderStaticAccessor; -use PHPStan\TrinaryLogic; use PHPStan\Type\AcceptsResult; use PHPStan\Type\ClassStringType; use PHPStan\Type\CompoundType; @@ -86,15 +85,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $this->type->accepts($objectType, $strictTypes); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($type instanceof ConstantStringType) { @@ -114,9 +108,9 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult // Do not use TemplateType's isSuperTypeOf handling directly because it takes ObjectType // uncertainty into account. if ($genericType instanceof TemplateType) { - $isSuperType = $genericType->getBound()->isSuperTypeOfWithReason($objectType); + $isSuperType = $genericType->getBound()->isSuperTypeOf($objectType); } else { - $isSuperType = $genericType->isSuperTypeOfWithReason($objectType); + $isSuperType = $genericType->isSuperTypeOf($objectType); } if (!$type->isClassString()->yes()) { @@ -125,7 +119,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return $isSuperType; } elseif ($type instanceof self) { - return $this->type->isSuperTypeOfWithReason($type->type); + return $this->type->isSuperTypeOf($type->type); } elseif ($type instanceof StringType) { return IsSuperTypeOfResult::createMaybe(); } diff --git a/src/Type/Generic/GenericObjectType.php b/src/Type/Generic/GenericObjectType.php index 779bfcc98d..a2bdadd7ae 100644 --- a/src/Type/Generic/GenericObjectType.php +++ b/src/Type/Generic/GenericObjectType.php @@ -13,7 +13,6 @@ use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection; use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\ShouldNotHappenException; -use PHPStan\TrinaryLogic; use PHPStan\Type\AcceptsResult; use PHPStan\Type\CompoundType; use PHPStan\Type\ErrorType; @@ -125,15 +124,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $this->isSuperTypeOfInternal($type, true)->toAcceptsResult(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return $this->isSuperTypeOfInternal($type, false); @@ -141,7 +135,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult private function isSuperTypeOfInternal(Type $type, bool $acceptsContext): IsSuperTypeOfResult { - $nakedSuperTypeOf = parent::isSuperTypeOfWithReason($type); + $nakedSuperTypeOf = parent::isSuperTypeOf($type); if ($nakedSuperTypeOf->no()) { return $nakedSuperTypeOf; } diff --git a/src/Type/Generic/TemplateMixedType.php b/src/Type/Generic/TemplateMixedType.php index e421d8f9a3..a62f9d6f14 100644 --- a/src/Type/Generic/TemplateMixedType.php +++ b/src/Type/Generic/TemplateMixedType.php @@ -2,8 +2,8 @@ namespace PHPStan\Type\Generic; -use PHPStan\TrinaryLogic; use PHPStan\Type\AcceptsResult; +use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\MixedType; use PHPStan\Type\StrictMixedType; use PHPStan\Type\Type; @@ -35,14 +35,14 @@ public function __construct( $this->bound = $bound; } - public function isSuperTypeOfMixed(MixedType $type): TrinaryLogic + public function isSuperTypeOfMixed(MixedType $type): IsSuperTypeOfResult { return $this->isSuperTypeOf($type); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - $isSuperType = $this->isSuperTypeOfWithReason($acceptingType)->toAcceptsResult(); + $isSuperType = $this->isSuperTypeOf($acceptingType)->toAcceptsResult(); if ($isSuperType->no()) { return $isSuperType; } diff --git a/src/Type/Generic/TemplateStrictMixedType.php b/src/Type/Generic/TemplateStrictMixedType.php index f363f249cd..13f52b276c 100644 --- a/src/Type/Generic/TemplateStrictMixedType.php +++ b/src/Type/Generic/TemplateStrictMixedType.php @@ -2,8 +2,8 @@ namespace PHPStan\Type\Generic; -use PHPStan\TrinaryLogic; use PHPStan\Type\AcceptsResult; +use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\MixedType; use PHPStan\Type\StrictMixedType; use PHPStan\Type\Type; @@ -33,14 +33,14 @@ public function __construct( $this->bound = $bound; } - public function isSuperTypeOfMixed(MixedType $type): TrinaryLogic + public function isSuperTypeOfMixed(MixedType $type): IsSuperTypeOfResult { return $this->isSuperTypeOf($type); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } } diff --git a/src/Type/Generic/TemplateTypeTrait.php b/src/Type/Generic/TemplateTypeTrait.php index 053bbf8160..5ea5a7da04 100644 --- a/src/Type/Generic/TemplateTypeTrait.php +++ b/src/Type/Generic/TemplateTypeTrait.php @@ -189,31 +189,21 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $this->strategy->accepts($this, $type, $strictTypes); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof TemplateType || $type instanceof IntersectionType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($type instanceof NeverType) { return IsSuperTypeOfResult::createYes(); } - return $this->getBound()->isSuperTypeOfWithReason($type) + return $this->getBound()->isSuperTypeOf($type) ->and(IsSuperTypeOfResult::createMaybe()); } - public function isSubTypeOf(Type $type): TrinaryLogic - { - return $this->isSubTypeOfWithReason($type)->result; - } - - public function isSubTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSubTypeOf(Type $type): IsSuperTypeOfResult { /** @var TBound $bound */ $bound = $this->getBound(); @@ -223,18 +213,18 @@ public function isSubTypeOfWithReason(Type $type): IsSuperTypeOfResult && !$type instanceof TemplateType && ($type instanceof UnionType || $type instanceof IntersectionType) ) { - return $type->isSuperTypeOfWithReason($this); + return $type->isSuperTypeOf($this); } if (!$type instanceof TemplateType) { - return $type->isSuperTypeOfWithReason($this->getBound()); + return $type->isSuperTypeOf($this->getBound()); } if ($this->getScope()->equals($type->getScope()) && $this->getName() === $type->getName()) { - return $type->getBound()->isSuperTypeOfWithReason($this->getBound()); + return $type->getBound()->isSuperTypeOf($this->getBound()); } - return $type->getBound()->isSuperTypeOfWithReason($this->getBound()) + return $type->getBound()->isSuperTypeOf($this->getBound()) ->and(IsSuperTypeOfResult::createMaybe()); } diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index a2269616c9..a630895bed 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -172,11 +172,11 @@ public function isValidVariance(TemplateType $templateType, Type $a, Type $b): I } if ($this->covariant()) { - return $a->isSuperTypeOfWithReason($b); + return $a->isSuperTypeOf($b); } if ($this->contravariant()) { - return $b->isSuperTypeOfWithReason($a); + return $b->isSuperTypeOf($a); } if ($this->bivariant()) { diff --git a/src/Type/IntegerRangeType.php b/src/Type/IntegerRangeType.php index 1f3ed5450b..2e9391e9d1 100644 --- a/src/Type/IntegerRangeType.php +++ b/src/Type/IntegerRangeType.php @@ -206,7 +206,7 @@ public function shift(int $amount): Type public function accepts(Type $type, bool $strictTypes): AcceptsResult { if ($type instanceof parent) { - return $this->isSuperTypeOfWithReason($type)->toAcceptsResult(); + return $this->isSuperTypeOf($type)->toAcceptsResult(); } if ($type instanceof CompoundType) { @@ -216,12 +216,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createNo(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self || $type instanceof ConstantIntegerType) { if ($type instanceof self) { @@ -251,21 +246,16 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof parent) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } if ($otherType instanceof UnionType) { @@ -273,7 +263,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult } if ($otherType instanceof IntersectionType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } return IsSuperTypeOfResult::createNo(); @@ -292,12 +282,12 @@ private function isSubTypeOfUnionWithReason(UnionType $otherType): IsSuperTypeOf } } - return IsSuperTypeOfResult::createNo()->or(...array_map(fn (Type $innerType) => $this->isSubTypeOfWithReason($innerType), $otherType->getTypes())); + return IsSuperTypeOfResult::createNo()->or(...array_map(fn (Type $innerType) => $this->isSubTypeOf($innerType), $otherType->getTypes())); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index 10fbe76b42..2dec6cc456 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -218,12 +218,7 @@ public function accepts(Type $otherType, bool $strictTypes): AcceptsResult return $result; } - public function isSuperTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($otherType)->result; - } - - public function isSuperTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSuperTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof IntersectionType && $this->equals($otherType)) { return IsSuperTypeOfResult::createYes(); @@ -233,21 +228,16 @@ public function isSuperTypeOfWithReason(Type $otherType): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return IsSuperTypeOfResult::createYes()->and(...array_map(static fn (Type $innerType) => $innerType->isSuperTypeOfWithReason($otherType), $this->types)); - } - - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; + return IsSuperTypeOfResult::createYes()->and(...array_map(static fn (Type $innerType) => $innerType->isSuperTypeOf($otherType), $this->types)); } - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if (($otherType instanceof self || $otherType instanceof UnionType) && !$otherType instanceof TemplateType) { - return $otherType->isSuperTypeOfWithReason($this); + return $otherType->isSuperTypeOf($this); } - $result = IsSuperTypeOfResult::maxMin(...array_map(static fn (Type $innerType) => $otherType->isSuperTypeOfWithReason($innerType), $this->types)); + $result = IsSuperTypeOfResult::maxMin(...array_map(static fn (Type $innerType) => $otherType->isSuperTypeOf($innerType), $this->types)); if ($this->isOversizedArray()->yes()) { if (!$result->no()) { return IsSuperTypeOfResult::createYes(); diff --git a/src/Type/IsSuperTypeOfResult.php b/src/Type/IsSuperTypeOfResult.php index 30e9fe6acc..61e9b4e9c8 100644 --- a/src/Type/IsSuperTypeOfResult.php +++ b/src/Type/IsSuperTypeOfResult.php @@ -139,6 +139,11 @@ public function negate(): self return new self($this->result->negate(), $this->reasons); } + public function describe(): string + { + return $this->result->describe(); + } + /** * @param array $operands * diff --git a/src/Type/IterableType.php b/src/Type/IterableType.php index 861b927d3c..c7ce1499ca 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -92,30 +92,25 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createNo(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return (new IsSuperTypeOfResult($type->isIterable(), [])) - ->and($this->getIterableValueType()->isSuperTypeOfWithReason($type->getIterableValueType())) - ->and($this->getIterableKeyType()->isSuperTypeOfWithReason($type->getIterableKeyType())); + ->and($this->getIterableValueType()->isSuperTypeOf($type->getIterableValueType())) + ->and($this->getIterableKeyType()->isSuperTypeOf($type->getIterableKeyType())); } - public function isSuperTypeOfMixed(Type $type): TrinaryLogic + public function isSuperTypeOfMixed(Type $type): IsSuperTypeOfResult { - return $type->isIterable() + return (new IsSuperTypeOfResult($type->isIterable(), [])) ->and($this->isNestedTypeSuperTypeOf($this->getIterableValueType(), $type->getIterableValueType())) ->and($this->isNestedTypeSuperTypeOf($this->getIterableKeyType(), $type->getIterableKeyType())); } - private function isNestedTypeSuperTypeOf(Type $a, Type $b): TrinaryLogic + private function isNestedTypeSuperTypeOf(Type $a, Type $b): IsSuperTypeOfResult { if (!$a instanceof MixedType || !$b instanceof MixedType) { return $a->isSuperTypeOf($b); @@ -127,24 +122,19 @@ private function isNestedTypeSuperTypeOf(Type $a, Type $b): TrinaryLogic if ($a->isExplicitMixed()) { if ($b->isExplicitMixed()) { - return TrinaryLogic::createYes(); + return IsSuperTypeOfResult::createYes(); } - return TrinaryLogic::createMaybe(); + return IsSuperTypeOfResult::createMaybe(); } - return TrinaryLogic::createYes(); - } - - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; + return IsSuperTypeOfResult::createYes(); } - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof IntersectionType || $otherType instanceof UnionType) { - return $otherType->isSuperTypeOfWithReason(new UnionType([ + return $otherType->isSuperTypeOf(new UnionType([ new ArrayType($this->keyType, $this->itemType), new IntersectionType([ new ObjectType(Traversable::class), @@ -165,14 +155,14 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult return $limit->and( new IsSuperTypeOfResult($otherType->isIterable(), []), - $otherType->getIterableValueType()->isSuperTypeOfWithReason($this->itemType), - $otherType->getIterableKeyType()->isSuperTypeOfWithReason($this->keyType), + $otherType->getIterableValueType()->isSuperTypeOf($this->itemType), + $otherType->getIterableKeyType()->isSuperTypeOf($this->keyType), ); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function equals(Type $type): bool diff --git a/src/Type/JustNullableTypeTrait.php b/src/Type/JustNullableTypeTrait.php index ac875ed66a..2100901a86 100644 --- a/src/Type/JustNullableTypeTrait.php +++ b/src/Type/JustNullableTypeTrait.php @@ -36,19 +36,14 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createNo(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); diff --git a/src/Type/MixedType.php b/src/Type/MixedType.php index f484a52c2b..810b0f5934 100644 --- a/src/Type/MixedType.php +++ b/src/Type/MixedType.php @@ -96,44 +96,39 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createYes(); } - public function isSuperTypeOfMixed(MixedType $type): TrinaryLogic + public function isSuperTypeOfMixed(MixedType $type): IsSuperTypeOfResult { if ($this->subtractedType === null) { if ($this->isExplicitMixed) { if ($type->isExplicitMixed) { - return TrinaryLogic::createYes(); + return IsSuperTypeOfResult::createYes(); } - return TrinaryLogic::createMaybe(); + return IsSuperTypeOfResult::createMaybe(); } - return TrinaryLogic::createYes(); + return IsSuperTypeOfResult::createYes(); } if ($type->subtractedType === null) { - return TrinaryLogic::createMaybe(); + return IsSuperTypeOfResult::createMaybe(); } $isSuperType = $type->subtractedType->isSuperTypeOf($this->subtractedType); if ($isSuperType->yes()) { if ($this->isExplicitMixed) { if ($type->isExplicitMixed) { - return TrinaryLogic::createYes(); + return IsSuperTypeOfResult::createYes(); } - return TrinaryLogic::createMaybe(); + return IsSuperTypeOfResult::createMaybe(); } - return TrinaryLogic::createYes(); + return IsSuperTypeOfResult::createYes(); } - return TrinaryLogic::createMaybe(); - } - - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; + return IsSuperTypeOfResult::createMaybe(); } - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($this->subtractedType === null || $type instanceof NeverType) { return IsSuperTypeOfResult::createYes(); @@ -143,7 +138,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult if ($type->subtractedType === null) { return IsSuperTypeOfResult::createMaybe(); } - $isSuperType = $type->subtractedType->isSuperTypeOfWithReason($this->subtractedType); + $isSuperType = $type->subtractedType->isSuperTypeOf($this->subtractedType); if ($isSuperType->yes()) { return $isSuperType; } @@ -151,7 +146,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createMaybe(); } - return $this->subtractedType->isSuperTypeOfWithReason($type)->negate(); + return $this->subtractedType->isSuperTypeOf($type)->negate(); } public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $unionValues = true): Type @@ -322,19 +317,14 @@ public function equals(Type $type): bool return $this->subtractedType->equals($type->subtractedType); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof self && !$otherType instanceof TemplateMixedType) { return IsSuperTypeOfResult::createYes(); } if ($this->subtractedType !== null) { - $isSuperType = $this->subtractedType->isSuperTypeOfWithReason($otherType); + $isSuperType = $this->subtractedType->isSuperTypeOf($otherType); if ($isSuperType->yes()) { return IsSuperTypeOfResult::createNo(); } @@ -345,7 +335,7 @@ public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - $isSuperType = $this->isSuperTypeOfWithReason($acceptingType)->toAcceptsResult(); + $isSuperType = $this->isSuperTypeOf($acceptingType)->toAcceptsResult(); if ($isSuperType->no()) { return $isSuperType; } diff --git a/src/Type/NeverType.php b/src/Type/NeverType.php index 5d5dbc81bc..878dfc3623 100644 --- a/src/Type/NeverType.php +++ b/src/Type/NeverType.php @@ -74,12 +74,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createYes(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createYes(); @@ -93,19 +88,14 @@ public function equals(Type $type): bool return $type instanceof self; } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { return IsSuperTypeOfResult::createYes(); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult { - return $this->isSubTypeOfWithReason($acceptingType)->toAcceptsResult(); + return $this->isSubTypeOf($acceptingType)->toAcceptsResult(); } public function describe(VerbosityLevel $level): string diff --git a/src/Type/NonAcceptingNeverType.php b/src/Type/NonAcceptingNeverType.php index f8c9dfc835..dd14d3f9d2 100644 --- a/src/Type/NonAcceptingNeverType.php +++ b/src/Type/NonAcceptingNeverType.php @@ -2,8 +2,6 @@ namespace PHPStan\Type; -use PHPStan\TrinaryLogic; - /** @api */ class NonAcceptingNeverType extends NeverType { @@ -14,12 +12,7 @@ public function __construct() parent::__construct(true); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createYes(); diff --git a/src/Type/NullType.php b/src/Type/NullType.php index 1f24c8a890..d3c0b94e7b 100644 --- a/src/Type/NullType.php +++ b/src/Type/NullType.php @@ -82,19 +82,14 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return AcceptsResult::createNo(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); diff --git a/src/Type/ObjectShapeType.php b/src/Type/ObjectShapeType.php index b80a6d1457..1a1beed6c0 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -230,15 +230,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $result->and(new AcceptsResult($type->isObject(), [])); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($type instanceof ObjectWithoutClassType) { @@ -292,7 +287,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } $otherPropertyType = $otherProperty->getReadableType(); - $isSuperType = $propertyType->isSuperTypeOfWithReason($otherPropertyType); + $isSuperType = $propertyType->isSuperTypeOf($otherPropertyType); if ($isSuperType->no()) { return $isSuperType; } diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 93d6346813..a9fc033a67 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -305,12 +305,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $this->checkSubclassAcceptability($thatClassNames[0]); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { $thatClassNames = $type->getObjectClassNames(); if (!$type instanceof CompoundType && $thatClassNames === [] && !$type instanceof ObjectWithoutClassType) { @@ -330,7 +325,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } if ($type instanceof CompoundType) { - return self::$superTypes[$thisDescription][$description] = $type->isSubTypeOfWithReason($this); + return self::$superTypes[$thisDescription][$description] = $type->isSubTypeOf($this); } if ($type instanceof ClosureType) { @@ -349,7 +344,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult $transformResult = static fn (IsSuperTypeOfResult $result) => $result; if ($this->subtractedType !== null) { - $isSuperType = $this->subtractedType->isSuperTypeOfWithReason($type); + $isSuperType = $this->subtractedType->isSuperTypeOf($type); if ($isSuperType->yes()) { return self::$superTypes[$thisDescription][$description] = IsSuperTypeOfResult::createNo(); } @@ -362,7 +357,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult $type instanceof SubtractableType && $type->getSubtractedType() !== null ) { - $isSuperType = $type->getSubtractedType()->isSuperTypeOfWithReason($this); + $isSuperType = $type->getSubtractedType()->isSuperTypeOf($this); if ($isSuperType->yes()) { return self::$superTypes[$thisDescription][$description] = IsSuperTypeOfResult::createNo(); } diff --git a/src/Type/ObjectWithoutClassType.php b/src/Type/ObjectWithoutClassType.php index 8cd1ebcf74..3abe064e3f 100644 --- a/src/Type/ObjectWithoutClassType.php +++ b/src/Type/ObjectWithoutClassType.php @@ -60,15 +60,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult ); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } if ($type instanceof self) { @@ -76,7 +71,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } if ($type->subtractedType !== null) { - $isSuperType = $type->subtractedType->isSuperTypeOfWithReason($this->subtractedType); + $isSuperType = $type->subtractedType->isSuperTypeOf($this->subtractedType); if ($isSuperType->yes()) { return $isSuperType; } @@ -97,7 +92,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return $this->subtractedType->isSuperTypeOfWithReason($type)->negate(); + return $this->subtractedType->isSuperTypeOf($type)->negate(); } public function equals(Type $type): bool diff --git a/src/Type/StaticType.php b/src/Type/StaticType.php index 990ac2e4b0..4729fdadf0 100644 --- a/src/Type/StaticType.php +++ b/src/Type/StaticType.php @@ -142,15 +142,10 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $this->getStaticObjectType()->accepts($type->getStaticObjectType(), $strictTypes); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { - return $this->getStaticObjectType()->isSuperTypeOfWithReason($type); + return $this->getStaticObjectType()->isSuperTypeOf($type); } if ($type instanceof ObjectWithoutClassType) { @@ -158,7 +153,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } if ($type instanceof ObjectType) { - $result = $this->getStaticObjectType()->isSuperTypeOfWithReason($type); + $result = $this->getStaticObjectType()->isSuperTypeOf($type); if ($result->yes()) { $classReflection = $type->getClassReflection(); if ($classReflection !== null && $classReflection->isFinal()) { @@ -170,7 +165,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); diff --git a/src/Type/StrictMixedType.php b/src/Type/StrictMixedType.php index 5fca1a75d5..f1b9a0b694 100644 --- a/src/Type/StrictMixedType.php +++ b/src/Type/StrictMixedType.php @@ -68,22 +68,12 @@ public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsRes return AcceptsResult::createMaybe(); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { return IsSuperTypeOfResult::createYes(); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { if ($otherType instanceof self) { return IsSuperTypeOfResult::createYes(); diff --git a/src/Type/StringAlwaysAcceptingObjectWithToStringType.php b/src/Type/StringAlwaysAcceptingObjectWithToStringType.php index 3bdf4e8631..feb18e97d6 100644 --- a/src/Type/StringAlwaysAcceptingObjectWithToStringType.php +++ b/src/Type/StringAlwaysAcceptingObjectWithToStringType.php @@ -3,25 +3,19 @@ namespace PHPStan\Type; use PHPStan\Reflection\ReflectionProviderStaticAccessor; -use PHPStan\TrinaryLogic; class StringAlwaysAcceptingObjectWithToStringType extends StringType { - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } $thatClassNames = $type->getObjectClassNames(); if ($thatClassNames === []) { - return parent::isSuperTypeOfWithReason($type); + return parent::isSuperTypeOf($type); } $result = IsSuperTypeOfResult::createNo(); diff --git a/src/Type/ThisType.php b/src/Type/ThisType.php index 052e9ab64f..39d4949ca8 100644 --- a/src/Type/ThisType.php +++ b/src/Type/ThisType.php @@ -5,7 +5,6 @@ use PHPStan\PhpDocParser\Ast\Type\ThisTypeNode; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\Reflection\ClassReflection; -use PHPStan\TrinaryLogic; use function sprintf; /** @api */ @@ -33,24 +32,19 @@ public function describe(VerbosityLevel $level): string return sprintf('$this(%s)', $this->getStaticObjectType()->describe($level)); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { - return $this->getStaticObjectType()->isSuperTypeOfWithReason($type); + return $this->getStaticObjectType()->isSuperTypeOf($type); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } $parent = new parent($this->getClassReflection(), $this->getSubtractedType()); - return $parent->isSuperTypeOfWithReason($type)->and(IsSuperTypeOfResult::createMaybe()); + return $parent->isSuperTypeOf($type)->and(IsSuperTypeOfResult::createMaybe()); } public function changeSubtractedType(?Type $subtractedType): Type diff --git a/src/Type/Traits/ConstantScalarTypeTrait.php b/src/Type/Traits/ConstantScalarTypeTrait.php index 4aac9818fc..b4757aaac2 100644 --- a/src/Type/Traits/ConstantScalarTypeTrait.php +++ b/src/Type/Traits/ConstantScalarTypeTrait.php @@ -30,12 +30,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return parent::accepts($type, $strictTypes)->and(AcceptsResult::createMaybe()); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createFromBoolean($this->equals($type)); @@ -46,7 +41,7 @@ public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); diff --git a/src/Type/Traits/LateResolvableTypeTrait.php b/src/Type/Traits/LateResolvableTypeTrait.php index 16dde87001..6753d7ed20 100644 --- a/src/Type/Traits/LateResolvableTypeTrait.php +++ b/src/Type/Traits/LateResolvableTypeTrait.php @@ -54,12 +54,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $this->resolve()->accepts($type, $strictTypes); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { return $this->isSuperTypeOfDefault($type); } @@ -74,7 +69,7 @@ private function isSuperTypeOfDefault(Type $type): IsSuperTypeOfResult $type = $type->resolve(); } - $isSuperType = $this->resolve()->isSuperTypeOfWithReason($type); + $isSuperType = $this->resolve()->isSuperTypeOf($type); if (!$this->isResolvable()) { $isSuperType = $isSuperType->and(IsSuperTypeOfResult::createMaybe()); @@ -523,20 +518,15 @@ public function tryRemove(Type $typeToRemove): ?Type return $this->resolve()->tryRemove($typeToRemove); } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { $result = $this->resolve(); if ($result instanceof CompoundType) { - return $result->isSubTypeOfWithReason($otherType); + return $result->isSubTypeOf($otherType); } - return $otherType->isSuperTypeOfWithReason($result); + return $otherType->isSuperTypeOf($result); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult diff --git a/src/Type/Type.php b/src/Type/Type.php index 6a0f25ef33..62d2b84d3a 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -73,16 +73,7 @@ public function getConstantStrings(): array; */ public function accepts(Type $type, bool $strictTypes): AcceptsResult; - public function isSuperTypeOf(Type $type): TrinaryLogic; - - /** - * This is like isSuperTypeOf() but gives reasons - * why the type was not/might not be accepted in some non-intuitive scenarios. - * - * In PHPStan 2.0 this method will be removed and the return type of isSuperTypeOf() - * will change to IsSuperTypeOfResult. - */ - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult; + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult; public function equals(Type $type): bool; diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 897aed75db..6e2caf675f 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -196,12 +196,7 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return $result; } - public function isSuperTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($otherType)->result; - } - - public function isSuperTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSuperTypeOf(Type $otherType): IsSuperTypeOfResult { if ( ($otherType instanceof self && !$otherType instanceof TemplateUnionType) @@ -211,29 +206,24 @@ public function isSuperTypeOfWithReason(Type $otherType): IsSuperTypeOfResult || $otherType instanceof ConditionalTypeForParameter || $otherType instanceof IntegerRangeType ) { - return $otherType->isSubTypeOfWithReason($this); + return $otherType->isSubTypeOf($this); } - $result = IsSuperTypeOfResult::createNo()->or(...array_map(static fn (Type $innerType) => $innerType->isSuperTypeOfWithReason($otherType), $this->types)); + $result = IsSuperTypeOfResult::createNo()->or(...array_map(static fn (Type $innerType) => $innerType->isSuperTypeOf($otherType), $this->types)); if ($result->yes()) { return $result; } if ($otherType instanceof TemplateUnionType) { - return $result->or($otherType->isSubTypeOfWithReason($this)); + return $result->or($otherType->isSubTypeOf($this)); } return $result; } - public function isSubTypeOf(Type $otherType): TrinaryLogic - { - return $this->isSubTypeOfWithReason($otherType)->result; - } - - public function isSubTypeOfWithReason(Type $otherType): IsSuperTypeOfResult + public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult { - return IsSuperTypeOfResult::extremeIdentity(...array_map(static fn (Type $innerType) => $otherType->isSuperTypeOfWithReason($innerType), $this->types)); + return IsSuperTypeOfResult::extremeIdentity(...array_map(static fn (Type $innerType) => $otherType->isSuperTypeOf($innerType), $this->types)); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult diff --git a/src/Type/VoidType.php b/src/Type/VoidType.php index e4f082d0bf..95c0bce136 100644 --- a/src/Type/VoidType.php +++ b/src/Type/VoidType.php @@ -61,19 +61,14 @@ public function accepts(Type $type, bool $strictTypes): AcceptsResult return new AcceptsResult($type->isVoid()->or($type->isNull()), []); } - public function isSuperTypeOf(Type $type): TrinaryLogic - { - return $this->isSuperTypeOfWithReason($type)->result; - } - - public function isSuperTypeOfWithReason(Type $type): IsSuperTypeOfResult + public function isSuperTypeOf(Type $type): IsSuperTypeOfResult { if ($type instanceof self) { return IsSuperTypeOfResult::createYes(); } if ($type instanceof CompoundType) { - return $type->isSubTypeOfWithReason($this); + return $type->isSubTypeOf($this); } return IsSuperTypeOfResult::createNo(); From f240ebde51f4f98bebfe5b329b8ca816a213065e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 7 Oct 2024 11:06:31 +0200 Subject: [PATCH 369/508] Do not comment on PRs on 2.0.x anymore --- .github/workflows/pr-base-on-previous-branch.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-base-on-previous-branch.yml b/.github/workflows/pr-base-on-previous-branch.yml index f522ea446e..7c2f57188d 100644 --- a/.github/workflows/pr-base-on-previous-branch.yml +++ b/.github/workflows/pr-base-on-previous-branch.yml @@ -7,7 +7,7 @@ on: types: - opened branches: - - '2.0.x' + - '2.1.x' jobs: @@ -19,6 +19,6 @@ jobs: - name: Comment PR uses: peter-evans/create-or-update-comment@v4 with: - body: "You've opened the pull request against the latest branch 2.0.x. PHPStan 2.0 is not going to be released for months. If your code is relevant on 1.12.x and you want it to be released sooner, please rebase your pull request and change its target to 1.12.x." + body: "You've opened the pull request against the latest branch 2.1.x. PHPStan 2.1 is not going to be released for months. If your code is relevant on 2.0.x and you want it to be released sooner, please rebase your pull request and change its target to 2.0.x." token: ${{ secrets.PHPSTAN_BOT_TOKEN }} issue-number: ${{ github.event.pull_request.number }} From 2fce656d249a3f3e4c1585a19e497ba9aa9b4f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Mirtes?= Date: Mon, 7 Oct 2024 11:29:44 +0200 Subject: [PATCH 370/508] Update changelog-2.0.md --- changelog-2.0.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index f0abba38de..b4967463c6 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -1,4 +1,6 @@ -When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](https://github.com/phpstan/phpstan/releases) + a separate [UPGRADING](./UPGRADING.md) document. +When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](https://github.com/phpstan/phpstan/releases). + +Check out the [**UPGRADING guide**](https://github.com/phpstan/phpstan-src/blob/2.0.x/UPGRADING.md)!. Major new features 🚀 ===================== From 97d5e8956891f8357d96e50aa7a8cd62b90d6db8 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 7 Oct 2024 11:34:53 +0200 Subject: [PATCH 371/508] Fix --- src/Type/Generic/TemplateTypeVariance.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index e48eb81bfb..a630895bed 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -6,6 +6,7 @@ use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\BenevolentUnionType; +use PHPStan\Type\IsSuperTypeOfResult; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; use PHPStan\Type\Type; From 8cfc080f04a5a8b98e4cb17181d1173d4ee61f94 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Mon, 7 Oct 2024 14:19:42 +0200 Subject: [PATCH 372/508] UPGRADING.md: typo --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index 5fe143b645..5aae2eeb29 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -151,7 +151,7 @@ return ['My error']; ```php return [ - RuleErrorBuilder::mesage('My error') + RuleErrorBuilder::message('My error') ->identifier('my.error') ->build(), ]; From f818ac594f1ac9e3c072aa13888921fffa47b29c Mon Sep 17 00:00:00 2001 From: Martin Herndl Date: Sun, 6 Oct 2024 20:26:06 +0200 Subject: [PATCH 373/508] Get rid of unnecessary `instanceof self` in `ConstantArrayType` --- phpstan-baseline.neon | 2 +- src/Type/Constant/ConstantArrayType.php | 55 +++++++------------------ 2 files changed, 17 insertions(+), 40 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 246118a8d5..fb4b06b279 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -882,7 +882,7 @@ parameters: - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType - count: 7 + count: 5 path: src/Type/Constant/ConstantArrayType.php - diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 46315a4eae..fdc0bdecef 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -52,7 +52,6 @@ use function array_merge; use function array_pop; use function array_push; -use function array_reverse; use function array_slice; use function array_unique; use function array_values; @@ -242,7 +241,7 @@ public function getAllArrays(): array } $array = $builder->getArray(); - if (!$array instanceof ConstantArrayType) { + if (!$array instanceof self) { throw new ShouldNotHappenException(); } @@ -858,14 +857,16 @@ public function popArray(): Type public function reverseArray(TrinaryLogic $preserveKeys): Type { - $keyTypesReversed = array_reverse($this->keyTypes, true); - $keyTypes = array_values($keyTypesReversed); - $keyTypesReversedKeys = array_keys($keyTypesReversed); - $optionalKeys = array_map(static fn (int $optionalKey): int => $keyTypesReversedKeys[$optionalKey], $this->optionalKeys); + $builder = ConstantArrayTypeBuilder::createEmpty(); - $reversed = new self($keyTypes, array_reverse($this->valueTypes), $this->nextAutoIndexes, $optionalKeys, TrinaryLogic::createNo()); + for ($i = count($this->keyTypes) - 1; $i >= 0; $i--) { + $offsetType = $preserveKeys->yes() || $this->keyTypes[$i]->isInteger()->no() + ? $this->keyTypes[$i] + : null; + $builder->setOffsetValueType($offsetType, $this->valueTypes[$i], $this->isOptionalKey($i)); + } - return $preserveKeys->yes() ? $reversed : $reversed->reindex(); + return $builder->getArray(); } public function searchArray(Type $needleType): Type @@ -994,15 +995,14 @@ public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $pre $isOptional = true; } - $builder->setOffsetValueType($this->keyTypes[$i], $this->valueTypes[$i], $isOptional); - } + $offsetType = $preserveKeys->yes() || $this->keyTypes[$i]->isInteger()->no() + ? $this->keyTypes[$i] + : null; - $slice = $builder->getArray(); - if (!$slice instanceof self) { - throw new ShouldNotHappenException(); + $builder->setOffsetValueType($offsetType, $this->valueTypes[$i], $isOptional); } - return $preserveKeys->yes() ? $slice : $slice->reindex(); + return $builder->getArray(); } public function isIterableAtLeastOnce(): TrinaryLogic @@ -1148,7 +1148,7 @@ private function removeLastElements(int $length): self } /** @param positive-int $length */ - private function removeFirstElements(int $length, bool $reindex = true): self + private function removeFirstElements(int $length, bool $reindex = true): Type { $builder = ConstantArrayTypeBuilder::createEmpty(); @@ -1175,30 +1175,7 @@ private function removeFirstElements(int $length, bool $reindex = true): self $builder->setOffsetValueType($keyType, $valueType, $isOptional); } - $array = $builder->getArray(); - if (!$array instanceof self) { - throw new ShouldNotHappenException(); - } - - return $array; - } - - private function reindex(): self - { - $keyTypes = []; - $autoIndex = 0; - - foreach ($this->keyTypes as $keyType) { - if (!$keyType instanceof ConstantIntegerType) { - $keyTypes[] = $keyType; - continue; - } - - $keyTypes[] = new ConstantIntegerType($autoIndex); - $autoIndex++; - } - - return new self($keyTypes, $this->valueTypes, [$autoIndex], $this->optionalKeys, TrinaryLogic::createYes()); + return $builder->getArray(); } public function toBoolean(): BooleanType From b37d269af794ded37236126165a68f761f060d5a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 7 Oct 2024 18:19:12 +0200 Subject: [PATCH 374/508] Revert "Get rid of unnecessary `instanceof self` in `ConstantArrayType`" This reverts commit f818ac594f1ac9e3c072aa13888921fffa47b29c. --- phpstan-baseline.neon | 2 +- src/Type/Constant/ConstantArrayType.php | 55 ++++++++++++++++++------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index fb4b06b279..246118a8d5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -882,7 +882,7 @@ parameters: - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType - count: 5 + count: 7 path: src/Type/Constant/ConstantArrayType.php - diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index fdc0bdecef..46315a4eae 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -52,6 +52,7 @@ use function array_merge; use function array_pop; use function array_push; +use function array_reverse; use function array_slice; use function array_unique; use function array_values; @@ -241,7 +242,7 @@ public function getAllArrays(): array } $array = $builder->getArray(); - if (!$array instanceof self) { + if (!$array instanceof ConstantArrayType) { throw new ShouldNotHappenException(); } @@ -857,16 +858,14 @@ public function popArray(): Type public function reverseArray(TrinaryLogic $preserveKeys): Type { - $builder = ConstantArrayTypeBuilder::createEmpty(); + $keyTypesReversed = array_reverse($this->keyTypes, true); + $keyTypes = array_values($keyTypesReversed); + $keyTypesReversedKeys = array_keys($keyTypesReversed); + $optionalKeys = array_map(static fn (int $optionalKey): int => $keyTypesReversedKeys[$optionalKey], $this->optionalKeys); - for ($i = count($this->keyTypes) - 1; $i >= 0; $i--) { - $offsetType = $preserveKeys->yes() || $this->keyTypes[$i]->isInteger()->no() - ? $this->keyTypes[$i] - : null; - $builder->setOffsetValueType($offsetType, $this->valueTypes[$i], $this->isOptionalKey($i)); - } + $reversed = new self($keyTypes, array_reverse($this->valueTypes), $this->nextAutoIndexes, $optionalKeys, TrinaryLogic::createNo()); - return $builder->getArray(); + return $preserveKeys->yes() ? $reversed : $reversed->reindex(); } public function searchArray(Type $needleType): Type @@ -995,14 +994,15 @@ public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $pre $isOptional = true; } - $offsetType = $preserveKeys->yes() || $this->keyTypes[$i]->isInteger()->no() - ? $this->keyTypes[$i] - : null; + $builder->setOffsetValueType($this->keyTypes[$i], $this->valueTypes[$i], $isOptional); + } - $builder->setOffsetValueType($offsetType, $this->valueTypes[$i], $isOptional); + $slice = $builder->getArray(); + if (!$slice instanceof self) { + throw new ShouldNotHappenException(); } - return $builder->getArray(); + return $preserveKeys->yes() ? $slice : $slice->reindex(); } public function isIterableAtLeastOnce(): TrinaryLogic @@ -1148,7 +1148,7 @@ private function removeLastElements(int $length): self } /** @param positive-int $length */ - private function removeFirstElements(int $length, bool $reindex = true): Type + private function removeFirstElements(int $length, bool $reindex = true): self { $builder = ConstantArrayTypeBuilder::createEmpty(); @@ -1175,7 +1175,30 @@ private function removeFirstElements(int $length, bool $reindex = true): Type $builder->setOffsetValueType($keyType, $valueType, $isOptional); } - return $builder->getArray(); + $array = $builder->getArray(); + if (!$array instanceof self) { + throw new ShouldNotHappenException(); + } + + return $array; + } + + private function reindex(): self + { + $keyTypes = []; + $autoIndex = 0; + + foreach ($this->keyTypes as $keyType) { + if (!$keyType instanceof ConstantIntegerType) { + $keyTypes[] = $keyType; + continue; + } + + $keyTypes[] = new ConstantIntegerType($autoIndex); + $autoIndex++; + } + + return new self($keyTypes, $this->valueTypes, [$autoIndex], $this->optionalKeys, TrinaryLogic::createYes()); } public function toBoolean(): BooleanType From e542a61c38f27a371cb3136bcf0030572466d3cc Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 8 Oct 2024 09:00:28 +0200 Subject: [PATCH 375/508] Fix --- .../Php/ReflectionGetAttributesMethodReturnTypeExtension.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php b/src/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php index 04454c63b2..493ec0e9c3 100644 --- a/src/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php +++ b/src/Type/Php/ReflectionGetAttributesMethodReturnTypeExtension.php @@ -11,6 +11,7 @@ use PHPStan\Type\Generic\GenericObjectType; use PHPStan\Type\IntegerType; use PHPStan\Type\Type; +use PHPStan\Type\TypeCombinator; use ReflectionAttribute; use function count; @@ -43,7 +44,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method $argType = $scope->getType($methodCall->getArgs()[0]->value); $classType = $argType->getClassStringObjectType(); - return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new GenericObjectType(ReflectionAttribute::class, [$classType]))); + return TypeCombinator::intersect(new ArrayType(new IntegerType(), new GenericObjectType(ReflectionAttribute::class, [$classType])), new AccessoryArrayListType()); } } From 37f4e564109dc69fd391c55d44747ed2e0bd130b Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Tue, 8 Oct 2024 00:19:20 +0000 Subject: [PATCH 376/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 1b3a8bedf2..54283827b4 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.9", - "phpstan/php-8-stubs": "0.4.0", + "phpstan/php-8-stubs": "0.4.1", "phpstan/phpdoc-parser": "^2.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index 660c3ad5ec..810f663d6b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "eb6f30bebe27d08d2b3b9e2c729ccf20", + "content-hash": "416d829025e6a2d8f7115f4c142b0718", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.0", + "version": "0.4.1", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "693817d86d0d0de1d39b97a70bff4fa728384aa1" + "reference": "212d2b20c3c6f8c06a224efb748ec4cd069ef251" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/693817d86d0d0de1d39b97a70bff4fa728384aa1", - "reference": "693817d86d0d0de1d39b97a70bff4fa728384aa1", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/212d2b20c3c6f8c06a224efb748ec4cd069ef251", + "reference": "212d2b20c3c6f8c06a224efb748ec4cd069ef251", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.0" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.1" }, - "time": "2024-09-30T19:56:21+00:00" + "time": "2024-10-08T00:18:48+00:00" }, { "name": "phpstan/phpdoc-parser", From 14a3b36d72f149fda2837cf11cc899db5aa87a7a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 8 Oct 2024 09:05:37 +0200 Subject: [PATCH 377/508] Fix generate-function-metadata.php script --- .github/workflows/update-phpstorm-stubs.yml | 2 +- bin/generate-function-metadata.php | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-phpstorm-stubs.yml b/.github/workflows/update-phpstorm-stubs.yml index c559efc208..320b4eba1b 100644 --- a/.github/workflows/update-phpstorm-stubs.yml +++ b/.github/workflows/update-phpstorm-stubs.yml @@ -16,7 +16,7 @@ jobs: - name: "Checkout" uses: actions/checkout@v4 with: - ref: 1.12.x + ref: 2.0.x fetch-depth: '0' token: ${{ secrets.PHPSTAN_BOT_TOKEN }} - name: "Install PHP" diff --git a/bin/generate-function-metadata.php b/bin/generate-function-metadata.php index f6f5131a53..7b834e2cbb 100755 --- a/bin/generate-function-metadata.php +++ b/bin/generate-function-metadata.php @@ -16,7 +16,7 @@ (function (): void { require_once __DIR__ . '/../vendor/autoload.php'; - $parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7); + $parser = (new ParserFactory())->createForNewestSupportedVersion(); $finder = new Finder(); $finder->in(__DIR__ . '/../vendor/jetbrains/phpstorm-stubs')->files()->name('*.php'); @@ -69,8 +69,19 @@ public function enterNode(Node $node) $traverser->addVisitor(new NodeConnectingVisitor()); $traverser->addVisitor($visitor); + $contents = FileReader::read($path); + if (str_ends_with($path, '/vendor/jetbrains/phpstorm-stubs/Core/Core.php')) { + $contents = str_replace([ + 'function exit', + 'function die', + ], [ + 'function _exit', + 'function _die', + ], $contents); + } + $traverser->traverse( - $parser->parse(FileReader::read($path)), + $parser->parse($contents), ); } From 9d19cd0a7babeb959ccc8f54e1b0d35ae5656882 Mon Sep 17 00:00:00 2001 From: Martin Herndl Date: Sun, 6 Oct 2024 20:26:06 +0200 Subject: [PATCH 378/508] Get rid of unnecessary `instanceof self` in `ConstantArrayType` --- phpstan-baseline.neon | 2 +- src/Type/Constant/ConstantArrayType.php | 40 +++++-------------------- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 246118a8d5..fb4b06b279 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -882,7 +882,7 @@ parameters: - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType - count: 7 + count: 5 path: src/Type/Constant/ConstantArrayType.php - diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index e77e12857d..fdc0bdecef 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -241,7 +241,7 @@ public function getAllArrays(): array } $array = $builder->getArray(); - if (!$array instanceof ConstantArrayType) { + if (!$array instanceof self) { throw new ShouldNotHappenException(); } @@ -995,15 +995,14 @@ public function sliceArray(Type $offsetType, Type $lengthType, TrinaryLogic $pre $isOptional = true; } - $builder->setOffsetValueType($this->keyTypes[$i], $this->valueTypes[$i], $isOptional); - } + $offsetType = $preserveKeys->yes() || $this->keyTypes[$i]->isInteger()->no() + ? $this->keyTypes[$i] + : null; - $slice = $builder->getArray(); - if (!$slice instanceof self) { - throw new ShouldNotHappenException(); + $builder->setOffsetValueType($offsetType, $this->valueTypes[$i], $isOptional); } - return $preserveKeys->yes() ? $slice : $slice->reindex(); + return $builder->getArray(); } public function isIterableAtLeastOnce(): TrinaryLogic @@ -1149,7 +1148,7 @@ private function removeLastElements(int $length): self } /** @param positive-int $length */ - private function removeFirstElements(int $length, bool $reindex = true): self + private function removeFirstElements(int $length, bool $reindex = true): Type { $builder = ConstantArrayTypeBuilder::createEmpty(); @@ -1176,30 +1175,7 @@ private function removeFirstElements(int $length, bool $reindex = true): self $builder->setOffsetValueType($keyType, $valueType, $isOptional); } - $array = $builder->getArray(); - if (!$array instanceof self) { - throw new ShouldNotHappenException(); - } - - return $array; - } - - private function reindex(): self - { - $keyTypes = []; - $autoIndex = 0; - - foreach ($this->keyTypes as $keyType) { - if (!$keyType instanceof ConstantIntegerType) { - $keyTypes[] = $keyType; - continue; - } - - $keyTypes[] = new ConstantIntegerType($autoIndex); - $autoIndex++; - } - - return new self($keyTypes, $this->valueTypes, [$autoIndex], $this->optionalKeys, TrinaryLogic::createYes()); + return $builder->getArray(); } public function toBoolean(): BooleanType From dddf98463200f8f050937821915a7744007fdeba Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 8 Oct 2024 13:51:40 +0200 Subject: [PATCH 379/508] Remove inefficient caching from `PhpMethodReflection` and `PhpFunctionReflection::isVariadic()` Co-authored-by: Ondrej Mirtes --- conf/config.neon | 13 +- src/Parser/FunctionCallStatementFinder.php | 47 ------- src/Parser/SimpleParser.php | 4 + src/Parser/VariadicFunctionsVisitor.php | 94 +++++++++++++ src/Parser/VariadicMethodsVisitor.php | 125 ++++++++++++++++++ src/Reflection/Php/PhpFunctionReflection.php | 97 +++----------- src/Reflection/Php/PhpMethodReflection.php | 103 ++++----------- tests/PHPStan/Parser/CleaningParserTest.php | 2 + tests/PHPStan/Parser/ParserTest.php | 99 ++++++++++++++ .../Parser/data/variadic-functions.php | 31 +++++ .../Parser/data/variadic-methods-in-enum.php | 16 +++ .../PHPStan/Parser/data/variadic-methods.php | 68 ++++++++++ .../Rules/Methods/CallMethodsRuleTest.php | 15 +++ .../PHPStan/Rules/Methods/data/bug-11559c.php | 16 +++ 14 files changed, 528 insertions(+), 202 deletions(-) delete mode 100644 src/Parser/FunctionCallStatementFinder.php create mode 100644 src/Parser/VariadicFunctionsVisitor.php create mode 100644 src/Parser/VariadicMethodsVisitor.php create mode 100644 tests/PHPStan/Parser/ParserTest.php create mode 100644 tests/PHPStan/Parser/data/variadic-functions.php create mode 100644 tests/PHPStan/Parser/data/variadic-methods-in-enum.php create mode 100644 tests/PHPStan/Parser/data/variadic-methods.php create mode 100644 tests/PHPStan/Rules/Methods/data/bug-11559c.php diff --git a/conf/config.neon b/conf/config.neon index 6a8f4d6897..583cceac81 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -302,6 +302,16 @@ services: tags: - phpstan.parser.richParserNodeVisitor + - + class: PHPStan\Parser\VariadicMethodsVisitor + tags: + - phpstan.parser.richParserNodeVisitor + + - + class: PHPStan\Parser\VariadicFunctionsVisitor + tags: + - phpstan.parser.richParserNodeVisitor + - class: PHPStan\Node\Printer\ExprPrinter @@ -634,9 +644,6 @@ services: tags: - phpstan.diagnoseExtension - - - class: PHPStan\Parser\FunctionCallStatementFinder - - class: PHPStan\Process\CpuCoreCounter diff --git a/src/Parser/FunctionCallStatementFinder.php b/src/Parser/FunctionCallStatementFinder.php deleted file mode 100644 index 9a4c1dd6bb..0000000000 --- a/src/Parser/FunctionCallStatementFinder.php +++ /dev/null @@ -1,47 +0,0 @@ -findFunctionCallInStatements($functionNames, $statement); - if ($result !== null) { - return $result; - } - } - - if (!($statement instanceof Node)) { - continue; - } - - if ($statement instanceof FuncCall && $statement->name instanceof Name) { - if (in_array((string) $statement->name, $functionNames, true)) { - return $statement; - } - } - - $result = $this->findFunctionCallInStatements($functionNames, $statement); - if ($result !== null) { - return $result; - } - } - - return null; - } - -} diff --git a/src/Parser/SimpleParser.php b/src/Parser/SimpleParser.php index 713c1502ef..8fbd112742 100644 --- a/src/Parser/SimpleParser.php +++ b/src/Parser/SimpleParser.php @@ -15,6 +15,8 @@ final class SimpleParser implements Parser public function __construct( private \PhpParser\Parser $parser, private NameResolver $nameResolver, + private VariadicMethodsVisitor $variadicMethodsVisitor, + private VariadicFunctionsVisitor $variadicFunctionsVisitor, ) { } @@ -48,6 +50,8 @@ public function parseString(string $sourceCode): array $nodeTraverser = new NodeTraverser(); $nodeTraverser->addVisitor($this->nameResolver); + $nodeTraverser->addVisitor($this->variadicMethodsVisitor); + $nodeTraverser->addVisitor($this->variadicFunctionsVisitor); /** @var array */ return $nodeTraverser->traverse($nodes); diff --git a/src/Parser/VariadicFunctionsVisitor.php b/src/Parser/VariadicFunctionsVisitor.php new file mode 100644 index 0000000000..5276d0eb47 --- /dev/null +++ b/src/Parser/VariadicFunctionsVisitor.php @@ -0,0 +1,94 @@ + */ + public static array $cache = []; + + /** @var array */ + private array $variadicFunctions = []; + + public const ATTRIBUTE_NAME = 'variadicFunctions'; + + public function beforeTraverse(array $nodes): ?array + { + $this->topNode = null; + $this->variadicFunctions = []; + $this->inNamespace = null; + $this->inFunction = null; + + return null; + } + + public function enterNode(Node $node): ?Node + { + if ($this->topNode === null) { + $this->topNode = $node; + } + + if ($node instanceof Node\Stmt\Namespace_ && $node->name !== null) { + $this->inNamespace = $node->name->toString(); + } + + if ($node instanceof Node\Stmt\Function_) { + $this->inFunction = $this->inNamespace !== null ? $this->inNamespace . '\\' . $node->name->name : $node->name->name; + } + + if ( + $this->inFunction !== null + && $node instanceof Node\Expr\FuncCall + && $node->name instanceof Name + && in_array((string) $node->name, ParametersAcceptor::VARIADIC_FUNCTIONS, true) + && !array_key_exists($this->inFunction, $this->variadicFunctions) + ) { + $this->variadicFunctions[$this->inFunction] = true; + } + + return null; + } + + public function leaveNode(Node $node): ?Node + { + if ($node instanceof Node\Stmt\Namespace_ && $node->name !== null) { + $this->inNamespace = null; + } + + if ($node instanceof Node\Stmt\Function_ && $this->inFunction !== null) { + $this->variadicFunctions[$this->inFunction] ??= false; + $this->inFunction = null; + } + + return null; + } + + public function afterTraverse(array $nodes): ?array + { + if ($this->topNode !== null && $this->variadicFunctions !== []) { + foreach ($this->variadicFunctions as $name => $variadic) { + self::$cache[$name] = $variadic; + } + $functions = array_filter($this->variadicFunctions, static fn (bool $variadic) => $variadic); + $this->topNode->setAttribute(self::ATTRIBUTE_NAME, $functions); + } + + return null; + } + +} diff --git a/src/Parser/VariadicMethodsVisitor.php b/src/Parser/VariadicMethodsVisitor.php new file mode 100644 index 0000000000..50882efc54 --- /dev/null +++ b/src/Parser/VariadicMethodsVisitor.php @@ -0,0 +1,125 @@ + */ + private array $classStack = []; + + private ?string $inMethod = null; + + /** @var array> */ + public static array $cache = []; + + /** @var array> */ + private array $variadicMethods = []; + + public function beforeTraverse(array $nodes): ?array + { + $this->topNode = null; + $this->variadicMethods = []; + $this->inNamespace = null; + $this->classStack = []; + $this->inMethod = null; + + return null; + } + + public function enterNode(Node $node): ?Node + { + if ($this->topNode === null) { + $this->topNode = $node; + } + + if ($node instanceof Node\Stmt\Namespace_ && $node->name !== null) { + $this->inNamespace = $node->name->toString(); + } + + if ($node instanceof Node\Stmt\ClassLike) { + if (!$node->name instanceof Node\Identifier) { + $className = sprintf('%s:%s:%s', self::ANONYMOUS_CLASS_PREFIX, $node->getStartLine(), $node->getEndLine()); + $this->classStack[] = $className; + } else { + $className = $node->name->name; + $this->classStack[] = $this->inNamespace !== null ? $this->inNamespace . '\\' . $className : $className; + } + } + + if ($node instanceof ClassMethod) { + $this->inMethod = $node->name->name; + } + + if ( + $this->inMethod !== null + && $node instanceof Node\Expr\FuncCall + && $node->name instanceof Name + && in_array((string) $node->name, ParametersAcceptor::VARIADIC_FUNCTIONS, true) + ) { + $lastClass = $this->classStack[count($this->classStack) - 1] ?? null; + if ($lastClass !== null) { + if ( + !array_key_exists($lastClass, $this->variadicMethods) + || !array_key_exists($this->inMethod, $this->variadicMethods[$lastClass]) + ) { + $this->variadicMethods[$lastClass][$this->inMethod] = true; + } + } + + } + + return null; + } + + public function leaveNode(Node $node): ?Node + { + if ($node instanceof ClassMethod) { + $this->inMethod = null; + } + + if ($node instanceof Node\Stmt\ClassLike) { + array_pop($this->classStack); + } + + if ($node instanceof Node\Stmt\Namespace_ && $node->name !== null) { + $this->inNamespace = null; + } + + return null; + } + + public function afterTraverse(array $nodes): ?array + { + if ($this->topNode !== null && $this->variadicMethods !== []) { + foreach ($this->variadicMethods as $class => $methods) { + foreach ($methods as $name => $variadic) { + self::$cache[$class][$name] = $variadic; + } + } + $this->topNode->setAttribute(self::ATTRIBUTE_NAME, $this->variadicMethods); + } + + return null; + } + +} diff --git a/src/Reflection/Php/PhpFunctionReflection.php b/src/Reflection/Php/PhpFunctionReflection.php index e28f19f879..e8fbc2e824 100644 --- a/src/Reflection/Php/PhpFunctionReflection.php +++ b/src/Reflection/Php/PhpFunctionReflection.php @@ -2,20 +2,16 @@ namespace PHPStan\Reflection\Php; -use PhpParser\Node; -use PhpParser\Node\Stmt\Function_; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionFunction; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter; -use PHPStan\Cache\Cache; -use PHPStan\Parser\FunctionCallStatementFinder; use PHPStan\Parser\Parser; +use PHPStan\Parser\VariadicFunctionsVisitor; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\InitializerExprTypeResolver; -use PHPStan\Reflection\ParametersAcceptor; use PHPStan\TrinaryLogic; use PHPStan\Type\Generic\TemplateTypeMap; use PHPStan\Type\MixedType; @@ -23,11 +19,9 @@ use PHPStan\Type\TypehintHelper; use function array_key_exists; use function array_map; -use function filemtime; +use function count; use function is_array; use function is_file; -use function sprintf; -use function time; final class PhpFunctionReflection implements FunctionReflection { @@ -35,6 +29,8 @@ final class PhpFunctionReflection implements FunctionReflection /** @var list|null */ private ?array $variants = null; + private ?bool $containsVariadicCalls = null; + /** * @param array $phpDocParameterTypes * @param array $phpDocParameterOutTypes @@ -45,8 +41,6 @@ public function __construct( private InitializerExprTypeResolver $initializerExprTypeResolver, private ReflectionFunction $reflection, private Parser $parser, - private FunctionCallStatementFinder $functionCallStatementFinder, - private Cache $cache, private TemplateTypeMap $templateTypeMap, private array $phpDocParameterTypes, private ?Type $phpDocReturnType, @@ -139,67 +133,33 @@ private function getParameters(): array private function isVariadic(): bool { $isNativelyVariadic = $this->reflection->isVariadic(); - if (!$isNativelyVariadic && $this->reflection - ->getFileName() !== false) { - $fileName = $this->reflection->getFileName(); - if (is_file($fileName)) { - $functionName = $this->reflection->getName(); - $modifiedTime = filemtime($fileName); - if ($modifiedTime === false) { - $modifiedTime = time(); - } - $variableCacheKey = sprintf('%d-v4', $modifiedTime); - $key = sprintf('variadic-function-%s-%s', $functionName, $fileName); - $cachedResult = $this->cache->load($key, $variableCacheKey); - if ($cachedResult === null) { - $nodes = $this->parser->parseFile($fileName); - $result = !$this->containsVariadicFunction($nodes)->no(); - $this->cache->save($key, $variableCacheKey, $result); - return $result; - } + if (!$isNativelyVariadic && $this->reflection->getFileName() !== false && !$this->isBuiltin()) { + $filename = $this->reflection->getFileName(); - return $cachedResult; + if ($this->containsVariadicCalls !== null) { + return $this->containsVariadicCalls; } - } - - return $isNativelyVariadic; - } - /** - * @param Node[]|scalar[]|Node $node - */ - private function containsVariadicFunction(array|Node $node): TrinaryLogic - { - $result = TrinaryLogic::createMaybe(); - - if ($node instanceof Node) { - if ($node instanceof Function_) { - $functionName = (string) $node->namespacedName; - - if ($functionName === $this->reflection->getName()) { - return TrinaryLogic::createFromBoolean($this->isFunctionNodeVariadic($node)); - } + if (array_key_exists($this->reflection->getName(), VariadicFunctionsVisitor::$cache)) { + return $this->containsVariadicCalls = VariadicFunctionsVisitor::$cache[$this->reflection->getName()]; } - foreach ($node->getSubNodeNames() as $subNodeName) { - $innerNode = $node->{$subNodeName}; - if (!$innerNode instanceof Node && !is_array($innerNode)) { - continue; - } + $nodes = $this->parser->parseFile($filename); + if (count($nodes) > 0) { + $variadicFunctions = $nodes[0]->getAttribute(VariadicFunctionsVisitor::ATTRIBUTE_NAME); - $result = $result->and($this->containsVariadicFunction($innerNode)); - } - } elseif (is_array($node)) { - foreach ($node as $subNode) { - if (!$subNode instanceof Node) { - continue; + if ( + is_array($variadicFunctions) + && array_key_exists($this->reflection->getName(), $variadicFunctions) + ) { + return $this->containsVariadicCalls = $variadicFunctions[$this->reflection->getName()]; } - - $result = $result->and($this->containsVariadicFunction($subNode)); } + + return $this->containsVariadicCalls = false; } - return $result; + return $isNativelyVariadic; } private function getReturnType(): Type @@ -296,19 +256,4 @@ public function acceptsNamedArguments(): TrinaryLogic return TrinaryLogic::createFromBoolean($this->acceptsNamedArguments); } - private function isFunctionNodeVariadic(Function_ $node): bool - { - foreach ($node->params as $parameter) { - if ($parameter->variadic) { - return true; - } - } - - if ($this->functionCallStatementFinder->findFunctionCallInStatements(ParametersAcceptor::VARIADIC_FUNCTIONS, $node->getStmts()) !== null) { - return true; - } - - return false; - } - } diff --git a/src/Reflection/Php/PhpMethodReflection.php b/src/Reflection/Php/PhpMethodReflection.php index d0e008a7ed..53f5d80054 100644 --- a/src/Reflection/Php/PhpMethodReflection.php +++ b/src/Reflection/Php/PhpMethodReflection.php @@ -2,16 +2,10 @@ namespace PHPStan\Reflection\Php; -use PhpParser\Node; -use PhpParser\Node\Stmt\ClassMethod; -use PhpParser\Node\Stmt\Declare_; -use PhpParser\Node\Stmt\Function_; -use PhpParser\Node\Stmt\Namespace_; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionParameter; -use PHPStan\Cache\Cache; -use PHPStan\Parser\FunctionCallStatementFinder; use PHPStan\Parser\Parser; +use PHPStan\Parser\VariadicMethodsVisitor; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; @@ -21,7 +15,6 @@ use PHPStan\Reflection\ExtendedParametersAcceptor; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\MethodPrototypeReflection; -use PHPStan\Reflection\ParametersAcceptor; use PHPStan\Reflection\ReflectionProvider; use PHPStan\TrinaryLogic; use PHPStan\Type\ArrayType; @@ -36,14 +29,14 @@ use PHPStan\Type\TypehintHelper; use PHPStan\Type\VoidType; use ReflectionException; +use function array_key_exists; use function array_map; +use function count; use function explode; -use function filemtime; use function in_array; -use function is_bool; +use function is_array; use function sprintf; use function strtolower; -use function time; use const PHP_VERSION_ID; /** @@ -62,6 +55,8 @@ final class PhpMethodReflection implements ExtendedMethodReflection /** @var list|null */ private ?array $variants = null; + private ?bool $containsVariadicCalls = null; + /** * @param Type[] $phpDocParameterTypes * @param Type[] $phpDocParameterOutTypes @@ -75,8 +70,6 @@ public function __construct( private ReflectionMethod $reflection, private ReflectionProvider $reflectionProvider, private Parser $parser, - private FunctionCallStatementFinder $functionCallStatementFinder, - private Cache $cache, private TemplateTypeMap $templateTypeMap, private array $phpDocParameterTypes, private ?Type $phpDocReturnType, @@ -252,82 +245,40 @@ private function isVariadic(): bool $filename = $this->declaringTrait->getFileName(); } - if (!$isNativelyVariadic && $filename !== null) { - $modifiedTime = @filemtime($filename); - if ($modifiedTime === false) { - $modifiedTime = time(); - } - $key = sprintf('variadic-method-%s-%s-%s', $declaringClass->getName(), $this->reflection->getName(), $filename); - $variableCacheKey = sprintf('%d-v4', $modifiedTime); - $cachedResult = $this->cache->load($key, $variableCacheKey); - if ($cachedResult === null || !is_bool($cachedResult)) { - $nodes = $this->parser->parseFile($filename); - $result = $this->callsFuncGetArgs($declaringClass, $nodes); - $this->cache->save($key, $variableCacheKey, $result); - return $result; + if (!$isNativelyVariadic && $filename !== null && !$this->declaringClass->isBuiltin()) { + if ($this->containsVariadicCalls !== null) { + return $this->containsVariadicCalls; } - return $cachedResult; - } - - return $isNativelyVariadic; - } - - /** - * @param Node[] $nodes - */ - private function callsFuncGetArgs(ClassReflection $declaringClass, array $nodes): bool - { - foreach ($nodes as $node) { - if ( - $node instanceof Node\Stmt\ClassLike - ) { - if (!isset($node->namespacedName)) { - continue; - } - if ($declaringClass->getName() !== (string) $node->namespacedName) { - continue; - } - if ($this->callsFuncGetArgs($declaringClass, $node->stmts)) { - return true; - } - continue; + $className = $declaringClass->getName(); + if ($declaringClass->isAnonymous()) { + $className = sprintf('%s:%s:%s', VariadicMethodsVisitor::ANONYMOUS_CLASS_PREFIX, $declaringClass->getNativeReflection()->getStartLine(), $declaringClass->getNativeReflection()->getEndLine()); } - - if ($node instanceof ClassMethod) { - if ($node->getStmts() === null) { - continue; // interface - } - - $methodName = $node->name->name; - if ($methodName === $this->reflection->getName()) { - return $this->functionCallStatementFinder->findFunctionCallInStatements(ParametersAcceptor::VARIADIC_FUNCTIONS, $node->getStmts()) !== null; + if (array_key_exists($className, VariadicMethodsVisitor::$cache)) { + if (array_key_exists($this->reflection->getName(), VariadicMethodsVisitor::$cache[$className])) { + return $this->containsVariadicCalls = VariadicMethodsVisitor::$cache[$className][$this->reflection->getName()]; } - continue; + return $this->containsVariadicCalls = false; } - if ($node instanceof Function_) { - continue; - } + $nodes = $this->parser->parseFile($filename); + if (count($nodes) > 0) { + $variadicMethods = $nodes[0]->getAttribute(VariadicMethodsVisitor::ATTRIBUTE_NAME); - if ($node instanceof Namespace_) { - if ($this->callsFuncGetArgs($declaringClass, $node->stmts)) { - return true; + if ( + is_array($variadicMethods) + && array_key_exists($className, $variadicMethods) + && array_key_exists($this->reflection->getName(), $variadicMethods[$className]) + ) { + return $this->containsVariadicCalls = $variadicMethods[$className][$this->reflection->getName()]; } - continue; - } - - if (!$node instanceof Declare_ || $node->stmts === null) { - continue; } - if ($this->callsFuncGetArgs($declaringClass, $node->stmts)) { - return true; - } + return $this->containsVariadicCalls = false; } - return false; + return $isNativelyVariadic; } public function isPrivate(): bool diff --git a/tests/PHPStan/Parser/CleaningParserTest.php b/tests/PHPStan/Parser/CleaningParserTest.php index 692ea7b699..835486fdc2 100644 --- a/tests/PHPStan/Parser/CleaningParserTest.php +++ b/tests/PHPStan/Parser/CleaningParserTest.php @@ -68,6 +68,8 @@ public function testParse( new SimpleParser( new Php7(new Emulative()), new NameResolver(), + new VariadicMethodsVisitor(), + new VariadicFunctionsVisitor(), ), new PhpVersion($phpVersionId), ); diff --git a/tests/PHPStan/Parser/ParserTest.php b/tests/PHPStan/Parser/ParserTest.php new file mode 100644 index 0000000000..94fe9a406b --- /dev/null +++ b/tests/PHPStan/Parser/ParserTest.php @@ -0,0 +1,99 @@ + true, + ], + ]; + + yield [ + __DIR__ . '/data/variadic-methods.php', + VariadicMethodsVisitor::ATTRIBUTE_NAME, + [ + 'VariadicMethod\X' => [ + 'implicit_variadic_fn1' => true, + ], + 'VariadicMethod\Z' => [ + 'implicit_variadic_fnZ' => true, + ], + 'class@anonymous:20:30' => [ + 'implicit_variadic_subZ' => true, + ], + 'class@anonymous:42:52' => [ + 'implicit_variadic_fn' => true, + ], + 'class@anonymous:54:58' => [ + 'implicit_variadic_fn' => true, + ], + 'class@anonymous:61:68' => [ + 'implicit_variadic_fn' => true, + ], + ], + ]; + + yield [ + __DIR__ . '/data/variadic-methods-in-enum.php', + VariadicMethodsVisitor::ATTRIBUTE_NAME, + [ + 'VariadicMethodEnum\X' => [ + 'implicit_variadic_fn1' => true, + ], + ], + ]; + } + + /** + * @dataProvider dataVariadicCallLikes + * @param array|array> $expectedVariadics + * @throws ParserErrorsException + */ + public function testSimpleParserVariadicCallLikes(string $file, string $attributeName, array $expectedVariadics): void + { + /** @var SimpleParser $parser */ + $parser = self::getContainer()->getService('currentPhpVersionSimpleParser'); + $ast = $parser->parseFile($file); + $variadics = $ast[0]->getAttribute($attributeName); + $this->assertIsArray($variadics); + $this->assertCount(count($expectedVariadics), $variadics); + foreach ($expectedVariadics as $key => $expectedVariadic) { + $this->assertArrayHasKey($key, $variadics); + $this->assertSame($expectedVariadic, $variadics[$key]); + } + } + + /** + * @dataProvider dataVariadicCallLikes + * @param array|array> $expectedVariadics + * @throws ParserErrorsException + */ + public function testRichParserVariadicCallLikes(string $file, string $attributeName, array $expectedVariadics): void + { + /** @var RichParser $parser */ + $parser = self::getContainer()->getService('currentPhpVersionRichParser'); + $ast = $parser->parseFile($file); + $variadics = $ast[0]->getAttribute($attributeName); + $this->assertIsArray($variadics); + $this->assertCount(count($expectedVariadics), $variadics); + foreach ($expectedVariadics as $key => $expectedVariadic) { + $this->assertArrayHasKey($key, $variadics); + $this->assertSame($expectedVariadic, $variadics[$key]); + } + } + +} diff --git a/tests/PHPStan/Parser/data/variadic-functions.php b/tests/PHPStan/Parser/data/variadic-functions.php new file mode 100644 index 0000000000..d1a572e1e0 --- /dev/null +++ b/tests/PHPStan/Parser/data/variadic-functions.php @@ -0,0 +1,31 @@ += 8.1 + +namespace VariadicMethodEnum; + +enum X { + + function non_variadic_fn1($v) { + } + + function variadic_fn1(...$v) { + } + + function implicit_variadic_fn1() { + $args = func_get_args(); + } +} diff --git a/tests/PHPStan/Parser/data/variadic-methods.php b/tests/PHPStan/Parser/data/variadic-methods.php new file mode 100644 index 0000000000..da6135b967 --- /dev/null +++ b/tests/PHPStan/Parser/data/variadic-methods.php @@ -0,0 +1,68 @@ +checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->checkExplicitMixed = true; + + $this->analyse([__DIR__ . '/data/bug-11559c.php'], [ + [ + 'Method class@anonymous/tests/PHPStan/Rules/Methods/data/bug-11559c.php:6:1::regular_fn() invoked with 3 parameters, 1 required.', + 15, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-11559c.php b/tests/PHPStan/Rules/Methods/data/bug-11559c.php new file mode 100644 index 0000000000..54e3ba27b0 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-11559c.php @@ -0,0 +1,16 @@ +implicit_variadic_fn(1, 2, 3); + $c->regular_fn(1, 2, 3); +} From 2f2d6a3848e637e27b175e067666d9b0a25c83f8 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 8 Oct 2024 14:37:23 +0200 Subject: [PATCH 380/508] Cleanup - visitor already registered --- conf/config.neon | 3 --- 1 file changed, 3 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index 583cceac81..990ae2969c 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -259,9 +259,6 @@ services: tags: - phpstan.parser.richParserNodeVisitor - - - class: PHPStan\Parser\TypeTraverserInstanceofVisitor - - class: PHPStan\Parser\ArrowFunctionArgVisitor tags: From 19cd999f252ce582061c26b126819103425c75be Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 8 Oct 2024 14:37:59 +0200 Subject: [PATCH 381/508] Fixed optimization --- src/Parser/VariadicMethodsVisitor.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Parser/VariadicMethodsVisitor.php b/src/Parser/VariadicMethodsVisitor.php index 50882efc54..cc3821d9f2 100644 --- a/src/Parser/VariadicMethodsVisitor.php +++ b/src/Parser/VariadicMethodsVisitor.php @@ -29,10 +29,10 @@ final class VariadicMethodsVisitor extends NodeVisitorAbstract private ?string $inMethod = null; - /** @var array> */ + /** @var array> */ public static array $cache = []; - /** @var array> */ + /** @var array> */ private array $variadicMethods = []; public function beforeTraverse(array $nodes): ?array @@ -94,6 +94,10 @@ public function enterNode(Node $node): ?Node public function leaveNode(Node $node): ?Node { if ($node instanceof ClassMethod) { + $lastClass = $this->classStack[count($this->classStack) - 1] ?? null; + if ($lastClass !== null) { + $this->variadicMethods[$lastClass][$this->inMethod] ??= false; + } $this->inMethod = null; } @@ -111,12 +115,18 @@ public function leaveNode(Node $node): ?Node public function afterTraverse(array $nodes): ?array { if ($this->topNode !== null && $this->variadicMethods !== []) { + $filteredMethods = []; foreach ($this->variadicMethods as $class => $methods) { foreach ($methods as $name => $variadic) { self::$cache[$class][$name] = $variadic; + if (!$variadic) { + continue; + } + + $filteredMethods[$class][$name] = true; } } - $this->topNode->setAttribute(self::ATTRIBUTE_NAME, $this->variadicMethods); + $this->topNode->setAttribute(self::ATTRIBUTE_NAME, $filteredMethods); } return null; From 466ad51740d629c9137a77dac28a676b71ef7197 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 8 Oct 2024 15:13:38 +0200 Subject: [PATCH 382/508] Clean file cache from unused items --- src/Cache/FileCacheStorage.php | 110 +++++++++++++++++++++++++++++++++ src/Command/CommandHelper.php | 5 ++ 2 files changed, 115 insertions(+) diff --git a/src/Cache/FileCacheStorage.php b/src/Cache/FileCacheStorage.php index 5ba76a768a..8337b859ec 100644 --- a/src/Cache/FileCacheStorage.php +++ b/src/Cache/FileCacheStorage.php @@ -4,16 +4,32 @@ use InvalidArgumentException; use Nette\Utils\Random; +use PHPStan\File\CouldNotReadFileException; +use PHPStan\File\CouldNotWriteFileException; +use PHPStan\File\FileReader; use PHPStan\File\FileWriter; use PHPStan\Internal\DirectoryCreator; use PHPStan\Internal\DirectoryCreatorException; use PHPStan\ShouldNotHappenException; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use function array_keys; +use function closedir; +use function dirname; use function error_get_last; +use function is_dir; use function is_file; +use function opendir; +use function readdir; use function rename; +use function rmdir; use function sha1; use function sprintf; +use function str_contains; +use function str_starts_with; +use function strlen; use function substr; +use function uksort; use function unlink; use function var_export; use const DIRECTORY_SEPARATOR; @@ -21,6 +37,8 @@ final class FileCacheStorage implements CacheStorage { + private const CACHED_CLEARED_VERSION = 'v1-variadic'; + public function __construct(private string $directory) { } @@ -100,4 +118,96 @@ private function getFilePaths(string $key): array ]; } + public function clearUnusedFiles(): void + { + if (!is_dir($this->directory)) { + return; + } + + $cachedClearedFile = $this->directory . '/cache-cleared'; + if (is_file($cachedClearedFile)) { + try { + $cachedClearedContents = FileReader::read($cachedClearedFile); + if ($cachedClearedContents === self::CACHED_CLEARED_VERSION) { + return; + } + } catch (CouldNotReadFileException) { + return; + } + } + + $iterator = new RecursiveDirectoryIterator($this->directory); + $iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS); + $files = new RecursiveIteratorIterator($iterator); + $beginFunction = sprintf( + "getPathname(); + $contents = FileReader::read($path); + if (str_contains($contents, 'odsl-')) { + continue; + } + if ( + !str_starts_with($contents, $beginFunction) + && !str_starts_with($contents, $beginMethod) + && !str_starts_with($contents, $beginOld) + ) { + continue; + } + + $emptyDirectoriesToCheck[dirname($path)] = true; + $emptyDirectoriesToCheck[dirname($path, 2)] = true; + + @unlink($path); + } catch (CouldNotReadFileException) { + continue; + } + } + + uksort($emptyDirectoriesToCheck, static fn ($a, $b) => strlen($b) - strlen($a)); + + foreach (array_keys($emptyDirectoriesToCheck) as $directory) { + if (!$this->isDirectoryEmpty($directory)) { + continue; + } + + @rmdir($directory); + } + + try { + FileWriter::write($cachedClearedFile, self::CACHED_CLEARED_VERSION); + } catch (CouldNotWriteFileException) { + // pass + } + } + + private function isDirectoryEmpty(string $directory): bool + { + $handle = opendir($directory); + if ($handle === false) { + return false; + } + while (($entry = readdir($handle)) !== false) { + if ($entry !== '.' && $entry !== '..') { + closedir($handle); + return false; + } + } + + closedir($handle); + return true; + } + } diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index 7c81447cd8..65b059073e 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -12,6 +12,7 @@ use Nette\Schema\ValidationException; use Nette\Utils\AssertionException; use Nette\Utils\Strings; +use PHPStan\Cache\FileCacheStorage; use PHPStan\Command\Symfony\SymfonyOutput; use PHPStan\Command\Symfony\SymfonyStyle; use PHPStan\DependencyInjection\Container; @@ -434,6 +435,10 @@ public static function begin( if ($cleanupContainerCache) { $containerFactory->clearOldContainers($tmpDir); + $cacheStorage = $container->getService('cacheStorage'); + if ($cacheStorage instanceof FileCacheStorage) { + $cacheStorage->clearUnusedFiles(); + } } /** @var bool|null $customRulesetUsed */ From 12a19b231ad9b46971682eb38d0acaa259c4ab9e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 8 Oct 2024 15:38:20 +0200 Subject: [PATCH 383/508] This was also used format --- src/Cache/FileCacheStorage.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Cache/FileCacheStorage.php b/src/Cache/FileCacheStorage.php index 8337b859ec..18075f7e36 100644 --- a/src/Cache/FileCacheStorage.php +++ b/src/Cache/FileCacheStorage.php @@ -37,7 +37,7 @@ final class FileCacheStorage implements CacheStorage { - private const CACHED_CLEARED_VERSION = 'v1-variadic'; + private const CACHED_CLEARED_VERSION = 'v2-old-two'; public function __construct(private string $directory) { @@ -151,6 +151,10 @@ public function clearUnusedFiles(): void " Date: Tue, 8 Oct 2024 15:40:22 +0200 Subject: [PATCH 384/508] Update cache deletion logic --- src/Cache/FileCacheStorage.php | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/Cache/FileCacheStorage.php b/src/Cache/FileCacheStorage.php index 18075f7e36..1b66f26e2a 100644 --- a/src/Cache/FileCacheStorage.php +++ b/src/Cache/FileCacheStorage.php @@ -25,7 +25,6 @@ use function rmdir; use function sha1; use function sprintf; -use function str_contains; use function str_starts_with; use function strlen; use function substr; @@ -37,7 +36,7 @@ final class FileCacheStorage implements CacheStorage { - private const CACHED_CLEARED_VERSION = 'v2-old-two'; + private const CACHED_CLEARED_VERSION = 'v2-new'; public function __construct(private string $directory) { @@ -147,27 +146,16 @@ public function clearUnusedFiles(): void "getPathname(); $contents = FileReader::read($path); - if (str_contains($contents, 'odsl-')) { - continue; - } if ( !str_starts_with($contents, $beginFunction) && !str_starts_with($contents, $beginMethod) - && !str_starts_with($contents, $beginOld) - && !str_starts_with($contents, $beginOld2) + && str_starts_with($contents, $beginNew) ) { continue; } From 57c65888e6372a4056afbbacc8207d411ea8559a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 8 Oct 2024 17:11:13 +0200 Subject: [PATCH 385/508] Journal for used generated containers --- src/Command/CommandHelper.php | 4 +- src/DependencyInjection/Configurator.php | 114 +++++++++++++++++- src/DependencyInjection/ContainerFactory.php | 49 ++------ .../DerivativeContainerFactory.php | 1 + 4 files changed, 124 insertions(+), 44 deletions(-) diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index 65b059073e..499ebb48e8 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -213,6 +213,9 @@ public static function begin( $analysedPathsFromConfig = []; $containerFactory = new ContainerFactory($currentWorkingDirectory); + if ($cleanupContainerCache) { + $containerFactory->setJournalContainer(); + } $projectConfig = null; if ($projectConfigFile !== null) { if (!is_file($projectConfigFile)) { @@ -434,7 +437,6 @@ public static function begin( } if ($cleanupContainerCache) { - $containerFactory->clearOldContainers($tmpDir); $cacheStorage = $container->getService('cacheStorage'); if ($cacheStorage instanceof FileCacheStorage) { $cacheStorage->clearUnusedFiles(); diff --git a/src/DependencyInjection/Configurator.php b/src/DependencyInjection/Configurator.php index 31886c52bf..524365e77e 100644 --- a/src/DependencyInjection/Configurator.php +++ b/src/DependencyInjection/Configurator.php @@ -2,15 +2,31 @@ namespace PHPStan\DependencyInjection; +use DirectoryIterator; use Nette\DI\Config\Loader; use Nette\DI\Container as OriginalNetteContainer; use Nette\DI\ContainerLoader; use PHPStan\File\CouldNotReadFileException; +use PHPStan\File\CouldNotWriteFileException; +use PHPStan\File\FileReader; +use PHPStan\File\FileWriter; use function array_keys; +use function count; use function error_reporting; +use function explode; +use function implode; +use function in_array; +use function is_dir; +use function is_file; use function restore_error_handler; use function set_error_handler; use function sha1_file; +use function sprintf; +use function str_ends_with; +use function substr; +use function time; +use function trim; +use function unlink; use const E_USER_DEPRECATED; use const PHP_RELEASE_VERSION; use const PHP_VERSION_ID; @@ -21,7 +37,7 @@ final class Configurator extends \Nette\Bootstrap\Configurator /** @var string[] */ private array $allConfigFiles = []; - public function __construct(private LoaderFactory $loaderFactory) + public function __construct(private LoaderFactory $loaderFactory, private bool $journalContainer) { parent::__construct(); } @@ -59,10 +75,104 @@ public function loadContainer(): string $this->staticParameters['debugMode'], ); - return $loader->load( + $className = $loader->load( [$this, 'generateContainer'], [$this->staticParameters, array_keys($this->dynamicParameters), $this->configs, PHP_VERSION_ID - PHP_RELEASE_VERSION, NeonAdapter::CACHE_KEY, $this->getAllConfigFilesHashes()], ); + + if ($this->journalContainer) { + $this->journal($className); + } + + return $className; + } + + private function journal(string $currentContainerClassName): void + { + $directory = $this->getContainerCacheDirectory(); + if (!is_dir($directory)) { + return; + } + + $journalFile = $directory . '/container.journal'; + if (!is_file($journalFile)) { + try { + FileWriter::write($journalFile, sprintf("%s:%d\n", $currentContainerClassName, time())); + } catch (CouldNotWriteFileException) { + // pass + } + + return; + } + + try { + $journalContents = FileReader::read($journalFile); + } catch (CouldNotReadFileException) { + return; + } + + $journalLines = explode("\n", trim($journalContents)); + $linesToWrite = []; + $usedInTheLastWeek = []; + $now = time(); + $currentAlreadyInTheJournal = false; + foreach ($journalLines as $journalLine) { + if ($journalLine === '') { + continue; + } + $journalLineParts = explode(':', $journalLine); + if (count($journalLineParts) !== 2) { + return; + } + $className = $journalLineParts[0]; + $containerLastUsedTime = (int) $journalLineParts[1]; + + $week = 3600 * 24 * 7; + + if ($containerLastUsedTime + $week >= $now) { + $usedInTheLastWeek[] = $className; + } + + if ($currentContainerClassName !== $className) { + $linesToWrite[] = sprintf('%s:%d', $className, $containerLastUsedTime); + continue; + } + + $linesToWrite[] = sprintf('%s:%d', $currentContainerClassName, $now); + $currentAlreadyInTheJournal = true; + } + + if (!$currentAlreadyInTheJournal) { + $linesToWrite[] = sprintf('%s:%d', $currentContainerClassName, $now); + $usedInTheLastWeek[] = $currentContainerClassName; + } + + try { + FileWriter::write($journalFile, implode("\n", $linesToWrite) . "\n"); + } catch (CouldNotWriteFileException) { + return; + } + + foreach (new DirectoryIterator($directory) as $fileInfo) { + if ($fileInfo->isDot()) { + continue; + } + $fileName = $fileInfo->getFilename(); + if ($fileName === 'container.journal') { + continue; + } + if (!str_ends_with($fileName, '.php')) { + continue; + } + $fileClassName = substr($fileName, 0, -4); + if (in_array($fileClassName, $usedInTheLastWeek, true)) { + continue; + } + $basePathname = $fileInfo->getPathname(); + @unlink($basePathname); + @unlink($basePathname . '.lock'); + @unlink($basePathname . '.meta'); + } } public function createContainer(bool $initialize = true): OriginalNetteContainer diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index c997c65ec2..7ac72d4fc4 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -31,7 +31,6 @@ use PHPStan\Reflection\ReflectionProviderStaticAccessor; use PHPStan\ShouldNotHappenException; use PHPStan\Type\ObjectType; -use Symfony\Component\Finder\Finder; use function array_diff_key; use function array_map; use function array_merge; @@ -42,15 +41,12 @@ use function getenv; use function ini_get; use function is_array; -use function is_dir; use function is_file; use function is_readable; use function spl_object_id; use function sprintf; use function str_ends_with; use function substr; -use function time; -use function unlink; /** * @api @@ -66,6 +62,8 @@ final class ContainerFactory private static ?int $lastInitializedContainerId = null; + private bool $journalContainer = false; + /** @api */ public function __construct(private string $currentWorkingDirectory) { @@ -83,6 +81,11 @@ public function __construct(private string $currentWorkingDirectory) $this->configDirectory = $originalRootDir . '/conf'; } + public function setJournalContainer(): void + { + $this->journalContainer = true; + } + /** * @param string[] $additionalConfigFiles * @param string[] $analysedPaths @@ -114,7 +117,7 @@ public function create( $this->rootDirectory, $this->currentWorkingDirectory, $generateBaselineFile, - )); + ), $this->journalContainer); $configurator->defaultExtensions = [ 'php' => PhpExtension::class, 'extensions' => ExtensionsExtension::class, @@ -188,42 +191,6 @@ public static function postInitializeContainer(Container $container): void BleedingEdgeToggle::setBleedingEdge($container->getParameter('featureToggles')['bleedingEdge']); } - public function clearOldContainers(string $tempDirectory): void - { - $configurator = new Configurator(new LoaderFactory( - $this->fileHelper, - $this->rootDirectory, - $this->currentWorkingDirectory, - null, - )); - $configurator->setDebugMode(true); - $configurator->setTempDirectory($tempDirectory); - - $containerDirectory = $configurator->getContainerCacheDirectory(); - if (!is_dir($containerDirectory)) { - return; - } - - $finder = new Finder(); - $finder->name('Container_*')->in($containerDirectory); - $twoDaysAgo = time() - 24 * 60 * 60 * 2; - - foreach ($finder as $containerFile) { - $path = $containerFile->getRealPath(); - if ($path === false) { - continue; - } - if ($containerFile->getATime() > $twoDaysAgo) { - continue; - } - if ($containerFile->getCTime() > $twoDaysAgo) { - continue; - } - - @unlink($path); - } - } - public function getCurrentWorkingDirectory(): string { return $this->currentWorkingDirectory; diff --git a/src/DependencyInjection/DerivativeContainerFactory.php b/src/DependencyInjection/DerivativeContainerFactory.php index a32bc2eb6a..218eb4e252 100644 --- a/src/DependencyInjection/DerivativeContainerFactory.php +++ b/src/DependencyInjection/DerivativeContainerFactory.php @@ -35,6 +35,7 @@ public function create(array $additionalConfigFiles): Container $containerFactory = new ContainerFactory( $this->currentWorkingDirectory, ); + $containerFactory->setJournalContainer(); return $containerFactory->create( $this->tempDirectory, From 338d6f9d34a1e1cb84e57df378f8fb2c7805afd0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 9 Oct 2024 09:20:24 +0200 Subject: [PATCH 386/508] Update nikic/php-parser --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 810f663d6b..3e705fbf75 100644 --- a/composer.lock +++ b/composer.lock @@ -2057,16 +2057,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.3.0", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3abf7425cd284141dc5d8d14a9ee444de3345d1a", - "reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { @@ -2109,9 +2109,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2024-09-29T13:56:26+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "ondram/ci-detector", From ca1e144cf83b1560d81292eb0a67e78d45e9525d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 9 Oct 2024 09:22:22 +0200 Subject: [PATCH 387/508] Revert "Fix generate-function-metadata.php script" This reverts commit 14a3b36d72f149fda2837cf11cc899db5aa87a7a. --- bin/generate-function-metadata.php | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/bin/generate-function-metadata.php b/bin/generate-function-metadata.php index 7b834e2cbb..97737499a5 100755 --- a/bin/generate-function-metadata.php +++ b/bin/generate-function-metadata.php @@ -69,19 +69,8 @@ public function enterNode(Node $node) $traverser->addVisitor(new NodeConnectingVisitor()); $traverser->addVisitor($visitor); - $contents = FileReader::read($path); - if (str_ends_with($path, '/vendor/jetbrains/phpstorm-stubs/Core/Core.php')) { - $contents = str_replace([ - 'function exit', - 'function die', - ], [ - 'function _exit', - 'function _die', - ], $contents); - } - $traverser->traverse( - $parser->parse($contents), + $parser->parse(FileReader::read($path)), ); } From 3316a152a417141318744461aebba28db47252a8 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Wed, 9 Oct 2024 07:26:28 +0000 Subject: [PATCH 388/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 54283827b4..01d6a7219f 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.9", - "phpstan/php-8-stubs": "0.4.1", + "phpstan/php-8-stubs": "0.4.2", "phpstan/phpdoc-parser": "^2.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index 3e705fbf75..a0e88b728c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "416d829025e6a2d8f7115f4c142b0718", + "content-hash": "ff0567b9fb64e25665e322c6daa69896", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.1", + "version": "0.4.2", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "212d2b20c3c6f8c06a224efb748ec4cd069ef251" + "reference": "64fbb357f86728a3d0a06d57178bf968bcf82206" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/212d2b20c3c6f8c06a224efb748ec4cd069ef251", - "reference": "212d2b20c3c6f8c06a224efb748ec4cd069ef251", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/64fbb357f86728a3d0a06d57178bf968bcf82206", + "reference": "64fbb357f86728a3d0a06d57178bf968bcf82206", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.1" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.2" }, - "time": "2024-10-08T00:18:48+00:00" + "time": "2024-10-09T07:25:55+00:00" }, { "name": "phpstan/phpdoc-parser", From 44a28cf81ca534970ba5d090285bf3858239c07c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 9 Oct 2024 09:28:38 +0200 Subject: [PATCH 389/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 10 +++++----- resources/functionMetadata.php | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 01d6a7219f..22bc7b1060 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#56f6b9e55f5885e651553843a1aaf9ec9c586c04", + "jetbrains/phpstorm-stubs": "dev-master#a45eab9318f66864e9840379d3a1976ffe9b8d63", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index a0e88b728c..8f8c4a2870 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ff0567b9fb64e25665e322c6daa69896", + "content-hash": "e1fa4f06ec0cf6213d6cc617ffcc992d", "packages": [ { "name": "clue/ndjson-react", @@ -1442,12 +1442,12 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "56f6b9e55f5885e651553843a1aaf9ec9c586c04" + "reference": "a45eab9318f66864e9840379d3a1976ffe9b8d63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/56f6b9e55f5885e651553843a1aaf9ec9c586c04", - "reference": "56f6b9e55f5885e651553843a1aaf9ec9c586c04", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/a45eab9318f66864e9840379d3a1976ffe9b8d63", + "reference": "a45eab9318f66864e9840379d3a1976ffe9b8d63", "shasum": "" }, "require-dev": { @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-09-06T13:20:48+00:00" + "time": "2024-10-05T19:50:06+00:00" }, { "name": "nette/bootstrap", diff --git a/resources/functionMetadata.php b/resources/functionMetadata.php index 4ba615393d..0c5c33759a 100644 --- a/resources/functionMetadata.php +++ b/resources/functionMetadata.php @@ -651,7 +651,6 @@ 'StringBackedEnum::tryFrom' => ['hasSideEffects' => false], 'StubTests\\CodeStyle\\BracesOneLineFixer::getDefinition' => ['hasSideEffects' => false], 'StubTests\\Parsers\\ExpectedFunctionArgumentsInfo::__toString' => ['hasSideEffects' => false], - 'StubTests\\Parsers\\Visitors\\CoreStubASTVisitor::__construct' => ['hasSideEffects' => false], 'StubTests\\StubsMetaExpectedArgumentsTest::getClassMemberFqn' => ['hasSideEffects' => false], 'StubTests\\StubsParameterNamesTest::printParameters' => ['hasSideEffects' => false], 'Transliterator::createInverse' => ['hasSideEffects' => false], From 35b532af83b42c3c1c1aebb7c9b961846cf66408 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 9 Oct 2024 09:53:51 +0200 Subject: [PATCH 390/508] Remove old containers from the journal --- src/DependencyInjection/Configurator.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/DependencyInjection/Configurator.php b/src/DependencyInjection/Configurator.php index 524365e77e..f5a9d9e713 100644 --- a/src/DependencyInjection/Configurator.php +++ b/src/DependencyInjection/Configurator.php @@ -131,6 +131,8 @@ private function journal(string $currentContainerClassName): void if ($containerLastUsedTime + $week >= $now) { $usedInTheLastWeek[] = $className; + } else { + continue; } if ($currentContainerClassName !== $className) { From a883c66f5390fa83bb3f2ef936c8501af716a516 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 9 Oct 2024 10:06:44 +0200 Subject: [PATCH 391/508] Fix CS --- src/DependencyInjection/Configurator.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DependencyInjection/Configurator.php b/src/DependencyInjection/Configurator.php index f5a9d9e713..9536925b9d 100644 --- a/src/DependencyInjection/Configurator.php +++ b/src/DependencyInjection/Configurator.php @@ -129,12 +129,12 @@ private function journal(string $currentContainerClassName): void $week = 3600 * 24 * 7; - if ($containerLastUsedTime + $week >= $now) { - $usedInTheLastWeek[] = $className; - } else { + if ($containerLastUsedTime + $week < $now) { continue; } + $usedInTheLastWeek[] = $className; + if ($currentContainerClassName !== $className) { $linesToWrite[] = sprintf('%s:%d', $className, $containerLastUsedTime); continue; From 48f8c85ee7198a5bd480023815f8b8cba809dc64 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 9 Oct 2024 12:43:08 +0200 Subject: [PATCH 392/508] Move template-default.php to nsrt --- tests/PHPStan/Analyser/NodeScopeResolverTest.php | 1 - tests/PHPStan/Analyser/{data => nsrt}/template-default.php | 0 2 files changed, 1 deletion(-) rename tests/PHPStan/Analyser/{data => nsrt}/template-default.php (100%) diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 37b26eb3f2..1363deb2fe 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -204,7 +204,6 @@ private static function findTestFiles(): iterable yield __DIR__ . '/../Rules/Classes/data/mixin-trait-use.php'; yield __DIR__ . '/../Rules/Methods/data/bug-4801.php'; - yield __DIR__ . '/data/template-default.php'; } /** diff --git a/tests/PHPStan/Analyser/data/template-default.php b/tests/PHPStan/Analyser/nsrt/template-default.php similarity index 100% rename from tests/PHPStan/Analyser/data/template-default.php rename to tests/PHPStan/Analyser/nsrt/template-default.php From 4a8d584308f04ad41161300112bac5dbadd5f7d7 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 9 Oct 2024 12:43:25 +0200 Subject: [PATCH 393/508] Test template-default.php only on PHP 8+ --- tests/PHPStan/Analyser/nsrt/template-default.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Analyser/nsrt/template-default.php b/tests/PHPStan/Analyser/nsrt/template-default.php index 979fbc3636..c73ce4ab38 100644 --- a/tests/PHPStan/Analyser/nsrt/template-default.php +++ b/tests/PHPStan/Analyser/nsrt/template-default.php @@ -1,4 +1,4 @@ -= 8.0 namespace TemplateDefault; From ee6e0ef18a6a1b365c8f0f5bc35e8a8b59694c20 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 9 Oct 2024 13:42:10 +0200 Subject: [PATCH 394/508] Added regression test --- .../Rules/Functions/ReturnTypeRuleTest.php | 12 +++++ .../Rules/Functions/data/bug-11301.php | 48 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tests/PHPStan/Rules/Functions/data/bug-11301.php diff --git a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php index d0a65124cc..de61bd96eb 100644 --- a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php @@ -322,4 +322,16 @@ public function testBug11549(): void $this->analyse([__DIR__ . '/data/bug-11549.php'], []); } + public function testBug11301(): void + { + $this->checkExplicitMixed = true; + $this->checkNullables = true; + $this->analyse([__DIR__ . '/data/bug-11301.php'], [ + [ + 'Function Bug11301\cString() should return array but returns array.', + 35, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Functions/data/bug-11301.php b/tests/PHPStan/Rules/Functions/data/bug-11301.php new file mode 100644 index 0000000000..5c9f80cc08 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-11301.php @@ -0,0 +1,48 @@ + + */ +function cInt(): array +{ + $a = ['12345']; + $b = ['abc']; + + return array_combine($a, $b); +} + +/** + * @return array + */ +function cInt2(): array +{ + $a = ['12345', 123]; + $b = ['abc', 'def']; + + return array_combine($a, $b); +} + +/** + * @return array + */ +function cString(): array +{ + $a = ['12345']; + $b = ['abc']; + + return array_combine($a, $b); +} + + +/** + * @return array + */ +function cString2(): array +{ + $a = ['12345', 123, 'a']; + $b = ['abc', 'def', 'xy']; + + return array_combine($a, $b); +} From eed9282f97246c03ec4374549b7f3e1712c48f06 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 9 Oct 2024 17:00:33 +0200 Subject: [PATCH 395/508] Update simple-downgrader --- composer.lock | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index 8f8c4a2870..beef5f73d8 100644 --- a/composer.lock +++ b/composer.lock @@ -4445,21 +4445,21 @@ }, { "name": "ondrejmirtes/simple-downgrader", - "version": "2.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/simple-downgrader.git", - "reference": "760b4c5c0b5ae631e6604bdcf074387e40e35ed1" + "reference": "fb8b7833034f0396d5e4518ed090e3d099b7d9bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/simple-downgrader/zipball/760b4c5c0b5ae631e6604bdcf074387e40e35ed1", - "reference": "760b4c5c0b5ae631e6604bdcf074387e40e35ed1", + "url": "https://api.github.com/repos/ondrejmirtes/simple-downgrader/zipball/fb8b7833034f0396d5e4518ed090e3d099b7d9bc", + "reference": "fb8b7833034f0396d5e4518ed090e3d099b7d9bc", "shasum": "" }, "require": { "nette/utils": "^3.2.5", - "nikic/php-parser": "^5.0", + "nikic/php-parser": "^5.3.0", "php": "^7.4|^8.0", "phpstan/phpdoc-parser": "^2.0", "symfony/console": "^5.4", @@ -4470,7 +4470,6 @@ "phpstan/phpstan": "^2.0", "phpunit/phpunit": "^9.6" }, - "default-branch": true, "bin": [ "bin/simple-downgrade" ], @@ -4489,9 +4488,9 @@ "description": "Simple Downgrader", "support": { "issues": "https://github.com/ondrejmirtes/simple-downgrader/issues", - "source": "https://github.com/ondrejmirtes/simple-downgrader/tree/2.x" + "source": "https://github.com/ondrejmirtes/simple-downgrader/tree/2.0.0" }, - "time": "2024-09-15T14:01:11+00:00" + "time": "2024-10-09T14:55:47+00:00" }, { "name": "phar-io/manifest", From 728ae75699494e476731afc606febadc986c4611 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Thu, 3 Oct 2024 15:45:43 +0200 Subject: [PATCH 396/508] test: use bashunit -a exit_code to check for errors and defer the execution call inside bashunit --- .github/workflows/e2e-tests.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 4d56668a56..6d486bc70e 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -160,49 +160,52 @@ jobs: cd e2e/trait-caching ../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/ patch -b data/TraitOne.php < TraitOne.patch - OUTPUT=$(../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/ || true) + OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/") echo "$OUTPUT" - ../bashunit -a line_count 1 "$OUTPUT" + ../bashunit -a line_count 2 "$OUTPUT" + ../bashunit -a matches "Note: Using configuration file .+phpstan.neon." "$OUTPUT" ../bashunit -a contains 'Method TraitsCachingIssue\TestClassUsingTrait::doBar() should return stdClass but returns Exception.' "$OUTPUT" - script: | cd e2e/trait-caching ../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/ patch -b data/TraitTwo.php < TraitTwo.patch - OUTPUT=$(../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/ || true) + OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/") echo "$OUTPUT" - ../bashunit -a line_count 1 "$OUTPUT" + ../bashunit -a line_count 2 "$OUTPUT" + ../bashunit -a matches "Note: Using configuration file .+phpstan.neon." "$OUTPUT" ../bashunit -a contains 'Method class@anonymous/TestClassUsingTrait.php:20::doBar() should return stdClass but returns Exception.' "$OUTPUT" - script: | cd e2e/trait-caching ../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/ patch -b data/TraitOne.php < TraitOne.patch patch -b data/TraitTwo.php < TraitTwo.patch - OUTPUT=$(../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/ || true) + OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyze --no-progress --level 8 --error-format raw data/") echo "$OUTPUT" - ../bashunit -a line_count 2 "$OUTPUT" + ../bashunit -a line_count 3 "$OUTPUT" + ../bashunit -a matches "Note: Using configuration file .+phpstan.neon." "$OUTPUT" ../bashunit -a contains 'Method TraitsCachingIssue\TestClassUsingTrait::doBar() should return stdClass but returns Exception.' "$OUTPUT" ../bashunit -a contains 'Method class@anonymous/TestClassUsingTrait.php:20::doBar() should return stdClass but returns Exception.' "$OUTPUT" - script: | cd e2e/bad-exclude-paths - OUTPUT=$(../../bin/phpstan analyse -c ignore.neon 2>&1 || true) + OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -c ignore.neon") echo "$OUTPUT" ../bashunit -a contains 'Invalid entry in ignoreErrors' "$OUTPUT" ../bashunit -a contains 'tests is neither a directory, nor a file path, nor a fnmatch pattern.' "$OUTPUT" - script: | cd e2e/bad-exclude-paths - OUTPUT=$(../../bin/phpstan analyse -c phpneon.php 2>&1 || true) + OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -c phpneon.php") echo "$OUTPUT" ../bashunit -a contains 'Invalid entry in ignoreErrors' "$OUTPUT" ../bashunit -a contains 'src/test.php is neither a directory, nor a file path, nor a fnmatch pattern.' "$OUTPUT" - script: | cd e2e/bad-exclude-paths - OUTPUT=$(../../bin/phpstan analyse -c excludePaths.neon 2>&1 || true) + OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -c excludePaths.neon") echo "$OUTPUT" ../bashunit -a contains 'Invalid entry in excludePaths' "$OUTPUT" ../bashunit -a contains 'tests is neither a directory, nor a file path, nor a fnmatch pattern.' "$OUTPUT" - script: | cd e2e/bad-exclude-paths - OUTPUT=$(../../bin/phpstan analyse -c phpneon2.php 2>&1 || true) + OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan analyse -c phpneon2.php") echo "$OUTPUT" ../bashunit -a contains 'Invalid entry in excludePaths' "$OUTPUT" ../bashunit -a contains 'src/test.php is neither a directory, nor a file path, nor a fnmatch pattern.' "$OUTPUT" From 93126b4590bb1c0c934be1dc52af180144ef45ef Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 12 Oct 2024 13:07:36 +0200 Subject: [PATCH 397/508] Revert "Simulate level 10 in issue bot on 1.12.x" This reverts commit def9f5abccb4b2e761dc7886f444e56aae25d97a. --- .github/workflows/issue-bot.yml | 3 --- issue-bot/config.level10.neon | 5 ----- 2 files changed, 8 deletions(-) delete mode 100644 issue-bot/config.level10.neon diff --git a/.github/workflows/issue-bot.yml b/.github/workflows/issue-bot.yml index 530886afff..6d6af362f1 100644 --- a/.github/workflows/issue-bot.yml +++ b/.github/workflows/issue-bot.yml @@ -106,9 +106,6 @@ jobs: attempt_limit: 5 attempt_delay: 1000 - - name: "Add level 10 config file" - run: "cp issue-bot/config.level10.neon conf/" - - name: "Run PHPStan" working-directory: "issue-bot" timeout-minutes: 5 diff --git a/issue-bot/config.level10.neon b/issue-bot/config.level10.neon deleted file mode 100644 index 5d052692c9..0000000000 --- a/issue-bot/config.level10.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - config.level9.neon - -parameters: - checkImplicitMixed: true From a9346394eafb588efe7af2c0650dfeb2b757a427 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 12 Oct 2024 13:16:12 +0200 Subject: [PATCH 398/508] Fix test --- tests/PHPStan/Rules/Debug/data/dump-phpdoc-type.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Rules/Debug/data/dump-phpdoc-type.php b/tests/PHPStan/Rules/Debug/data/dump-phpdoc-type.php index e8d009fe0f..2b5c9c1d40 100644 --- a/tests/PHPStan/Rules/Debug/data/dump-phpdoc-type.php +++ b/tests/PHPStan/Rules/Debug/data/dump-phpdoc-type.php @@ -31,7 +31,7 @@ * @param T $value * @return T */ -function id(mixed $value): mixed +function id($value) { dumpPhpDocType($value); From 6cf223840f89c972551f373ade9eea16d12e143b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 12 Oct 2024 15:46:37 +0200 Subject: [PATCH 399/508] ArrayType::describe - explicit mixed should be stated explicitly --- phpstan-baseline.neon | 2 +- src/Type/ArrayType.php | 8 +-- ...ySearchFunctionTypeSpecifyingExtension.php | 5 +- .../Analyser/AnalyserIntegrationTest.php | 2 +- .../Analyser/LegacyNodeScopeResolverTest.php | 8 +-- tests/PHPStan/Analyser/TypeSpecifierTest.php | 10 ++-- tests/PHPStan/Analyser/data/param-out.php | 6 +- tests/PHPStan/Analyser/nsrt/array-chunk.php | 2 +- .../Analyser/nsrt/array-fill-keys-php8.php | 2 +- .../PHPStan/Analyser/nsrt/array-flip-php8.php | 2 +- .../nsrt/array-intersect-key-php8.php | 2 +- tests/PHPStan/Analyser/nsrt/array-pop.php | 2 +- tests/PHPStan/Analyser/nsrt/array-reverse.php | 8 +-- .../Analyser/nsrt/array-search-php8.php | 2 +- tests/PHPStan/Analyser/nsrt/array-shift.php | 2 +- tests/PHPStan/Analyser/nsrt/array-slice.php | 2 +- tests/PHPStan/Analyser/nsrt/array_keys.php | 2 +- tests/PHPStan/Analyser/nsrt/array_values.php | 2 +- .../PHPStan/Analyser/nsrt/assert-docblock.php | 22 +++---- .../PHPStan/Analyser/nsrt/assert-methods.php | 4 +- tests/PHPStan/Analyser/nsrt/bug-1209.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-1233.php | 6 +- tests/PHPStan/Analyser/nsrt/bug-3446.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-6329.php | 14 ++--- .../nsrt/bug-7144-composer-integration.php | 8 +-- tests/PHPStan/Analyser/nsrt/bug-7915.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-9662.php | 58 +++++++++---------- tests/PHPStan/Analyser/nsrt/bug-9734.php | 4 +- .../nsrt/conditional-types-inference.php | 2 +- .../Analyser/nsrt/filter-var-array.php | 6 +- tests/PHPStan/Analyser/nsrt/generics.php | 4 +- tests/PHPStan/Analyser/nsrt/globals.php | 18 +++--- .../Analyser/nsrt/has-offset-type-bug.php | 6 +- tests/PHPStan/Analyser/nsrt/memcache-get.php | 2 +- .../PHPStan/Analyser/nsrt/mixed-subtract.php | 4 +- .../PHPStan/Analyser/nsrt/mixed-to-number.php | 2 +- tests/PHPStan/Analyser/nsrt/narrow-cast.php | 4 +- .../Analyser/nsrt/native-expressions.php | 2 +- .../prestashop-breakdowns-empty-array.php | 6 +- .../Php8SignatureMapProviderTest.php | 2 +- ...nexistentOffsetInArrayDimFetchRuleTest.php | 2 +- tests/PHPStan/Rules/Classes/data/bug-5333.php | 2 +- .../CallToFunctionParametersRuleTest.php | 8 +-- .../Rules/Methods/CallMethodsRuleTest.php | 6 +- .../Methods/CallStaticMethodsRuleTest.php | 6 +- .../Rules/Methods/ReturnTypeRuleTest.php | 4 +- .../VarTagChangedExpressionTypeRuleTest.php | 8 +-- .../WrongVariableNameInVarTagRuleTest.php | 2 +- .../TypesAssignedToPropertiesRuleTest.php | 6 +- .../PHPStan/Rules/Variables/data/bug-8113.php | 12 ++-- 50 files changed, 151 insertions(+), 154 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index fb4b06b279..a652b6a836 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -13,7 +13,7 @@ parameters: path: src/Analyser/AnalyserResultFinalizer.php - - message: '#^Cannot assign offset ''realCount'' to array\|string\.$#' + message: '#^Cannot assign offset ''realCount'' to array\\|string\.$#' identifier: offsetAssign.dimType count: 1 path: src/Analyser/Ignore/IgnoredErrorHelperResult.php diff --git a/src/Type/ArrayType.php b/src/Type/ArrayType.php index 8fb1a219d5..488dac119e 100644 --- a/src/Type/ArrayType.php +++ b/src/Type/ArrayType.php @@ -128,8 +128,8 @@ public function equals(Type $type): bool public function describe(VerbosityLevel $level): string { - $isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed'; - $isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed'; + $isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->keyType->isExplicitMixed(); + $isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->itemType->isExplicitMixed(); $valueHandler = function () use ($level, $isMixedKeyType, $isMixedItemType): string { if ($isMixedKeyType || $this->keyType instanceof NeverType) { @@ -500,8 +500,8 @@ public function traverse(callable $cb): Type public function toPhpDocNode(): TypeNode { - $isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed'; - $isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed'; + $isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->keyType->isExplicitMixed(); + $isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->itemType->isExplicitMixed(); if ($isMixedKeyType) { if ($isMixedItemType) { diff --git a/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php b/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php index b382891275..68f2992096 100644 --- a/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php @@ -10,10 +10,7 @@ use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\Accessory\NonEmptyArrayType; -use PHPStan\Type\ArrayType; use PHPStan\Type\FunctionTypeSpecifyingExtension; -use PHPStan\Type\MixedType; -use PHPStan\Type\TypeCombinator; use function strtolower; final class ArraySearchFunctionTypeSpecifyingExtension implements FunctionTypeSpecifyingExtension, TypeSpecifierAwareExtension @@ -45,7 +42,7 @@ public function specifyTypes( return $this->typeSpecifier->create( $arrayArg, - TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new NonEmptyArrayType()), + new NonEmptyArrayType(), $context, $scope, ); diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index 52791b8b95..d64cd88617 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -1198,7 +1198,7 @@ public function testBug9459(): void { $errors = $this->runAnalyse(__DIR__ . '/data/bug-9459.php'); $this->assertCount(1, $errors); - $this->assertSame('PHPDoc tag @var with type callable(): array is not subtype of native type Closure(): array{}.', $errors[0]->getMessage()); + $this->assertSame('PHPDoc tag @var with type callable(): array is not subtype of native type Closure(): array{}.', $errors[0]->getMessage()); $this->assertSame(10, $errors[0]->getLine()); } diff --git a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php index 6113db22b3..d24d24338d 100644 --- a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php @@ -1763,7 +1763,7 @@ public function dataProperties(): array '$this->arrayPropertyOne', ], [ - 'array', + 'array', '$this->arrayPropertyOther', ], [ @@ -3423,7 +3423,7 @@ public function dataTypeFromFunctionPhpDocs(): array '$arrayParameterOne', ], [ - 'array', + 'array', '$arrayParameterOther', ], [ @@ -5779,7 +5779,7 @@ public function dataSpecifiedTypesUsingIsFunctions(): array '$null', ], [ - 'array', + 'array', '$array', ], [ @@ -9252,7 +9252,7 @@ public function dataInferPrivatePropertyTypeFromConstructor(): array '$this->bool', ], [ - 'array', + 'array', '$this->array', ], ]; diff --git a/tests/PHPStan/Analyser/TypeSpecifierTest.php b/tests/PHPStan/Analyser/TypeSpecifierTest.php index 04abebab3c..99cbb8db71 100644 --- a/tests/PHPStan/Analyser/TypeSpecifierTest.php +++ b/tests/PHPStan/Analyser/TypeSpecifierTest.php @@ -1218,8 +1218,8 @@ public function dataCondition(): iterable ), new Identical(new Expr\ConstFetch(new Name('null')), new Variable('a')), ), - ['$a' => 'non-empty-array|null'], - ['$a' => 'mixed~non-empty-array & ~null'], + ['$a' => 'non-empty-array|null'], + ['$a' => 'mixed~non-empty-array & ~null'], ], [ new Expr\BinaryOp\BooleanAnd( @@ -1234,7 +1234,7 @@ public function dataCondition(): iterable ), [ '$foo' => 'array', - 'array_filter($foo, \'is_string\', ARRAY_FILTER_USE_KEY)' => 'array', // could be 'array' + 'array_filter($foo, \'is_string\', ARRAY_FILTER_USE_KEY)' => 'array', // could be 'array' ], [], ], @@ -1250,7 +1250,7 @@ public function dataCondition(): iterable ), ), [ - '$foo' => 'non-empty-array', + '$foo' => 'non-empty-array', 'count($foo)' => 'mixed~(0.0|int|false|null)', ], [], @@ -1267,7 +1267,7 @@ public function dataCondition(): iterable ), ), [ - '$foo' => 'non-empty-array', + '$foo' => 'non-empty-array', 'count($foo)' => '2', ], [], diff --git a/tests/PHPStan/Analyser/data/param-out.php b/tests/PHPStan/Analyser/data/param-out.php index 05684938b8..d172b358e1 100644 --- a/tests/PHPStan/Analyser/data/param-out.php +++ b/tests/PHPStan/Analyser/data/param-out.php @@ -315,7 +315,7 @@ function testParseStr() { echo $output['arr'][1];//baz */ - \PHPStan\Testing\assertType('array', $output); + \PHPStan\Testing\assertType('array|lowercase-string>', $output); } function fooSimilar() { @@ -392,10 +392,10 @@ function fooHeadersSent() { function fooMbParseStr() { mb_parse_str("foo=bar", $output); - assertType('array', $output); + assertType('array|string>', $output); mb_parse_str('email=mail@example.org&city=town&x=1&y[g]=3&f=1.23', $output); - assertType('array', $output); + assertType('array|string>', $output); } function fooPreg() diff --git a/tests/PHPStan/Analyser/nsrt/array-chunk.php b/tests/PHPStan/Analyser/nsrt/array-chunk.php index 8e6fa67cf2..c0b79ffbae 100644 --- a/tests/PHPStan/Analyser/nsrt/array-chunk.php +++ b/tests/PHPStan/Analyser/nsrt/array-chunk.php @@ -11,7 +11,7 @@ public function generalArrays(array $arr): void { /** @var mixed[] $arr */ assertType('list>', array_chunk($arr, 2)); - assertType('list', array_chunk($arr, 2, true)); + assertType('list>', array_chunk($arr, 2, true)); /** @var array $arr */ assertType('list>', array_chunk($arr, 2)); diff --git a/tests/PHPStan/Analyser/nsrt/array-fill-keys-php8.php b/tests/PHPStan/Analyser/nsrt/array-fill-keys-php8.php index 07c06367dc..4710482534 100644 --- a/tests/PHPStan/Analyser/nsrt/array-fill-keys-php8.php +++ b/tests/PHPStan/Analyser/nsrt/array-fill-keys-php8.php @@ -7,7 +7,7 @@ function mixedAndSubtractedArray($mixed): void { if (is_array($mixed)) { - assertType("array<'b'>", array_fill_keys($mixed, 'b')); + assertType("array", array_fill_keys($mixed, 'b')); } else { assertType("*NEVER*", array_fill_keys($mixed, 'b')); } diff --git a/tests/PHPStan/Analyser/nsrt/array-flip-php8.php b/tests/PHPStan/Analyser/nsrt/array-flip-php8.php index b8f0e6793d..2b75c17aba 100644 --- a/tests/PHPStan/Analyser/nsrt/array-flip-php8.php +++ b/tests/PHPStan/Analyser/nsrt/array-flip-php8.php @@ -9,7 +9,7 @@ function mixedAndSubtractedArray($mixed) if (is_array($mixed)) { assertType('array', array_flip($mixed)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('*NEVER*', array_flip($mixed)); } } diff --git a/tests/PHPStan/Analyser/nsrt/array-intersect-key-php8.php b/tests/PHPStan/Analyser/nsrt/array-intersect-key-php8.php index 4bfd3140e0..9ffde9da83 100644 --- a/tests/PHPStan/Analyser/nsrt/array-intersect-key-php8.php +++ b/tests/PHPStan/Analyser/nsrt/array-intersect-key-php8.php @@ -16,7 +16,7 @@ public function mixedAndSubtractedArray($mixed, array $otherArrs): void /** @var array $otherArrs */ assertType('array', array_intersect_key($mixed, $otherArrs)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); /** @var array $otherArrs */ assertType('*NEVER*', array_intersect_key($mixed, $otherArrs)); /** @var array $otherArrs */ diff --git a/tests/PHPStan/Analyser/nsrt/array-pop.php b/tests/PHPStan/Analyser/nsrt/array-pop.php index 04494a96df..37a986b0ce 100644 --- a/tests/PHPStan/Analyser/nsrt/array-pop.php +++ b/tests/PHPStan/Analyser/nsrt/array-pop.php @@ -77,7 +77,7 @@ public function foo1($mixed): void if(is_array($mixed)) { assertType('mixed', array_pop($mixed)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('mixed', array_pop($mixed)); assertType('*ERROR*', $mixed); } diff --git a/tests/PHPStan/Analyser/nsrt/array-reverse.php b/tests/PHPStan/Analyser/nsrt/array-reverse.php index 5d341b6290..6f05e9b9f0 100644 --- a/tests/PHPStan/Analyser/nsrt/array-reverse.php +++ b/tests/PHPStan/Analyser/nsrt/array-reverse.php @@ -14,8 +14,8 @@ class Foo */ public function normalArrays(array $a, array $b): void { - assertType('array', array_reverse($a)); - assertType('array', array_reverse($a, true)); + assertType('array', array_reverse($a)); + assertType('array', array_reverse($a, true)); assertType('array', array_reverse($b)); assertType('array', array_reverse($b, true)); @@ -68,8 +68,8 @@ public function list(array $a, array $b): void public function mixed(mixed $mixed): void { - assertType('array', array_reverse($mixed)); - assertType('array', array_reverse($mixed, true)); + assertType('array', array_reverse($mixed)); + assertType('array', array_reverse($mixed, true)); if (array_key_exists('foo', $mixed)) { assertType('non-empty-array', array_reverse($mixed)); diff --git a/tests/PHPStan/Analyser/nsrt/array-search-php8.php b/tests/PHPStan/Analyser/nsrt/array-search-php8.php index c3430cc1b5..30b9527e10 100644 --- a/tests/PHPStan/Analyser/nsrt/array-search-php8.php +++ b/tests/PHPStan/Analyser/nsrt/array-search-php8.php @@ -16,7 +16,7 @@ public function mixedAndSubtractedArray($mixed, string $string): void assertType('int|string|false', array_search('foo', $mixed)); assertType('int|string|false', array_search($string, $mixed, true)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('*NEVER*', array_search('foo', $mixed, true)); assertType('*NEVER*', array_search('foo', $mixed)); assertType('*NEVER*', array_search($string, $mixed, true)); diff --git a/tests/PHPStan/Analyser/nsrt/array-shift.php b/tests/PHPStan/Analyser/nsrt/array-shift.php index eb227de3f6..2d8ef21d7e 100644 --- a/tests/PHPStan/Analyser/nsrt/array-shift.php +++ b/tests/PHPStan/Analyser/nsrt/array-shift.php @@ -77,7 +77,7 @@ public function foo1($mixed): void if(is_array($mixed)) { assertType('mixed', array_shift($mixed)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('mixed', array_shift($mixed)); assertType('*ERROR*', $mixed); } diff --git a/tests/PHPStan/Analyser/nsrt/array-slice.php b/tests/PHPStan/Analyser/nsrt/array-slice.php index 87fa61e36f..e2faabd113 100644 --- a/tests/PHPStan/Analyser/nsrt/array-slice.php +++ b/tests/PHPStan/Analyser/nsrt/array-slice.php @@ -24,7 +24,7 @@ public function nonEmpty(array $a, array $b, array $c): void */ public function fromMixed($arr): void { - assertType('array', array_slice($arr, 1, 2)); + assertType('array', array_slice($arr, 1, 2)); } public function normalArrays(array $arr): void diff --git a/tests/PHPStan/Analyser/nsrt/array_keys.php b/tests/PHPStan/Analyser/nsrt/array_keys.php index 7ea0a40ff5..6808bf36b3 100644 --- a/tests/PHPStan/Analyser/nsrt/array_keys.php +++ b/tests/PHPStan/Analyser/nsrt/array_keys.php @@ -11,7 +11,7 @@ public function sayHello($mixed): void if(is_array($mixed)) { assertType('list<(int|string)>', array_keys($mixed)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('*NEVER*', array_keys($mixed)); } } diff --git a/tests/PHPStan/Analyser/nsrt/array_values.php b/tests/PHPStan/Analyser/nsrt/array_values.php index a9fc01c947..18074963a4 100644 --- a/tests/PHPStan/Analyser/nsrt/array_values.php +++ b/tests/PHPStan/Analyser/nsrt/array_values.php @@ -11,7 +11,7 @@ public function foo1($mixed): void if(is_array($mixed)) { assertType('list', array_values($mixed)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('*NEVER*', array_values($mixed)); } } diff --git a/tests/PHPStan/Analyser/nsrt/assert-docblock.php b/tests/PHPStan/Analyser/nsrt/assert-docblock.php index 8451a48ebd..a1cbcc9b3e 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-docblock.php +++ b/tests/PHPStan/Analyser/nsrt/assert-docblock.php @@ -56,7 +56,7 @@ function validateNotNull($value) : void {} * @param mixed[] $arr */ function takesArray(array $arr) : void { - assertType('array', $arr); + assertType('array', $arr); validateStringArray($arr); assertType('array', $arr); @@ -66,22 +66,22 @@ function takesArray(array $arr) : void { * @param mixed[] $arr */ function takesArrayIfTrue(array $arr) : void { - assertType('array', $arr); + assertType('array', $arr); if (validateStringArrayIfTrue($arr)) { assertType('array', $arr); } else { - assertType('array', $arr); + assertType('array', $arr); } } /** * @param mixed[] $arr */ function takesArrayIfTrue1(array $arr) : void { - assertType('array', $arr); + assertType('array', $arr); if (!validateStringArrayIfTrue($arr)) { - assertType('array', $arr); + assertType('array', $arr); } else { assertType('array', $arr); } @@ -91,12 +91,12 @@ function takesArrayIfTrue1(array $arr) : void { * @param mixed[] $arr */ function takesArrayIfFalse(array $arr) : void { - assertType('array', $arr); + assertType('array', $arr); if (!validateStringArrayIfFalse($arr)) { assertType('array', $arr); } else { - assertType('array', $arr); + assertType('array', $arr); } } @@ -104,10 +104,10 @@ function takesArrayIfFalse(array $arr) : void { * @param mixed[] $arr */ function takesArrayIfFalse1(array $arr) : void { - assertType('array', $arr); + assertType('array', $arr); if (validateStringArrayIfFalse($arr)) { - assertType('array', $arr); + assertType('array', $arr); } else { assertType('array', $arr); } @@ -117,7 +117,7 @@ function takesArrayIfFalse1(array $arr) : void { * @param mixed[] $arr */ function takesStringOrIntArray(array $arr) : void { - assertType('array', $arr); + assertType('array', $arr); if (validateStringOrIntArray($arr)) { assertType('array', $arr); @@ -130,7 +130,7 @@ function takesStringOrIntArray(array $arr) : void { * @param mixed[] $arr */ function takesStringOrNonEmptyIntArray(array $arr) : void { - assertType('array', $arr); + assertType('array', $arr); if (validateStringOrNonEmptyIntArray($arr)) { assertType('array', $arr); diff --git a/tests/PHPStan/Analyser/nsrt/assert-methods.php b/tests/PHPStan/Analyser/nsrt/assert-methods.php index f6609f3f8f..6c278c21ed 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-methods.php +++ b/tests/PHPStan/Analyser/nsrt/assert-methods.php @@ -37,7 +37,7 @@ public function doBar($mixed) public function doBar2(array $objects) { self::doFoo($objects, stdClass::class); - assertType('array', $objects); + assertType('array', $objects); } /** @@ -47,7 +47,7 @@ public function doBar2(array $objects) public function doBar3(array $strings) { self::doFoo($strings, stdClass::class); - assertType('array>', $strings); + assertType('array>', $strings); } /** diff --git a/tests/PHPStan/Analyser/nsrt/bug-1209.php b/tests/PHPStan/Analyser/nsrt/bug-1209.php index fff8d13dff..4b4ce770d1 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-1209.php +++ b/tests/PHPStan/Analyser/nsrt/bug-1209.php @@ -13,7 +13,7 @@ public function sayHello($value): void { $isArray = is_array($value); if($isArray){ - assertType('array', $value); + assertType('array', $value); } } diff --git a/tests/PHPStan/Analyser/nsrt/bug-1233.php b/tests/PHPStan/Analyser/nsrt/bug-1233.php index 7d70679585..17267e0001 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-1233.php +++ b/tests/PHPStan/Analyser/nsrt/bug-1233.php @@ -10,18 +10,18 @@ public function toArray($value): array { assertType('mixed', $value); if (is_array($value)) { - assertType('array', $value); + assertType('array', $value); return $value; } - assertType('mixed~array', $value); + assertType('mixed~array', $value); if (is_iterable($value)) { assertType('Traversable', $value); return iterator_to_array($value); } - assertType('mixed~array', $value); + assertType('mixed~array', $value); throw new \LogicException(); } diff --git a/tests/PHPStan/Analyser/nsrt/bug-3446.php b/tests/PHPStan/Analyser/nsrt/bug-3446.php index cc02033da3..c01b4bdbdc 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-3446.php +++ b/tests/PHPStan/Analyser/nsrt/bug-3446.php @@ -15,7 +15,7 @@ public function takesString(string $s) : void{} public function main2(string $input) : void{ if(is_array($var = json_decode($input))){ - assertType('array', $var); + assertType('array', $var); } } } diff --git a/tests/PHPStan/Analyser/nsrt/bug-6329.php b/tests/PHPStan/Analyser/nsrt/bug-6329.php index c6b49e87e4..b31842e05f 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-6329.php +++ b/tests/PHPStan/Analyser/nsrt/bug-6329.php @@ -106,19 +106,19 @@ function true($a): void function nonEmptyArray1($a): void { if (is_array($a) && [] !== $a || null === $a) { - assertType('non-empty-array|null', $a); + assertType('non-empty-array|null', $a); } if ([] !== $a && is_array($a) || null === $a) { - assertType('non-empty-array|null', $a); + assertType('non-empty-array|null', $a); } if (null === $a || is_array($a) && [] !== $a) { - assertType('non-empty-array|null', $a); + assertType('non-empty-array|null', $a); } if (null === $a || [] !== $a && is_array($a)) { - assertType('non-empty-array|null', $a); + assertType('non-empty-array|null', $a); } } @@ -128,11 +128,11 @@ function nonEmptyArray1($a): void function nonEmptyArray2($a): void { if (is_array($a) && count($a) > 0 || null === $a) { - assertType('non-empty-array|null', $a); + assertType('non-empty-array|null', $a); } if (null === $a || is_array($a) && count($a) > 0) { - assertType('non-empty-array|null', $a); + assertType('non-empty-array|null', $a); } } @@ -155,7 +155,7 @@ function inverse($a, $b, $c): void if (null !== $c && (!is_array($c) || count($c) <= 0)) { } else { - assertType('non-empty-array|null', $c); + assertType('non-empty-array|null', $c); } } diff --git a/tests/PHPStan/Analyser/nsrt/bug-7144-composer-integration.php b/tests/PHPStan/Analyser/nsrt/bug-7144-composer-integration.php index 057067411c..c60d776d38 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7144-composer-integration.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7144-composer-integration.php @@ -32,14 +32,14 @@ public function test3(array $options): void $curlHandle = curl_init(); foreach (self::$options as $type => $curlOptions) { foreach ($curlOptions as $name => $curlOption) { - \PHPStan\Testing\assertType('array{http: array{header: array, proxy?: string, request_fulluri: bool}, ssl?: array}', $options); + \PHPStan\Testing\assertType('array{http: array{header: array, proxy?: string, request_fulluri: bool}, ssl?: array}', $options); if (isset($options[$type][$name])) { - \PHPStan\Testing\assertType('array{http: array{header: array, proxy?: string, request_fulluri: bool}, ssl?: array}', $options); + \PHPStan\Testing\assertType('array{http: array{header: array, proxy?: string, request_fulluri: bool}, ssl?: array}', $options); if ($type === 'ssl' && $name === 'verify_peer_name') { - \PHPStan\Testing\assertType('array{http: array{header: array, proxy?: string, request_fulluri: bool}, ssl?: array}', $options); + \PHPStan\Testing\assertType('array{http: array{header: array, proxy?: string, request_fulluri: bool}, ssl?: array}', $options); curl_setopt($curlHandle, $curlOption, $options[$type][$name] === true ? 2 : $options[$type][$name]); } else { - \PHPStan\Testing\assertType('array{http: array{header: array, proxy?: string, request_fulluri: bool}, ssl?: array}', $options); + \PHPStan\Testing\assertType('array{http: array{header: array, proxy?: string, request_fulluri: bool}, ssl?: array}', $options); curl_setopt($curlHandle, $curlOption, $options[$type][$name]); } } diff --git a/tests/PHPStan/Analyser/nsrt/bug-7915.php b/tests/PHPStan/Analyser/nsrt/bug-7915.php index 1dee1a63d5..a2e63375a7 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7915.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7915.php @@ -63,7 +63,7 @@ public function setConfigMimicConditionalParamType($name, $value): void function to_utf8($data, bool $isArray = false) { if ($isArray) { - assertType('array', $data); + assertType('array', $data); if (is_array($data)) { // always true foreach ($data as $k => $value) { $data[$k] = to_utf8($value, is_array($value)); diff --git a/tests/PHPStan/Analyser/nsrt/bug-9662.php b/tests/PHPStan/Analyser/nsrt/bug-9662.php index 4da94355c7..d88555a863 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9662.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9662.php @@ -11,74 +11,74 @@ */ function doFoo(string $s, $a, $strings, $mixed) { if (in_array('foo', $a, true)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array('foo', $a, false)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array('foo', $a)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array('0', $a)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array('1', $a)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array(true, $a)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array(false, $a)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array($s, $a, true)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array($s, $a, false)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array($s, $a)) { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } else { - assertType("array", $a); + assertType("array", $a); } - assertType('array', $a); + assertType('array', $a); if (in_array($mixed, $strings, true)) { assertType('non-empty-array', $strings); diff --git a/tests/PHPStan/Analyser/nsrt/bug-9734.php b/tests/PHPStan/Analyser/nsrt/bug-9734.php index ce75fa7197..353b1d91f9 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9734.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9734.php @@ -17,7 +17,7 @@ public function doFoo(array $a): void if (array_is_list($a)) { assertType('list', $a); } else { - assertType('array', $a); // could be non-empty-array + assertType('array', $a); // could be non-empty-array } } @@ -40,7 +40,7 @@ public function doFoo3(array $a): void if (array_is_list($a)) { assertType('non-empty-list', $a); } else { - assertType('non-empty-array', $a); + assertType('non-empty-array', $a); } } diff --git a/tests/PHPStan/Analyser/nsrt/conditional-types-inference.php b/tests/PHPStan/Analyser/nsrt/conditional-types-inference.php index 89bfa50a22..596e97634a 100644 --- a/tests/PHPStan/Analyser/nsrt/conditional-types-inference.php +++ b/tests/PHPStan/Analyser/nsrt/conditional-types-inference.php @@ -89,5 +89,5 @@ function invariant(bool $condition, string $message): void function (mixed $value) { invariant(is_array($value), 'must be array'); - assertType('array', $value); + assertType('array', $value); }; diff --git a/tests/PHPStan/Analyser/nsrt/filter-var-array.php b/tests/PHPStan/Analyser/nsrt/filter-var-array.php index 38db914722..1151d370c1 100644 --- a/tests/PHPStan/Analyser/nsrt/filter-var-array.php +++ b/tests/PHPStan/Analyser/nsrt/filter-var-array.php @@ -85,11 +85,11 @@ function mixedInput(mixed $input): void ], false)); // filter flag with add_empty=default - assertType('array', filter_var_array($input, FILTER_VALIDATE_INT)); + assertType('array', filter_var_array($input, FILTER_VALIDATE_INT)); // filter flag with add_empty=true - assertType('array', filter_var_array($input, FILTER_VALIDATE_INT, true)); + assertType('array', filter_var_array($input, FILTER_VALIDATE_INT, true)); // filter flag with add_empty=false - assertType('array', filter_var_array($input, FILTER_VALIDATE_INT, false)); + assertType('array', filter_var_array($input, FILTER_VALIDATE_INT, false)); $filter = [ 'filter' => FILTER_VALIDATE_INT, diff --git a/tests/PHPStan/Analyser/nsrt/generics.php b/tests/PHPStan/Analyser/nsrt/generics.php index 873ad66b6d..60840465c1 100644 --- a/tests/PHPStan/Analyser/nsrt/generics.php +++ b/tests/PHPStan/Analyser/nsrt/generics.php @@ -163,8 +163,8 @@ function testF($arrayOfInt, $callableOrNull) return $a; })); assertType('array', f($arrayOfInt, $callableOrNull)); - assertType('array', f($arrayOfInt, null)); - assertType('array', f($arrayOfInt, '')); + assertType('array', f($arrayOfInt, null)); + assertType('array', f($arrayOfInt, '')); } /** diff --git a/tests/PHPStan/Analyser/nsrt/globals.php b/tests/PHPStan/Analyser/nsrt/globals.php index 7b7b7b8a01..da2ae35787 100644 --- a/tests/PHPStan/Analyser/nsrt/globals.php +++ b/tests/PHPStan/Analyser/nsrt/globals.php @@ -1,11 +1,11 @@ ', $GLOBALS); +\PHPStan\Testing\assertType('array', $_SERVER); +\PHPStan\Testing\assertType('array', $_GET); +\PHPStan\Testing\assertType('array', $_POST); +\PHPStan\Testing\assertType('array', $_FILES); +\PHPStan\Testing\assertType('array', $_COOKIE); +\PHPStan\Testing\assertType('array', $_SESSION); +\PHPStan\Testing\assertType('array', $_REQUEST); +\PHPStan\Testing\assertType('array', $_ENV); diff --git a/tests/PHPStan/Analyser/nsrt/has-offset-type-bug.php b/tests/PHPStan/Analyser/nsrt/has-offset-type-bug.php index 8b470ba316..d1e8fd92a0 100644 --- a/tests/PHPStan/Analyser/nsrt/has-offset-type-bug.php +++ b/tests/PHPStan/Analyser/nsrt/has-offset-type-bug.php @@ -44,14 +44,14 @@ public function doFoo(array $errorMessages): void */ public function doBar(array $result): void { - assertType('array', $result); + assertType('array', $result); assert($result['totals']['file_errors'] === 3); - assertType("array", $result); + assertType("array", $result); assertType("mixed", $result['totals']); assertType('3', $result['totals']['file_errors']); assertType('mixed', $result['totals']['errors']); assert($result['totals']['errors'] === 0); - assertType("array", $result); + assertType("array", $result); assertType("mixed", $result['totals']); assertType('3', $result['totals']['file_errors']); assertType('0', $result['totals']['errors']); diff --git a/tests/PHPStan/Analyser/nsrt/memcache-get.php b/tests/PHPStan/Analyser/nsrt/memcache-get.php index 735e85b545..533e483682 100644 --- a/tests/PHPStan/Analyser/nsrt/memcache-get.php +++ b/tests/PHPStan/Analyser/nsrt/memcache-get.php @@ -10,5 +10,5 @@ function (): void { $memcache = new Memcache(); assertType('mixed', $memcache->get("key1")); - assertType('array|false', $memcache->get(array("key1", "key2", "key3"))); + assertType('array|false', $memcache->get(array("key1", "key2", "key3"))); }; diff --git a/tests/PHPStan/Analyser/nsrt/mixed-subtract.php b/tests/PHPStan/Analyser/nsrt/mixed-subtract.php index 59fa2afa13..c544802655 100644 --- a/tests/PHPStan/Analyser/nsrt/mixed-subtract.php +++ b/tests/PHPStan/Analyser/nsrt/mixed-subtract.php @@ -21,7 +21,7 @@ function subtract(mixed $m, $moreThenFalsy) { assertType('bool', (bool) $m); } if (!is_array($m)) { - assertType('mixed~array', $m); + assertType('mixed~array', $m); assertType('bool', (bool) $m); } @@ -55,7 +55,7 @@ function subtract(mixed $m, $moreThenFalsy) { } if ($m != 0 && !is_array($m) && $m != null && !is_object($m)) { // subtract more types then falsy - assertType("mixed~(0|0.0|''|'0'|array|object|false|null)", $m); + assertType("mixed~(0|0.0|''|'0'|array|object|false|null)", $m); assertType('true', (bool) $m); } } diff --git a/tests/PHPStan/Analyser/nsrt/mixed-to-number.php b/tests/PHPStan/Analyser/nsrt/mixed-to-number.php index 97cc9d0842..fee2d7bed4 100644 --- a/tests/PHPStan/Analyser/nsrt/mixed-to-number.php +++ b/tests/PHPStan/Analyser/nsrt/mixed-to-number.php @@ -35,7 +35,7 @@ function doFoo($mixed, int $i, float $f, $numericS) { } if (!is_array($mixed)) { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('(float|int)', $mixed + $mixed); } } diff --git a/tests/PHPStan/Analyser/nsrt/narrow-cast.php b/tests/PHPStan/Analyser/nsrt/narrow-cast.php index 82e09e0bd3..fc70c128e9 100644 --- a/tests/PHPStan/Analyser/nsrt/narrow-cast.php +++ b/tests/PHPStan/Analyser/nsrt/narrow-cast.php @@ -14,9 +14,9 @@ function doFoo(string $x, array $arr): void { assertType('string', $x); if ((bool) array_search($x, $arr, true)) { - assertType('non-empty-array', $arr); + assertType('non-empty-array', $arr); } else { - assertType('array', $arr); + assertType('array', $arr); } assertType('string', $x); diff --git a/tests/PHPStan/Analyser/nsrt/native-expressions.php b/tests/PHPStan/Analyser/nsrt/native-expressions.php index 72f5a47e7e..abe041686a 100644 --- a/tests/PHPStan/Analyser/nsrt/native-expressions.php +++ b/tests/PHPStan/Analyser/nsrt/native-expressions.php @@ -34,7 +34,7 @@ public function __construct( /** @var non-empty-array */ private array $array ){ - assertType('non-empty-array', $this->array); + assertType('non-empty-array', $this->array); assertNativeType('array', $this->array); if(count($array) === 0){ throw new \InvalidArgumentException(); diff --git a/tests/PHPStan/Analyser/nsrt/prestashop-breakdowns-empty-array.php b/tests/PHPStan/Analyser/nsrt/prestashop-breakdowns-empty-array.php index b9e0920141..a115a32359 100644 --- a/tests/PHPStan/Analyser/nsrt/prestashop-breakdowns-empty-array.php +++ b/tests/PHPStan/Analyser/nsrt/prestashop-breakdowns-empty-array.php @@ -21,13 +21,13 @@ public function getTaxBreakdown($mixed, $arrayMixed): void foreach ($breakdowns as $type => $bd) { if (empty($bd)) { - assertType('array{product_tax?: mixed, shipping_tax?: array, ecotax_tax?: array, wrapping_tax?: array}', $breakdowns); + assertType('array{product_tax?: mixed, shipping_tax?: array, ecotax_tax?: array, wrapping_tax?: array}', $breakdowns); unset($breakdowns[$type]); - assertType('array{product_tax?: mixed, shipping_tax?: array, ecotax_tax?: array, wrapping_tax?: array}', $breakdowns); + assertType('array{product_tax?: mixed, shipping_tax?: array, ecotax_tax?: array, wrapping_tax?: array}', $breakdowns); } } - assertType('array{product_tax?: mixed, shipping_tax?: array, ecotax_tax?: array, wrapping_tax?: array}', $breakdowns); + assertType('array{product_tax?: mixed, shipping_tax?: array, ecotax_tax?: array, wrapping_tax?: array}', $breakdowns); } public function doFoo(): void diff --git a/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php b/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php index f5511bfc33..41d62d1c36 100644 --- a/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php +++ b/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php @@ -107,7 +107,7 @@ public function dataFunctions(): array ]), new UnionType([ new ConstantBooleanType(false), - new ArrayType(new MixedType(true), new MixedType(true)), + new ArrayType(new MixedType(), new MixedType()), ]), false, ], diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index b45c120089..0383dadc52 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -551,7 +551,7 @@ public function testBug8356(): void { $this->analyse([__DIR__ . '/data/bug-8356.php'], [ [ - "Offset 'x' might not exist on array|string.", + "Offset 'x' might not exist on array|string.", 7, ], ]); diff --git a/tests/PHPStan/Rules/Classes/data/bug-5333.php b/tests/PHPStan/Rules/Classes/data/bug-5333.php index f38c46cddf..67845acd46 100644 --- a/tests/PHPStan/Rules/Classes/data/bug-5333.php +++ b/tests/PHPStan/Rules/Classes/data/bug-5333.php @@ -27,7 +27,7 @@ public function sayHello($foo): Route } assertType('array', $foo); - assertNativeType('array', $foo); + assertNativeType('array', $foo); assertType('Bug5333\Route', $res); assertNativeType('Bug5333\Route', $res); diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index eda1ad4ee3..98927b4bd2 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -1688,22 +1688,22 @@ public function testCountArrayShift(): void if (PHP_VERSION_ID < 80000) { $errors = [ [ - 'Parameter #1 $var of function count expects array|Countable, array|false given.', + 'Parameter #1 $var of function count expects array|Countable, array|false given.', 8, ], [ - 'Parameter #1 $var of function count expects array|Countable, array|false given.', + 'Parameter #1 $var of function count expects array|Countable, array|false given.', 16, ], ]; } else { $errors = [ [ - 'Parameter #1 $value of function count expects array|Countable, array|false given.', + 'Parameter #1 $value of function count expects array|Countable, array|false given.', 8, ], [ - 'Parameter #1 $value of function count expects array|Countable, array|false given.', + 'Parameter #1 $value of function count expects array|Countable, array|false given.', 16, ], ]; diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index ed96439687..88b0eb949f 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -1949,7 +1949,7 @@ public function testOnlyRelevantUnableToResolveTemplateType(): void $this->checkUnionTypes = true; $this->analyse([__DIR__ . '/data/only-relevant-unable-to-resolve-template-type.php'], [ [ - 'Parameter #1 $a of method OnlyRelevantUnableToResolve\Foo::doBaz() expects array, int given.', + 'Parameter #1 $a of method OnlyRelevantUnableToResolve\Foo::doBaz() expects array, int given.', 41, ], [ @@ -2260,11 +2260,11 @@ public function testLiteralString(): void 58, ], [ - 'Parameter #1 $a of method LiteralStringMethod\Foo::requireArrayOfLiteralStrings() expects array, array given.', + 'Parameter #1 $a of method LiteralStringMethod\Foo::requireArrayOfLiteralStrings() expects array, array given.', 60, ], [ - 'Parameter #1 $s of method LiteralStringMethod\Foo::requireLiteralString() expects literal-string, array given.', + 'Parameter #1 $s of method LiteralStringMethod\Foo::requireLiteralString() expects literal-string, array given.', 65, ], [ diff --git a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php index c3842d461b..fe23c44a83 100644 --- a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php @@ -546,15 +546,15 @@ public function testDiscussion7004(): void $this->checkExplicitMixed = true; $this->analyse([__DIR__ . '/data/discussion-7004.php'], [ [ - 'Parameter #1 $data of static method Discussion7004\Foo::fromArray1() expects array, array given.', + 'Parameter #1 $data of static method Discussion7004\Foo::fromArray1() expects array, array given.', 46, ], [ - 'Parameter #1 $data of static method Discussion7004\Foo::fromArray2() expects array{array{newsletterName: string, subscriberCount: int}}, array given.', + 'Parameter #1 $data of static method Discussion7004\Foo::fromArray2() expects array{array{newsletterName: string, subscriberCount: int}}, array given.', 47, ], [ - 'Parameter #1 $data of static method Discussion7004\Foo::fromArray3() expects array{newsletterName: string, subscriberCount: int}, array given.', + 'Parameter #1 $data of static method Discussion7004\Foo::fromArray3() expects array{newsletterName: string, subscriberCount: int}, array given.', 48, ], ]); diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index 4c19971d5e..5ebfb238e7 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -901,7 +901,7 @@ public function testMagicSerialization(): void { $this->analyse([__DIR__ . '/data/magic-serialization.php'], [ [ - 'Method MagicSerialization\WrongSignature::__serialize() should return array but returns string.', + 'Method MagicSerialization\WrongSignature::__serialize() should return array but returns string.', 23, ], [ @@ -928,7 +928,7 @@ public function testMagicSignatures(): void 43, ], [ - 'Method MagicSignatures\WrongSignature::__debugInfo() should return array|null but returns string.', + 'Method MagicSignatures\WrongSignature::__debugInfo() should return array|null but returns string.', 47, ], [ diff --git a/tests/PHPStan/Rules/PhpDoc/VarTagChangedExpressionTypeRuleTest.php b/tests/PHPStan/Rules/PhpDoc/VarTagChangedExpressionTypeRuleTest.php index f3ea56d12f..c092304ff1 100644 --- a/tests/PHPStan/Rules/PhpDoc/VarTagChangedExpressionTypeRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/VarTagChangedExpressionTypeRuleTest.php @@ -52,19 +52,19 @@ public function testBug10130(): void { $this->analyse([__DIR__ . '/data/bug-10130.php'], [ [ - 'PHPDoc tag @var with type array is not subtype of type array.', + 'PHPDoc tag @var with type array is not subtype of type array.', 14, ], [ - 'PHPDoc tag @var with type array is not subtype of type list.', + 'PHPDoc tag @var with type array is not subtype of type list.', 17, ], [ - 'PHPDoc tag @var with type array is not subtype of type array{id: int}.', + 'PHPDoc tag @var with type array is not subtype of type array{id: int}.', 20, ], [ - 'PHPDoc tag @var with type array is not subtype of type list.', + 'PHPDoc tag @var with type array is not subtype of type list.', 23, ], ]); diff --git a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php index 155c0d6ea4..8a1ce3ba51 100644 --- a/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php @@ -466,7 +466,7 @@ public function dataReportWrongType(): iterable 204, ], [ - 'PHPDoc tag @var with type array|null is not subtype of type array{id: int}|null.', + 'PHPDoc tag @var with type array|null is not subtype of type array{id: int}|null.', 235, ], ]]; diff --git a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php index 3616824c7f..e75b7cec10 100644 --- a/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php @@ -656,15 +656,15 @@ public function testBug11617(): void $this->checkExplicitMixed = true; $this->analyse([__DIR__ . '/data/bug-11617.php'], [ [ - 'Property Bug11617\HelloWorld::$params (array) does not accept array.', + 'Property Bug11617\HelloWorld::$params (array) does not accept array|string>.', 14, ], [ - 'Property Bug11617\HelloWorld::$params (array) does not accept array.', + 'Property Bug11617\HelloWorld::$params (array) does not accept array|string>.', 16, ], [ - 'Property Bug11617\HelloWorld::$params (array) does not accept array.', + 'Property Bug11617\HelloWorld::$params (array) does not accept array|string>.', 21, ], ]); diff --git a/tests/PHPStan/Rules/Variables/data/bug-8113.php b/tests/PHPStan/Rules/Variables/data/bug-8113.php index 2c2807e48f..97b5841941 100644 --- a/tests/PHPStan/Rules/Variables/data/bug-8113.php +++ b/tests/PHPStan/Rules/Variables/data/bug-8113.php @@ -20,25 +20,25 @@ function () { ), ); - assertType('array', $review); + assertType('array>', $review); if ( array_key_exists('review', $review['SurveyInvitation']) && $review['SurveyInvitation']['review'] === null ) { - assertType("array&hasOffsetValue('SurveyInvitation', array&hasOffsetValue('review', null))", $review); + assertType("array>&hasOffsetValue('SurveyInvitation', array&hasOffsetValue('review', null))", $review); $review['Review'] = [ 'id' => null, 'text' => null, 'answer' => null, ]; - assertType("non-empty-array&hasOffsetValue('Review', array{id: null, text: null, answer: null})&hasOffsetValue('SurveyInvitation', array&hasOffsetValue('review', null))", $review); + assertType("non-empty-array>&hasOffsetValue('Review', array{id: null, text: null, answer: null})&hasOffsetValue('SurveyInvitation', array&hasOffsetValue('review', null))", $review); unset($review['SurveyInvitation']['review']); - assertType("non-empty-array&hasOffsetValue('Review', array)&hasOffsetValue('SurveyInvitation', array)", $review); + assertType("non-empty-array>&hasOffsetValue('Review', array)&hasOffsetValue('SurveyInvitation', array)", $review); } - assertType('array', $review); + assertType('array>', $review); if (array_key_exists('User', $review['Review'])) { - assertType("array&hasOffsetValue('Review', array&hasOffset('User'))", $review); + assertType("array>&hasOffsetValue('Review', array&hasOffset('User'))", $review); $review['User'] = $review['Review']['User']; assertType("hasOffsetValue('Review', array&hasOffset('User'))&hasOffsetValue('User', mixed)&non-empty-array", $review); unset($review['Review']['User']); From 4007e653b9a9fe9db7d8c4b9d977ca4175786ff1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 4 Sep 2024 16:11:41 +0200 Subject: [PATCH 400/508] Issue bot - let all comments about improved `ArrayType::describe()` through --- issue-bot/src/Console/EvaluateCommand.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index 0f8d05a8d8..f18941039b 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,10 +158,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { - if (count($toPost) > 20) { - $output->writeln('Too many comments to post, something is probably wrong.'); - return 1; - } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From 2de40d19b19b150eb4c05171e24d9377fc529c1a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 12 Oct 2024 17:40:02 +0200 Subject: [PATCH 401/508] Revert "Issue bot - let all comments about improved `ArrayType::describe()` through" This reverts commit 4007e653b9a9fe9db7d8c4b9d977ca4175786ff1. --- issue-bot/src/Console/EvaluateCommand.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/issue-bot/src/Console/EvaluateCommand.php b/issue-bot/src/Console/EvaluateCommand.php index f18941039b..0f8d05a8d8 100644 --- a/issue-bot/src/Console/EvaluateCommand.php +++ b/issue-bot/src/Console/EvaluateCommand.php @@ -158,6 +158,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $postComments = (bool) $input->getOption('post-comments'); if ($postComments) { + if (count($toPost) > 20) { + $output->writeln('Too many comments to post, something is probably wrong.'); + return 1; + } foreach ($toPost as ['issue' => $issue, 'hash' => $hash, 'users' => $users, 'diff' => $diff, 'details' => $details]) { $text = sprintf( "%s After [the latest push in %s](https://github.com/phpstan/phpstan-src/compare/%s...%s), PHPStan now reports different result with your [code snippet](https://phpstan.org/r/%s):\n\n```diff\n%s```", From 96bd303c6c818b8ddd270ebc6101a585849251e4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 13 Oct 2024 13:45:56 +0200 Subject: [PATCH 402/508] Fix build --- changelog-generator/phpstan.neon | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog-generator/phpstan.neon b/changelog-generator/phpstan.neon index d187d34c96..a1fee9d3a7 100644 --- a/changelog-generator/phpstan.neon +++ b/changelog-generator/phpstan.neon @@ -11,4 +11,6 @@ parameters: paths: - src - run.php - checkGenericClassInNonGenericObjectType: false + ignoreErrors: + - + identifier: missingType.generics From 67fbfaee6585c2d47485dc2a159ee76d3ed02b35 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 12 Oct 2024 13:09:35 +0200 Subject: [PATCH 403/508] Refactor IntersectionType::describe() --- phpstan-baseline.neon | 4 +- src/Type/IntersectionType.php | 152 ++++++++---- .../Analyser/LegacyNodeScopeResolverTest.php | 8 +- tests/PHPStan/Analyser/TypeSpecifierTest.php | 4 +- tests/PHPStan/Analyser/data/param-out.php | 2 +- tests/PHPStan/Analyser/nsrt/array-chunk.php | 8 +- .../Analyser/nsrt/array-column-php82.php | 6 +- tests/PHPStan/Analyser/nsrt/array-flip.php | 10 +- .../Analyser/nsrt/array-intersect-key.php | 6 +- .../nsrt/array-is-list-type-specifying.php | 8 +- tests/PHPStan/Analyser/nsrt/array-reverse.php | 2 +- .../nsrt/array-shape-list-optional.php | 8 +- tests/PHPStan/Analyser/nsrt/array-slice.php | 6 +- .../Analyser/nsrt/assert-intersected.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-10721.php | 50 ++-- .../PHPStan/Analyser/nsrt/bug-11518-types.php | 6 +- tests/PHPStan/Analyser/nsrt/bug-2112.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-2911.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-4099.php | 6 +- tests/PHPStan/Analyser/nsrt/bug-4117.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-4398.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-4565.php | 4 +- tests/PHPStan/Analyser/nsrt/bug-4708.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-6859.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-7805.php | 2 +- tests/PHPStan/Analyser/nsrt/bug-9734.php | 4 +- tests/PHPStan/Analyser/nsrt/bug-9985.php | 2 +- .../Analyser/nsrt/composer-array-bug.php | 4 +- .../Analyser/nsrt/conditional-vars.php | 4 +- ...namic-return-type-extension-regression.php | 4 +- .../Analyser/nsrt/has-offset-type-bug.php | 4 +- tests/PHPStan/Analyser/nsrt/list-count.php | 12 +- tests/PHPStan/Analyser/nsrt/list-type.php | 16 +- .../PHPStan/Analyser/nsrt/non-empty-array.php | 2 +- tests/PHPStan/Analyser/nsrt/shuffle.php | 44 ++-- tests/PHPStan/Analyser/nsrt/sort.php | 6 +- .../Rules/Comparison/data/bug-4708.php | 2 +- .../PHPStan/Rules/Functions/data/bug-3931.php | 2 +- .../PHPStan/Rules/Functions/data/bug-7156.php | 4 +- .../Rules/Methods/ReturnTypeRuleTest.php | 2 +- .../PHPStan/Rules/Variables/data/bug-3391.php | 4 +- .../PHPStan/Rules/Variables/data/bug-7417.php | 4 +- .../PHPStan/Rules/Variables/data/bug-8113.php | 12 +- tests/PHPStan/Type/IntersectionTypeTest.php | 217 +++++++++++++++++- tests/PHPStan/Type/TypeCombinatorTest.php | 24 +- tests/PHPStan/Type/TypeToPhpDocNodeTest.php | 121 +++++++++- 46 files changed, 601 insertions(+), 199 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a652b6a836..122462ff00 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1314,7 +1314,7 @@ parameters: - message: '#^Doing instanceof PHPStan\\Type\\ArrayType is error\-prone and deprecated\. Use Type\:\:isArray\(\) or Type\:\:getArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType - count: 1 + count: 3 path: src/Type/IntersectionType.php - @@ -1332,7 +1332,7 @@ parameters: - message: '#^Doing instanceof PHPStan\\Type\\Constant\\ConstantArrayType is error\-prone and deprecated\. Use Type\:\:getConstantArrays\(\) instead\.$#' identifier: phpstanApi.instanceofType - count: 1 + count: 3 path: src/Type/IntersectionType.php - diff --git a/src/Type/IntersectionType.php b/src/Type/IntersectionType.php index 2dec6cc456..496910eab3 100644 --- a/src/Type/IntersectionType.php +++ b/src/Type/IntersectionType.php @@ -3,6 +3,7 @@ namespace PHPStan\Type; use PHPStan\Php\PhpVersion; +use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode; use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode; @@ -45,7 +46,6 @@ use function ksort; use function md5; use function sprintf; -use function str_starts_with; use function strcasecmp; use function strlen; use function substr; @@ -347,6 +347,10 @@ private function describeItself(VerbosityLevel $level, bool $skipAccessoryTypes) $nonEmptyStr = false; $nonFalsyStr = false; + $isList = $this->isList()->yes(); + $isArray = $this->isArray()->yes(); + $isNonEmptyArray = $this->isIterableAtLeastOnce()->yes(); + $describedTypes = []; foreach ($this->getSortedTypes() as $i => $type) { if ($type instanceof AccessoryNonEmptyStringType || $type instanceof AccessoryLiteralStringType @@ -379,10 +383,45 @@ private function describeItself(VerbosityLevel $level, bool $skipAccessoryTypes) $skipTypeNames[] = 'string'; continue; } - if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { - $typesToDescribe[$i] = $type; - $skipTypeNames[] = 'array'; - continue; + if ($isList || $isArray) { + if ($type instanceof ArrayType) { + $keyType = $type->getKeyType(); + $valueType = $type->getItemType(); + if ($isList) { + $isMixedValueType = $valueType instanceof MixedType && $valueType->describe(VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); + $valueTypeDescription = ''; + if (!$isMixedValueType) { + $valueTypeDescription = sprintf('<%s>', $valueType->describe($level)); + } + + $describedTypes[$i] = ($isNonEmptyArray ? 'non-empty-list' : 'list') . $valueTypeDescription; + } else { + $isMixedKeyType = $keyType instanceof MixedType && $keyType->describe(VerbosityLevel::precise()) === 'mixed' && !$keyType->isExplicitMixed(); + $isMixedValueType = $valueType instanceof MixedType && $valueType->describe(VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); + $typeDescription = ''; + if (!$isMixedKeyType) { + $typeDescription = sprintf('<%s, %s>', $keyType->describe($level), $valueType->describe($level)); + } elseif (!$isMixedValueType) { + $typeDescription = sprintf('<%s>', $valueType->describe($level)); + } + + $describedTypes[$i] = ($isNonEmptyArray ? 'non-empty-array' : 'array') . $typeDescription; + } + continue; + } elseif ($type instanceof ConstantArrayType) { + $description = $type->describe($level); + $descriptionWithoutKind = substr($description, strlen('array')); + $begin = $isList ? 'list' : 'array'; + if ($isNonEmptyArray && !$type->isIterableAtLeastOnce()->yes()) { + $begin = 'non-empty-' . $begin; + } + + $describedTypes[$i] = $begin . $descriptionWithoutKind; + continue; + } + if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { + continue; + } } if ($type instanceof CallableType && $type->isCommonCallable()) { @@ -404,7 +443,6 @@ private function describeItself(VerbosityLevel $level, bool $skipAccessoryTypes) $typesToDescribe[$i] = $type; } - $describedTypes = []; foreach ($baseTypes as $i => $type) { $typeDescription = $type->describe($level); @@ -418,36 +456,6 @@ private function describeItself(VerbosityLevel $level, bool $skipAccessoryTypes) } } - if ( - str_starts_with($typeDescription, 'array<') - && in_array('array', $skipTypeNames, true) - ) { - $nonEmpty = false; - $typeName = 'array'; - foreach ($typesToDescribe as $j => $typeToDescribe) { - if ( - $typeToDescribe instanceof AccessoryArrayListType - && substr($typeDescription, 0, strlen('array, ')) === 'array, ' - ) { - $typeName = 'list'; - $typeDescription = 'array<' . substr($typeDescription, strlen('array, ')); - } elseif ($typeToDescribe instanceof NonEmptyArrayType) { - $nonEmpty = true; - } else { - continue; - } - - unset($typesToDescribe[$j]); - } - - if ($nonEmpty) { - $typeName = 'non-empty-' . $typeName; - } - - $describedTypes[$i] = $typeName . '<' . substr($typeDescription, strlen('array<')); - continue; - } - if (in_array($typeDescription, $skipTypeNames, true)) { continue; } @@ -1139,6 +1147,10 @@ public function toPhpDocNode(): TypeNode $nonEmptyStr = false; $nonFalsyStr = false; + $isList = $this->isList()->yes(); + $isArray = $this->isArray()->yes(); + $isNonEmptyArray = $this->isIterableAtLeastOnce()->yes(); + $describedTypes = []; foreach ($this->getSortedTypes() as $i => $type) { if ($type instanceof AccessoryNonEmptyStringType @@ -1168,11 +1180,70 @@ public function toPhpDocNode(): TypeNode $skipTypeNames[] = 'string'; continue; } - if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { - $typesToDescribe[$i] = $type; - $skipTypeNames[] = 'array'; - continue; + + if ($isList || $isArray) { + if ($type instanceof ArrayType) { + $keyType = $type->getKeyType(); + $valueType = $type->getItemType(); + if ($isList) { + $isMixedValueType = $valueType instanceof MixedType && $valueType->describe(VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); + $identifierTypeNode = new IdentifierTypeNode($isNonEmptyArray ? 'non-empty-list' : 'list'); + if (!$isMixedValueType) { + $describedTypes[$i] = new GenericTypeNode($identifierTypeNode, [ + $valueType->toPhpDocNode(), + ]); + } else { + $describedTypes[$i] = $identifierTypeNode; + } + } else { + $isMixedKeyType = $keyType instanceof MixedType && $keyType->describe(VerbosityLevel::precise()) === 'mixed' && !$keyType->isExplicitMixed(); + $isMixedValueType = $valueType instanceof MixedType && $valueType->describe(VerbosityLevel::precise()) === 'mixed' && !$valueType->isExplicitMixed(); + $identifierTypeNode = new IdentifierTypeNode($isNonEmptyArray ? 'non-empty-array' : 'array'); + if (!$isMixedKeyType) { + $describedTypes[$i] = new GenericTypeNode($identifierTypeNode, [ + $keyType->toPhpDocNode(), + $valueType->toPhpDocNode(), + ]); + } elseif (!$isMixedValueType) { + $describedTypes[$i] = new GenericTypeNode($identifierTypeNode, [ + $valueType->toPhpDocNode(), + ]); + } else { + $describedTypes[$i] = $identifierTypeNode; + } + } + continue; + } elseif ($type instanceof ConstantArrayType) { + $constantArrayTypeNode = $type->toPhpDocNode(); + if ($constantArrayTypeNode instanceof ArrayShapeNode) { + $newKind = $constantArrayTypeNode->kind; + if ($isList) { + if ($isNonEmptyArray && !$type->isIterableAtLeastOnce()->yes()) { + $newKind = ArrayShapeNode::KIND_NON_EMPTY_LIST; + } else { + $newKind = ArrayShapeNode::KIND_LIST; + } + } elseif ($isNonEmptyArray && !$type->isIterableAtLeastOnce()->yes()) { + $newKind = ArrayShapeNode::KIND_NON_EMPTY_ARRAY; + } + + if ($newKind !== $constantArrayTypeNode->kind) { + if ($constantArrayTypeNode->sealed) { + $constantArrayTypeNode = ArrayShapeNode::createSealed($constantArrayTypeNode->items, $newKind); + } else { + $constantArrayTypeNode = ArrayShapeNode::createUnsealed($constantArrayTypeNode->items, $constantArrayTypeNode->unsealedType, $newKind); + } + } + + $describedTypes[$i] = $constantArrayTypeNode; + continue; + } + } + if ($type instanceof NonEmptyArrayType || $type instanceof AccessoryArrayListType) { + continue; + } } + if (!$type instanceof AccessoryType) { $baseTypes[$i] = $type; continue; @@ -1186,7 +1257,6 @@ public function toPhpDocNode(): TypeNode $typesToDescribe[$i] = $type; } - $describedTypes = []; foreach ($baseTypes as $i => $type) { $typeNode = $type->toPhpDocNode(); if ($typeNode instanceof GenericTypeNode && $typeNode->type->name === 'array') { diff --git a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php index d24d24338d..e97a5f4a06 100644 --- a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php @@ -4846,7 +4846,7 @@ public function dataArrayFunctions(): array 'array_pop($stringKeys)', ], [ - 'array&hasOffsetValue(\'baz\', stdClass)', + 'non-empty-array&hasOffsetValue(\'baz\', stdClass)', '$stdClassesWithIsset', ], [ @@ -8077,7 +8077,7 @@ public function dataArrayKeysInBranches(): array '$array', ], [ - 'array&hasOffsetValue(\'key\', mixed)', + 'non-empty-array&hasOffsetValue(\'key\', mixed)', '$generalArray', ], [ @@ -8563,11 +8563,11 @@ public function dataIsset(): array '$mixedIsset', ], [ - 'array&hasOffset(\'a\')', + 'non-empty-array&hasOffset(\'a\')', '$mixedArrayKeyExists', ], [ - 'array&hasOffsetValue(\'a\', int)', + 'non-empty-array&hasOffsetValue(\'a\', int)', '$integers', ], [ diff --git a/tests/PHPStan/Analyser/TypeSpecifierTest.php b/tests/PHPStan/Analyser/TypeSpecifierTest.php index 99cbb8db71..36bf122d87 100644 --- a/tests/PHPStan/Analyser/TypeSpecifierTest.php +++ b/tests/PHPStan/Analyser/TypeSpecifierTest.php @@ -1064,7 +1064,7 @@ public function dataCondition(): iterable new Arg(new Variable('array')), ]), [ - '$array' => 'array&hasOffset(\'foo\')', + '$array' => 'non-empty-array&hasOffset(\'foo\')', ], [ '$array' => '~hasOffset(\'foo\')', @@ -1112,7 +1112,7 @@ public function dataCondition(): iterable new Arg(new Variable('array')), ]), [ - '$array' => 'array&hasOffset(\'foo\')', + '$array' => 'non-empty-array&hasOffset(\'foo\')', ], [ '$array' => '~hasOffset(\'foo\')', diff --git a/tests/PHPStan/Analyser/data/param-out.php b/tests/PHPStan/Analyser/data/param-out.php index d172b358e1..36d7837034 100644 --- a/tests/PHPStan/Analyser/data/param-out.php +++ b/tests/PHPStan/Analyser/data/param-out.php @@ -240,7 +240,7 @@ function foo16() { function fooShuffle() { $array = ["foo" => 123, "bar" => 456]; shuffle($array); - assertType('non-empty-array<0|1, 123|456>&list', $array); + assertType('non-empty-list<123|456>', $array); $emptyArray = []; shuffle($emptyArray); diff --git a/tests/PHPStan/Analyser/nsrt/array-chunk.php b/tests/PHPStan/Analyser/nsrt/array-chunk.php index c0b79ffbae..cedb50ddb7 100644 --- a/tests/PHPStan/Analyser/nsrt/array-chunk.php +++ b/tests/PHPStan/Analyser/nsrt/array-chunk.php @@ -60,8 +60,8 @@ public function chunkUnionTypeLength(array $arr, $positiveRange, $positiveUnion) * @param int<50, max> $bigger50 */ public function lengthIntRanges(array $arr, int $positiveInt, int $bigger50) { - assertType('list>', array_chunk($arr, $positiveInt)); - assertType('list>', array_chunk($arr, $bigger50)); + assertType('list', array_chunk($arr, $positiveInt)); + assertType('list', array_chunk($arr, $bigger50)); } /** @@ -78,11 +78,11 @@ function testLimits(array $arr, int $oneToFour, int $tooBig) { public function offsets(array $arr, array $map): void { if (array_key_exists('foo', $arr)) { - assertType('non-empty-list>', array_chunk($arr, 2)); + assertType('non-empty-list', array_chunk($arr, 2)); assertType('non-empty-list', array_chunk($arr, 2, true)); } if (array_key_exists('foo', $arr) && $arr['foo'] === 'bar') { - assertType('non-empty-list>', array_chunk($arr, 2)); + assertType('non-empty-list', array_chunk($arr, 2)); assertType('non-empty-list', array_chunk($arr, 2, true)); } diff --git a/tests/PHPStan/Analyser/nsrt/array-column-php82.php b/tests/PHPStan/Analyser/nsrt/array-column-php82.php index 62350f5992..07dc05f399 100644 --- a/tests/PHPStan/Analyser/nsrt/array-column-php82.php +++ b/tests/PHPStan/Analyser/nsrt/array-column-php82.php @@ -175,7 +175,7 @@ public function testImprecise5(array $array): void assertType('list', array_column($array, 'nodeName')); assertType('array', array_column($array, 'nodeName', 'tagName')); assertType('array', array_column($array, null, 'tagName')); - assertType('list', array_column($array, 'foo')); + assertType('list', array_column($array, 'foo')); assertType('array', array_column($array, 'foo', 'tagName')); assertType('array', array_column($array, 'nodeName', 'foo')); assertType('array', array_column($array, null, 'foo')); @@ -187,7 +187,7 @@ public function testObjects1(array $array): void assertType('non-empty-list', array_column($array, 'nodeName')); assertType('non-empty-array', array_column($array, 'nodeName', 'tagName')); assertType('non-empty-array', array_column($array, null, 'tagName')); - assertType('list', array_column($array, 'foo')); + assertType('list', array_column($array, 'foo')); assertType('array', array_column($array, 'foo', 'tagName')); assertType('non-empty-array', array_column($array, 'nodeName', 'foo')); assertType('non-empty-array', array_column($array, null, 'foo')); @@ -199,7 +199,7 @@ public function testObjects2(array $array): void assertType('array{string}', array_column($array, 'nodeName')); assertType('non-empty-array', array_column($array, 'nodeName', 'tagName')); assertType('non-empty-array', array_column($array, null, 'tagName')); - assertType('list', array_column($array, 'foo')); + assertType('list', array_column($array, 'foo')); assertType('array', array_column($array, 'foo', 'tagName')); assertType('non-empty-array', array_column($array, 'nodeName', 'foo')); assertType('non-empty-array', array_column($array, null, 'foo')); diff --git a/tests/PHPStan/Analyser/nsrt/array-flip.php b/tests/PHPStan/Analyser/nsrt/array-flip.php index 2f02f1e733..ef91f40c36 100644 --- a/tests/PHPStan/Analyser/nsrt/array-flip.php +++ b/tests/PHPStan/Analyser/nsrt/array-flip.php @@ -71,25 +71,25 @@ function foo8($mixed) function foo10(array $array) { if (array_key_exists('foo', $array)) { - assertType('array&hasOffset(\'foo\')', $array); + assertType('non-empty-array&hasOffset(\'foo\')', $array); assertType('array', array_flip($array)); } if (array_key_exists('foo', $array) && is_int($array['foo'])) { - assertType("array&hasOffsetValue('foo', int)", $array); + assertType("non-empty-array&hasOffsetValue('foo', int)", $array); assertType('array', array_flip($array)); } if (array_key_exists('foo', $array) && $array['foo'] === 17) { - assertType("array&hasOffsetValue('foo', 17)", $array); - assertType("array&hasOffsetValue(17, 'foo')", array_flip($array)); + assertType("non-empty-array&hasOffsetValue('foo', 17)", $array); + assertType("non-empty-array&hasOffsetValue(17, 'foo')", array_flip($array)); } if ( array_key_exists('foo', $array) && $array['foo'] === 17 && array_key_exists('bar', $array) && $array['bar'] === 17 ) { - assertType("array&hasOffsetValue('bar', 17)&hasOffsetValue('foo', 17)", $array); + assertType("non-empty-array&hasOffsetValue('bar', 17)&hasOffsetValue('foo', 17)", $array); assertType("*NEVER*", array_flip($array)); // this could be array&hasOffsetValue(17, 'bar') according to https://3v4l.org/1TAFk } } diff --git a/tests/PHPStan/Analyser/nsrt/array-intersect-key.php b/tests/PHPStan/Analyser/nsrt/array-intersect-key.php index bf620b508b..288ba539a2 100644 --- a/tests/PHPStan/Analyser/nsrt/array-intersect-key.php +++ b/tests/PHPStan/Analyser/nsrt/array-intersect-key.php @@ -48,7 +48,7 @@ public function normalArrays(array $arr, array $arr2, array $otherArrs): void assertType('array{}', array_intersect_key($arr, $otherArrs)); if (array_key_exists(17, $arr2)) { - assertType('array<17, string>&hasOffset(17)', array_intersect_key($arr2, [17 => 'bar'])); + assertType('non-empty-array<17, string>&hasOffset(17)', array_intersect_key($arr2, [17 => 'bar'])); /** @var array $otherArrs */ assertType('array', array_intersect_key($arr2, $otherArrs)); /** @var array $otherArrs */ @@ -56,7 +56,7 @@ public function normalArrays(array $arr, array $arr2, array $otherArrs): void } if (array_key_exists(17, $arr2) && $arr2[17] === 'foo') { - assertType("array<17, string>&hasOffsetValue(17, 'foo')", array_intersect_key($arr2, [17 => 'bar'])); + assertType("non-empty-array<17, string>&hasOffsetValue(17, 'foo')", array_intersect_key($arr2, [17 => 'bar'])); /** @var array $otherArrs */ assertType('array', array_intersect_key($arr2, $otherArrs)); /** @var array $otherArrs */ @@ -79,7 +79,7 @@ public function arrayUnpacking(array $arrs, array $arrs2): void /** @param list $arr */ public function list(array $arr, array $otherArrs): void { - assertType('array<0|1, string>&list', array_intersect_key($arr, ['foo', 'bar'])); + assertType('list', array_intersect_key($arr, ['foo', 'bar'])); /** @var array $otherArrs */ assertType('array, string>', array_intersect_key($arr, $otherArrs)); /** @var array $otherArrs */ diff --git a/tests/PHPStan/Analyser/nsrt/array-is-list-type-specifying.php b/tests/PHPStan/Analyser/nsrt/array-is-list-type-specifying.php index aa21248ec6..1b788158d6 100644 --- a/tests/PHPStan/Analyser/nsrt/array-is-list-type-specifying.php +++ b/tests/PHPStan/Analyser/nsrt/array-is-list-type-specifying.php @@ -6,7 +6,7 @@ function foo(array $foo) { if (array_is_list($foo)) { - assertType('list', $foo); + assertType('list', $foo); } else { assertType('array', $foo); } @@ -14,9 +14,9 @@ function foo(array $foo) { function foo2($foo) { if (array_is_list($foo)) { - assertType('list', $foo); + assertType('list', $foo); } else { - assertType('mixed~list', $foo); + assertType('mixed~list', $foo); } } @@ -49,7 +49,7 @@ function foo4(array $foo) { /** @var array $foo */ if (array_is_list($foo)) { - assertType('list', $foo); + assertType('list', $foo); } else { assertType('array', $foo); } diff --git a/tests/PHPStan/Analyser/nsrt/array-reverse.php b/tests/PHPStan/Analyser/nsrt/array-reverse.php index 6f05e9b9f0..86a3bb72cf 100644 --- a/tests/PHPStan/Analyser/nsrt/array-reverse.php +++ b/tests/PHPStan/Analyser/nsrt/array-reverse.php @@ -73,7 +73,7 @@ public function mixed(mixed $mixed): void if (array_key_exists('foo', $mixed)) { assertType('non-empty-array', array_reverse($mixed)); - assertType("array&hasOffset('foo')", array_reverse($mixed, true)); + assertType("non-empty-array&hasOffset('foo')", array_reverse($mixed, true)); } } } diff --git a/tests/PHPStan/Analyser/nsrt/array-shape-list-optional.php b/tests/PHPStan/Analyser/nsrt/array-shape-list-optional.php index f059d14c4d..10049a8317 100644 --- a/tests/PHPStan/Analyser/nsrt/array-shape-list-optional.php +++ b/tests/PHPStan/Analyser/nsrt/array-shape-list-optional.php @@ -9,7 +9,7 @@ class Foo /** * @param list{0: string, 1: int, 2?: string, 3?: string} $valid1 - * @param non-empty-list{0: string, 1: int, 2?: string, 3?: string} $valid2 + * @param non-empty-list{0?: string, 1?: int, 2?: string, 3?: string} $valid2 * @param non-empty-array{0?: string, 1?: int, 2?: string, 3?: string} $valid3 * @param list{0: string, 1: int, 2?: string, 4?: string} $invalid1 * @param list{0: string, 1: int, 2?: string, foo?: string} $invalid2 @@ -22,9 +22,9 @@ public function doFoo( $invalid2 ): void { - assertType('array{0: string, 1: int, 2?: string, 3?: string}&list', $valid1); - assertType('array{0: string, 1: int, 2?: string, 3?: string}&list', $valid2); - assertType('array{0?: string, 1?: int, 2?: string, 3?: string}&non-empty-array', $valid3); + assertType('list{0: string, 1: int, 2?: string, 3?: string}', $valid1); + assertType('non-empty-list{0?: string, 1?: int, 2?: string, 3?: string}', $valid2); + assertType('non-empty-array{0?: string, 1?: int, 2?: string, 3?: string}', $valid3); assertType('*NEVER*', $invalid1); assertType('*NEVER*', $invalid2); } diff --git a/tests/PHPStan/Analyser/nsrt/array-slice.php b/tests/PHPStan/Analyser/nsrt/array-slice.php index e2faabd113..847f535df1 100644 --- a/tests/PHPStan/Analyser/nsrt/array-slice.php +++ b/tests/PHPStan/Analyser/nsrt/array-slice.php @@ -15,7 +15,7 @@ class Foo public function nonEmpty(array $a, array $b, array $c): void { assertType('array', array_slice($a, 1)); - assertType('list', array_slice($b, 1)); + assertType('list', array_slice($b, 1)); assertType('array', array_slice($c, 1)); } @@ -94,11 +94,11 @@ public function offsets(array $arr): void { if (array_key_exists(1, $arr)) { assertType('non-empty-array', array_slice($arr, 1, null, false)); - assertType('hasOffset(1)&non-empty-array', array_slice($arr, 1, null, true)); + assertType('non-empty-array&hasOffset(1)', array_slice($arr, 1, null, true)); } if (array_key_exists(1, $arr) && $arr[1] === 'foo') { assertType('non-empty-array', array_slice($arr, 1, null, false)); - assertType("hasOffsetValue(1, 'foo')&non-empty-array", array_slice($arr, 1, null, true)); + assertType("non-empty-array&hasOffsetValue(1, 'foo')", array_slice($arr, 1, null, true)); } } diff --git a/tests/PHPStan/Analyser/nsrt/assert-intersected.php b/tests/PHPStan/Analyser/nsrt/assert-intersected.php index 17aa63957a..913f1e9034 100644 --- a/tests/PHPStan/Analyser/nsrt/assert-intersected.php +++ b/tests/PHPStan/Analyser/nsrt/assert-intersected.php @@ -26,5 +26,5 @@ public function assert(mixed $value): void; function intersection($assert, mixed $value): void { $assert->assert($value); - assertType('non-empty-list', $value); + assertType('non-empty-list', $value); } diff --git a/tests/PHPStan/Analyser/nsrt/bug-10721.php b/tests/PHPStan/Analyser/nsrt/bug-10721.php index cf7ce49272..52d511c163 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-10721.php +++ b/tests/PHPStan/Analyser/nsrt/bug-10721.php @@ -22,9 +22,9 @@ public function retrieve(?int $limit = 20): array assertType("array{'zib', 'zib 2', 'zeit im bild', 'soko', 'landkrimi', 'tatort'}", $list); shuffle($list); - assertType("non-empty-array<0|1|2|3|4|5, 'landkrimi'|'soko'|'tatort'|'zeit im bild'|'zib'|'zib 2'>&list", $list); + assertType("non-empty-list<'landkrimi'|'soko'|'tatort'|'zeit im bild'|'zib'|'zib 2'>", $list); - assertType("non-empty-array<0|1|2|3|4|5, 'landkrimi'|'soko'|'tatort'|'zeit im bild'|'zib'|'zib 2'>&list", array_slice($list, 0, max($limit, 1))); + assertType("non-empty-list<'landkrimi'|'soko'|'tatort'|'zeit im bild'|'zib'|'zib 2'>", array_slice($list, 0, max($limit, 1))); return array_slice($list, 0, max($limit, 1)); } @@ -37,7 +37,7 @@ public function listVariants(): void assertType("array{2: 'zib', 4: 'zib 2'}", $arr); shuffle($arr); - assertType("non-empty-array<0|1, 'zib'|'zib 2'>&list", $arr); + assertType("non-empty-list<'zib'|'zib 2'>", $arr); $list = [ 'zib', @@ -46,37 +46,37 @@ public function listVariants(): void assertType("array{'zib', 'zib 2'}", $list); shuffle($list); - assertType("non-empty-array<0|1, 'zib'|'zib 2'>&list", $list); + assertType("non-empty-list<'zib'|'zib 2'>", $list); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, -1)); - assertType("non-empty-array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 0)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 1)); // could be non-empty-array - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 2)); + assertType("list<'zib'|'zib 2'>", array_slice($list, -1)); + assertType("non-empty-list<'zib'|'zib 2'>", array_slice($list, 0)); + assertType("list<'zib'|'zib 2'>", array_slice($list, 1)); // could be non-empty-array + assertType("list<'zib'|'zib 2'>", array_slice($list, 2)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, -1, 1)); - assertType("non-empty-array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 0, 1)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 1, 1)); // could be non-empty-array - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 2, 1)); + assertType("list<'zib'|'zib 2'>", array_slice($list, -1, 1)); + assertType("non-empty-list<'zib'|'zib 2'>", array_slice($list, 0, 1)); + assertType("list<'zib'|'zib 2'>", array_slice($list, 1, 1)); // could be non-empty-array + assertType("list<'zib'|'zib 2'>", array_slice($list, 2, 1)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, -1, 2)); - assertType("non-empty-array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 0, 2)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 1, 2)); // could be non-empty-array - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 2, 2)); + assertType("list<'zib'|'zib 2'>", array_slice($list, -1, 2)); + assertType("non-empty-list<'zib'|'zib 2'>", array_slice($list, 0, 2)); + assertType("list<'zib'|'zib 2'>", array_slice($list, 1, 2)); // could be non-empty-array + assertType("list<'zib'|'zib 2'>", array_slice($list, 2, 2)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, -1, 3)); - assertType("non-empty-array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 0, 3)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 1, 3)); // could be non-empty-array - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 2, 3)); + assertType("list<'zib'|'zib 2'>", array_slice($list, -1, 3)); + assertType("non-empty-list<'zib'|'zib 2'>", array_slice($list, 0, 3)); + assertType("list<'zib'|'zib 2'>", array_slice($list, 1, 3)); // could be non-empty-array + assertType("list<'zib'|'zib 2'>", array_slice($list, 2, 3)); assertType("array<0|1, 'zib'|'zib 2'>", array_slice($list, -1, 3, true)); - assertType("non-empty-array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 0, 3, true)); + assertType("non-empty-list<'zib'|'zib 2'>", array_slice($list, 0, 3, true)); assertType("array<0|1, 'zib'|'zib 2'>", array_slice($list, 1, 3, true)); // could be non-empty-array assertType("array<0|1, 'zib'|'zib 2'>", array_slice($list, 2, 3, true)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, -1, 3, false)); - assertType("non-empty-array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 0, 3, false)); - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 1, 3, false)); // could be non-empty-array - assertType("array<0|1, 'zib'|'zib 2'>&list", array_slice($list, 2, 3, false)); + assertType("list<'zib'|'zib 2'>", array_slice($list, -1, 3, false)); + assertType("non-empty-list<'zib'|'zib 2'>", array_slice($list, 0, 3, false)); + assertType("list<'zib'|'zib 2'>", array_slice($list, 1, 3, false)); // could be non-empty-array + assertType("list<'zib'|'zib 2'>", array_slice($list, 2, 3, false)); } /** diff --git a/tests/PHPStan/Analyser/nsrt/bug-11518-types.php b/tests/PHPStan/Analyser/nsrt/bug-11518-types.php index 4f66f4f0af..19d5aeb15f 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-11518-types.php +++ b/tests/PHPStan/Analyser/nsrt/bug-11518-types.php @@ -12,12 +12,12 @@ function blah(array $a): array { if (!array_key_exists('thing', $a)) { $a['thing'] = 'bla'; - assertType('hasOffsetValue(\'thing\', \'bla\')&non-empty-array', $a); + assertType('non-empty-array&hasOffsetValue(\'thing\', \'bla\')', $a); } else { - assertType('array&hasOffset(\'thing\')', $a); + assertType('non-empty-array&hasOffset(\'thing\')', $a); } - assertType('array&hasOffsetValue(\'thing\', mixed)', $a); + assertType('non-empty-array&hasOffsetValue(\'thing\', mixed)', $a); return $a; } diff --git a/tests/PHPStan/Analyser/nsrt/bug-2112.php b/tests/PHPStan/Analyser/nsrt/bug-2112.php index a7d33d1538..65634c415b 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-2112.php +++ b/tests/PHPStan/Analyser/nsrt/bug-2112.php @@ -19,7 +19,7 @@ public function doBar(): void $foos[0] = null; assertType('null', $foos[0]); - assertType('hasOffsetValue(0, null)&non-empty-array', $foos); + assertType('non-empty-array&hasOffsetValue(0, null)', $foos); } /** @return self[] */ diff --git a/tests/PHPStan/Analyser/nsrt/bug-2911.php b/tests/PHPStan/Analyser/nsrt/bug-2911.php index 1d75efdcbe..3cfbd308f1 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-2911.php +++ b/tests/PHPStan/Analyser/nsrt/bug-2911.php @@ -134,6 +134,6 @@ private function getResultSettings(array $settings): array function foo(array $array): void { $array['bar'] = 'string'; - assertType("hasOffsetValue('bar', 'string')&non-empty-array", $array); + assertType("non-empty-array&hasOffsetValue('bar', 'string')", $array); } } diff --git a/tests/PHPStan/Analyser/nsrt/bug-4099.php b/tests/PHPStan/Analyser/nsrt/bug-4099.php index 0a8d1b4b48..5e5eb30ca2 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-4099.php +++ b/tests/PHPStan/Analyser/nsrt/bug-4099.php @@ -22,20 +22,20 @@ function arrayHint(array $arr): void throw new \Exception('no key "key" found.'); } assertType('array{key: array{inner: mixed}}', $arr); - assertNativeType('array&hasOffset(\'key\')', $arr); + assertNativeType('non-empty-array&hasOffset(\'key\')', $arr); assertType('array{inner: mixed}', $arr['key']); assertNativeType('mixed', $arr['key']); if (!array_key_exists('inner', $arr['key'])) { assertType('*NEVER*', $arr); - assertNativeType('array&hasOffset(\'key\')', $arr); + assertNativeType('non-empty-array&hasOffset(\'key\')', $arr); assertType('*NEVER*', $arr['key']); assertNativeType("mixed~hasOffset('inner')", $arr['key']); throw new \Exception('need key.inner'); } assertType('array{key: array{inner: mixed}}', $arr); - assertNativeType('array&hasOffset(\'key\')', $arr); + assertNativeType('non-empty-array&hasOffset(\'key\')', $arr); } } diff --git a/tests/PHPStan/Analyser/nsrt/bug-4117.php b/tests/PHPStan/Analyser/nsrt/bug-4117.php index 510df695f1..14732b77b6 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-4117.php +++ b/tests/PHPStan/Analyser/nsrt/bug-4117.php @@ -34,7 +34,7 @@ public function broken(int $key) if ($item) { assertType("T of mixed~(0|0.0|''|'0'|array{}|false|null) (class Bug4117Types\GenericList, argument)", $item); } else { - assertType("(T of mixed~null (class Bug4117Types\GenericList, argument)&false)|(0.0&T of mixed~null (class Bug4117Types\GenericList, argument))|(0&T of mixed~null (class Bug4117Types\GenericList, argument))|(array{}&T of mixed~null (class Bug4117Types\GenericList, argument))|(''&T of mixed~null (class Bug4117Types\GenericList, argument))|('0'&T of mixed~null (class Bug4117Types\GenericList, argument))|null", $item); + assertType("(T of mixed~null (class Bug4117Types\GenericList, argument)&false)|(0.0&T of mixed~null (class Bug4117Types\GenericList, argument))|(0&T of mixed~null (class Bug4117Types\GenericList, argument))|(list{}&T of mixed~null (class Bug4117Types\GenericList, argument))|(''&T of mixed~null (class Bug4117Types\GenericList, argument))|('0'&T of mixed~null (class Bug4117Types\GenericList, argument))|null", $item); } assertType('T of mixed~null (class Bug4117Types\GenericList, argument)|null', $item); diff --git a/tests/PHPStan/Analyser/nsrt/bug-4398.php b/tests/PHPStan/Analyser/nsrt/bug-4398.php index 297484c2cf..6fd566cd62 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-4398.php +++ b/tests/PHPStan/Analyser/nsrt/bug-4398.php @@ -14,5 +14,5 @@ function (array $meters): void { assertType('array', array_reverse()); assertType('non-empty-array', array_reverse($meters)); assertType('non-empty-list<(int|string)>', array_keys($meters)); - assertType('non-empty-list', array_values($meters)); + assertType('non-empty-list', array_values($meters)); }; diff --git a/tests/PHPStan/Analyser/nsrt/bug-4565.php b/tests/PHPStan/Analyser/nsrt/bug-4565.php index af941f8098..55a1c372a5 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-4565.php +++ b/tests/PHPStan/Analyser/nsrt/bug-4565.php @@ -10,9 +10,9 @@ function test(array $variables) { if (!empty($variables['button'])) { assertType('non-empty-array', $attributes); $attributes['type'] = 'button'; - assertType("hasOffsetValue('type', 'button')&non-empty-array", $attributes); + assertType("non-empty-array&hasOffsetValue('type', 'button')", $attributes); unset($attributes['href']); - assertType("array&hasOffsetValue('type', 'button')", $attributes); + assertType("non-empty-array&hasOffsetValue('type', 'button')", $attributes); } assertType('array', $attributes); return $attributes; diff --git a/tests/PHPStan/Analyser/nsrt/bug-4708.php b/tests/PHPStan/Analyser/nsrt/bug-4708.php index d6bae28afc..b6f2302722 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-4708.php +++ b/tests/PHPStan/Analyser/nsrt/bug-4708.php @@ -57,7 +57,7 @@ function GetASCConfig() } else { - assertType("array&hasOffsetValue('bsw', string)", $result); + assertType("non-empty-array&hasOffsetValue('bsw', string)", $result); $result['bsw'] = (int) $result['bsw']; assertType("non-empty-array&hasOffsetValue('bsw', int)", $result); } diff --git a/tests/PHPStan/Analyser/nsrt/bug-6859.php b/tests/PHPStan/Analyser/nsrt/bug-6859.php index 0f6d43963e..56cd257c5e 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-6859.php +++ b/tests/PHPStan/Analyser/nsrt/bug-6859.php @@ -30,7 +30,7 @@ public function keys($body) public function values($body) { if (array_key_exists("someParam", $body)) { - assertType('non-empty-list', array_values($body)); + assertType('non-empty-list', array_values($body)); } } } diff --git a/tests/PHPStan/Analyser/nsrt/bug-7805.php b/tests/PHPStan/Analyser/nsrt/bug-7805.php index 859b504e50..ec9464ebd3 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-7805.php +++ b/tests/PHPStan/Analyser/nsrt/bug-7805.php @@ -14,7 +14,7 @@ function foo(array $params) assertNativeType('array', $params); if (array_key_exists('help', $params)) { assertType('array{help: null}', $params); - assertNativeType("array&hasOffset('help')", $params); + assertNativeType("non-empty-array&hasOffset('help')", $params); unset($params['help']); assertType('array{}', $params); diff --git a/tests/PHPStan/Analyser/nsrt/bug-9734.php b/tests/PHPStan/Analyser/nsrt/bug-9734.php index 353b1d91f9..1628ad6859 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9734.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9734.php @@ -15,7 +15,7 @@ class Foo public function doFoo(array $a): void { if (array_is_list($a)) { - assertType('list', $a); + assertType('list', $a); } else { assertType('array', $a); // could be non-empty-array } @@ -38,7 +38,7 @@ public function doFoo2(): void public function doFoo3(array $a): void { if (array_is_list($a)) { - assertType('non-empty-list', $a); + assertType('non-empty-list', $a); } else { assertType('non-empty-array', $a); } diff --git a/tests/PHPStan/Analyser/nsrt/bug-9985.php b/tests/PHPStan/Analyser/nsrt/bug-9985.php index edbfebffc5..09a7ad92ea 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-9985.php +++ b/tests/PHPStan/Analyser/nsrt/bug-9985.php @@ -20,6 +20,6 @@ function (): void { assertType('array{}|array{a?: true, b: true}|array{a?: true, c?: true}', $warnings); if (!empty($warnings)) { - assertType('array{a?: true, b: true}|(array{a?: true, c?: true}&non-empty-array)', $warnings); + assertType('array{a?: true, b: true}|non-empty-array{a?: true, c?: true}', $warnings); } }; diff --git a/tests/PHPStan/Analyser/nsrt/composer-array-bug.php b/tests/PHPStan/Analyser/nsrt/composer-array-bug.php index fbbcff38a8..354577f098 100644 --- a/tests/PHPStan/Analyser/nsrt/composer-array-bug.php +++ b/tests/PHPStan/Analyser/nsrt/composer-array-bug.php @@ -44,14 +44,14 @@ public function doFoo(): void } } - assertType("array&hasOffsetValue('authors', mixed)", $this->config); + assertType("non-empty-array&hasOffsetValue('authors', mixed)", $this->config); assertType("mixed", $this->config['authors']); if (empty($this->config['authors'])) { unset($this->config['authors']); assertType("array", $this->config); } else { - assertType("array&hasOffsetValue('authors', mixed~(0|0.0|''|'0'|array{}|false|null))", $this->config); + assertType("non-empty-array&hasOffsetValue('authors', mixed~(0|0.0|''|'0'|array{}|false|null))", $this->config); } assertType('array', $this->config); diff --git a/tests/PHPStan/Analyser/nsrt/conditional-vars.php b/tests/PHPStan/Analyser/nsrt/conditional-vars.php index 6d86c88014..e76b112f4d 100644 --- a/tests/PHPStan/Analyser/nsrt/conditional-vars.php +++ b/tests/PHPStan/Analyser/nsrt/conditional-vars.php @@ -12,7 +12,7 @@ public function conditionalVarInTernary(array $innerHits): void if (array_key_exists('nearest_premise', $innerHits) || array_key_exists('matching_premises', $innerHits)) { assertType('array', $innerHits); $x = array_key_exists('nearest_premise', $innerHits) - ? assertType("array&hasOffset('nearest_premise')", $innerHits) + ? assertType("non-empty-array&hasOffset('nearest_premise')", $innerHits) : assertType('array', $innerHits); assertType('array', $innerHits); @@ -25,7 +25,7 @@ public function conditionalVarInIf(array $innerHits): void if (array_key_exists('nearest_premise', $innerHits) || array_key_exists('matching_premises', $innerHits)) { assertType('array', $innerHits); if (array_key_exists('nearest_premise', $innerHits)) { - assertType("array&hasOffset('nearest_premise')", $innerHits); + assertType("non-empty-array&hasOffset('nearest_premise')", $innerHits); } else { assertType('array', $innerHits); } diff --git a/tests/PHPStan/Analyser/nsrt/filter-var-dynamic-return-type-extension-regression.php b/tests/PHPStan/Analyser/nsrt/filter-var-dynamic-return-type-extension-regression.php index 69fc99f613..172fa40b4f 100644 --- a/tests/PHPStan/Analyser/nsrt/filter-var-dynamic-return-type-extension-regression.php +++ b/tests/PHPStan/Analyser/nsrt/filter-var-dynamic-return-type-extension-regression.php @@ -46,9 +46,9 @@ public function test() } assertType('array{default?: PHPStan\Type\Type, range: PHPStan\Type\Type}', $otherTypes); } - assertType('array{default?: PHPStan\Type\Type, range?: PHPStan\Type\Type}&non-empty-array', $otherTypes); + assertType('non-empty-array{default?: PHPStan\Type\Type, range?: PHPStan\Type\Type}', $otherTypes); if ($exactType !== null) { - assertType('array{default?: PHPStan\Type\Type, range?: PHPStan\Type\Type}&non-empty-array', $otherTypes); + assertType('non-empty-array{default?: PHPStan\Type\Type, range?: PHPStan\Type\Type}', $otherTypes); unset($otherTypes['default']); assertType('array{range?: PHPStan\Type\Type}', $otherTypes); } diff --git a/tests/PHPStan/Analyser/nsrt/has-offset-type-bug.php b/tests/PHPStan/Analyser/nsrt/has-offset-type-bug.php index d1e8fd92a0..eacfb06af6 100644 --- a/tests/PHPStan/Analyser/nsrt/has-offset-type-bug.php +++ b/tests/PHPStan/Analyser/nsrt/has-offset-type-bug.php @@ -65,7 +65,7 @@ public function testIsset($range): void { assertType("array{}|array{min?: bool|float|int|string|null, max?: bool|float|int|string|null}", $range); if (isset($range['min']) || isset($range['max'])) { - assertType("array{min?: bool|float|int|string|null, max?: bool|float|int|string|null}&non-empty-array", $range); + assertType("non-empty-array{min?: bool|float|int|string|null, max?: bool|float|int|string|null}", $range); } else { assertType("array{}|array{min?: bool|float|int|string|null, max?: bool|float|int|string|null}", $range); } @@ -144,7 +144,7 @@ public function doBar(array $a, int $i) public function doFoo2(array $a) { if (is_int($a['a'])) { - assertType("array&hasOffsetValue('a', *NEVER*)", $a); + assertType("non-empty-array&hasOffsetValue('a', *NEVER*)", $a); } } diff --git a/tests/PHPStan/Analyser/nsrt/list-count.php b/tests/PHPStan/Analyser/nsrt/list-count.php index caf0a17c87..c51ea31efc 100644 --- a/tests/PHPStan/Analyser/nsrt/list-count.php +++ b/tests/PHPStan/Analyser/nsrt/list-count.php @@ -351,25 +351,25 @@ protected function testOptionalKeysInUnionListWithIntRange($row, $twoOrThree, $t if (count($row) >= $twoOrThree) { assertType('array{0: int, 1: string|null, 2?: int|null}', $row); } else { - assertType('(array{0: int, 1?: string|null, 2?: int|null, 3?: float|null}&list)|array{string}', $row); + assertType('array{string}|list{0: int, 1?: string|null, 2?: int|null, 3?: float|null}', $row); } if (count($row) >= $tenOrEleven) { assertType('*NEVER*', $row); } else { - assertType('(array{0: int, 1?: string|null, 2?: int|null, 3?: float|null}&list)|array{string}', $row); + assertType('array{string}|list{0: int, 1?: string|null, 2?: int|null, 3?: float|null}', $row); } if (count($row) >= $twoOrMore) { - assertType('array{0: int, 1: string|null, 2?: int|null, 3?: float|null}&list', $row); + assertType('list{0: int, 1: string|null, 2?: int|null, 3?: float|null}', $row); } else { - assertType('(array{0: int, 1?: string|null, 2?: int|null, 3?: float|null}&list)|array{string}', $row); + assertType('array{string}|list{0: int, 1?: string|null, 2?: int|null, 3?: float|null}', $row); } if (count($row) >= $maxThree) { - assertType('(array{0: int, 1?: string|null, 2?: int|null, 3?: float|null}&list)|array{string}', $row); + assertType('array{string}|list{0: int, 1?: string|null, 2?: int|null, 3?: float|null}', $row); } else { - assertType('array{0: int, 1?: string|null, 2?: int|null, 3?: float|null}&list', $row); + assertType('list{0: int, 1?: string|null, 2?: int|null, 3?: float|null}', $row); } } diff --git a/tests/PHPStan/Analyser/nsrt/list-type.php b/tests/PHPStan/Analyser/nsrt/list-type.php index a80e8b066d..647d44f718 100644 --- a/tests/PHPStan/Analyser/nsrt/list-type.php +++ b/tests/PHPStan/Analyser/nsrt/list-type.php @@ -9,19 +9,19 @@ class Foo /** @param list $list */ public function directAssertion($list): void { - assertType('list', $list); + assertType('list', $list); } /** @param list $list */ public function directAssertionParamHint(array $list): void { - assertType('list', $list); + assertType('list', $list); } /** @param list $list */ public function directAssertionNullableParamHint(array $list = null): void { - assertType('list|null', $list); + assertType('list|null', $list); } /** @param list<\DateTime> $list */ @@ -37,7 +37,7 @@ public function withoutGenerics(): void $list[] = '1'; $list[] = true; $list[] = new \stdClass(); - assertType('non-empty-list', $list); + assertType('non-empty-list', $list); } @@ -83,17 +83,17 @@ public function withFullListFunctionality(): void // These won't output errors for now but should when list type will be fully implemented /** @var list $list */ $list = []; - assertType('list', $list); + assertType('list', $list); $list[] = '1'; - assertType('non-empty-list', $list); + assertType('non-empty-list', $list); $list[] = '2'; - assertType('non-empty-list', $list); + assertType('non-empty-list', $list); unset($list[0]);//break list behaviour assertType('array, mixed>', $list); /** @var list $list2 */ $list2 = []; - assertType('list', $list2); + assertType('list', $list2); $list2[2] = '1';//Most likely to create a gap in indexes assertType('non-empty-array, mixed>&hasOffsetValue(2, \'1\')', $list2); } diff --git a/tests/PHPStan/Analyser/nsrt/non-empty-array.php b/tests/PHPStan/Analyser/nsrt/non-empty-array.php index a7cdc6540a..af34c0da25 100644 --- a/tests/PHPStan/Analyser/nsrt/non-empty-array.php +++ b/tests/PHPStan/Analyser/nsrt/non-empty-array.php @@ -26,7 +26,7 @@ public function doFoo( ): void { assertType('non-empty-array', $array); - assertType('non-empty-list', $list); + assertType('non-empty-list', $list); assertType('non-empty-array', $arrayOfStrings); assertType('non-empty-list', $listOfStd); assertType('non-empty-list', $listOfStd2); diff --git a/tests/PHPStan/Analyser/nsrt/shuffle.php b/tests/PHPStan/Analyser/nsrt/shuffle.php index c2bf853776..6b699e598a 100644 --- a/tests/PHPStan/Analyser/nsrt/shuffle.php +++ b/tests/PHPStan/Analyser/nsrt/shuffle.php @@ -13,7 +13,7 @@ public function normalArrays1(array $arr): void /** @var mixed[] $arr */ shuffle($arr); assertType('list', $arr); - assertNativeType('list', $arr); + assertNativeType('list', $arr); assertType('list>', array_keys($arr)); assertType('list', array_values($arr)); } @@ -23,7 +23,7 @@ public function normalArrays2(array $arr): void /** @var non-empty-array $arr */ shuffle($arr); assertType('non-empty-list', $arr); - assertNativeType('list', $arr); + assertNativeType('list', $arr); assertType('non-empty-list>', array_keys($arr)); assertType('non-empty-list', array_values($arr)); } @@ -33,10 +33,10 @@ public function normalArrays3(array $arr): void /** @var array $arr */ if (array_key_exists('foo', $arr)) { shuffle($arr); - assertType('non-empty-list', $arr); - assertNativeType('non-empty-list', $arr); + assertType('non-empty-list', $arr); + assertNativeType('non-empty-list', $arr); assertType('non-empty-list>', array_keys($arr)); - assertType('non-empty-list', array_values($arr)); + assertType('non-empty-list', array_values($arr)); } } @@ -45,10 +45,10 @@ public function normalArrays4(array $arr): void /** @var array $arr */ if (array_key_exists('foo', $arr) && $arr['foo'] === 'bar') { shuffle($arr); - assertType('non-empty-list', $arr); - assertNativeType('non-empty-list', $arr); + assertType('non-empty-list', $arr); + assertNativeType('non-empty-list', $arr); assertType('non-empty-list>', array_keys($arr)); - assertType('non-empty-list', array_values($arr)); + assertType('non-empty-list', array_values($arr)); } } @@ -66,8 +66,8 @@ public function constantArrays2(array $arr): void { /** @var array{0?: 1, 1?: 2, 2?: 3} $arr */ shuffle($arr); - assertType('array<0|1|2, 1|2|3>&list', $arr); - assertNativeType('list', $arr); + assertType('list<1|2|3>', $arr); + assertNativeType('list', $arr); assertType('list<0|1|2>', array_keys($arr)); assertType('list<1|2|3>', array_values($arr)); } @@ -76,8 +76,8 @@ public function constantArrays3(array $arr): void { $arr = [1, 2, 3]; shuffle($arr); - assertType('non-empty-array<0|1|2, 1|2|3>&list', $arr); - assertNativeType('non-empty-array<0|1|2, 1|2|3>&list', $arr); + assertType('non-empty-list<1|2|3>', $arr); + assertNativeType('non-empty-list<1|2|3>', $arr); assertType('non-empty-list<0|1|2>', array_keys($arr)); assertType('non-empty-list<1|2|3>', array_values($arr)); } @@ -86,8 +86,8 @@ public function constantArrays4(array $arr): void { $arr = ['a' => 1, 'b' => 2, 'c' => 3]; shuffle($arr); - assertType('non-empty-array<0|1|2, 1|2|3>&list', $arr); - assertNativeType('non-empty-array<0|1|2, 1|2|3>&list', $arr); + assertType('non-empty-list<1|2|3>', $arr); + assertNativeType('non-empty-list<1|2|3>', $arr); assertType('non-empty-list<0|1|2>', array_keys($arr)); assertType('non-empty-list<1|2|3>', array_values($arr)); } @@ -96,8 +96,8 @@ public function constantArrays5(array $arr): void { $arr = [0 => 1, 3 => 2, 42 => 3]; shuffle($arr); - assertType('non-empty-array<0|1|2, 1|2|3>&list', $arr); - assertNativeType('non-empty-array<0|1|2, 1|2|3>&list', $arr); + assertType('non-empty-list<1|2|3>', $arr); + assertNativeType('non-empty-list<1|2|3>', $arr); assertType('non-empty-list<0|1|2>', array_keys($arr)); assertType('non-empty-list<1|2|3>', array_values($arr)); } @@ -106,8 +106,8 @@ public function constantArrays6(array $arr): void { /** @var array{foo?: 1, bar: 2, }|array{baz: 3, foobar?: 4} $arr */ shuffle($arr); - assertType('non-empty-array<0|1, 1|2|3|4>&list', $arr); - assertNativeType('list', $arr); + assertType('non-empty-list<1|2|3|4>', $arr); + assertNativeType('list', $arr); assertType('non-empty-list<0|1>', array_keys($arr)); assertType('non-empty-list<1|2|3|4>', array_values($arr)); } @@ -115,10 +115,10 @@ public function constantArrays6(array $arr): void public function mixed($arr): void { shuffle($arr); - assertType('list', $arr); - assertNativeType('list', $arr); + assertType('list', $arr); + assertNativeType('list', $arr); assertType('list>', array_keys($arr)); - assertType('list', array_values($arr)); + assertType('list', array_values($arr)); } public function subtractedArray($arr): void @@ -134,7 +134,7 @@ public function subtractedArray($arr): void assertType('*ERROR*', $arr); assertNativeType('*ERROR*', $arr); assertType('list', array_keys($arr)); - assertType('list', array_values($arr)); + assertType('list', array_values($arr)); } } diff --git a/tests/PHPStan/Analyser/nsrt/sort.php b/tests/PHPStan/Analyser/nsrt/sort.php index e92b006713..93dfe0d147 100644 --- a/tests/PHPStan/Analyser/nsrt/sort.php +++ b/tests/PHPStan/Analyser/nsrt/sort.php @@ -91,17 +91,17 @@ public function normalArray(array $arr): void $arr1 = $arr; sort($arr1); assertType('list', $arr1); - assertNativeType('list', $arr1); + assertNativeType('list', $arr1); $arr2 = $arr; rsort($arr2); assertType('list', $arr2); - assertNativeType('list', $arr2); + assertNativeType('list', $arr2); $arr3 = $arr; usort($arr3, fn(int $a, int $b) => $a <=> $b); assertType('list', $arr3); - assertNativeType('list', $arr3); + assertNativeType('list', $arr3); } public function mixed($arr): void diff --git a/tests/PHPStan/Rules/Comparison/data/bug-4708.php b/tests/PHPStan/Rules/Comparison/data/bug-4708.php index 5c60d3dec1..2afa164340 100644 --- a/tests/PHPStan/Rules/Comparison/data/bug-4708.php +++ b/tests/PHPStan/Rules/Comparison/data/bug-4708.php @@ -57,7 +57,7 @@ function GetASCConfig() } else { - assertType('array&hasOffsetValue(\'bsw\', string)', $result); + assertType('non-empty-array&hasOffsetValue(\'bsw\', string)', $result); $result['bsw'] = (int) $result['bsw']; assertType("non-empty-array&hasOffsetValue('bsw', int)", $result); } diff --git a/tests/PHPStan/Rules/Functions/data/bug-3931.php b/tests/PHPStan/Rules/Functions/data/bug-3931.php index ca84648938..424c7ca236 100644 --- a/tests/PHPStan/Rules/Functions/data/bug-3931.php +++ b/tests/PHPStan/Rules/Functions/data/bug-3931.php @@ -11,7 +11,7 @@ */ function addSomeKey(array $arr, int $value): array { $arr['mykey'] = $value; - assertType("hasOffsetValue('mykey', int)&non-empty-array", $arr); // should preserve T + assertType("non-empty-array&hasOffsetValue('mykey', int)", $arr); // should preserve T return $arr; } diff --git a/tests/PHPStan/Rules/Functions/data/bug-7156.php b/tests/PHPStan/Rules/Functions/data/bug-7156.php index 96dd5ee26c..209a9decf5 100644 --- a/tests/PHPStan/Rules/Functions/data/bug-7156.php +++ b/tests/PHPStan/Rules/Functions/data/bug-7156.php @@ -21,7 +21,7 @@ function foobar(array $data): void throw new \RuntimeException(); } - assertType("array&hasOffsetValue('value', string)", $data); + assertType("non-empty-array&hasOffsetValue('value', string)", $data); foo($data); } @@ -32,7 +32,7 @@ function foobar2(mixed $data): void throw new \RuntimeException(); } - assertType("array&hasOffsetValue('value', string)", $data); + assertType("non-empty-array&hasOffsetValue('value', string)", $data); foo($data); } diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index 5ebfb238e7..41200b9ad5 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -865,7 +865,7 @@ public function testBug8146bErrors(): void $this->checkBenevolentUnionTypes = true; $this->analyse([__DIR__ . '/data/bug-8146b-errors.php'], [ [ - "Method Bug8146bError\LocationFixtures::getData() should return array, coordinates: array{lat: float, lng: float}}>> but returns array{Bács-Kiskun: array{Ágasegyháza: array{constituencies: array{'Bács-Kiskun 4.', true, false, Bug8146bError\X, null}, coordinates: array{lat: 46.8386043, lng: 19.4502899}}, Akasztó: array{constituencies: array{'Bács-Kiskun 3.'}, coordinates: array{lat: 46.6898175, lng: 19.205086}}, Apostag: array{constituencies: array{'Bács-Kiskun 3.'}, coordinates: array{lat: 46.8812652, lng: 18.9648478}}, Bácsalmás: array{constituencies: array{'Bács-Kiskun 5.'}, coordinates: array{lat: 46.1250396, lng: 19.3357509}}, Bácsbokod: array{constituencies: array{'Bács-Kiskun 6.'}, coordinates: array{lat: 46.1234737, lng: 19.155708}}, Bácsborsód: array{constituencies: array{'Bács-Kiskun 6.'}, coordinates: array{lat: 46.0989373, lng: 19.1566725}}, Bácsszentgyörgy: array{constituencies: array{'Bács-Kiskun 6.'}, coordinates: array{lat: 45.9746039, lng: 19.0398066}}, Bácsszőlős: array{constituencies: array{'Bács-Kiskun 5.'}, coordinates: array{lat: 46.1352003, lng: 19.4215997}}, ...}, Baranya: non-empty-array|(literal-string&non-falsy-string), float|(literal-string&non-falsy-string)>>>, Békés: array{Almáskamarás: array{constituencies: array{'Békés 4.'}, coordinates: array{lat: 46.4617785, lng: 21.092448}}, Battonya: array{constituencies: array{'Békés 4.'}, coordinates: array{lat: 46.2902462, lng: 21.0199215}}, Békés: array{constituencies: array{'Békés 2.'}, coordinates: array{lat: 46.6704899, lng: 21.0434996}}, Békéscsaba: array{constituencies: array{'Békés 1.'}, coordinates: array{lat: 46.6735939, lng: 21.0877309}}, Békéssámson: array{constituencies: array{'Békés 4.'}, coordinates: array{lat: 46.4208677, lng: 20.6176498}}, Békésszentandrás: array{constituencies: array{'Békés 2.'}, coordinates: array{lat: 46.8715996, lng: 20.48336}}, Bélmegyer: array{constituencies: array{'Békés 3.'}, coordinates: array{lat: 46.8726019, lng: 21.1832832}}, Biharugra: array{constituencies: array{'Békés 3.'}, coordinates: array{lat: 46.9691009, lng: 21.5987651}}, ...}, Borsod-Abaúj-Zemplén: non-empty-array|(literal-string&non-falsy-string), float|(literal-string&non-falsy-string)>>>, Budapest: array{Budapest I. ker.: array{constituencies: array{'Budapest 01.'}, coordinates: array{lat: 47.4968219, lng: 19.037458}}, Budapest II. ker.: array{constituencies: array{'Budapest 03.', 'Budapest 04.'}, coordinates: array{lat: 47.5393329, lng: 18.986934}}, Budapest III. ker.: array{constituencies: array{'Budapest 04.', 'Budapest 10.'}, coordinates: array{lat: 47.5671768, lng: 19.0368517}}, Budapest IV. ker.: array{constituencies: array{'Budapest 11.', 'Budapest 12.'}, coordinates: array{lat: 47.5648915, lng: 19.0913149}}, Budapest V. ker.: array{constituencies: array{'Budapest 01.'}, coordinates: array{lat: 47.5002319, lng: 19.0520181}}, Budapest VI. ker.: array{constituencies: array{'Budapest 05.'}, coordinates: array{lat: 47.509863, lng: 19.0625813}}, Budapest VII. ker.: array{constituencies: array{'Budapest 05.'}, coordinates: array{lat: 47.5027289, lng: 19.073376}}, Budapest VIII. ker.: array{constituencies: array{'Budapest 01.', 'Budapest 06.'}, coordinates: array{lat: 47.4894184, lng: 19.070668}}, ...}, Csongrád-Csanád: array{Algyő: array{constituencies: array{'Csongrád-Csanád 4.'}, coordinates: array{lat: 46.3329625, lng: 20.207889}}, Ambrózfalva: array{constituencies: array{'Csongrád-Csanád 4.'}, coordinates: array{lat: 46.3501417, lng: 20.7313995}}, Apátfalva: array{constituencies: array{'Csongrád-Csanád 4.'}, coordinates: array{lat: 46.173317, lng: 20.5800472}}, Árpádhalom: array{constituencies: array{'Csongrád-Csanád 3.'}, coordinates: array{lat: 46.6158286, lng: 20.547733}}, Ásotthalom: array{constituencies: array{'Csongrád-Csanád 2.'}, coordinates: array{lat: 46.1995983, lng: 19.7833756}}, Baks: array{constituencies: array{'Csongrád-Csanád 3.'}, coordinates: array{lat: 46.5518708, lng: 20.1064166}}, Balástya: array{constituencies: array{'Csongrád-Csanád 3.'}, coordinates: array{lat: 46.4261828, lng: 20.004933}}, Bordány: array{constituencies: array{'Csongrád-Csanád 2.'}, coordinates: array{lat: 46.3194213, lng: 19.9227063}}, ...}, Fejér: array{Aba: array{constituencies: array{'Fejér 5.'}, coordinates: array{lat: 47.0328193, lng: 18.522359}}, Adony: array{constituencies: array{'Fejér 4.'}, coordinates: array{lat: 47.119831, lng: 18.8612469}}, Alap: array{constituencies: array{'Fejér 5.'}, coordinates: array{lat: 46.8075763, lng: 18.684028}}, Alcsútdoboz: array{constituencies: array{'Fejér 3.'}, coordinates: array{lat: 47.4277067, lng: 18.6030325}}, Alsószentiván: array{constituencies: array{'Fejér 5.'}, coordinates: array{lat: 46.7910573, lng: 18.732161}}, Bakonycsernye: array{constituencies: array{'Fejér 2.'}, coordinates: array{lat: 47.321719, lng: 18.0907379}}, Bakonykúti: array{constituencies: array{'Fejér 2.'}, coordinates: array{lat: 47.2458464, lng: 18.195769}}, Balinka: array{constituencies: array{'Fejér 2.'}, coordinates: array{lat: 47.3135736, lng: 18.1907168}}, ...}, Győr-Moson-Sopron: array{Abda: array{constituencies: array{'Győr-Moson-Sopron 5.'}, coordinates: array{lat: 47.6962149, lng: 17.5445786}}, Acsalag: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.676095, lng: 17.1977771}}, Ágfalva: array{constituencies: array{'Győr-Moson-Sopron 4.'}, coordinates: array{lat: 47.688862, lng: 16.5110233}}, Agyagosszergény: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.608545, lng: 16.9409912}}, Árpás: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.5134127, lng: 17.3931579}}, Ásványráró: array{constituencies: array{'Győr-Moson-Sopron 5.'}, coordinates: array{lat: 47.8287695, lng: 17.499195}}, Babót: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.5752269, lng: 17.0758604}}, Bágyogszovát: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.5866036, lng: 17.3617273}}, ...}, ...}.", + "Method Bug8146bError\LocationFixtures::getData() should return array, coordinates: array{lat: float, lng: float}}>> but returns array{Bács-Kiskun: array{Ágasegyháza: array{constituencies: array{'Bács-Kiskun 4.', true, false, Bug8146bError\X, null}, coordinates: array{lat: 46.8386043, lng: 19.4502899}}, Akasztó: array{constituencies: array{'Bács-Kiskun 3.'}, coordinates: array{lat: 46.6898175, lng: 19.205086}}, Apostag: array{constituencies: array{'Bács-Kiskun 3.'}, coordinates: array{lat: 46.8812652, lng: 18.9648478}}, Bácsalmás: array{constituencies: array{'Bács-Kiskun 5.'}, coordinates: array{lat: 46.1250396, lng: 19.3357509}}, Bácsbokod: array{constituencies: array{'Bács-Kiskun 6.'}, coordinates: array{lat: 46.1234737, lng: 19.155708}}, Bácsborsód: array{constituencies: array{'Bács-Kiskun 6.'}, coordinates: array{lat: 46.0989373, lng: 19.1566725}}, Bácsszentgyörgy: array{constituencies: array{'Bács-Kiskun 6.'}, coordinates: array{lat: 45.9746039, lng: 19.0398066}}, Bácsszőlős: array{constituencies: array{'Bács-Kiskun 5.'}, coordinates: array{lat: 46.1352003, lng: 19.4215997}}, ...}, Baranya: non-empty-array|(literal-string&non-falsy-string), float|(literal-string&non-falsy-string)>>>, Békés: array{Almáskamarás: array{constituencies: array{'Békés 4.'}, coordinates: array{lat: 46.4617785, lng: 21.092448}}, Battonya: array{constituencies: array{'Békés 4.'}, coordinates: array{lat: 46.2902462, lng: 21.0199215}}, Békés: array{constituencies: array{'Békés 2.'}, coordinates: array{lat: 46.6704899, lng: 21.0434996}}, Békéscsaba: array{constituencies: array{'Békés 1.'}, coordinates: array{lat: 46.6735939, lng: 21.0877309}}, Békéssámson: array{constituencies: array{'Békés 4.'}, coordinates: array{lat: 46.4208677, lng: 20.6176498}}, Békésszentandrás: array{constituencies: array{'Békés 2.'}, coordinates: array{lat: 46.8715996, lng: 20.48336}}, Bélmegyer: array{constituencies: array{'Békés 3.'}, coordinates: array{lat: 46.8726019, lng: 21.1832832}}, Biharugra: array{constituencies: array{'Békés 3.'}, coordinates: array{lat: 46.9691009, lng: 21.5987651}}, ...}, Borsod-Abaúj-Zemplén: non-empty-array|(literal-string&non-falsy-string), float|(literal-string&non-falsy-string)>>>, Budapest: array{Budapest I. ker.: array{constituencies: array{'Budapest 01.'}, coordinates: array{lat: 47.4968219, lng: 19.037458}}, Budapest II. ker.: array{constituencies: array{'Budapest 03.', 'Budapest 04.'}, coordinates: array{lat: 47.5393329, lng: 18.986934}}, Budapest III. ker.: array{constituencies: array{'Budapest 04.', 'Budapest 10.'}, coordinates: array{lat: 47.5671768, lng: 19.0368517}}, Budapest IV. ker.: array{constituencies: array{'Budapest 11.', 'Budapest 12.'}, coordinates: array{lat: 47.5648915, lng: 19.0913149}}, Budapest V. ker.: array{constituencies: array{'Budapest 01.'}, coordinates: array{lat: 47.5002319, lng: 19.0520181}}, Budapest VI. ker.: array{constituencies: array{'Budapest 05.'}, coordinates: array{lat: 47.509863, lng: 19.0625813}}, Budapest VII. ker.: array{constituencies: array{'Budapest 05.'}, coordinates: array{lat: 47.5027289, lng: 19.073376}}, Budapest VIII. ker.: array{constituencies: array{'Budapest 01.', 'Budapest 06.'}, coordinates: array{lat: 47.4894184, lng: 19.070668}}, ...}, Csongrád-Csanád: array{Algyő: array{constituencies: array{'Csongrád-Csanád 4.'}, coordinates: array{lat: 46.3329625, lng: 20.207889}}, Ambrózfalva: array{constituencies: array{'Csongrád-Csanád 4.'}, coordinates: array{lat: 46.3501417, lng: 20.7313995}}, Apátfalva: array{constituencies: array{'Csongrád-Csanád 4.'}, coordinates: array{lat: 46.173317, lng: 20.5800472}}, Árpádhalom: array{constituencies: array{'Csongrád-Csanád 3.'}, coordinates: array{lat: 46.6158286, lng: 20.547733}}, Ásotthalom: array{constituencies: array{'Csongrád-Csanád 2.'}, coordinates: array{lat: 46.1995983, lng: 19.7833756}}, Baks: array{constituencies: array{'Csongrád-Csanád 3.'}, coordinates: array{lat: 46.5518708, lng: 20.1064166}}, Balástya: array{constituencies: array{'Csongrád-Csanád 3.'}, coordinates: array{lat: 46.4261828, lng: 20.004933}}, Bordány: array{constituencies: array{'Csongrád-Csanád 2.'}, coordinates: array{lat: 46.3194213, lng: 19.9227063}}, ...}, Fejér: array{Aba: array{constituencies: array{'Fejér 5.'}, coordinates: array{lat: 47.0328193, lng: 18.522359}}, Adony: array{constituencies: array{'Fejér 4.'}, coordinates: array{lat: 47.119831, lng: 18.8612469}}, Alap: array{constituencies: array{'Fejér 5.'}, coordinates: array{lat: 46.8075763, lng: 18.684028}}, Alcsútdoboz: array{constituencies: array{'Fejér 3.'}, coordinates: array{lat: 47.4277067, lng: 18.6030325}}, Alsószentiván: array{constituencies: array{'Fejér 5.'}, coordinates: array{lat: 46.7910573, lng: 18.732161}}, Bakonycsernye: array{constituencies: array{'Fejér 2.'}, coordinates: array{lat: 47.321719, lng: 18.0907379}}, Bakonykúti: array{constituencies: array{'Fejér 2.'}, coordinates: array{lat: 47.2458464, lng: 18.195769}}, Balinka: array{constituencies: array{'Fejér 2.'}, coordinates: array{lat: 47.3135736, lng: 18.1907168}}, ...}, Győr-Moson-Sopron: array{Abda: array{constituencies: array{'Győr-Moson-Sopron 5.'}, coordinates: array{lat: 47.6962149, lng: 17.5445786}}, Acsalag: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.676095, lng: 17.1977771}}, Ágfalva: array{constituencies: array{'Győr-Moson-Sopron 4.'}, coordinates: array{lat: 47.688862, lng: 16.5110233}}, Agyagosszergény: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.608545, lng: 16.9409912}}, Árpás: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.5134127, lng: 17.3931579}}, Ásványráró: array{constituencies: array{'Győr-Moson-Sopron 5.'}, coordinates: array{lat: 47.8287695, lng: 17.499195}}, Babót: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.5752269, lng: 17.0758604}}, Bágyogszovát: array{constituencies: array{'Győr-Moson-Sopron 3.'}, coordinates: array{lat: 47.5866036, lng: 17.3617273}}, ...}, ...}.", 12, "Offset 'constituencies' (non-empty-list) does not accept type array{'Bács-Kiskun 4.', true, false, Bug8146bError\X, null}.", ], diff --git a/tests/PHPStan/Rules/Variables/data/bug-3391.php b/tests/PHPStan/Rules/Variables/data/bug-3391.php index bfe756a020..2d57843622 100644 --- a/tests/PHPStan/Rules/Variables/data/bug-3391.php +++ b/tests/PHPStan/Rules/Variables/data/bug-3391.php @@ -22,11 +22,11 @@ public function test() $data['foo'] = 'a'; $data['bar'] = 'b'; - assertType("hasOffsetValue('bar', 'b')&hasOffsetValue('foo', 'a')&non-empty-array", $data); + assertType("non-empty-array&hasOffsetValue('bar', 'b')&hasOffsetValue('foo', 'a')", $data); unset($data['id']); - assertType("array&hasOffsetValue('bar', 'b')&hasOffsetValue('foo', 'a')", $data); + assertType("non-empty-array&hasOffsetValue('bar', 'b')&hasOffsetValue('foo', 'a')", $data); return $data; } } diff --git a/tests/PHPStan/Rules/Variables/data/bug-7417.php b/tests/PHPStan/Rules/Variables/data/bug-7417.php index 24fb2c4a7f..fcf698a9ec 100644 --- a/tests/PHPStan/Rules/Variables/data/bug-7417.php +++ b/tests/PHPStan/Rules/Variables/data/bug-7417.php @@ -20,9 +20,9 @@ function doFoo() { // in core.extension so this will come before it's base theme. $extensions['theme']['test_subtheme'] = 0; $extensions['theme']['test_subsubtheme'] = 0; - assertType("hasOffsetValue('theme', mixed)&non-empty-array", $extensions); + assertType("non-empty-array&hasOffsetValue('theme', mixed)", $extensions); unset($extensions['theme']['test_basetheme']); unset($extensions['theme']['test_subsubtheme']); unset($extensions['theme']['test_subtheme']); - assertType("hasOffsetValue('theme', mixed)&non-empty-array", $extensions); + assertType("non-empty-array&hasOffsetValue('theme', mixed)", $extensions); } diff --git a/tests/PHPStan/Rules/Variables/data/bug-8113.php b/tests/PHPStan/Rules/Variables/data/bug-8113.php index 97b5841941..27ebe729ae 100644 --- a/tests/PHPStan/Rules/Variables/data/bug-8113.php +++ b/tests/PHPStan/Rules/Variables/data/bug-8113.php @@ -26,23 +26,23 @@ function () { array_key_exists('review', $review['SurveyInvitation']) && $review['SurveyInvitation']['review'] === null ) { - assertType("array>&hasOffsetValue('SurveyInvitation', array&hasOffsetValue('review', null))", $review); + assertType("non-empty-array>&hasOffsetValue('SurveyInvitation', non-empty-array&hasOffsetValue('review', null))", $review); $review['Review'] = [ 'id' => null, 'text' => null, 'answer' => null, ]; - assertType("non-empty-array>&hasOffsetValue('Review', array{id: null, text: null, answer: null})&hasOffsetValue('SurveyInvitation', array&hasOffsetValue('review', null))", $review); + assertType("non-empty-array>&hasOffsetValue('Review', array{id: null, text: null, answer: null})&hasOffsetValue('SurveyInvitation', non-empty-array&hasOffsetValue('review', null))", $review); unset($review['SurveyInvitation']['review']); assertType("non-empty-array>&hasOffsetValue('Review', array)&hasOffsetValue('SurveyInvitation', array)", $review); } assertType('array>', $review); if (array_key_exists('User', $review['Review'])) { - assertType("array>&hasOffsetValue('Review', array&hasOffset('User'))", $review); + assertType("non-empty-array>&hasOffsetValue('Review', non-empty-array&hasOffset('User'))", $review); $review['User'] = $review['Review']['User']; - assertType("hasOffsetValue('Review', array&hasOffset('User'))&hasOffsetValue('User', mixed)&non-empty-array", $review); + assertType("non-empty-array&hasOffsetValue('Review', non-empty-array&hasOffset('User'))&hasOffsetValue('User', mixed)", $review); unset($review['Review']['User']); - assertType("hasOffsetValue('Review', array)&hasOffsetValue('User', array)&non-empty-array", $review); + assertType("non-empty-array&hasOffsetValue('Review', array)&hasOffsetValue('User', array)", $review); } - assertType("array&hasOffsetValue('Review', array)", $review); + assertType("non-empty-array&hasOffsetValue('Review', array)", $review); }; diff --git a/tests/PHPStan/Type/IntersectionTypeTest.php b/tests/PHPStan/Type/IntersectionTypeTest.php index 7648a80ae9..c5111cbeae 100644 --- a/tests/PHPStan/Type/IntersectionTypeTest.php +++ b/tests/PHPStan/Type/IntersectionTypeTest.php @@ -436,7 +436,7 @@ public function dataDescribe(): iterable new NonEmptyArrayType(), ]), VerbosityLevel::value(), - 'non-empty-list', + 'non-empty-list', ]; yield [ @@ -491,6 +491,221 @@ public function dataDescribe(): iterable VerbosityLevel::value(), 'non-empty-array', ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new IntegerType()), + new AccessoryArrayListType(), + ]), + VerbosityLevel::typeOnly(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new IntegerType()), + new AccessoryArrayListType(), + ]), + VerbosityLevel::value(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new AccessoryArrayListType(), + ]), + VerbosityLevel::typeOnly(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new AccessoryArrayListType(), + ]), + VerbosityLevel::value(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new AccessoryArrayListType(), + ]), + VerbosityLevel::typeOnly(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new AccessoryArrayListType(), + ]), + VerbosityLevel::value(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + VerbosityLevel::typeOnly(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + VerbosityLevel::typeOnly(), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new NonEmptyArrayType(), + ]), + VerbosityLevel::typeOnly(), + 'array', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-array', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new NonEmptyArrayType(), + ]), + VerbosityLevel::typeOnly(), + 'array', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-array', + ]; + + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new NonEmptyArrayType(), + new OversizedArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-array', + ]; + + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new NonEmptyArrayType(), + new OversizedArrayType(), + ]), + VerbosityLevel::precise(), + 'non-empty-array&oversized-array', + ]; + + $constantArrayWithOptionalKeys = new ConstantArrayType([ + new ConstantIntegerType(0), + new ConstantIntegerType(1), + new ConstantIntegerType(2), + new ConstantIntegerType(3), + ], [ + new StringType(), + new StringType(), + new StringType(), + new StringType(), + ], [3], [2, 3], TrinaryLogic::createMaybe()); + + yield [ + new IntersectionType([ + $constantArrayWithOptionalKeys, + new AccessoryArrayListType(), + ]), + VerbosityLevel::typeOnly(), + 'list', + ]; + + yield [ + new IntersectionType([ + $constantArrayWithOptionalKeys, + new AccessoryArrayListType(), + ]), + VerbosityLevel::value(), + 'list{0: string, 1: string, 2?: string, 3?: string}', + ]; + + yield [ + new IntersectionType([ + $constantArrayWithOptionalKeys, + new AccessoryArrayListType(), + ]), + VerbosityLevel::precise(), + 'list{0: string, 1: string, 2?: string, 3?: string}', + ]; + + $constantArrayWithAllOptionalKeys = new ConstantArrayType([ + new ConstantIntegerType(0), + new ConstantIntegerType(1), + new ConstantIntegerType(2), + new ConstantIntegerType(3), + ], [ + new StringType(), + new StringType(), + new StringType(), + new StringType(), + ], [3], [0, 1, 2, 3], TrinaryLogic::createMaybe()); + + yield [ + new IntersectionType([ + $constantArrayWithAllOptionalKeys, + new AccessoryArrayListType(), + ]), + VerbosityLevel::value(), + 'list{0?: string, 1?: string, 2?: string, 3?: string}', + ]; + + yield [ + new IntersectionType([ + $constantArrayWithAllOptionalKeys, + new NonEmptyArrayType(), + new AccessoryArrayListType(), + ]), + VerbosityLevel::value(), + 'non-empty-list{0?: string, 1?: string, 2?: string, 3?: string}', + ]; + + yield [ + new IntersectionType([ + $constantArrayWithAllOptionalKeys, + new NonEmptyArrayType(), + ]), + VerbosityLevel::value(), + 'non-empty-array{0?: string, 1?: string, 2?: string, 3?: string}', + ]; } /** diff --git a/tests/PHPStan/Type/TypeCombinatorTest.php b/tests/PHPStan/Type/TypeCombinatorTest.php index 6084574e73..2694d0f3eb 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -965,7 +965,7 @@ public function dataUnion(): iterable ]), ], IntersectionType::class, - 'array&hasOffsetValue(\'foo\', mixed)', + 'non-empty-array&hasOffsetValue(\'foo\', mixed)', ], [ [ @@ -2267,7 +2267,7 @@ public function dataUnion(): iterable TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new HasOffsetValueType(new ConstantStringType('a'), new IntegerType())), ], IntersectionType::class, - 'array&hasOffsetValue(\'a\', int)', + 'non-empty-array&hasOffsetValue(\'a\', int)', ]; yield [ @@ -2288,7 +2288,7 @@ public function dataUnion(): iterable ]), ], IntersectionType::class, - "array&hasOffsetValue('a', mixed)", + "non-empty-array&hasOffsetValue('a', mixed)", ]; yield [ @@ -2315,7 +2315,7 @@ public function dataUnion(): iterable ]), ], IntersectionType::class, - "array&hasOffsetValue(0, array&hasOffsetValue('code', mixed))", + "non-empty-array&hasOffsetValue(0, non-empty-array&hasOffsetValue('code', mixed))", ]; yield [ @@ -2513,7 +2513,7 @@ public function dataUnion(): iterable ]), ], UnionType::class, - 'array{a?: true, b: true}|(array{a?: true, c?: true}&non-empty-array)', + 'array{a?: true, b: true}|non-empty-array{a?: true, c?: true}', ]; yield [ @@ -2600,7 +2600,7 @@ public function dataUnion(): iterable ]), ], IntersectionType::class, - 'array&hasOffsetValue(\'thing\', mixed)', + 'non-empty-array&hasOffsetValue(\'thing\', mixed)', ]; } @@ -3109,7 +3109,7 @@ public function dataIntersect(): iterable new HasOffsetType(new ConstantStringType('a')), ], IntersectionType::class, - 'array&hasOffset(\'a\')', + 'non-empty-array&hasOffset(\'a\')', ], [ [ @@ -3118,7 +3118,7 @@ public function dataIntersect(): iterable new HasOffsetType(new ConstantStringType('a')), ], IntersectionType::class, - 'array&hasOffset(\'a\')', + 'non-empty-array&hasOffset(\'a\')', ], [ [ @@ -3267,7 +3267,7 @@ public function dataIntersect(): iterable ]), ], IntersectionType::class, - 'array&hasOffset(\'bar\')&hasOffset(\'foo\')', + 'non-empty-array&hasOffset(\'bar\')&hasOffset(\'foo\')', ], [ [ @@ -4047,7 +4047,7 @@ public function dataIntersect(): iterable TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new HasOffsetValueType(new ConstantStringType('a'), new IntegerType())), ], IntersectionType::class, - 'array&hasOffsetValue(\'a\', 1)', + 'non-empty-array&hasOffsetValue(\'a\', 1)', ]; yield [ [ @@ -4207,7 +4207,7 @@ public function dataIntersect(): iterable new NonEmptyArrayType(), ], UnionType::class, - 'array{a?: true, b: true}|(array{a?: true, c?: true}&non-empty-array)', + 'array{a?: true, b: true}|non-empty-array{a?: true, c?: true}', ]; yield [ [ @@ -4243,7 +4243,7 @@ public function dataIntersect(): iterable new NonEmptyArrayType(), ], IntersectionType::class, - 'array{a?: true, c?: true}&non-empty-array', + 'non-empty-array{a?: true, c?: true}', ]; yield [ [ diff --git a/tests/PHPStan/Type/TypeToPhpDocNodeTest.php b/tests/PHPStan/Type/TypeToPhpDocNodeTest.php index eebdb08014..ffb42f1edf 100644 --- a/tests/PHPStan/Type/TypeToPhpDocNodeTest.php +++ b/tests/PHPStan/Type/TypeToPhpDocNodeTest.php @@ -4,6 +4,7 @@ use PHPStan\PhpDoc\TypeStringResolver; use PHPStan\Testing\PHPStanTestCase; +use PHPStan\TrinaryLogic; use PHPStan\Type\Accessory\AccessoryArrayListType; use PHPStan\Type\Accessory\AccessoryLiteralStringType; use PHPStan\Type\Accessory\AccessoryLowercaseStringType; @@ -265,7 +266,7 @@ public function dataToPhpDocNode(): iterable yield [ new IntersectionType([new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), new AccessoryArrayListType()]), - 'list', + 'list', ]; yield [ @@ -274,7 +275,7 @@ public function dataToPhpDocNode(): iterable new NonEmptyArrayType(), new AccessoryArrayListType(), ]), - 'non-empty-list', + 'non-empty-list', ]; yield [ @@ -309,6 +310,122 @@ public function dataToPhpDocNode(): iterable ], [2], [1]), "array{0: 'foo', 1?: 'bar'}", ]; + + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new IntegerType()), + new AccessoryArrayListType(), + ]), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), + new AccessoryArrayListType(), + ]), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType(true)), + new AccessoryArrayListType(), + ]), + 'list', + ]; + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType()), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + 'non-empty-list', + ]; + yield [ + new IntersectionType([ + new ArrayType(IntegerRangeType::createAllGreaterThanOrEqualTo(0), new MixedType(true)), + new AccessoryArrayListType(), + new NonEmptyArrayType(), + ]), + 'non-empty-list', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType()), + new NonEmptyArrayType(), + ]), + 'non-empty-array', + ]; + yield [ + new IntersectionType([ + new ArrayType(new MixedType(), new MixedType(true)), + new NonEmptyArrayType(), + ]), + 'non-empty-array', + ]; + $constantArrayWithOptionalKeys = new ConstantArrayType([ + new ConstantIntegerType(0), + new ConstantIntegerType(1), + new ConstantIntegerType(2), + new ConstantIntegerType(3), + ], [ + new StringType(), + new StringType(), + new StringType(), + new StringType(), + ], [3], [2, 3], TrinaryLogic::createMaybe()); + + yield [ + new IntersectionType([ + $constantArrayWithOptionalKeys, + new AccessoryArrayListType(), + ]), + 'list{0: string, 1: string, 2?: string, 3?: string}', + ]; + + yield [ + new IntersectionType([ + $constantArrayWithOptionalKeys, + new AccessoryArrayListType(), + ]), + 'list{0: string, 1: string, 2?: string, 3?: string}', + ]; + + $constantArrayWithAllOptionalKeys = new ConstantArrayType([ + new ConstantIntegerType(0), + new ConstantIntegerType(1), + new ConstantIntegerType(2), + new ConstantIntegerType(3), + ], [ + new StringType(), + new StringType(), + new StringType(), + new StringType(), + ], [3], [0, 1, 2, 3], TrinaryLogic::createMaybe()); + + yield [ + new IntersectionType([ + $constantArrayWithAllOptionalKeys, + new AccessoryArrayListType(), + ]), + 'list{0?: string, 1?: string, 2?: string, 3?: string}', + ]; + + yield [ + new IntersectionType([ + $constantArrayWithAllOptionalKeys, + new NonEmptyArrayType(), + new AccessoryArrayListType(), + ]), + 'non-empty-list{0?: string, 1?: string, 2?: string, 3?: string}', + ]; + + yield [ + new IntersectionType([ + $constantArrayWithAllOptionalKeys, + new NonEmptyArrayType(), + ]), + 'non-empty-array{0?: string, 1?: string, 2?: string, 3?: string}', + ]; } /** From 70f319a25cc75cbb22288674108cf3212b6fe735 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 13 Oct 2024 17:01:59 +0200 Subject: [PATCH 404/508] StubParser --- conf/config.stubValidator.neon | 6 ++++ src/Parser/StubParser.php | 56 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/Parser/StubParser.php diff --git a/conf/config.stubValidator.neon b/conf/config.stubValidator.neon index 07390c7b8f..74e943d911 100644 --- a/conf/config.stubValidator.neon +++ b/conf/config.stubValidator.neon @@ -11,6 +11,12 @@ services: arguments: php8Parser: @php8PhpParser + defaultAnalysisParser: + class: PHPStan\Parser\StubParser + arguments!: + parser: @php8PhpParser + autowired: false + nodeScopeResolverReflector: factory: @stubReflector diff --git a/src/Parser/StubParser.php b/src/Parser/StubParser.php new file mode 100644 index 0000000000..d98a2cc721 --- /dev/null +++ b/src/Parser/StubParser.php @@ -0,0 +1,56 @@ +parseString(FileReader::read($file)); + } catch (ParserErrorsException $e) { + throw new ParserErrorsException($e->getErrors(), $file); + } + } + + /** + * @return Node\Stmt[] + */ + public function parseString(string $sourceCode): array + { + $errorHandler = new Collecting(); + $nodes = $this->parser->parse($sourceCode, $errorHandler); + if ($errorHandler->hasErrors()) { + throw new ParserErrorsException($errorHandler->getErrors(), null); + } + if ($nodes === null) { + throw new ShouldNotHappenException(); + } + + $nodeTraverser = new NodeTraverser(); + $nodeTraverser->addVisitor($this->nameResolver); + + /** @var array */ + return $nodeTraverser->traverse($nodes); + } + +} From b651a22caedaf13cfa29fe62ad38d7cc41ba0d88 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 13 Oct 2024 17:07:10 +0200 Subject: [PATCH 405/508] Fix tests --- tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php | 2 +- tests/PHPStan/Analyser/nsrt/array-column.php | 8 ++++---- tests/PHPStan/Analyser/nsrt/array-fill-keys-php7.php | 2 +- tests/PHPStan/Analyser/nsrt/array-flip-php7.php | 2 +- tests/PHPStan/Analyser/nsrt/array-intersect-key-php7.php | 2 +- tests/PHPStan/Analyser/nsrt/array-search-php7.php | 2 +- tests/PHPStan/Analyser/nsrt/array_keys-php7.php | 2 +- tests/PHPStan/Analyser/nsrt/array_values-php7.php | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php index e97a5f4a06..8338e6f13c 100644 --- a/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php @@ -4264,7 +4264,7 @@ public function dataAnonymousFunction(): array '$str', ], [ - PHP_VERSION_ID < 80000 ? 'list' : 'array', + PHP_VERSION_ID < 80000 ? 'list' : 'array', '$arr', ], [ diff --git a/tests/PHPStan/Analyser/nsrt/array-column.php b/tests/PHPStan/Analyser/nsrt/array-column.php index 2455d6ace9..017490d534 100644 --- a/tests/PHPStan/Analyser/nsrt/array-column.php +++ b/tests/PHPStan/Analyser/nsrt/array-column.php @@ -189,7 +189,7 @@ public function testImprecise5(array $array): void assertType('list', array_column($array, 'nodeName')); assertType('array', array_column($array, 'nodeName', 'tagName')); assertType('array', array_column($array, null, 'tagName')); - assertType('list', array_column($array, 'foo')); + assertType('list', array_column($array, 'foo')); assertType('array', array_column($array, 'foo', 'tagName')); assertType('array', array_column($array, 'nodeName', 'foo')); assertType('array', array_column($array, null, 'foo')); @@ -201,7 +201,7 @@ public function testObjects1(array $array): void assertType('non-empty-list', array_column($array, 'nodeName')); assertType('non-empty-array', array_column($array, 'nodeName', 'tagName')); assertType('non-empty-array', array_column($array, null, 'tagName')); - assertType('list', array_column($array, 'foo')); + assertType('list', array_column($array, 'foo')); assertType('array', array_column($array, 'foo', 'tagName')); assertType('non-empty-array', array_column($array, 'nodeName', 'foo')); assertType('non-empty-array', array_column($array, null, 'foo')); @@ -213,7 +213,7 @@ public function testObjects2(array $array): void assertType('array{string}', array_column($array, 'nodeName')); assertType('non-empty-array', array_column($array, 'nodeName', 'tagName')); assertType('non-empty-array', array_column($array, null, 'tagName')); - assertType('list', array_column($array, 'foo')); + assertType('list', array_column($array, 'foo')); assertType('array', array_column($array, 'foo', 'tagName')); assertType('non-empty-array', array_column($array, 'nodeName', 'foo')); assertType('non-empty-array', array_column($array, null, 'foo')); @@ -227,7 +227,7 @@ final class Foo /** @param array $a */ public function doFoo(array $a): void { - assertType('list', array_column($a, 'nodeName')); + assertType('list', array_column($a, 'nodeName')); assertType('array', array_column($a, 'nodeName', 'tagName')); } diff --git a/tests/PHPStan/Analyser/nsrt/array-fill-keys-php7.php b/tests/PHPStan/Analyser/nsrt/array-fill-keys-php7.php index 7bbc485b5a..c0a4e8dd7a 100644 --- a/tests/PHPStan/Analyser/nsrt/array-fill-keys-php7.php +++ b/tests/PHPStan/Analyser/nsrt/array-fill-keys-php7.php @@ -7,7 +7,7 @@ function mixedAndSubtractedArray($mixed): void { if (is_array($mixed)) { - assertType("array<'b'>", array_fill_keys($mixed, 'b')); + assertType("array", array_fill_keys($mixed, 'b')); } else { assertType("null", array_fill_keys($mixed, 'b')); } diff --git a/tests/PHPStan/Analyser/nsrt/array-flip-php7.php b/tests/PHPStan/Analyser/nsrt/array-flip-php7.php index 0b7058de01..f62e1a6628 100644 --- a/tests/PHPStan/Analyser/nsrt/array-flip-php7.php +++ b/tests/PHPStan/Analyser/nsrt/array-flip-php7.php @@ -9,7 +9,7 @@ function mixedAndSubtractedArray($mixed) if (is_array($mixed)) { assertType('array', array_flip($mixed)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('null', array_flip($mixed)); } } diff --git a/tests/PHPStan/Analyser/nsrt/array-intersect-key-php7.php b/tests/PHPStan/Analyser/nsrt/array-intersect-key-php7.php index 79b7af7b18..14dd7b5d0d 100644 --- a/tests/PHPStan/Analyser/nsrt/array-intersect-key-php7.php +++ b/tests/PHPStan/Analyser/nsrt/array-intersect-key-php7.php @@ -16,7 +16,7 @@ public function mixedAndSubtractedArray($mixed, array $otherArrs): void /** @var array $otherArrs */ assertType('array', array_intersect_key($mixed, $otherArrs)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); /** @var array $otherArrs */ assertType('null', array_intersect_key($mixed, $otherArrs)); /** @var array $otherArrs */ diff --git a/tests/PHPStan/Analyser/nsrt/array-search-php7.php b/tests/PHPStan/Analyser/nsrt/array-search-php7.php index 2cd24b7c9d..5816daf659 100644 --- a/tests/PHPStan/Analyser/nsrt/array-search-php7.php +++ b/tests/PHPStan/Analyser/nsrt/array-search-php7.php @@ -16,7 +16,7 @@ public function mixedAndSubtractedArray($mixed, string $string): void assertType('int|string|false', array_search('foo', $mixed)); assertType('int|string|false', array_search($string, $mixed, true)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('null', array_search('foo', $mixed, true)); assertType('null', array_search('foo', $mixed)); assertType('null', array_search($string, $mixed, true)); diff --git a/tests/PHPStan/Analyser/nsrt/array_keys-php7.php b/tests/PHPStan/Analyser/nsrt/array_keys-php7.php index 103cb0a003..9f5ca43682 100644 --- a/tests/PHPStan/Analyser/nsrt/array_keys-php7.php +++ b/tests/PHPStan/Analyser/nsrt/array_keys-php7.php @@ -12,7 +12,7 @@ public function sayHello($mixed): void if (is_array($mixed)) { assertType('list<(int|string)>', array_keys($mixed)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('null', array_keys($mixed)); } } diff --git a/tests/PHPStan/Analyser/nsrt/array_values-php7.php b/tests/PHPStan/Analyser/nsrt/array_values-php7.php index 10de823980..db378c95aa 100644 --- a/tests/PHPStan/Analyser/nsrt/array_values-php7.php +++ b/tests/PHPStan/Analyser/nsrt/array_values-php7.php @@ -12,7 +12,7 @@ public function foo1($mixed): void if (is_array($mixed)) { assertType('list', array_values($mixed)); } else { - assertType('mixed~array', $mixed); + assertType('mixed~array', $mixed); assertType('null', array_values($mixed)); } } From 7ed2d67fa4db81323e4957894416be84a1022115 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 13 Oct 2024 17:14:22 +0200 Subject: [PATCH 406/508] Fix tests --- tests/PHPStan/Levels/data/acceptTypes-5.json | 4 ++-- tests/PHPStan/Levels/data/arrayDestructuring-8.json | 4 ++-- tests/PHPStan/Levels/data/arrayDimFetches-8.json | 4 ++-- tests/PHPStan/Levels/data/casts-7.json | 6 +++--- tests/PHPStan/Levels/data/echo_-2.json | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/PHPStan/Levels/data/acceptTypes-5.json b/tests/PHPStan/Levels/data/acceptTypes-5.json index 88d4749a45..76aac5c080 100644 --- a/tests/PHPStan/Levels/data/acceptTypes-5.json +++ b/tests/PHPStan/Levels/data/acceptTypes-5.json @@ -180,7 +180,7 @@ "ignorable": true }, { - "message": "Parameter #1 $nonEmpty of method Levels\\AcceptTypes\\AcceptNonEmpty::doBar() expects non-empty-array, array{} given.", + "message": "Parameter #1 $nonEmpty of method Levels\\AcceptTypes\\AcceptNonEmpty::doBar() expects non-empty-array, array{} given.", "line": 733, "ignorable": true }, @@ -189,4 +189,4 @@ "line": 763, "ignorable": true } -] \ No newline at end of file +] diff --git a/tests/PHPStan/Levels/data/arrayDestructuring-8.json b/tests/PHPStan/Levels/data/arrayDestructuring-8.json index 7842bce806..3b033abd6d 100644 --- a/tests/PHPStan/Levels/data/arrayDestructuring-8.json +++ b/tests/PHPStan/Levels/data/arrayDestructuring-8.json @@ -1,7 +1,7 @@ [ { - "message": "Cannot use array destructuring on array|null.", + "message": "Cannot use array destructuring on array|null.", "line": 15, "ignorable": true } -] \ No newline at end of file +] diff --git a/tests/PHPStan/Levels/data/arrayDimFetches-8.json b/tests/PHPStan/Levels/data/arrayDimFetches-8.json index 07568e3768..e7e6efcd13 100644 --- a/tests/PHPStan/Levels/data/arrayDimFetches-8.json +++ b/tests/PHPStan/Levels/data/arrayDimFetches-8.json @@ -1,6 +1,6 @@ [ { - "message": "Offset 0 might not exist on array|null.", + "message": "Offset 0 might not exist on array|null.", "line": 15, "ignorable": true }, @@ -9,4 +9,4 @@ "line": 50, "ignorable": true } -] \ No newline at end of file +] diff --git a/tests/PHPStan/Levels/data/casts-7.json b/tests/PHPStan/Levels/data/casts-7.json index d9b7a85b78..e2810b0e42 100644 --- a/tests/PHPStan/Levels/data/casts-7.json +++ b/tests/PHPStan/Levels/data/casts-7.json @@ -1,12 +1,12 @@ [ { - "message": "Cannot cast array|(callable(): mixed) to int.", + "message": "Cannot cast array|(callable(): mixed) to int.", "line": 20, "ignorable": true }, { - "message": "Cannot cast array|float|int to string.", + "message": "Cannot cast array|float|int to string.", "line": 21, "ignorable": true } -] \ No newline at end of file +] diff --git a/tests/PHPStan/Levels/data/echo_-2.json b/tests/PHPStan/Levels/data/echo_-2.json index 1c35f8ef7c..1e30f3b562 100644 --- a/tests/PHPStan/Levels/data/echo_-2.json +++ b/tests/PHPStan/Levels/data/echo_-2.json @@ -1,6 +1,6 @@ [ { - "message": "Parameter #1 (array) of echo cannot be converted to string.", + "message": "Parameter #1 (array) of echo cannot be converted to string.", "line": 21, "ignorable": true }, @@ -9,4 +9,4 @@ "line": 21, "ignorable": true } -] \ No newline at end of file +] From 0ce1ce53ff55d9ab0a0bae7f28326167bcc5aebb Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 13 Oct 2024 17:22:20 +0200 Subject: [PATCH 407/508] Use StubParser more --- conf/config.neon | 8 +++++++- conf/config.stubValidator.neon | 7 ++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index d71fbfbdfd..4823b1c90e 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1944,7 +1944,7 @@ services: stubPhpDocProvider: class: PHPStan\PhpDoc\StubPhpDocProvider arguments: - parser: @defaultAnalysisParser + parser: @stubParser # Reflection providers @@ -2045,6 +2045,12 @@ services: php8Parser: @php8Parser autowired: false + stubParser: + class: PHPStan\Parser\StubParser + arguments: + parser: @php8PhpParser + autowired: false + phpstanDiagnoseExtension: class: PHPStan\Diagnose\PHPStanDiagnoseExtension arguments: diff --git a/conf/config.stubValidator.neon b/conf/config.stubValidator.neon index 74e943d911..52eac72312 100644 --- a/conf/config.stubValidator.neon +++ b/conf/config.stubValidator.neon @@ -11,11 +11,8 @@ services: arguments: php8Parser: @php8PhpParser - defaultAnalysisParser: - class: PHPStan\Parser\StubParser - arguments!: - parser: @php8PhpParser - autowired: false + defaultAnalysisParser!: + factory: @stubParser nodeScopeResolverReflector: factory: @stubReflector From 8285a25d90f242bde0aaed94f215713446c4a664 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 13 Oct 2024 17:24:36 +0200 Subject: [PATCH 408/508] Fix tests --- tests/PHPStan/Levels/data/acceptTypes-7.json | 8 ++++---- tests/PHPStan/Levels/data/echo_-2.json | 2 +- tests/PHPStan/Levels/data/iterable-7.json | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/PHPStan/Levels/data/acceptTypes-7.json b/tests/PHPStan/Levels/data/acceptTypes-7.json index 9e0afc2f64..92912a0f9e 100644 --- a/tests/PHPStan/Levels/data/acceptTypes-7.json +++ b/tests/PHPStan/Levels/data/acceptTypes-7.json @@ -85,7 +85,7 @@ "ignorable": true }, { - "message": "Parameter #1 $array of method Levels\\AcceptTypes\\Baz::requireArray() expects array, array|Levels\\AcceptTypes\\Foo given.", + "message": "Parameter #1 $array of method Levels\\AcceptTypes\\Baz::requireArray() expects array, array|Levels\\AcceptTypes\\Foo given.", "line": 531, "ignorable": true }, @@ -95,7 +95,7 @@ "ignorable": true }, { - "message": "Parameter #1 $array of method Levels\\AcceptTypes\\Baz::requireArray() expects array, array|Levels\\AcceptTypes\\Foo given.", + "message": "Parameter #1 $array of method Levels\\AcceptTypes\\Baz::requireArray() expects array, array|Levels\\AcceptTypes\\Foo given.", "line": 542, "ignorable": true }, @@ -160,7 +160,7 @@ "ignorable": true }, { - "message": "Parameter #1 $nonEmpty of method Levels\\AcceptTypes\\AcceptNonEmpty::doBar() expects non-empty-array, array given.", + "message": "Parameter #1 $nonEmpty of method Levels\\AcceptTypes\\AcceptNonEmpty::doBar() expects non-empty-array, array given.", "line": 735, "ignorable": true }, @@ -169,4 +169,4 @@ "line": 756, "ignorable": true } -] \ No newline at end of file +] diff --git a/tests/PHPStan/Levels/data/echo_-2.json b/tests/PHPStan/Levels/data/echo_-2.json index 1e30f3b562..330e326e8e 100644 --- a/tests/PHPStan/Levels/data/echo_-2.json +++ b/tests/PHPStan/Levels/data/echo_-2.json @@ -5,7 +5,7 @@ "ignorable": true }, { - "message": "Parameter #2 (array|(callable(): mixed)) of echo cannot be converted to string.", + "message": "Parameter #2 (array|(callable(): mixed)) of echo cannot be converted to string.", "line": 21, "ignorable": true } diff --git a/tests/PHPStan/Levels/data/iterable-7.json b/tests/PHPStan/Levels/data/iterable-7.json index 74440d64d8..5c3c24924d 100644 --- a/tests/PHPStan/Levels/data/iterable-7.json +++ b/tests/PHPStan/Levels/data/iterable-7.json @@ -1,7 +1,7 @@ [ { - "message": "Argument of an invalid type array|false supplied for foreach, only iterables are supported.", + "message": "Argument of an invalid type array|false supplied for foreach, only iterables are supported.", "line": 35, "ignorable": true } -] \ No newline at end of file +] From 1aec4300794594d8f87a6e018070ccdf955fd0ef Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 13 Oct 2024 17:29:24 +0200 Subject: [PATCH 409/508] Fixed types --- tests/PHPStan/Levels/data/acceptTypes-7.json | 6 +++--- tests/PHPStan/Levels/data/echo_-7.json | 6 +++--- tests/PHPStan/Levels/data/iterable-8.json | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/PHPStan/Levels/data/acceptTypes-7.json b/tests/PHPStan/Levels/data/acceptTypes-7.json index 92912a0f9e..ba67e6a9d6 100644 --- a/tests/PHPStan/Levels/data/acceptTypes-7.json +++ b/tests/PHPStan/Levels/data/acceptTypes-7.json @@ -95,12 +95,12 @@ "ignorable": true }, { - "message": "Parameter #1 $array of method Levels\\AcceptTypes\\Baz::requireArray() expects array, array|Levels\\AcceptTypes\\Foo given.", + "message": "Parameter #1 $array of method Levels\\AcceptTypes\\Baz::requireArray() expects array, array|Levels\\AcceptTypes\\Foo given.", "line": 542, "ignorable": true }, { - "message": "Parameter #1 $foo of method Levels\\AcceptTypes\\Baz::requireFoo() expects Levels\\AcceptTypes\\Foo, array|Levels\\AcceptTypes\\Foo given.", + "message": "Parameter #1 $foo of method Levels\\AcceptTypes\\Baz::requireFoo() expects Levels\\AcceptTypes\\Foo, array|Levels\\AcceptTypes\\Foo given.", "line": 543, "ignorable": true }, @@ -160,7 +160,7 @@ "ignorable": true }, { - "message": "Parameter #1 $nonEmpty of method Levels\\AcceptTypes\\AcceptNonEmpty::doBar() expects non-empty-array, array given.", + "message": "Parameter #1 $nonEmpty of method Levels\\AcceptTypes\\AcceptNonEmpty::doBar() expects non-empty-array, array given.", "line": 735, "ignorable": true }, diff --git a/tests/PHPStan/Levels/data/echo_-7.json b/tests/PHPStan/Levels/data/echo_-7.json index 3f32efd774..275583f027 100644 --- a/tests/PHPStan/Levels/data/echo_-7.json +++ b/tests/PHPStan/Levels/data/echo_-7.json @@ -1,12 +1,12 @@ [ { - "message": "Parameter #3 (array|float|int) of echo cannot be converted to string.", + "message": "Parameter #3 (array|float|int) of echo cannot be converted to string.", "line": 21, "ignorable": true }, { - "message": "Parameter #4 (array|string) of echo cannot be converted to string.", + "message": "Parameter #4 (array|string) of echo cannot be converted to string.", "line": 21, "ignorable": true } -] \ No newline at end of file +] diff --git a/tests/PHPStan/Levels/data/iterable-8.json b/tests/PHPStan/Levels/data/iterable-8.json index 17e368b276..0a46f4b75e 100644 --- a/tests/PHPStan/Levels/data/iterable-8.json +++ b/tests/PHPStan/Levels/data/iterable-8.json @@ -1,7 +1,7 @@ [ { - "message": "Argument of an invalid type array|null supplied for foreach, only iterables are supported.", + "message": "Argument of an invalid type array|null supplied for foreach, only iterables are supported.", "line": 26, "ignorable": true } -] \ No newline at end of file +] From 428ef84a20ba1a2a2f7bfd12dc9aacb0e5c62e7d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 14 Oct 2024 04:54:38 +0200 Subject: [PATCH 410/508] Separate FileTypeMapper for StubPhpDocProvider --- conf/config.neon | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/conf/config.neon b/conf/config.neon index 4823b1c90e..1e64b54187 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1032,6 +1032,12 @@ services: arguments: phpParser: @defaultAnalysisParser + stubFileTypeMapper: + class: PHPStan\Type\FileTypeMapper + arguments: + phpParser: @stubParser + autowired: false + - class: PHPStan\Type\TypeAliasResolver factory: PHPStan\Type\UsefulTypeAliasResolver @@ -1945,6 +1951,7 @@ services: class: PHPStan\PhpDoc\StubPhpDocProvider arguments: parser: @stubParser + fileTypeMapper: @stubFileTypeMapper # Reflection providers @@ -2045,12 +2052,19 @@ services: php8Parser: @php8Parser autowired: false - stubParser: + freshStubParser: class: PHPStan\Parser\StubParser arguments: parser: @php8PhpParser autowired: false + stubParser: + class: PHPStan\Parser\CachedParser + arguments: + originalParser: @freshStubParser + cachedNodesByStringCountMax: %cache.nodesByStringCountMax% + autowired: false + phpstanDiagnoseExtension: class: PHPStan\Diagnose\PHPStanDiagnoseExtension arguments: From aa75de05bdb6fcccded87b6e825a32a0e19f6914 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 14 Oct 2024 04:55:48 +0200 Subject: [PATCH 411/508] Fixed tests --- tests/PHPStan/Levels/data/print_-2.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/PHPStan/Levels/data/print_-2.json b/tests/PHPStan/Levels/data/print_-2.json index d0a53d8362..5978bf90e0 100644 --- a/tests/PHPStan/Levels/data/print_-2.json +++ b/tests/PHPStan/Levels/data/print_-2.json @@ -1,12 +1,12 @@ [ { - "message": "Parameter array of print cannot be converted to string.", + "message": "Parameter array of print cannot be converted to string.", "line": 21, "ignorable": true }, { - "message": "Parameter array|(callable(): mixed) of print cannot be converted to string.", + "message": "Parameter array|(callable(): mixed) of print cannot be converted to string.", "line": 22, "ignorable": true } -] \ No newline at end of file +] From fba5607a664eddb0ac9c52b7f8defd665b9c5ef3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 14 Oct 2024 05:08:56 +0200 Subject: [PATCH 412/508] Fixed tests --- tests/PHPStan/Levels/data/encapsedString-2.json | 4 ++-- tests/PHPStan/Levels/data/encapsedString-7.json | 4 ++-- tests/PHPStan/Levels/data/print_-7.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/PHPStan/Levels/data/encapsedString-2.json b/tests/PHPStan/Levels/data/encapsedString-2.json index 01ea01b977..8035809eb6 100644 --- a/tests/PHPStan/Levels/data/encapsedString-2.json +++ b/tests/PHPStan/Levels/data/encapsedString-2.json @@ -1,11 +1,11 @@ [ { - "message": "Part $array (array) of encapsed string cannot be cast to string.", + "message": "Part $array (array) of encapsed string cannot be cast to string.", "line": 21, "ignorable": true }, { - "message": "Part $arrayOrCallable (array|(callable(): mixed)) of encapsed string cannot be cast to string.", + "message": "Part $arrayOrCallable (array|(callable(): mixed)) of encapsed string cannot be cast to string.", "line": 22, "ignorable": true } diff --git a/tests/PHPStan/Levels/data/encapsedString-7.json b/tests/PHPStan/Levels/data/encapsedString-7.json index 577b87c127..c468ffbc0a 100644 --- a/tests/PHPStan/Levels/data/encapsedString-7.json +++ b/tests/PHPStan/Levels/data/encapsedString-7.json @@ -1,11 +1,11 @@ [ { - "message": "Part $arrayOrFloatOrInt (array|float|int) of encapsed string cannot be cast to string.", + "message": "Part $arrayOrFloatOrInt (array|float|int) of encapsed string cannot be cast to string.", "line": 23, "ignorable": true }, { - "message": "Part $arrayOrString (array|string) of encapsed string cannot be cast to string.", + "message": "Part $arrayOrString (array|string) of encapsed string cannot be cast to string.", "line": 24, "ignorable": true } diff --git a/tests/PHPStan/Levels/data/print_-7.json b/tests/PHPStan/Levels/data/print_-7.json index 84c94b44c4..532f660fad 100644 --- a/tests/PHPStan/Levels/data/print_-7.json +++ b/tests/PHPStan/Levels/data/print_-7.json @@ -1,11 +1,11 @@ [ { - "message": "Parameter array|float|int of print cannot be converted to string.", + "message": "Parameter array|float|int of print cannot be converted to string.", "line": 23, "ignorable": true }, { - "message": "Parameter array|string of print cannot be converted to string.", + "message": "Parameter array|string of print cannot be converted to string.", "line": 24, "ignorable": true } From cf39148cd0342a76e5ebef1f7ebbdeedb831c60c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 14 Oct 2024 08:46:52 +0200 Subject: [PATCH 413/508] Do not run integration tests on PHAR for now --- .github/workflows/phar.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index 04cda78057..28d8d8b36b 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -103,14 +103,14 @@ jobs: - name: "Delete checksum PHAR" run: "rm tmp/phpstan.phar" - - integration-tests: - if: github.event_name == 'pull_request' - needs: compiler-tests - uses: phpstan/phpstan/.github/workflows/integration-tests.yml@2.0.x - with: - ref: 2.0.x - phar-checksum: ${{needs.compiler-tests.outputs.checksum}} +# +# integration-tests: +# if: github.event_name == 'pull_request' +# needs: compiler-tests +# uses: phpstan/phpstan/.github/workflows/integration-tests.yml@2.0.x +# with: +# ref: 2.0.x +# phar-checksum: ${{needs.compiler-tests.outputs.checksum}} extension-tests: if: github.event_name == 'pull_request' From c90d966cfaff4818a65c5b1d2a2e4bb6e2dda0e0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 14 Oct 2024 11:02:49 +0200 Subject: [PATCH 414/508] Upgrading notes about 1st party extensions --- UPGRADING.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 5aae2eeb29..bc65ba774e 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -101,6 +101,17 @@ parameters: Appending `(?)` in `ignoreErrors` is not supported. +### Changes in 1st party PHPStan extensions + +* [phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine) + * Removed config parameter `searchOtherMethodsForQueryBuilderBeginning` (extension now behaves as when this was set to `true`) + * Removed config parameter `queryBuilderFastAlgorithm` (extension now behaves as when this was set to `false`) +* [phpstan-symfony](https://github.com/phpstan/phpstan-symfony) + * Removed legacy options with `_` in the name + * `container_xml_path` -> use `containerXmlPath` + * `constant_hassers` -> use `constantHassers` + * `console_application_loader` -> use `consoleApplicationLoader` + ### Docker images no longer tagged without a PHP version Tags without a PHP version are no longer published - `nightly`, `2`, `latest` are no longer updated. Instead, use `nightly-php8.3`, `2-php8.3`, `latest-php8.3`. You can replace `8.3` with PHP versions `8.0`-`8.3`. From 87b0dcc44c032a74c271b62dc0940f3ab241f743 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 15 Oct 2024 00:03:46 +0000 Subject: [PATCH 415/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 80c2c2cd1c..aac23594f0 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#a45eab9318f66864e9840379d3a1976ffe9b8d63", + "jetbrains/phpstorm-stubs": "dev-master#345cde8b2bdc981a07030c18fe7236153c824a05", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index bef8714c74..c3ff064825 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bcacbb78aee0b072323001df71bce3ba", + "content-hash": "82fbdb85736d80091ff20ba37d78546d", "packages": [ { "name": "clue/ndjson-react", @@ -1442,17 +1442,17 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "a45eab9318f66864e9840379d3a1976ffe9b8d63" + "reference": "345cde8b2bdc981a07030c18fe7236153c824a05" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/a45eab9318f66864e9840379d3a1976ffe9b8d63", - "reference": "a45eab9318f66864e9840379d3a1976ffe9b8d63", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/345cde8b2bdc981a07030c18fe7236153c824a05", + "reference": "345cde8b2bdc981a07030c18fe7236153c824a05", "shasum": "" }, "require-dev": { "friendsofphp/php-cs-fixer": "v3.61.1", - "nikic/php-parser": "v5.1.0", + "nikic/php-parser": "v5.3.1", "phpdocumentor/reflection-docblock": "5.4.1", "phpunit/phpunit": "11.3.0" }, @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-10-05T19:50:06+00:00" + "time": "2024-10-14T12:35:31+00:00" }, { "name": "nette/bootstrap", From 2f0fd8578fda941dabb90b820e2169b9bdfcfb2e Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 16 Oct 2024 10:33:00 +0200 Subject: [PATCH 416/508] Remove dead code --- bin/phpstan | 9 --------- 1 file changed, 9 deletions(-) diff --git a/bin/phpstan b/bin/phpstan index 978d755ac1..ba27551db6 100755 --- a/bin/phpstan +++ b/bin/phpstan @@ -13,15 +13,6 @@ use Symfony\Component\Console\Helper\ProgressBar; (function () { error_reporting(E_ALL); ini_set('display_errors', 'stderr'); - if (version_compare(PHP_VERSION, '7.4.0', '<')) { - // PHP earlier than 7.4.x with OpCache triggers a bug when we intercept - // custom autoloaders' reads to discover file paths. See PHPStan #4881. - ini_set('opcache.enable', 'Off'); - } - - if (PHP_VERSION_ID < 70300) { - gc_disable(); // performance boost - } define('__PHPSTAN_RUNNING__', true); From 79319b3af98491bbbfe76851753de59ad63f75c4 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Fri, 18 Oct 2024 00:19:43 +0000 Subject: [PATCH 417/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index aac23594f0..b57ec8dd52 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.11", - "phpstan/php-8-stubs": "0.4.2", + "phpstan/php-8-stubs": "0.4.3", "phpstan/phpdoc-parser": "^2.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index c3ff064825..271b9c0192 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "82fbdb85736d80091ff20ba37d78546d", + "content-hash": "66d7fc0ee35d6ebdf822a59598a3c9f1", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.2", + "version": "0.4.3", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "64fbb357f86728a3d0a06d57178bf968bcf82206" + "reference": "b30c6975205b4b51e7d8c635f57d29b869220a9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/64fbb357f86728a3d0a06d57178bf968bcf82206", - "reference": "64fbb357f86728a3d0a06d57178bf968bcf82206", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/b30c6975205b4b51e7d8c635f57d29b869220a9e", + "reference": "b30c6975205b4b51e7d8c635f57d29b869220a9e", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.2" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.3" }, - "time": "2024-10-09T07:25:55+00:00" + "time": "2024-10-18T00:19:10+00:00" }, { "name": "phpstan/phpdoc-parser", From 4b3406e420e0a3bfc796de0e62226d7cbcbb6785 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 22 Oct 2024 00:03:32 +0000 Subject: [PATCH 418/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index b57ec8dd52..fd100caeb6 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#345cde8b2bdc981a07030c18fe7236153c824a05", + "jetbrains/phpstorm-stubs": "dev-master#f8625adce08b146bf481a0f1bbee06e82a488059", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index 271b9c0192..88147fa23b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "66d7fc0ee35d6ebdf822a59598a3c9f1", + "content-hash": "b46b210764567d0dae89d02afb1c9b92", "packages": [ { "name": "clue/ndjson-react", @@ -1442,12 +1442,12 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "345cde8b2bdc981a07030c18fe7236153c824a05" + "reference": "f8625adce08b146bf481a0f1bbee06e82a488059" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/345cde8b2bdc981a07030c18fe7236153c824a05", - "reference": "345cde8b2bdc981a07030c18fe7236153c824a05", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/f8625adce08b146bf481a0f1bbee06e82a488059", + "reference": "f8625adce08b146bf481a0f1bbee06e82a488059", "shasum": "" }, "require-dev": { @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-10-14T12:35:31+00:00" + "time": "2024-10-20T18:41:15+00:00" }, { "name": "nette/bootstrap", From d73acef87f9d3ebd04bb6671d6b83755a8e62e8e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 22 Oct 2024 09:51:15 +0200 Subject: [PATCH 419/508] Fix build --- build/deprecated-8.4.neon | 7 +++++++ build/ignore-by-php-version.neon.php | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 build/deprecated-8.4.neon diff --git a/build/deprecated-8.4.neon b/build/deprecated-8.4.neon new file mode 100644 index 0000000000..6b3bd6db5e --- /dev/null +++ b/build/deprecated-8.4.neon @@ -0,0 +1,7 @@ +parameters: + ignoreErrors: + - + message: '#^Use of constant E_STRICT is deprecated\.$#' + identifier: constant.deprecated + count: 1 + path: ../src/Analyser/FileAnalyser.php diff --git a/build/ignore-by-php-version.neon.php b/build/ignore-by-php-version.neon.php index 2c808909bc..c250ea9eec 100644 --- a/build/ignore-by-php-version.neon.php +++ b/build/ignore-by-php-version.neon.php @@ -29,6 +29,10 @@ $includes[] = __DIR__ . '/datetime-php-83.neon'; } +if (PHP_VERSION_ID >= 80400) { + $includes[] = __DIR__ . '/deprecated-8.4.neon'; +} + $config = []; $config['includes'] = $includes; From b0df8498353291d982553306005b4669d50a8ff4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 26 Oct 2024 13:10:49 +0200 Subject: [PATCH 420/508] Fix CS --- src/Rules/RuleLevelHelper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php index 81d166902f..416583546f 100644 --- a/src/Rules/RuleLevelHelper.php +++ b/src/Rules/RuleLevelHelper.php @@ -21,7 +21,6 @@ use PHPStan\Type\TypeTraverser; use PHPStan\Type\TypeUtils; use PHPStan\Type\UnionType; -use PHPStan\Type\VerbosityLevel; use function count; use function sprintf; From 5797c27e0d7e943b67b717f023e2ac2fd8a25140 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 29 Oct 2024 00:03:56 +0000 Subject: [PATCH 421/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index fd100caeb6..a14b805eaa 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#f8625adce08b146bf481a0f1bbee06e82a488059", + "jetbrains/phpstorm-stubs": "dev-master#08ee6c06d3d6021399c02ae1e4e91ae2ceaf90ab", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index 88147fa23b..caf98eda55 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b46b210764567d0dae89d02afb1c9b92", + "content-hash": "092bad73652f5dc799eca247aaeb21db", "packages": [ { "name": "clue/ndjson-react", @@ -1442,12 +1442,12 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "f8625adce08b146bf481a0f1bbee06e82a488059" + "reference": "08ee6c06d3d6021399c02ae1e4e91ae2ceaf90ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/f8625adce08b146bf481a0f1bbee06e82a488059", - "reference": "f8625adce08b146bf481a0f1bbee06e82a488059", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/08ee6c06d3d6021399c02ae1e4e91ae2ceaf90ab", + "reference": "08ee6c06d3d6021399c02ae1e4e91ae2ceaf90ab", "shasum": "" }, "require-dev": { @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-10-20T18:41:15+00:00" + "time": "2024-10-28T16:40:57+00:00" }, { "name": "nette/bootstrap", From 6bd0a5fc3054326a2134ab8bd4d28814b3da16c7 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:22:40 +0000 Subject: [PATCH 422/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index a14b805eaa..28752bbba8 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.11", - "phpstan/php-8-stubs": "0.4.3", + "phpstan/php-8-stubs": "0.4.4", "phpstan/phpdoc-parser": "^2.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index caf98eda55..2c31e7e3db 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "092bad73652f5dc799eca247aaeb21db", + "content-hash": "35d6da6b01195515a7b8fcee8a2f952b", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.3", + "version": "0.4.4", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "b30c6975205b4b51e7d8c635f57d29b869220a9e" + "reference": "c42f6e278d600b219b76d20f80f8455259bcd593" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/b30c6975205b4b51e7d8c635f57d29b869220a9e", - "reference": "b30c6975205b4b51e7d8c635f57d29b869220a9e", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/c42f6e278d600b219b76d20f80f8455259bcd593", + "reference": "c42f6e278d600b219b76d20f80f8455259bcd593", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.3" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.4" }, - "time": "2024-10-18T00:19:10+00:00" + "time": "2024-11-01T00:22:02+00:00" }, { "name": "phpstan/phpdoc-parser", From 88d5b8cf0cb2da8873dc33222b5f8b4727f0756a Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 2 Nov 2024 14:34:39 +0100 Subject: [PATCH 423/508] Remove dead code in ConstantConditionRuleHelper --- src/Rules/Comparison/ConstantConditionRuleHelper.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Rules/Comparison/ConstantConditionRuleHelper.php b/src/Rules/Comparison/ConstantConditionRuleHelper.php index dc3167a38d..36b2c569d8 100644 --- a/src/Rules/Comparison/ConstantConditionRuleHelper.php +++ b/src/Rules/Comparison/ConstantConditionRuleHelper.php @@ -18,16 +18,6 @@ public function __construct( { } - public function shouldReportAlwaysTrueByDefault(Expr $expr): bool - { - return $expr instanceof Expr\BooleanNot - || $expr instanceof Expr\BinaryOp\BooleanOr - || $expr instanceof Expr\BinaryOp\BooleanAnd - || $expr instanceof Expr\Ternary - || $expr instanceof Expr\Isset_ - || $expr instanceof Expr\Empty_; - } - public function shouldSkip(Scope $scope, Expr $expr): bool { if ( From 1b4997efa65974b5a7827fe764ca14f0768a7afa Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 5 Nov 2024 00:03:15 +0000 Subject: [PATCH 424/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 28752bbba8..1afe40674c 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#08ee6c06d3d6021399c02ae1e4e91ae2ceaf90ab", + "jetbrains/phpstorm-stubs": "dev-master#1f0dca06d54cf187adb3481a9c3e7d74af01743b", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index 2c31e7e3db..4a1e51a351 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "35d6da6b01195515a7b8fcee8a2f952b", + "content-hash": "350cc72e1a307581ffc8228f105bd273", "packages": [ { "name": "clue/ndjson-react", @@ -1442,19 +1442,19 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "08ee6c06d3d6021399c02ae1e4e91ae2ceaf90ab" + "reference": "1f0dca06d54cf187adb3481a9c3e7d74af01743b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/08ee6c06d3d6021399c02ae1e4e91ae2ceaf90ab", - "reference": "08ee6c06d3d6021399c02ae1e4e91ae2ceaf90ab", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/1f0dca06d54cf187adb3481a9c3e7d74af01743b", + "reference": "1f0dca06d54cf187adb3481a9c3e7d74af01743b", "shasum": "" }, "require-dev": { - "friendsofphp/php-cs-fixer": "v3.61.1", + "friendsofphp/php-cs-fixer": "v3.64.0", "nikic/php-parser": "v5.3.1", "phpdocumentor/reflection-docblock": "5.4.1", - "phpunit/phpunit": "11.3.0" + "phpunit/phpunit": "11.4.3" }, "default-branch": true, "type": "library", @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-10-28T16:40:57+00:00" + "time": "2024-11-04T21:28:48+00:00" }, { "name": "nette/bootstrap", From 801924357745759a86d9118f1ccf04f9114d554d Mon Sep 17 00:00:00 2001 From: Jonathan Goode Date: Fri, 1 Nov 2024 16:31:47 +0000 Subject: [PATCH 425/508] Support returning an array or a string in `count_chars()` --- conf/config.neon | 7 ++- ...harsFunctionDynamicReturnTypeExtension.php | 59 +++++++++++++++++++ .../PHPStan/Analyser/nsrt/count-chars-7.4.php | 21 +++++++ .../PHPStan/Analyser/nsrt/count-chars-8.0.php | 21 +++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php create mode 100644 tests/PHPStan/Analyser/nsrt/count-chars-7.4.php create mode 100644 tests/PHPStan/Analyser/nsrt/count-chars-8.0.php diff --git a/conf/config.neon b/conf/config.neon index e307d1380b..24156dc09b 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1262,13 +1262,18 @@ services: - phpstan.broker.dynamicFunctionReturnTypeExtension - - class: PHPStan\Type\Php\ConstantHelper + class: PHPStan\Type\Php\ConstantHelper - class: PHPStan\Type\Php\CountFunctionReturnTypeExtension tags: - phpstan.broker.dynamicFunctionReturnTypeExtension + - + class: PHPStan\Type\Php\CountCharsFunctionDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + - class: PHPStan\Type\Php\CountFunctionTypeSpecifyingExtension tags: diff --git a/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php b/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php new file mode 100644 index 0000000000..cddb7e7989 --- /dev/null +++ b/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php @@ -0,0 +1,59 @@ +getName() === 'count_chars'; + } + + public function getTypeFromFunctionCall( + FunctionReflection $functionReflection, + FuncCall $functionCall, + Scope $scope, + ): ?Type + { + if (count($functionCall->getArgs()) < 1) { + return null; + } + + $modeType = $scope->getType($functionCall->getArgs()[1]->value); + + if (IntegerRangeType::fromInterval(0, 2)->isSuperTypeOf($modeType)->yes()) { + $arrayType = new ArrayType(new IntegerType(), new IntegerType()); + + return $this->phpVersion->throwsValueErrorForInternalFunctions() + ? $arrayType + : TypeUtils::toBenevolentUnion(new UnionType([$arrayType, new ConstantBooleanType(false)])); + } + + $stringType = new StringType(); + + return $this->phpVersion->throwsValueErrorForInternalFunctions() + ? $stringType + : TypeUtils::toBenevolentUnion(new UnionType([$stringType, new ConstantBooleanType(false)])); + } + +} diff --git a/tests/PHPStan/Analyser/nsrt/count-chars-7.4.php b/tests/PHPStan/Analyser/nsrt/count-chars-7.4.php new file mode 100644 index 0000000000..713d73a5e1 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/count-chars-7.4.php @@ -0,0 +1,21 @@ +|false', count_chars(self::ABC, 0)); + assertType('array|false', count_chars(self::ABC, 1)); + assertType('array|false', count_chars(self::ABC, 2)); + + assertType('string|false', count_chars(self::ABC, 3)); + assertType('string|false', count_chars(self::ABC, 4)); + + assertType('string|false', count_chars(self::ABC, -1)); + assertType('string|false', count_chars(self::ABC, 5)); + } +} diff --git a/tests/PHPStan/Analyser/nsrt/count-chars-8.0.php b/tests/PHPStan/Analyser/nsrt/count-chars-8.0.php new file mode 100644 index 0000000000..88a165e931 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/count-chars-8.0.php @@ -0,0 +1,21 @@ += 8.0 + +namespace CountChars; + +use function PHPStan\Testing\assertType; + +class Y { + const ABC = 'abcdef'; + + function doFoo(): void { + assertType('array', count_chars(self::ABC, 0)); + assertType('array', count_chars(self::ABC, 1)); + assertType('array', count_chars(self::ABC, 2)); + + assertType('string', count_chars(self::ABC, 3)); + assertType('string', count_chars(self::ABC, 4)); + + assertType('string', count_chars(self::ABC, -1)); + assertType('string', count_chars(self::ABC, 5)); + } +} From 71d01d661a5602d19f0a313a95ff8d66fd00798b Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Wed, 6 Nov 2024 11:41:43 +0100 Subject: [PATCH 426/508] xdebug_get_function_stack: fix signature --- resources/functionMap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/functionMap.php b/resources/functionMap.php index 275eea976f..cb8b4c5870 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -13272,7 +13272,7 @@ 'xdebug_get_declared_vars' => ['array'], 'xdebug_get_formatted_function_stack' => [''], 'xdebug_get_function_count' => ['int'], -'xdebug_get_function_stack' => ['array', 'message='=>'string', 'options='=>'int'], +'xdebug_get_function_stack' => ['array', 'options='=>'array{local_vars?: bool, params_as_values?: bool, from_exception?: Throwable}'], 'xdebug_get_headers' => ['array'], 'xdebug_get_monitored_functions' => ['array'], 'xdebug_get_profiler_filename' => ['string'], From 11998ed4eb36ef036877e14e9ce3eb8a7cb8fc76 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 6 Nov 2024 12:01:44 +0100 Subject: [PATCH 427/508] Update changelog --- changelog-2.0.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index b4967463c6..1e2d866a1f 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -134,7 +134,12 @@ Improvements 🔧 * Collected PHP errors cannot be ignored (https://github.com/phpstan/phpstan-src/commit/1d3f4313955dc6fa5c6ce60fa58afe765964e5b0) * Added missing rules to StubValidator (https://github.com/phpstan/phpstan-src/commit/bf19914cac1682d0eab8bf65a874ba368522311c) * Report precise offsets in errors ([#3504](https://github.com/phpstan/phpstan-src/pull/3504)), thanks @ruudk! - +* IntersectionType - always describe list as list (https://github.com/phpstan/phpstan-src/commit/f680629bc92e4dd5d7acd3bc60c9539fb047452b) +* ArrayType::describe - explicit mixed should be stated explicitly (https://github.com/phpstan/phpstan-src/commit/6cf223840f89c972551f373ade9eea16d12e143b) +* Refactor IntersectionType::describe() (https://github.com/phpstan/phpstan-src/commit/67fbfaee6585c2d47485dc2a159ee76d3ed02b35) +* Remove inefficient caching from `PhpMethodReflection` and `PhpFunctionReflection::isVariadic()` ([#3534](https://github.com/phpstan/phpstan-src/pull/3534)), thanks @staabm! +* Clean file cache from unused items (https://github.com/phpstan/phpstan-src/commit/466ad51740d629c9137a77dac28a676b71ef7197) +* Journal for used generated containers (https://github.com/phpstan/phpstan-src/commit/57c65888e6372a4056afbbacc8207d411ea8559a) Bugfixes 🐛 ===================== @@ -165,6 +170,8 @@ Function signature fixes 🤖 * Update `Locale` signatures ([#2880](https://github.com/phpstan/phpstan-src/pull/2880)), thanks @devnix! * Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3!* Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! * Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! +* Support returning an array or a string in `count_chars()` ([#3596](https://github.com/phpstan/phpstan-src/pull/3596)), thanks @u01jmg3! +* xdebug_get_function_stack: fix signature ([#3605](https://github.com/phpstan/phpstan-src/pull/3605)), thanks @janedbal! Internals 🔍 @@ -194,3 +201,8 @@ Internals 🔍 * More interfaces that are not supposed to be implemented in userland (https://github.com/phpstan/phpstan-src/commit/778af2ed74ba59bfb2a69fd5b45821ccdb1107c9, https://github.com/phpstan/phpstan-src/commit/cb6ab5544a016c52f931fc390bcdf9c627819d8f) * Refactored `FunctionCallParametersCheck::check()` parameters (https://github.com/phpstan/phpstan-src/commit/710e09c41698efb1d8d3ae31791944077dbb9cc1) * Spread list usages in Reflection, Scope, Type ([#3530](https://github.com/phpstan/phpstan-src/pull/3530)), thanks @janedbal! +* Remove $isFinal dead-code in PhpFunctionReflection ([#3545](https://github.com/phpstan/phpstan-src/pull/3545)), thanks @staabm! +* Get rid of unnecessary `instanceof self` in `ConstantArrayType` ([#3552](https://github.com/phpstan/phpstan-src/pull/3552)), thanks @herndlm! +* test: use `bashunit -a` exit_code to check for errors ([#3533](https://github.com/phpstan/phpstan-src/pull/3533)), thanks @Chemaclass! +* Remove dead code ([#3575](https://github.com/phpstan/phpstan-src/pull/3575)), thanks @staabm! +* Remove dead code in ConstantConditionRuleHelper ([#3597](https://github.com/phpstan/phpstan-src/pull/3597)), thanks @staabm! From 6924e46f4af313fc70403120ff7a08a62594bb55 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 6 Nov 2024 17:35:43 +0100 Subject: [PATCH 428/508] Utilize PHP version constraint from composer.json to narrow `PHP_*` constants --- .github/workflows/e2e-tests.yml | 45 +++++ conf/config.neon | 8 +- conf/parametersSchema.neon | 8 +- e2e/composer-max-version/.gitignore | 2 + e2e/composer-max-version/composer.json | 5 + e2e/composer-max-version/test.php | 10 ++ e2e/composer-min-max-version/.gitignore | 2 + e2e/composer-min-max-version/composer.json | 5 + e2e/composer-min-max-version/test.php | 10 ++ e2e/composer-min-open-end-version/.gitignore | 2 + .../composer.json | 5 + e2e/composer-min-open-end-version/test.php | 6 + e2e/composer-min-version-v5/.gitignore | 2 + e2e/composer-min-version-v5/composer.json | 5 + e2e/composer-min-version-v5/test.php | 6 + e2e/composer-min-version-v7/.gitignore | 2 + e2e/composer-min-version-v7/composer.json | 5 + e2e/composer-min-version-v7/test.php | 6 + e2e/composer-min-version/.gitignore | 2 + e2e/composer-min-version/composer.json | 5 + e2e/composer-min-version/test.php | 6 + e2e/composer-no-versions/.gitignore | 2 + e2e/composer-no-versions/composer.json | 2 + e2e/composer-no-versions/test.php | 6 + .../phpstan.neon | 5 + e2e/composer-version-config-patch/.gitignore | 2 + .../composer.json | 5 + e2e/composer-version-config-patch/test.php | 7 + e2e/composer-version-config/.gitignore | 2 + e2e/composer-version-config/composer.json | 5 + e2e/composer-version-config/phpstan.neon | 4 + e2e/composer-version-config/test.php | 11 ++ src/Analyser/ConstantResolver.php | 69 +++++++- src/Analyser/ConstantResolverFactory.php | 5 + src/DependencyInjection/ContainerFactory.php | 13 ++ .../InvalidPhpVersionException.php | 10 ++ .../ValidateIgnoredErrorsExtension.php | 2 +- src/Php/ComposerPhpVersionFactory.php | 158 ++++++++++++++++++ src/Php/PhpVersion.php | 21 ++- src/Php/PhpVersionFactory.php | 9 +- src/Php/PhpVersionFactoryFactory.php | 17 +- src/Testing/PHPStanTestCase.php | 2 +- ...pareFunctionDynamicReturnTypeExtension.php | 38 ++++- 43 files changed, 521 insertions(+), 21 deletions(-) create mode 100644 e2e/composer-max-version/.gitignore create mode 100644 e2e/composer-max-version/composer.json create mode 100644 e2e/composer-max-version/test.php create mode 100644 e2e/composer-min-max-version/.gitignore create mode 100644 e2e/composer-min-max-version/composer.json create mode 100644 e2e/composer-min-max-version/test.php create mode 100644 e2e/composer-min-open-end-version/.gitignore create mode 100644 e2e/composer-min-open-end-version/composer.json create mode 100644 e2e/composer-min-open-end-version/test.php create mode 100644 e2e/composer-min-version-v5/.gitignore create mode 100644 e2e/composer-min-version-v5/composer.json create mode 100644 e2e/composer-min-version-v5/test.php create mode 100644 e2e/composer-min-version-v7/.gitignore create mode 100644 e2e/composer-min-version-v7/composer.json create mode 100644 e2e/composer-min-version-v7/test.php create mode 100644 e2e/composer-min-version/.gitignore create mode 100644 e2e/composer-min-version/composer.json create mode 100644 e2e/composer-min-version/test.php create mode 100644 e2e/composer-no-versions/.gitignore create mode 100644 e2e/composer-no-versions/composer.json create mode 100644 e2e/composer-no-versions/test.php create mode 100644 e2e/composer-version-config-invalid/phpstan.neon create mode 100644 e2e/composer-version-config-patch/.gitignore create mode 100644 e2e/composer-version-config-patch/composer.json create mode 100644 e2e/composer-version-config-patch/test.php create mode 100644 e2e/composer-version-config/.gitignore create mode 100644 e2e/composer-version-config/composer.json create mode 100644 e2e/composer-version-config/phpstan.neon create mode 100644 e2e/composer-version-config/test.php create mode 100644 src/DependencyInjection/InvalidPhpVersionException.php create mode 100644 src/Php/ComposerPhpVersionFactory.php diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 9c134d199c..7577e5c04f 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -292,6 +292,48 @@ jobs: - script: | cd e2e/bug-11819 ../../bin/phpstan + - script: | + cd e2e/composer-max-version + composer install + ../../bin/phpstan analyze test.php --level=0 + - script: | + cd e2e/composer-min-max-version + composer install + ../../bin/phpstan analyze test.php --level=0 + - script: | + cd e2e/composer-min-open-end-version + composer install + ../../bin/phpstan analyze test.php --level=0 + - script: | + cd e2e/composer-min-version-v5 + composer install --ignore-platform-reqs + ../../bin/phpstan analyze test.php --level=0 + - script: | + cd e2e/composer-min-version-v7 + composer install --ignore-platform-reqs + ../../bin/phpstan analyze test.php --level=0 + - script: | + cd e2e/composer-min-version + composer install + ../../bin/phpstan analyze test.php --level=0 + - script: | + cd e2e/composer-no-versions + composer install + ../../bin/phpstan analyze test.php --level=0 + - script: | + cd e2e/composer-version-config-invalid + OUTPUT=$(../bashunit -a exit_code "1" ../../bin/phpstan) + echo "$OUTPUT" + ../bashunit -a contains 'Invalid configuration' "$OUTPUT" + ../bashunit -a contains 'Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.' "$OUTPUT" + - script: | + cd e2e/composer-version-config-patch + composer install --ignore-platform-reqs + ../../bin/phpstan analyze test.php --level=0 + - script: | + cd e2e/composer-version-config + composer install + ../../bin/phpstan analyze test.php --level=0 steps: - name: "Checkout" @@ -308,5 +350,8 @@ jobs: - name: "Install dependencies" run: "composer install --no-interaction --no-progress" + - name: "Install bashunit" + run: "curl -s https://bashunit.typeddevs.com/install.sh | bash -s e2e/ 0.17.0" + - name: "Test" run: ${{ matrix.script }} diff --git a/conf/config.neon b/conf/config.neon index 7d1bf16616..df5c15ddec 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -339,7 +339,13 @@ services: - class: PHPStan\Php\PhpVersionFactoryFactory arguments: - versionId: %phpVersion% + phpVersion: %phpVersion% + composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% + + - + class: PHPStan\Php\ComposerPhpVersionFactory + arguments: + phpVersion: %phpVersion% composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% - diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index d6e4a34882..6c7f9c40e6 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -79,7 +79,13 @@ parametersSchema: minimumNumberOfJobsPerProcess: int(), buffer: int() ]) - phpVersion: schema(anyOf(schema(int(), min(70100), max(80499))), nullable()) + phpVersion: schema(anyOf( + schema(int(), min(70100), max(80499)), + structure([ + min: schema(int(), min(70100), max(80499)), + max: schema(int(), min(70100), max(80499)) + ]) + ), nullable()) polluteScopeWithLoopInitialAssignments: bool() polluteScopeWithAlwaysIterableForeach: bool() polluteScopeWithBlock: bool() diff --git a/e2e/composer-max-version/.gitignore b/e2e/composer-max-version/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-max-version/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-max-version/composer.json b/e2e/composer-max-version/composer.json new file mode 100644 index 0000000000..4d4ca141ef --- /dev/null +++ b/e2e/composer-max-version/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": "<=8.3" + } +} diff --git a/e2e/composer-max-version/test.php b/e2e/composer-max-version/test.php new file mode 100644 index 0000000000..038f559122 --- /dev/null +++ b/e2e/composer-max-version/test.php @@ -0,0 +1,10 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('int<5, 8>', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_RELEASE_VERSION); + +\PHPStan\Testing\assertType('-1|0|1', version_compare(PHP_VERSION, '7.0.0')); +\PHPStan\Testing\assertType('bool', version_compare(PHP_VERSION, '7.0.0', '<')); +\PHPStan\Testing\assertType('bool', version_compare(PHP_VERSION, '7.0.0', '>')); diff --git a/e2e/composer-min-max-version/.gitignore b/e2e/composer-min-max-version/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-min-max-version/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-min-max-version/composer.json b/e2e/composer-min-max-version/composer.json new file mode 100644 index 0000000000..869fd2ce42 --- /dev/null +++ b/e2e/composer-min-max-version/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": ">=8.1, <=8.2.99" + } +} diff --git a/e2e/composer-min-max-version/test.php b/e2e/composer-min-max-version/test.php new file mode 100644 index 0000000000..28d770f3bb --- /dev/null +++ b/e2e/composer-min-max-version/test.php @@ -0,0 +1,10 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('8', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('int<1, 2>', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_RELEASE_VERSION); + +\PHPStan\Testing\assertType('1', version_compare(PHP_VERSION, '7.0.0')); +\PHPStan\Testing\assertType('false', version_compare(PHP_VERSION, '7.0.0', '<')); +\PHPStan\Testing\assertType('true', version_compare(PHP_VERSION, '7.0.0', '>')); diff --git a/e2e/composer-min-open-end-version/.gitignore b/e2e/composer-min-open-end-version/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-min-open-end-version/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-min-open-end-version/composer.json b/e2e/composer-min-open-end-version/composer.json new file mode 100644 index 0000000000..b6303c6b77 --- /dev/null +++ b/e2e/composer-min-open-end-version/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": ">= 8.1" + } +} diff --git a/e2e/composer-min-open-end-version/test.php b/e2e/composer-min-open-end-version/test.php new file mode 100644 index 0000000000..d4d06a34eb --- /dev/null +++ b/e2e/composer-min-open-end-version/test.php @@ -0,0 +1,6 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('8', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('int<1, 4>', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_RELEASE_VERSION); diff --git a/e2e/composer-min-version-v5/.gitignore b/e2e/composer-min-version-v5/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-min-version-v5/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-min-version-v5/composer.json b/e2e/composer-min-version-v5/composer.json new file mode 100644 index 0000000000..b73464d219 --- /dev/null +++ b/e2e/composer-min-version-v5/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": "^5.6" + } +} diff --git a/e2e/composer-min-version-v5/test.php b/e2e/composer-min-version-v5/test.php new file mode 100644 index 0000000000..2f652079a6 --- /dev/null +++ b/e2e/composer-min-version-v5/test.php @@ -0,0 +1,6 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('5', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('6', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, 99>', PHP_RELEASE_VERSION); diff --git a/e2e/composer-min-version-v7/.gitignore b/e2e/composer-min-version-v7/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-min-version-v7/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-min-version-v7/composer.json b/e2e/composer-min-version-v7/composer.json new file mode 100644 index 0000000000..9f9b263871 --- /dev/null +++ b/e2e/composer-min-version-v7/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": "^7" + } +} diff --git a/e2e/composer-min-version-v7/test.php b/e2e/composer-min-version-v7/test.php new file mode 100644 index 0000000000..e8876bd78f --- /dev/null +++ b/e2e/composer-min-version-v7/test.php @@ -0,0 +1,6 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('7', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('int<0, 4>', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_RELEASE_VERSION); diff --git a/e2e/composer-min-version/.gitignore b/e2e/composer-min-version/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-min-version/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-min-version/composer.json b/e2e/composer-min-version/composer.json new file mode 100644 index 0000000000..9be64619f1 --- /dev/null +++ b/e2e/composer-min-version/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": "^8.1" + } +} diff --git a/e2e/composer-min-version/test.php b/e2e/composer-min-version/test.php new file mode 100644 index 0000000000..d4d06a34eb --- /dev/null +++ b/e2e/composer-min-version/test.php @@ -0,0 +1,6 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('8', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('int<1, 4>', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_RELEASE_VERSION); diff --git a/e2e/composer-no-versions/.gitignore b/e2e/composer-no-versions/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-no-versions/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-no-versions/composer.json b/e2e/composer-no-versions/composer.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/e2e/composer-no-versions/composer.json @@ -0,0 +1,2 @@ +{ +} diff --git a/e2e/composer-no-versions/test.php b/e2e/composer-no-versions/test.php new file mode 100644 index 0000000000..28c8a3183b --- /dev/null +++ b/e2e/composer-no-versions/test.php @@ -0,0 +1,6 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('int<5, 8>', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_RELEASE_VERSION); diff --git a/e2e/composer-version-config-invalid/phpstan.neon b/e2e/composer-version-config-invalid/phpstan.neon new file mode 100644 index 0000000000..96977def5f --- /dev/null +++ b/e2e/composer-version-config-invalid/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + phpVersion: + min: 80303 + max: 80104 + diff --git a/e2e/composer-version-config-patch/.gitignore b/e2e/composer-version-config-patch/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-version-config-patch/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-version-config-patch/composer.json b/e2e/composer-version-config-patch/composer.json new file mode 100644 index 0000000000..d6103988c8 --- /dev/null +++ b/e2e/composer-version-config-patch/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": ">=8.0.2, <8.0.15" + } +} diff --git a/e2e/composer-version-config-patch/test.php b/e2e/composer-version-config-patch/test.php new file mode 100644 index 0000000000..3f201eadab --- /dev/null +++ b/e2e/composer-version-config-patch/test.php @@ -0,0 +1,7 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('8', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('0', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<2, 15>', PHP_RELEASE_VERSION); diff --git a/e2e/composer-version-config/.gitignore b/e2e/composer-version-config/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-version-config/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-version-config/composer.json b/e2e/composer-version-config/composer.json new file mode 100644 index 0000000000..2da0adaf1c --- /dev/null +++ b/e2e/composer-version-config/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": "^8.0" + } +} diff --git a/e2e/composer-version-config/phpstan.neon b/e2e/composer-version-config/phpstan.neon new file mode 100644 index 0000000000..003e5e1484 --- /dev/null +++ b/e2e/composer-version-config/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + phpVersion: + min: 80103 + max: 80304 diff --git a/e2e/composer-version-config/test.php b/e2e/composer-version-config/test.php new file mode 100644 index 0000000000..a9afaa4b65 --- /dev/null +++ b/e2e/composer-version-config/test.php @@ -0,0 +1,11 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('8', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('int<1, 3>', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_RELEASE_VERSION); + +\PHPStan\Testing\assertType('1', version_compare(PHP_VERSION, '7.0.0')); +\PHPStan\Testing\assertType('false', version_compare(PHP_VERSION, '7.0.0', '<')); +\PHPStan\Testing\assertType('true', version_compare(PHP_VERSION, '7.0.0', '>')); diff --git a/src/Analyser/ConstantResolver.php b/src/Analyser/ConstantResolver.php index b209533fac..8176fe8abc 100644 --- a/src/Analyser/ConstantResolver.php +++ b/src/Analyser/ConstantResolver.php @@ -3,6 +3,7 @@ namespace PHPStan\Analyser; use PhpParser\Node\Name; +use PHPStan\Php\PhpVersion; use PHPStan\Reflection\NamespaceAnswerer; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Reflection\ReflectionProvider\ReflectionProviderProvider; @@ -20,6 +21,7 @@ use PHPStan\Type\UnionType; use function array_key_exists; use function in_array; +use function max; use function sprintf; use const INF; use const NAN; @@ -34,7 +36,12 @@ final class ConstantResolver /** * @param string[] $dynamicConstantNames */ - public function __construct(private ReflectionProviderProvider $reflectionProviderProvider, private array $dynamicConstantNames) + public function __construct( + private ReflectionProviderProvider $reflectionProviderProvider, + private array $dynamicConstantNames, + private ?PhpVersion $composerMinPhpVersion, + private ?PhpVersion $composerMaxPhpVersion, + ) { } @@ -77,16 +84,60 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type ]); } if ($resolvedConstantName === 'PHP_MAJOR_VERSION') { - return IntegerRangeType::fromInterval(5, null); + $minMajor = 5; + $maxMajor = null; + + if ($this->composerMinPhpVersion !== null) { + $minMajor = max($minMajor, $this->composerMinPhpVersion->getMajorVersionId()); + } + if ($this->composerMaxPhpVersion !== null) { + $maxMajor = $this->composerMaxPhpVersion->getMajorVersionId(); + } + + return $this->createInteger($minMajor, $maxMajor); } if ($resolvedConstantName === 'PHP_MINOR_VERSION') { - return IntegerRangeType::fromInterval(0, null); + $minMinor = 0; + $maxMinor = null; + + if ( + $this->composerMinPhpVersion !== null + && $this->composerMaxPhpVersion !== null + && $this->composerMaxPhpVersion->getMajorVersionId() === $this->composerMinPhpVersion->getMajorVersionId() + ) { + $minMinor = $this->composerMinPhpVersion->getMinorVersionId(); + $maxMinor = $this->composerMaxPhpVersion->getMinorVersionId(); + } + + return $this->createInteger($minMinor, $maxMinor); } if ($resolvedConstantName === 'PHP_RELEASE_VERSION') { - return IntegerRangeType::fromInterval(0, null); + $minRelease = 0; + $maxRelease = null; + + if ( + $this->composerMinPhpVersion !== null + && $this->composerMaxPhpVersion !== null + && $this->composerMaxPhpVersion->getMajorVersionId() === $this->composerMinPhpVersion->getMajorVersionId() + && $this->composerMaxPhpVersion->getMinorVersionId() === $this->composerMinPhpVersion->getMinorVersionId() + ) { + $minRelease = $this->composerMinPhpVersion->getPatchVersionId(); + $maxRelease = $this->composerMaxPhpVersion->getPatchVersionId(); + } + + return $this->createInteger($minRelease, $maxRelease); } if ($resolvedConstantName === 'PHP_VERSION_ID') { - return IntegerRangeType::fromInterval(50207, null); + $minVersion = 50207; + $maxVersion = null; + if ($this->composerMinPhpVersion !== null) { + $minVersion = max($minVersion, $this->composerMinPhpVersion->getVersionId()); + } + if ($this->composerMaxPhpVersion !== null) { + $maxVersion = $this->composerMaxPhpVersion->getVersionId(); + } + + return $this->createInteger($minVersion, $maxVersion); } if ($resolvedConstantName === 'PHP_ZTS') { return new UnionType([ @@ -325,6 +376,14 @@ public function resolveClassConstantType(string $className, string $constantName return $constantType; } + private function createInteger(?int $min, ?int $max): Type + { + if ($min !== null && $min === $max) { + return new ConstantIntegerType($min); + } + return IntegerRangeType::fromInterval($min, $max); + } + private function getReflectionProvider(): ReflectionProvider { return $this->reflectionProviderProvider->getReflectionProvider(); diff --git a/src/Analyser/ConstantResolverFactory.php b/src/Analyser/ConstantResolverFactory.php index 67a98408a0..f111da14ec 100644 --- a/src/Analyser/ConstantResolverFactory.php +++ b/src/Analyser/ConstantResolverFactory.php @@ -3,6 +3,7 @@ namespace PHPStan\Analyser; use PHPStan\DependencyInjection\Container; +use PHPStan\Php\ComposerPhpVersionFactory; use PHPStan\Reflection\ReflectionProvider\ReflectionProviderProvider; final class ConstantResolverFactory @@ -17,9 +18,13 @@ public function __construct( public function create(): ConstantResolver { + $composerFactory = $this->container->getByType(ComposerPhpVersionFactory::class); + return new ConstantResolver( $this->reflectionProviderProvider, $this->container->getParameter('dynamicConstantNames'), + $composerFactory->getMinVersion(), + $composerFactory->getMaxVersion(), ); } diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index 7ac72d4fc4..75c79d6678 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -32,6 +32,7 @@ use PHPStan\ShouldNotHappenException; use PHPStan\Type\ObjectType; use function array_diff_key; +use function array_key_exists; use function array_map; use function array_merge; use function array_unique; @@ -310,6 +311,18 @@ private function validateParameters(array $parameters, array $parametersSchema): $context->path = ['parameters']; }; $processor->process($schema, $parameters); + + if ( + !array_key_exists('phpVersion', $parameters) + || !is_array($parameters['phpVersion'])) { + return; + } + + $phpVersion = $parameters['phpVersion']; + + if ($phpVersion['max'] < $phpVersion['min']) { + throw new InvalidPhpVersionException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.'); + } } /** diff --git a/src/DependencyInjection/InvalidPhpVersionException.php b/src/DependencyInjection/InvalidPhpVersionException.php new file mode 100644 index 0000000000..f9b41690a3 --- /dev/null +++ b/src/DependencyInjection/InvalidPhpVersionException.php @@ -0,0 +1,10 @@ +initialized = true; + + $phpVersion = $this->phpVersion; + + if (is_int($phpVersion)) { + throw new ShouldNotHappenException(); + } + + if (is_array($phpVersion)) { + if ($phpVersion['max'] < $phpVersion['min']) { + throw new ShouldNotHappenException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.'); + } + + $this->minVersion = new PhpVersion($phpVersion['min']); + $this->maxVersion = new PhpVersion($phpVersion['max']); + + return; + } + + // don't limit minVersion... PHPStan can analyze even PHP5 + $this->maxVersion = new PhpVersion(PhpVersionFactory::MAX_PHP_VERSION); + + // fallback to composer.json based php-version constraint + $composerPhpVersion = $this->getComposerRequireVersion(); + if ($composerPhpVersion === null) { + return; + } + + $parser = new VersionParser(); + $constraint = $parser->parseConstraints($composerPhpVersion); + + if (!$constraint->getLowerBound()->isZero()) { + $minVersion = $this->buildVersion($constraint->getLowerBound()->getVersion(), false); + + if ($minVersion !== null) { + $this->minVersion = new PhpVersion($minVersion->getVersionId()); + } + } + if ($constraint->getUpperBound()->isPositiveInfinity()) { + return; + } + + $this->maxVersion = $this->buildVersion($constraint->getUpperBound()->getVersion(), true); + } + + public function getMinVersion(): ?PhpVersion + { + if (is_int($this->phpVersion)) { + return null; + } + + if ($this->initialized === false) { + $this->initializeVersions(); + } + + return $this->minVersion; + } + + public function getMaxVersion(): ?PhpVersion + { + if (is_int($this->phpVersion)) { + return null; + } + + if ($this->initialized === false) { + $this->initializeVersions(); + } + + return $this->maxVersion; + } + + private function getComposerRequireVersion(): ?string + { + $composerPhpVersion = null; + if (count($this->composerAutoloaderProjectPaths) > 0) { + $composerJsonPath = end($this->composerAutoloaderProjectPaths) . '/composer.json'; + if (is_file($composerJsonPath)) { + try { + $composerJsonContents = FileReader::read($composerJsonPath); + $composer = Json::decode($composerJsonContents, Json::FORCE_ARRAY); + $requiredVersion = $composer['require']['php'] ?? null; + if (is_string($requiredVersion)) { + $composerPhpVersion = $requiredVersion; + } + } catch (CouldNotReadFileException | JsonException) { + // pass + } + } + } + return $composerPhpVersion; + } + + private function buildVersion(string $version, bool $isMaxVersion): ?PhpVersion + { + $matches = Strings::match($version, '#^(\d+)\.(\d+)(?:\.(\d+))?#'); + if ($matches === null) { + return null; + } + + $major = $matches[1]; + $minor = $matches[2]; + $patch = $matches[3] ?? 0; + $versionId = (int) sprintf('%d%02d%02d', $major, $minor, $patch); + + if ($isMaxVersion && $version === '6.0.0.0-dev') { + $versionId = min($versionId, PhpVersionFactory::MAX_PHP5_VERSION); + } elseif ($isMaxVersion && $version === '8.0.0.0-dev') { + $versionId = min($versionId, PhpVersionFactory::MAX_PHP7_VERSION); + } else { + $versionId = min($versionId, PhpVersionFactory::MAX_PHP_VERSION); + } + + return new PhpVersion($versionId); + } + +} diff --git a/src/Php/PhpVersion.php b/src/Php/PhpVersion.php index fcd6871c39..83ca1245b5 100644 --- a/src/Php/PhpVersion.php +++ b/src/Php/PhpVersion.php @@ -41,11 +41,26 @@ public function getVersionId(): int return $this->versionId; } + public function getMajorVersionId(): int + { + return (int) floor($this->versionId / 10000); + } + + public function getMinorVersionId(): int + { + return (int) floor(($this->versionId % 10000) / 100); + } + + public function getPatchVersionId(): int + { + return (int) floor($this->versionId % 100); + } + public function getVersionString(): string { - $first = (int) floor($this->versionId / 10000); - $second = (int) floor(($this->versionId % 10000) / 100); - $third = (int) floor($this->versionId % 100); + $first = $this->getMajorVersionId(); + $second = $this->getMinorVersionId(); + $third = $this->getPatchVersionId(); return $first . '.' . $second . ($third !== 0 ? '.' . $third : ''); } diff --git a/src/Php/PhpVersionFactory.php b/src/Php/PhpVersionFactory.php index d926420e77..bd1bfcabf5 100644 --- a/src/Php/PhpVersionFactory.php +++ b/src/Php/PhpVersionFactory.php @@ -10,6 +10,11 @@ final class PhpVersionFactory { + public const MIN_PHP_VERSION = 70100; + public const MAX_PHP_VERSION = 80499; + public const MAX_PHP5_VERSION = 50699; + public const MAX_PHP7_VERSION = 70499; + public function __construct( private ?int $versionId, private ?string $composerPhpVersion, @@ -25,8 +30,8 @@ public function create(): PhpVersion } elseif ($this->composerPhpVersion !== null) { $parts = explode('.', $this->composerPhpVersion); $tmp = (int) $parts[0] * 10000 + (int) ($parts[1] ?? 0) * 100 + (int) ($parts[2] ?? 0); - $tmp = max($tmp, 70100); - $versionId = min($tmp, 80499); + $tmp = max($tmp, self::MIN_PHP_VERSION); + $versionId = min($tmp, self::MAX_PHP_VERSION); $source = PhpVersion::SOURCE_COMPOSER_PLATFORM_PHP; } else { $versionId = PHP_VERSION_ID; diff --git a/src/Php/PhpVersionFactoryFactory.php b/src/Php/PhpVersionFactoryFactory.php index c578ef06fc..0190ca0e82 100644 --- a/src/Php/PhpVersionFactoryFactory.php +++ b/src/Php/PhpVersionFactoryFactory.php @@ -8,17 +8,20 @@ use PHPStan\File\FileReader; use function count; use function end; +use function is_array; use function is_file; +use function is_int; use function is_string; final class PhpVersionFactoryFactory { /** + * @param int|array{min: int, max: int}|null $phpVersion * @param string[] $composerAutoloaderProjectPaths */ public function __construct( - private ?int $versionId, + private int|array|null $phpVersion, private array $composerAutoloaderProjectPaths, ) { @@ -43,7 +46,17 @@ public function create(): PhpVersionFactory } } - return new PhpVersionFactory($this->versionId, $composerPhpVersion); + $versionId = null; + + if (is_int($this->phpVersion)) { + $versionId = $this->phpVersion; + } + + if (is_array($this->phpVersion)) { + $versionId = $this->phpVersion['min']; + } + + return new PhpVersionFactory($versionId, $composerPhpVersion); } } diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index 87d5bab299..aee824bfbc 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -137,7 +137,7 @@ public static function createScopeFactory(ReflectionProvider $reflectionProvider } $reflectionProviderProvider = new DirectReflectionProviderProvider($reflectionProvider); - $constantResolver = new ConstantResolver($reflectionProviderProvider, $dynamicConstantNames); + $constantResolver = new ConstantResolver($reflectionProviderProvider, $dynamicConstantNames, null, null); $initializerExprTypeResolver = new InitializerExprTypeResolver( $constantResolver, diff --git a/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php b/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php index 9a5592bf40..d79ebf0706 100644 --- a/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php @@ -2,12 +2,15 @@ namespace PHPStan\Type\Php; +use PhpParser\Node\Expr; use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; +use PHPStan\Php\ComposerPhpVersionFactory; use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\BooleanType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantIntegerType; +use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; @@ -18,6 +21,10 @@ final class VersionCompareFunctionDynamicReturnTypeExtension implements DynamicFunctionReturnTypeExtension { + public function __construct(private ComposerPhpVersionFactory $composerPhpVersionFactory) + { + } + public function isFunctionSupported(FunctionReflection $functionReflection): bool { return $functionReflection->getName() === 'version_compare'; @@ -29,19 +36,20 @@ public function getTypeFromFunctionCall( Scope $scope, ): ?Type { - if (count($functionCall->getArgs()) < 2) { + $args = $functionCall->getArgs(); + if (count($args) < 2) { return null; } - $version1Strings = $scope->getType($functionCall->getArgs()[0]->value)->getConstantStrings(); - $version2Strings = $scope->getType($functionCall->getArgs()[1]->value)->getConstantStrings(); + $version1Strings = $this->getVersionStrings($args[0]->value, $scope); + $version2Strings = $this->getVersionStrings($args[1]->value, $scope); $counts = [ count($version1Strings), count($version2Strings), ]; - if (isset($functionCall->getArgs()[2])) { - $operatorStrings = $scope->getType($functionCall->getArgs()[2]->value)->getConstantStrings(); + if (isset($args[2])) { + $operatorStrings = $scope->getType($args[2]->value)->getConstantStrings(); $counts[] = count($operatorStrings); $returnType = new BooleanType(); } else { @@ -77,4 +85,24 @@ public function getTypeFromFunctionCall( return TypeCombinator::union(...$types); } + /** + * @return ConstantStringType[] + */ + private function getVersionStrings(Expr $expr, Scope $scope): array + { + if ( + $expr instanceof Expr\ConstFetch + && $expr->name->toString() === 'PHP_VERSION' + && $this->composerPhpVersionFactory->getMinVersion() !== null + && $this->composerPhpVersionFactory->getMaxVersion() !== null + ) { + return [ + new ConstantStringType($this->composerPhpVersionFactory->getMinVersion()->getVersionString()), + new ConstantStringType($this->composerPhpVersionFactory->getMaxVersion()->getVersionString()), + ]; + } + + return $scope->getType($expr)->getConstantStrings(); + } + } From 2385a690dc907725900b62389b6caff0baad3c57 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 7 Nov 2024 09:23:17 +0100 Subject: [PATCH 429/508] Reorganize new rules in changelog --- changelog-2.0.md | 120 +++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/changelog-2.0.md b/changelog-2.0.md index 1e2d866a1f..1756a96aa0 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -8,72 +8,78 @@ Major new features 🚀 * **Level 10** - level 9 on steroids, treats all `mixed` types strictly, not just explicit `mixed` * **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! * Lists are arrays with sequential integer keys starting at 0 -* **Validate inline PHPDoc `@var` tag** type against native type (level 2) (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) - * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones - * Use config option `reportAnyTypeWideningInVarTag: true` for stricter behaviour ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! * **Lower memory consumption** thanks to breaking up of reference cycles * [Learn more »](https://phpstan.org/blog/preprocessing-ast-for-custom-rules) * In testing the memory consumption was reduced by 50–70 %. * **Enhancements in handling parameters passed by reference** * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! -* Check too wide private property type (level 4) (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) -* Always report always true conditions, except for last elseif and match arm (https://github.com/phpstan/phpstan-src/commit/565fb0f6da9cdc58e8686598015561a848693972) -* Remove "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule - * Because "always true" is always reported, these are no longer needed +* New rules (level 0): + * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! + * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! + * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! + * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! + * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! + * Rule about `@phpstan-consistent-constructor` ([#1296](https://github.com/phpstan/phpstan-src/pull/1296)), thanks @canvural! + * Check code in custom PHPStan extensions for runtime reflection concepts like `is_a()` or `class_parents()` (https://github.com/phpstan/phpstan-src/commit/c4a662ac6c3ec63f063238880b243b5399c34fcc) + * Check code in custom PHPStan extensions for runtime reflection concepts like `new ReflectionMethod()` (https://github.com/phpstan/phpstan-src/commit/536306611cbb5877b6565755cd07b87f9ccfdf08) + * ApiInstanceofRule + * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) + * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) + * Check that PHPStan class in class constant fetch is covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) + * Previously absent type checks: + * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) + * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) + * Check unresolvable types in local type aliases (https://github.com/phpstan/phpstan-src/commit/5f7d12b2fb2809525ab0e96eeae95093204ea4d3) + * Check generics in local type aliases (https://github.com/phpstan/phpstan-src/commit/5a2d4416d94ab77a2a2e7e1bfaba4c5ed2a13c25) + * Check existing classes in `@param-out` (https://github.com/phpstan/phpstan-src/commit/30c4b9e80f51af8b5f166ba3aae93d8409c9c0ea), #10260 + * Check existing classes in `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/2fa539a39e06bcc3155b109fd8d246703ceb176d), #10933 +* New rules (level 2): + * **Validate inline PHPDoc `@var` tag** type against native type (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) + * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones + * Use config option `reportAnyTypeWideningInVarTag: true` for stricter behaviour ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! + * IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) + * Checking truthiness of `@phpstan-pure` above functions and methods + * Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! + * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 + * Previously absent type checks: + * Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) + * Check `@extends`, `@implements`, `@use` for unresolvable types (https://github.com/phpstan/phpstan-src/commit/2bb528233edb75312614166e282776f279cf2018), #11552 + * Check types in `@method` tags (https://github.com/phpstan/phpstan-src/commit/5b7e474680eaf33874b7ed6a227677adcbed9ca5) + * Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) + * Check types in `@property` tags (https://github.com/phpstan/phpstan-src/commit/55ea2ae516df22a071ab873fdd6f748a3af0520e), #10752, #9356 +* New rule (level 3): + * ArrayUnpackingRule ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! +* New rules (level 4): + * Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) + * LogicalXorConstantConditionRule (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 + * Check that each trait is used and analysed at least once (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) + * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! + * ConstantLooseComparisonRule (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) + * Check `new`/function call/method call/static method call on a separate line without any side effects even without `@phpstan-pure` PHPDoc tag on the declaration side + * https://github.com/phpstan/phpstan-src/commit/281a87d1ab61809076ecfa6dfc2cc86e3babe235 + * [#3020](https://github.com/phpstan/phpstan-src/pull/3020), thanks @staabm! + * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! + * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! + * Always report always true conditions, except for last elseif and match arm (https://github.com/phpstan/phpstan-src/commit/565fb0f6da9cdc58e8686598015561a848693972) + * Remove "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule + * Because "always true" is always reported, these are no longer needed +* New rules (level 5): + * Check preg_quote delimiter sanity ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! + * Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! + * Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! + * Report useless `array_values()` calls ([#2917](https://github.com/phpstan/phpstan-src/pull/2917)), thanks @kamil-zacek! + * Check array functions which require stringish values ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! + * Check unresolvable parameters ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! + * Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 +* New rules (level 6): + * Previously absent type checks: + * Check missing types in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/892b319f25f04bc1b55c3d0063b607909612fe6d) + * Check missing types in local type aliases (https://github.com/phpstan/phpstan-src/commit/ce7ffaf02d624a7fb9d38f8e5dffc9739f1233fc) + * Check missing types in `@mixin` (https://github.com/phpstan/phpstan-src/commit/3175c81f26fd5bcb4a161b24e774921870ed2533) * New option: `polluteScopeWithBlock` (defaults to `true`, `false` in `phpstan-strict-rules`) (https://github.com/phpstan/phpstan-src/commit/946cf180c960930c2c42075d0f28ff9090507272) -* Checking truthiness of `@phpstan-pure` above functions and methods -* Check `new`/function call/method call/static method call on a separate line without any side effects even without `@phpstan-pure` PHPDoc tag on the declaration side - * https://github.com/phpstan/phpstan-src/commit/281a87d1ab61809076ecfa6dfc2cc86e3babe235 - * [#3020](https://github.com/phpstan/phpstan-src/pull/3020), thanks @staabm! - * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! - * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! -* LogicalXorConstantConditionRule (level 4) (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 -* Check that each trait is used and analysed at least once (level 4) (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) -* Check preg_quote delimiter sanity (level 5) ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! -* MagicConstantContextRule (level 0) ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! -* MissingMagicSerializationMethodsRule (level 0) ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! -* Check vprintf/vsprintf arguments against placeholder count (level 0) ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! -* Report useless return values of function calls like `var_export` without `$return=true` (level 4) ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! -* Rule for `call_user_func()` (level 5) ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! -* Report useless `array_filter()` calls (level 5) ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! -* Report useless `array_values()` calls (level 5) ([#2917](https://github.com/phpstan/phpstan-src/pull/2917)), thanks @kamil-zacek! -* Check if required file exists (level 0) ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! -* ConstantLooseComparisonRule - level 4 (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) -* Check array functions which require stringish values (level 5) ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! -* Check variance of template types in properties (level 2) ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! -* ArrayUnpackingRule (level 3) ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! -* Check unresolvable parameters (level 5) ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! -* Enforce `@no-named-arguments` (level 5) (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 * Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! -* Add `@readonly` rule that disallows default values (level 0) ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! -* IncompatibleDefaultParameterTypeRule for closures (level 2) (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) -* Added previously absent type checks (level 0) - * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) - * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) - * Check unresolvable types in local type aliases (https://github.com/phpstan/phpstan-src/commit/5f7d12b2fb2809525ab0e96eeae95093204ea4d3) - * Check generics in local type aliases (https://github.com/phpstan/phpstan-src/commit/5a2d4416d94ab77a2a2e7e1bfaba4c5ed2a13c25) - * Check existing classes in `@param-out` (https://github.com/phpstan/phpstan-src/commit/30c4b9e80f51af8b5f166ba3aae93d8409c9c0ea), #10260 - * Check existing classes in `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/2fa539a39e06bcc3155b109fd8d246703ceb176d), #10933 -* Added previously absent type checks (level 2) - * Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) - * Check `@extends`, `@implements`, `@use` for unresolvable types (https://github.com/phpstan/phpstan-src/commit/2bb528233edb75312614166e282776f279cf2018), #11552 - * Check types in `@method` tags (https://github.com/phpstan/phpstan-src/commit/5b7e474680eaf33874b7ed6a227677adcbed9ca5) - * Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) - * Check types in `@property` tags (https://github.com/phpstan/phpstan-src/commit/55ea2ae516df22a071ab873fdd6f748a3af0520e), #10752, #9356 -* Added previously absent type checks (level 6) - * Check missing types in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/892b319f25f04bc1b55c3d0063b607909612fe6d) - * Check missing types in local type aliases (https://github.com/phpstan/phpstan-src/commit/ce7ffaf02d624a7fb9d38f8e5dffc9739f1233fc) - * Check missing types in `@mixin` (https://github.com/phpstan/phpstan-src/commit/3175c81f26fd5bcb4a161b24e774921870ed2533) -* Rule about `@phpstan-consistent-constructor` (level 0) ([#1296](https://github.com/phpstan/phpstan-src/pull/1296)), thanks @canvural! -* Check code in custom PHPStan extensions for runtime reflection concepts like `is_a()` or `class_parents()` (level 0) (https://github.com/phpstan/phpstan-src/commit/c4a662ac6c3ec63f063238880b243b5399c34fcc) -* Check code in custom PHPStan extensions for runtime reflection concepts like `new ReflectionMethod()` (level 0) (https://github.com/phpstan/phpstan-src/commit/536306611cbb5877b6565755cd07b87f9ccfdf08) -* ApiInstanceofRule (level 0) - * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) - * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) -* Check that PHPStan class in class constant fetch is covered by backward compatibility promise (level 0) (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) * Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) -* Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 Improvements 🔧 From 3dc64a29f1fb003630bb7164dfcce12f5bb40fad Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:00:06 +0000 Subject: [PATCH 430/508] Update phpdoc-parser --- composer.json | 2 +- composer.lock | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 1afe40674c..23c5c46c7a 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.11", "phpstan/php-8-stubs": "0.4.4", - "phpstan/phpdoc-parser": "^2.0", + "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", "react/async": "^3", "react/child-process": "^0.7", diff --git a/composer.lock b/composer.lock index 4a1e51a351..3197c29134 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "350cc72e1a307581ffc8228f105bd273", + "content-hash": "8793a11aa08550fce8d98648609fda3b", "packages": [ { "name": "clue/ndjson-react", @@ -2290,7 +2290,7 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.0.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", @@ -2316,7 +2316,6 @@ "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2332,7 +2331,7 @@ "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/2.0.x" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0" }, "time": "2024-10-13T11:29:49+00:00" }, From d44f4df6bbccf05a0913b7eb1ad0ea0f6928e824 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 8 Nov 2024 15:31:11 +0100 Subject: [PATCH 431/508] Fix after merge --- src/Analyser/TypeSpecifier.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 8b6e3c4541..cee4acb569 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -340,8 +340,7 @@ public function specifyTypesInCondition( $scope, new Expr\BinaryOp\NotIdentical($expr->right, new ConstFetch(new Name('false'))), $context, - $rootExpr, - ); + )->setRootExpr($expr); } if ( From a965e73470dd35568b19f0cbe4c366036821ab35 Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Fri, 8 Nov 2024 16:06:14 +0100 Subject: [PATCH 432/508] Use named argument in error for variadic types When a type is variadic, and multiple named arguments are used, it's often hard to tell for which argument the error is coming. Since we have the named argument, we could use it in this situation. --- src/Rules/AttributesCheck.php | 6 +++--- src/Rules/Classes/InstantiationRule.php | 6 +++--- src/Rules/FunctionCallParametersCheck.php | 15 ++++++++++----- src/Rules/Functions/CallCallablesRule.php | 6 +++--- .../Functions/CallToFunctionParametersRule.php | 6 +++--- src/Rules/Functions/CallUserFuncRule.php | 6 +++--- src/Rules/Methods/CallMethodsRule.php | 6 +++--- src/Rules/Methods/CallStaticMethodsRule.php | 6 +++--- .../PHPStan/Rules/Methods/CallMethodsRuleTest.php | 10 +++++++++- .../Rules/Methods/data/named-arguments.php | 1 + 10 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/Rules/AttributesCheck.php b/src/Rules/AttributesCheck.php index 8633178d9f..e12f906c00 100644 --- a/src/Rules/AttributesCheck.php +++ b/src/Rules/AttributesCheck.php @@ -144,14 +144,14 @@ public function check( 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, at least %d required.', 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, %d-%d required.', 'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, %d-%d required.', - 'Parameter %s of attribute class ' . $attributeClassName . ' constructor expects %s, %s given.', + '%s of attribute class ' . $attributeClassName . ' constructor expects %s, %s given.', '', // constructor does not have a return type - 'Parameter %s of attribute class ' . $attributeClassName . ' constructor is passed by reference, so it expects variables only', + '%s of attribute class ' . $attributeClassName . ' constructor is passed by reference, so it expects variables only', 'Unable to resolve the template type %s in instantiation of attribute class ' . $attributeClassName, 'Missing parameter $%s in call to ' . $attributeClassName . ' constructor.', 'Unknown parameter $%s in call to ' . $attributeClassName . ' constructor.', 'Return type of call to ' . $attributeClassName . ' constructor contains unresolvable type.', - 'Parameter %s of attribute class ' . $attributeClassName . ' constructor contains unresolvable type.', + '%s of attribute class ' . $attributeClassName . ' constructor contains unresolvable type.', 'Attribute class ' . $attributeClassName . ' constructorinvoked with %s, but it\'s not allowed because of @no-named-arguments.', ); diff --git a/src/Rules/Classes/InstantiationRule.php b/src/Rules/Classes/InstantiationRule.php index 604038d1fa..7dd65488a0 100644 --- a/src/Rules/Classes/InstantiationRule.php +++ b/src/Rules/Classes/InstantiationRule.php @@ -209,14 +209,14 @@ private function checkClassName(string $class, bool $isName, Node $node, Scope $ 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, at least %d required.', 'Class ' . $classDisplayName . ' constructor invoked with %d parameter, %d-%d required.', 'Class ' . $classDisplayName . ' constructor invoked with %d parameters, %d-%d required.', - 'Parameter %s of class ' . $classDisplayName . ' constructor expects %s, %s given.', + '%s of class ' . $classDisplayName . ' constructor expects %s, %s given.', '', // constructor does not have a return type - 'Parameter %s of class ' . $classDisplayName . ' constructor is passed by reference, so it expects variables only', + ' %s of class ' . $classDisplayName . ' constructor is passed by reference, so it expects variables only', 'Unable to resolve the template type %s in instantiation of class ' . $classDisplayName, 'Missing parameter $%s in call to ' . $classDisplayName . ' constructor.', 'Unknown parameter $%s in call to ' . $classDisplayName . ' constructor.', 'Return type of call to ' . $classDisplayName . ' constructor contains unresolvable type.', - 'Parameter %s of class ' . $classDisplayName . ' constructor contains unresolvable type.', + '%s of class ' . $classDisplayName . ' constructor contains unresolvable type.', 'Class ' . $classDisplayName . ' constructor invoked with %s, but it\'s not allowed because of @no-named-arguments.', )); } diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index eb714ab171..10e4e50212 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -30,6 +30,7 @@ use function array_key_exists; use function count; use function implode; +use function is_int; use function is_string; use function max; use function sprintf; @@ -331,7 +332,7 @@ public function check( $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $argumentValueType); $errors[] = RuleErrorBuilder::message(sprintf( $wrongArgumentTypeMessage, - $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), + $this->describeParameter($parameter, $argumentName ?? $i + 1), $parameterType->describe($verbosityLevel), $argumentValueType->describe($verbosityLevel), )) @@ -409,7 +410,7 @@ public function check( } $errors[] = RuleErrorBuilder::message(sprintf( - 'Parameter %s is passed by reference so it does not accept %s.', + '%s is passed by reference so it does not accept %s.', $this->describeParameter($parameter, $argumentName === null ? $i + 1 : null), $propertyDescription, ))->identifier('argument.byRef')->line($argumentLine)->build(); @@ -625,11 +626,15 @@ private function processArguments( return [$errors, $newArguments]; } - private function describeParameter(ParameterReflection $parameter, ?int $position): string + private function describeParameter(ParameterReflection $parameter, int|string|null $positionOrNamed): string { $parts = []; - if ($position !== null) { - $parts[] = '#' . $position; + if (is_int($positionOrNamed)) { + $parts[] = 'Parameter #' . $positionOrNamed; + } elseif ($parameter->isVariadic() && is_string($positionOrNamed)) { + $parts[] = 'Named argument ' . $positionOrNamed . ' for variadic parameter'; + } else { + $parts[] = 'Parameter'; } $name = $parameter->getName(); diff --git a/src/Rules/Functions/CallCallablesRule.php b/src/Rules/Functions/CallCallablesRule.php index 15c0bfb9ca..162894e266 100644 --- a/src/Rules/Functions/CallCallablesRule.php +++ b/src/Rules/Functions/CallCallablesRule.php @@ -126,14 +126,14 @@ public function processNode( ucfirst($callableDescription) . ' invoked with %d parameters, at least %d required.', ucfirst($callableDescription) . ' invoked with %d parameter, %d-%d required.', ucfirst($callableDescription) . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of ' . $callableDescription . ' expects %s, %s given.', + '%s of ' . $callableDescription . ' expects %s, %s given.', 'Result of ' . $callableDescription . ' (void) is used.', - 'Parameter %s of ' . $callableDescription . ' is passed by reference, so it expects variables only.', + '%s of ' . $callableDescription . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to ' . $callableDescription, 'Missing parameter $%s in call to ' . $callableDescription . '.', 'Unknown parameter $%s in call to ' . $callableDescription . '.', 'Return type of call to ' . $callableDescription . ' contains unresolvable type.', - 'Parameter %s of ' . $callableDescription . ' contains unresolvable type.', + '%s of ' . $callableDescription . ' contains unresolvable type.', ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', ), ); diff --git a/src/Rules/Functions/CallToFunctionParametersRule.php b/src/Rules/Functions/CallToFunctionParametersRule.php index 39b4ee650f..63e1b93c7a 100644 --- a/src/Rules/Functions/CallToFunctionParametersRule.php +++ b/src/Rules/Functions/CallToFunctionParametersRule.php @@ -57,14 +57,14 @@ public function processNode(Node $node, Scope $scope): array 'Function ' . $functionName . ' invoked with %d parameters, at least %d required.', 'Function ' . $functionName . ' invoked with %d parameter, %d-%d required.', 'Function ' . $functionName . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of function ' . $functionName . ' expects %s, %s given.', + '%s of function ' . $functionName . ' expects %s, %s given.', 'Result of function ' . $functionName . ' (void) is used.', - 'Parameter %s of function ' . $functionName . ' is passed by reference, so it expects variables only.', + '%s of function ' . $functionName . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to function ' . $functionName, 'Missing parameter $%s in call to function ' . $functionName . '.', 'Unknown parameter $%s in call to function ' . $functionName . '.', 'Return type of call to function ' . $functionName . ' contains unresolvable type.', - 'Parameter %s of function ' . $functionName . ' contains unresolvable type.', + '%s of function ' . $functionName . ' contains unresolvable type.', 'Function ' . $functionName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', ); } diff --git a/src/Rules/Functions/CallUserFuncRule.php b/src/Rules/Functions/CallUserFuncRule.php index 2ea1fb2777..5eb21c2128 100644 --- a/src/Rules/Functions/CallUserFuncRule.php +++ b/src/Rules/Functions/CallUserFuncRule.php @@ -73,14 +73,14 @@ public function processNode(Node $node, Scope $scope): array ucfirst($callableDescription) . ' invoked with %d parameters, at least %d required.', ucfirst($callableDescription) . ' invoked with %d parameter, %d-%d required.', ucfirst($callableDescription) . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of ' . $callableDescription . ' expects %s, %s given.', + '%s of ' . $callableDescription . ' expects %s, %s given.', 'Result of ' . $callableDescription . ' (void) is used.', - 'Parameter %s of ' . $callableDescription . ' is passed by reference, so it expects variables only.', + '%s of ' . $callableDescription . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to ' . $callableDescription, 'Missing parameter $%s in call to ' . $callableDescription . '.', 'Unknown parameter $%s in call to ' . $callableDescription . '.', 'Return type of call to ' . $callableDescription . ' contains unresolvable type.', - 'Parameter %s of ' . $callableDescription . ' contains unresolvable type.', + '%s of ' . $callableDescription . ' contains unresolvable type.', ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', ); } diff --git a/src/Rules/Methods/CallMethodsRule.php b/src/Rules/Methods/CallMethodsRule.php index b0d522f439..19bc52fe80 100644 --- a/src/Rules/Methods/CallMethodsRule.php +++ b/src/Rules/Methods/CallMethodsRule.php @@ -63,14 +63,14 @@ public function processNode(Node $node, Scope $scope): array 'Method ' . $messagesMethodName . ' invoked with %d parameters, at least %d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameter, %d-%d required.', 'Method ' . $messagesMethodName . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of method ' . $messagesMethodName . ' expects %s, %s given.', + '%s of method ' . $messagesMethodName . ' expects %s, %s given.', 'Result of method ' . $messagesMethodName . ' (void) is used.', - 'Parameter %s of method ' . $messagesMethodName . ' is passed by reference, so it expects variables only.', + '%s of method ' . $messagesMethodName . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to method ' . $messagesMethodName, 'Missing parameter $%s in call to method ' . $messagesMethodName . '.', 'Unknown parameter $%s in call to method ' . $messagesMethodName . '.', 'Return type of call to method ' . $messagesMethodName . ' contains unresolvable type.', - 'Parameter %s of method ' . $messagesMethodName . ' contains unresolvable type.', + '%s of method ' . $messagesMethodName . ' contains unresolvable type.', 'Method ' . $messagesMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', )); } diff --git a/src/Rules/Methods/CallStaticMethodsRule.php b/src/Rules/Methods/CallStaticMethodsRule.php index 0f98eca2d9..e6b2c9dbb5 100644 --- a/src/Rules/Methods/CallStaticMethodsRule.php +++ b/src/Rules/Methods/CallStaticMethodsRule.php @@ -71,14 +71,14 @@ public function processNode(Node $node, Scope $scope): array $displayMethodName . ' invoked with %d parameters, at least %d required.', $displayMethodName . ' invoked with %d parameter, %d-%d required.', $displayMethodName . ' invoked with %d parameters, %d-%d required.', - 'Parameter %s of ' . $lowercasedMethodName . ' expects %s, %s given.', + '%s of ' . $lowercasedMethodName . ' expects %s, %s given.', 'Result of ' . $lowercasedMethodName . ' (void) is used.', - 'Parameter %s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.', + '%s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.', 'Unable to resolve the template type %s in call to method ' . $lowercasedMethodName, 'Missing parameter $%s in call to ' . $lowercasedMethodName . '.', 'Unknown parameter $%s in call to ' . $lowercasedMethodName . '.', 'Return type of call to ' . $lowercasedMethodName . ' contains unresolvable type.', - 'Parameter %s of ' . $lowercasedMethodName . ' contains unresolvable type.', + '%s of ' . $lowercasedMethodName . ' contains unresolvable type.', $displayMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.', )); diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index cc614cef95..a883c768d9 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -1907,7 +1907,7 @@ public function testNamedArguments(): void 91, ], [ - 'Parameter ...$args of method NamedArgumentsMethod\Foo::doIpsum() expects string, int given.', + 'Named argument foo for variadic parameter ...$args of method NamedArgumentsMethod\Foo::doIpsum() expects string, int given.', 91, ], [ @@ -1922,6 +1922,14 @@ public function testNamedArguments(): void 'Unpacked argument (...) cannot be followed by a non-unpacked argument.', 94, ], + [ + 'Named argument foo for variadic parameter ...$args of method NamedArgumentsMethod\Foo::doIpsum() expects string, int given.', + 95, + ], + [ + 'Named argument bar for variadic parameter ...$args of method NamedArgumentsMethod\Foo::doIpsum() expects string, int given.', + 95, + ], ]); } diff --git a/tests/PHPStan/Rules/Methods/data/named-arguments.php b/tests/PHPStan/Rules/Methods/data/named-arguments.php index f5c779f171..25d9ef362b 100644 --- a/tests/PHPStan/Rules/Methods/data/named-arguments.php +++ b/tests/PHPStan/Rules/Methods/data/named-arguments.php @@ -92,6 +92,7 @@ public function doDolor(): void $this->doIpsum(...['a' => 1, 'foo' => 'foo']); $this->doIpsum(...['b' => 1, 'foo' => 'foo']); $this->doIpsum(...[1, 2], 'foo'); + $this->doIpsum(1, 2, foo: 1, bar: 2); } } From ac1f53936d37c04da80023b7c88c9cfed9f0e890 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 9 Nov 2024 10:20:22 +0100 Subject: [PATCH 433/508] Fix after merge --- .../TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php b/tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php index f3aad9f7da..a98c638d24 100644 --- a/tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php +++ b/tests/PHPStan/Rules/TooWideTypehints/TooWideMethodReturnTypehintRuleTest.php @@ -192,7 +192,6 @@ public function testAlwaysCheckFinal(bool $checkProtectedAndPublicMethods, array public function testBug11980(): void { $this->checkProtectedAndPublicMethods = true; - $this->alwaysCheckFinal = true; $this->analyse([__DIR__ . '/data/bug-11980.php'], [ [ 'Method Bug11980\Demo::process2() never returns void so it can be removed from the return type.', From a0b6b3ba95e9a0e22a47259066890c35b1c15749 Mon Sep 17 00:00:00 2001 From: "Jose M. Valera Reales" Date: Sat, 9 Nov 2024 18:55:02 +0100 Subject: [PATCH 434/508] Upgrade bashunit:0.18.0 for e2e tests --- .github/workflows/e2e-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 21071b8ed6..6d7233d38a 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -253,7 +253,7 @@ jobs: run: "patch src/Analyser/Error.php < e2e/PHPStanErrorPatch.patch" - name: "Install bashunit" - run: "curl -s https://bashunit.typeddevs.com/install.sh | bash -s e2e/ 0.17.0" + run: "curl -s https://bashunit.typeddevs.com/install.sh | bash -s e2e/ 0.18.0" - name: "Test" run: "${{ matrix.script }}" @@ -355,7 +355,7 @@ jobs: run: "composer install --no-interaction --no-progress" - name: "Install bashunit" - run: "curl -s https://bashunit.typeddevs.com/install.sh | bash -s e2e/ 0.17.0" + run: "curl -s https://bashunit.typeddevs.com/install.sh | bash -s e2e/ 0.18.0" - name: "Test" run: ${{ matrix.script }} From 40be73a94ba6eff3e1f080826b66c99c2ec16465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Mirtes?= Date: Sun, 10 Nov 2024 18:19:58 +0100 Subject: [PATCH 435/508] Update UPGRADING.md --- UPGRADING.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index bc65ba774e..1b76768ec4 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -112,10 +112,6 @@ Appending `(?)` in `ignoreErrors` is not supported. * `constant_hassers` -> use `constantHassers` * `console_application_loader` -> use `consoleApplicationLoader` -### Docker images no longer tagged without a PHP version - -Tags without a PHP version are no longer published - `nightly`, `2`, `latest` are no longer updated. Instead, use `nightly-php8.3`, `2-php8.3`, `latest-php8.3`. You can replace `8.3` with PHP versions `8.0`-`8.3`. - ### Minor backward compatibility breaks * Removed unused config parameter `cache.nodesByFileCountMax` From eb82cb2ad17807a062fea3cd8cf31a446991a23c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 11 Nov 2024 08:01:50 +0100 Subject: [PATCH 436/508] Update changelog one last time --- changelog-2.0.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog-2.0.md b/changelog-2.0.md index 1756a96aa0..b504a3281d 100644 --- a/changelog-2.0.md +++ b/changelog-2.0.md @@ -146,6 +146,7 @@ Improvements 🔧 * Remove inefficient caching from `PhpMethodReflection` and `PhpFunctionReflection::isVariadic()` ([#3534](https://github.com/phpstan/phpstan-src/pull/3534)), thanks @staabm! * Clean file cache from unused items (https://github.com/phpstan/phpstan-src/commit/466ad51740d629c9137a77dac28a676b71ef7197) * Journal for used generated containers (https://github.com/phpstan/phpstan-src/commit/57c65888e6372a4056afbbacc8207d411ea8559a) +* Use named argument in error for variadic types ([#3611](https://github.com/phpstan/phpstan-src/pull/3611)), thanks @ruudk! Bugfixes 🐛 ===================== @@ -210,5 +211,6 @@ Internals 🔍 * Remove $isFinal dead-code in PhpFunctionReflection ([#3545](https://github.com/phpstan/phpstan-src/pull/3545)), thanks @staabm! * Get rid of unnecessary `instanceof self` in `ConstantArrayType` ([#3552](https://github.com/phpstan/phpstan-src/pull/3552)), thanks @herndlm! * test: use `bashunit -a` exit_code to check for errors ([#3533](https://github.com/phpstan/phpstan-src/pull/3533)), thanks @Chemaclass! +* Upgrade bashunit:0.18.0 for e2e tests ([#3614](https://github.com/phpstan/phpstan-src/pull/3614)), thanks @Chemaclass! * Remove dead code ([#3575](https://github.com/phpstan/phpstan-src/pull/3575)), thanks @staabm! * Remove dead code in ConstantConditionRuleHelper ([#3597](https://github.com/phpstan/phpstan-src/pull/3597)), thanks @staabm! From 91d1b11c8740cdadea3d5f7b96af4f64c5a1f6c8 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 11 Nov 2024 08:44:29 +0100 Subject: [PATCH 437/508] Update PHPStan extensions --- composer.lock | 53 ++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/composer.lock b/composer.lock index 3197c29134..4a377463ad 100644 --- a/composer.lock +++ b/composer.lock @@ -4672,16 +4672,16 @@ }, { "name": "phpstan/phpstan-deprecation-rules", - "version": "2.0.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "392bbe7be54b00fbe945fede6a8ef543216f3b9c" + "reference": "81833b5787e2e8f451b31218875e29e4ed600ab2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/392bbe7be54b00fbe945fede6a8ef543216f3b9c", - "reference": "392bbe7be54b00fbe945fede6a8ef543216f3b9c", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/81833b5787e2e8f451b31218875e29e4ed600ab2", + "reference": "81833b5787e2e8f451b31218875e29e4ed600ab2", "shasum": "" }, "require": { @@ -4693,7 +4693,6 @@ "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^9.6" }, - "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { @@ -4714,22 +4713,22 @@ "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", "support": { "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.x" + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.0" }, - "time": "2024-09-26T12:14:06+00:00" + "time": "2024-10-26T16:04:11+00:00" }, { "name": "phpstan/phpstan-nette", - "version": "2.0.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-nette.git", - "reference": "c903386c4e3d1d25a57f66458476bfb6347f1c66" + "reference": "cacb6983bbdf44d5c3a7222e5ca74f61f8531806" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-nette/zipball/c903386c4e3d1d25a57f66458476bfb6347f1c66", - "reference": "c903386c4e3d1d25a57f66458476bfb6347f1c66", + "url": "https://api.github.com/repos/phpstan/phpstan-nette/zipball/cacb6983bbdf44d5c3a7222e5ca74f61f8531806", + "reference": "cacb6983bbdf44d5c3a7222e5ca74f61f8531806", "shasum": "" }, "require": { @@ -4746,6 +4745,7 @@ }, "require-dev": { "nette/application": "^3.0", + "nette/di": "^3.1.10", "nette/forms": "^3.0", "nette/utils": "^2.3.0 || ^3.0.0", "php-parallel-lint/php-parallel-lint": "^1.2", @@ -4753,7 +4753,6 @@ "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^9.6" }, - "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { @@ -4775,22 +4774,22 @@ "description": "Nette Framework class reflection extension for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-nette/issues", - "source": "https://github.com/phpstan/phpstan-nette/tree/2.0.x" + "source": "https://github.com/phpstan/phpstan-nette/tree/2.0.0" }, - "time": "2024-09-24T16:09:34+00:00" + "time": "2024-10-26T16:03:48+00:00" }, { "name": "phpstan/phpstan-phpunit", - "version": "2.0.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "09e2d3b470bdda02824c626735153dfd962e3f29" + "reference": "3cc855474263ad6220dfa49167cbea34ca1dd300" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/09e2d3b470bdda02824c626735153dfd962e3f29", - "reference": "09e2d3b470bdda02824c626735153dfd962e3f29", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/3cc855474263ad6220dfa49167cbea34ca1dd300", + "reference": "3cc855474263ad6220dfa49167cbea34ca1dd300", "shasum": "" }, "require": { @@ -4805,7 +4804,6 @@ "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^9.6" }, - "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { @@ -4827,22 +4825,22 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.x" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.0" }, - "time": "2024-09-24T16:07:03+00:00" + "time": "2024-10-14T03:16:27+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "2.0.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "e208c9311872047b903511e2e03cb0df795014b0" + "reference": "a4a6a08bd4a461e516b9c3b8fdbf0f1883b34158" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/e208c9311872047b903511e2e03cb0df795014b0", - "reference": "e208c9311872047b903511e2e03cb0df795014b0", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/a4a6a08bd4a461e516b9c3b8fdbf0f1883b34158", + "reference": "a4a6a08bd4a461e516b9c3b8fdbf0f1883b34158", "shasum": "" }, "require": { @@ -4855,7 +4853,6 @@ "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^9.6" }, - "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { @@ -4876,9 +4873,9 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.0" }, - "time": "2024-09-30T19:35:25+00:00" + "time": "2024-10-26T16:04:33+00:00" }, { "name": "phpunit/php-code-coverage", From ae38fe5857f403ca466907d16e1265fead5f46d0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 11 Nov 2024 08:44:41 +0100 Subject: [PATCH 438/508] Remove changelog --- changelog-2.0.md | 216 ----------------------------------------------- 1 file changed, 216 deletions(-) delete mode 100644 changelog-2.0.md diff --git a/changelog-2.0.md b/changelog-2.0.md deleted file mode 100644 index b504a3281d..0000000000 --- a/changelog-2.0.md +++ /dev/null @@ -1,216 +0,0 @@ -When PHPStan 2.0 gets released, this will turn into [releases notes on GitHub](https://github.com/phpstan/phpstan/releases). - -Check out the [**UPGRADING guide**](https://github.com/phpstan/phpstan-src/blob/2.0.x/UPGRADING.md)!. - -Major new features 🚀 -===================== - -* **Level 10** - level 9 on steroids, treats all `mixed` types strictly, not just explicit `mixed` -* **Array `list` type** ([#1751](https://github.com/phpstan/phpstan-src/pull/1751)), #3311, #8185, #6243, thanks @rvanvelzen! - * Lists are arrays with sequential integer keys starting at 0 -* **Lower memory consumption** thanks to breaking up of reference cycles - * [Learn more »](https://phpstan.org/blog/preprocessing-ast-for-custom-rules) - * In testing the memory consumption was reduced by 50–70 %. -* **Enhancements in handling parameters passed by reference** - * [Learn more on phpstan.org](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) - * [#2941](https://github.com/phpstan/phpstan-src/pull/2941), thanks @ljmaskey! -* New rules (level 0): - * MagicConstantContextRule ([#2741](https://github.com/phpstan/phpstan-src/pull/2741)), #10099, thanks @staabm! - * MissingMagicSerializationMethodsRule ([#1711](https://github.com/phpstan/phpstan-src/pull/1711)), #7482, thanks @staabm! - * Check vprintf/vsprintf arguments against placeholder count ([#3126](https://github.com/phpstan/phpstan-src/pull/3126)), thanks @staabm! - * Check if required file exists ([#3294](https://github.com/phpstan/phpstan-src/pull/3294)), #3397, thanks @Bellangelo! - * Add `@readonly` rule that disallows default values ([#1391](https://github.com/phpstan/phpstan-src/pull/1391)), thanks @herndlm! - * Rule about `@phpstan-consistent-constructor` ([#1296](https://github.com/phpstan/phpstan-src/pull/1296)), thanks @canvural! - * Check code in custom PHPStan extensions for runtime reflection concepts like `is_a()` or `class_parents()` (https://github.com/phpstan/phpstan-src/commit/c4a662ac6c3ec63f063238880b243b5399c34fcc) - * Check code in custom PHPStan extensions for runtime reflection concepts like `new ReflectionMethod()` (https://github.com/phpstan/phpstan-src/commit/536306611cbb5877b6565755cd07b87f9ccfdf08) - * ApiInstanceofRule - * Report `instanceof` of classes not covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/ff4d02d62a7a2e2c4d928d48d31d49246dba7139) - * Report `instanceof` of classes covered by backward compatibility promise but where the assumption might change (https://github.com/phpstan/phpstan-src/commit/996bc69fa977aa64f601bd82b8a0ae39be0cbeef) - * Check that PHPStan class in class constant fetch is covered by backward compatibility promise (https://github.com/phpstan/phpstan-src/commit/9e007251ce61788f6a0319a53f1de6cf801ed233) - * Previously absent type checks: - * Check existing classes in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/6838669976bf20232abde36ecdd52b1770fa50c9) - * Check nonexistent classes in local type aliases (https://github.com/phpstan/phpstan-src/commit/2485b2e9c129e789ec3b2d7db81ca30f87c63911) - * Check unresolvable types in local type aliases (https://github.com/phpstan/phpstan-src/commit/5f7d12b2fb2809525ab0e96eeae95093204ea4d3) - * Check generics in local type aliases (https://github.com/phpstan/phpstan-src/commit/5a2d4416d94ab77a2a2e7e1bfaba4c5ed2a13c25) - * Check existing classes in `@param-out` (https://github.com/phpstan/phpstan-src/commit/30c4b9e80f51af8b5f166ba3aae93d8409c9c0ea), #10260 - * Check existing classes in `@param-closure-this` (https://github.com/phpstan/phpstan-src/commit/2fa539a39e06bcc3155b109fd8d246703ceb176d), #10933 -* New rules (level 2): - * **Validate inline PHPDoc `@var` tag** type against native type (https://github.com/phpstan/phpstan-src/commit/a69e3bc2f1e87f6da1e65d7935f1cc36bd5c42fe) - * Set [`reportWrongPhpDocTypeInVarTag`](https://phpstan.org/config-reference#reportwrongphpdoctypeinvartag) to `true` to have all types validated, not just native ones - * Use config option `reportAnyTypeWideningInVarTag: true` for stricter behaviour ([#2840](https://github.com/phpstan/phpstan-src/pull/2840)), thanks @janedbal! - * IncompatibleDefaultParameterTypeRule for closures (https://github.com/phpstan/phpstan-src/commit/0264f5bc48448c7e02a23b82eef4177d0617a82f) - * Checking truthiness of `@phpstan-pure` above functions and methods - * Check variance of template types in properties ([#2314](https://github.com/phpstan/phpstan-src/pull/2314)), thanks @jiripudil! - * Report narrowing `PHPStan\Type\Type` interface via `@var` (https://github.com/phpstan/phpstan-src/commit/713b98fb107213c28e3d8c8b4b43c5f5fc47c144), https://github.com/nunomaduro/larastan/issues/1567#issuecomment-1460445389 - * Previously absent type checks: - * Check `@mixin` PHPDoc tag above traits (https://github.com/phpstan/phpstan-src/commit/0d0de946900adf4eb3c799b1b547567536e23147) - * Check `@extends`, `@implements`, `@use` for unresolvable types (https://github.com/phpstan/phpstan-src/commit/2bb528233edb75312614166e282776f279cf2018), #11552 - * Check types in `@method` tags (https://github.com/phpstan/phpstan-src/commit/5b7e474680eaf33874b7ed6a227677adcbed9ca5) - * Check generics `@method` `@template` tags above traits (https://github.com/phpstan/phpstan-src/commit/aadbf62d3ae4517fc7a212b07130bedcef8d13ac) - * Check types in `@property` tags (https://github.com/phpstan/phpstan-src/commit/55ea2ae516df22a071ab873fdd6f748a3af0520e), #10752, #9356 -* New rule (level 3): - * ArrayUnpackingRule ([#856](https://github.com/phpstan/phpstan-src/pull/856)), thanks @canvural! -* New rules (level 4): - * Check too wide private property type (https://github.com/phpstan/phpstan-src/commit/7453f4f75fae3d635063589467842aae29d88b54) - * LogicalXorConstantConditionRule (https://github.com/phpstan/phpstan-src/commit/3a12724fd636b1bcf36c22b36e8f765d97150895, https://github.com/phpstan/phpstan-src/commit/3b011f6524254dad0f16840fdcfdbe7421548617), #7539 - * Check that each trait is used and analysed at least once (https://github.com/phpstan/phpstan-src/commit/c4d05276fb8605d6ac20acbe1cc5df31cd6c10b0) - * Report useless return values of function calls like `var_export` without `$return=true` ([#3225](https://github.com/phpstan/phpstan-src/pull/3225)), #11320, thanks @staabm! - * ConstantLooseComparisonRule (https://github.com/phpstan/phpstan-src/commit/6ebf2361a3c831dd105a815521889428c295dc9f) - * Check `new`/function call/method call/static method call on a separate line without any side effects even without `@phpstan-pure` PHPDoc tag on the declaration side - * https://github.com/phpstan/phpstan-src/commit/281a87d1ab61809076ecfa6dfc2cc86e3babe235 - * [#3020](https://github.com/phpstan/phpstan-src/pull/3020), thanks @staabm! - * [#3022](https://github.com/phpstan/phpstan-src/pull/3022), thanks @staabm! - * [#3023](https://github.com/phpstan/phpstan-src/pull/3023), thanks @staabm! - * Always report always true conditions, except for last elseif and match arm (https://github.com/phpstan/phpstan-src/commit/565fb0f6da9cdc58e8686598015561a848693972) - * Remove "unreachable branches" rules: UnreachableIfBranchesRule, UnreachableTernaryElseBranchRule, unreachable arm error in MatchExpressionRule - * Because "always true" is always reported, these are no longer needed -* New rules (level 5): - * Check preg_quote delimiter sanity ([#3252](https://github.com/phpstan/phpstan-src/pull/3252)), #11338, thanks @staabm! - * Rule for `call_user_func()` ([#2479](https://github.com/phpstan/phpstan-src/pull/2479)), thanks @staabm! - * Report useless `array_filter()` calls ([#1077](https://github.com/phpstan/phpstan-src/pull/1077)), #6840, thanks @leongersen! - * Report useless `array_values()` calls ([#2917](https://github.com/phpstan/phpstan-src/pull/2917)), thanks @kamil-zacek! - * Check array functions which require stringish values ([#3132](https://github.com/phpstan/phpstan-src/pull/3132)), #11141, #5848, #3694, #11111, thanks @schlndh! - * Check unresolvable parameters ([#1319](https://github.com/phpstan/phpstan-src/pull/1319)), thanks @rvanvelzen! - * Enforce `@no-named-arguments` (https://github.com/phpstan/phpstan-src/commit/74ba8c23696948f2647d880df72f375346f41010), #5968 -* New rules (level 6): - * Previously absent type checks: - * Check missing types in `@phpstan-self-out` (https://github.com/phpstan/phpstan-src/commit/892b319f25f04bc1b55c3d0063b607909612fe6d) - * Check missing types in local type aliases (https://github.com/phpstan/phpstan-src/commit/ce7ffaf02d624a7fb9d38f8e5dffc9739f1233fc) - * Check missing types in `@mixin` (https://github.com/phpstan/phpstan-src/commit/3175c81f26fd5bcb4a161b24e774921870ed2533) -* New option: `polluteScopeWithBlock` (defaults to `true`, `false` in `phpstan-strict-rules`) (https://github.com/phpstan/phpstan-src/commit/946cf180c960930c2c42075d0f28ff9090507272) -* Support `@readonly` property and `@immutable` class PHPDoc ([#1295](https://github.com/phpstan/phpstan-src/pull/1295), [#1335](https://github.com/phpstan/phpstan-src/pull/1335)), #4082, thanks @herndlm! -* Deprecate various `instanceof *Type` in favour of new methods on `Type` interface, (https://github.com/phpstan/phpstan-src/commit/436e6d3015cbeba4645d38bc7a6a865b9c6d7c74), learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) - - -Improvements 🔧 -===================== - -* TableErrorFormatter - always output identifiers (https://github.com/phpstan/phpstan-src/commit/fc66c24113e9fe88c3155703224eb03768846fdd) -* Config option `exceptions.check.tooWideThrowType` made true by default (https://github.com/phpstan/phpstan-src/commit/1b1da3e2ce3acf10dde03d9656638cda4f7389a4) -* Use `implicitThrows` to only look for explicit throw points in too-wide `@throws` rules when set to `false` (https://github.com/phpstan/phpstan-src/commit/a0e688c1d1e4c5e82f989b26485eb9162f47aa97) -* Rules about tooWideThrowType moved to level 4 (https://github.com/phpstan/phpstan-src/commit/d7798d7f2c47f426efe91c566e6cafd5a4e2410c) -* Both .php and .neon baselines now include error identifiers (https://github.com/phpstan/phpstan-src/commit/f38addda2b151b6e41a746a37659c0bbe9e2293b, https://github.com/phpstan/phpstan-src/commit/c8b7ea9e8f51c8bbc38dfa6b04f9a0172f5cfea0) -* PHPDoc parser: Require whitespace before description with limited start tokens (https://github.com/phpstan/phpdoc-parser/pull/128), https://github.com/phpstan/phpdoc-parser/issues/125, thanks @rvanvelzen! -* Unescape strings in PHPDoc parser (https://github.com/phpstan/phpstan-src/commit/97786ed8376b478ec541ea9df1c450c1fbfe7461) -* PHPDoc parser: add config for lines in its AST & enable ignoring errors within PHPDocs ([#2807](https://github.com/phpstan/phpstan-src/pull/2807)), thanks @janedbal! -* InvalidPhpDocTagValueRule: include PHPDoc line number in the error message (https://github.com/phpstan/phpstan-src/commit/a04e0be832900749b5b4ba22e2de21db8bfa09a0) -* No implicit wildcard in FileExcluder (https://github.com/phpstan/phpstan-src/commit/e19e6e5f8cfa706cc30e44a17276a6bc269f995c), #10299 -* Report invalid exclude paths in PHP config (https://github.com/phpstan/phpstan-src/commit/9718c14f1ffac81ba3d2bf331b4e8b4041a4d004) -* Do not generalize template types, except when in `GenericObjectType` ([#2818](https://github.com/phpstan/phpstan-src/pull/2818), [#2821](https://github.com/phpstan/phpstan-src/pull/2821)) - * This fixes following **20 issues**: #8166, #8127, #7944, #7283, #6653, #6196, #9084, #8683, #8074, #7984, #7301, #7087, #5594, #5592, #9472, #9764, #10092, #11126, #11032, #10653 -* Non-static methods cannot be used as static callables in PHP 8+ ([#2420](https://github.com/phpstan/phpstan-src/pull/2420)), thanks @staabm! -* Analysis with zero files results in non-zero exit code (https://github.com/phpstan/phpstan-src/commit/46ff440648e62617df86aa74ba905ffa99897737), #9410 -* Fail build when project config uses custom extensions outside of analysed paths - * This will only occur after a run that uses already present and valid result cache -* Returning plain strings as errors no longer supported, use RuleErrorBuilder - * Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) -* Require identifier in custom rules (https://github.com/phpstan/phpstan-src/commit/969e6fa31d5484d42dab902703cfc6820a983cfd) -* New `RuleLevelHelper::accepts()` behaviour (https://github.com/phpstan/phpstan-src/commit/941fc815db49315b8783dc466cf593e0d8a85d23), #11119, #4174 -* Infer explicit mixed when instantiating generic class with unknown template types (https://github.com/phpstan/phpstan-src/commit/089d4c6fb6eb709c44123548d33990113d174b86), #6398 -* Use explicit mixed for global array variables ([#1411](https://github.com/phpstan/phpstan-src/pull/1411)), #7082, thanks @herndlm! -* Consider implicit throw points when the only explicit one is `Throw_` (https://github.com/phpstan/phpstan-src/commit/22eef6d5ab9a4afafb2305258fea273be6cc06e4), #4912 -* Run missing type check on `@param-out` (https://github.com/phpstan/phpstan-src/commit/56b20024386d983927c64dfa895ff026bed2798c) -* Report "missing return" error closer to where the return is missing (https://github.com/phpstan/phpstan-src/commit/04f8636e6577cbcaefc944725eed74c0d7865ead) -* Report dead types even in multi-exception catch ([#2399](https://github.com/phpstan/phpstan-src/pull/2399)), thanks @JanTvrdik! -* MethodSignatureRule - look at abstract trait method (https://github.com/phpstan/phpstan-src/commit/5fd8cee591ce1b07daa5f98a1ddcdfc723f1b5eb) -* OverridingMethodRule - include template types in prototype declaring class description (https://github.com/phpstan/phpstan-src/commit/ca2c66cc4dff59ba44d52b82cb9e0aa3256240f3) -* Detect overriding `@final` method in OverridingMethodRule, #9135 -* Improve error wording of the NonexistentOffset, BooleanAndConstantConditionRule, and BooleanOrConstantConditionRule ([#1882](https://github.com/phpstan/phpstan-src/pull/1882)), thanks @VincentLanglet! -* Stricter ++/-- operator check ([#3255](https://github.com/phpstan/phpstan-src/pull/3255)), thanks @schlndh! -* Check mixed in binary operator ([#3231](https://github.com/phpstan/phpstan-src/pull/3231)), #7538, #10440, thanks @schlndh! -* Check mixed in unary operator ([#3253](https://github.com/phpstan/phpstan-src/pull/3253)), thanks @schlndh! -* Stub files validation - detect duplicate classes and functions (https://github.com/phpstan/phpstan-src/commit/ddf8d5c3859c2c75c20f525a0e2ca8b99032373a, https://github.com/phpstan/phpstan-src/commit/17e4b74335e5235d7cd6708eb687a774a0eeead4) -* NoopRule - take advantage of impure points (https://github.com/phpstan/phpstan-src/commit/a6470521b65d7424f552633c1f3827704c6262c3), #10389 -* Improve impossible type checker for void-returning functions ([#1857](https://github.com/phpstan/phpstan-src/pull/1857)), #8169, thanks @rvanvelzen! -* Check template type variance in `@param-out` (https://github.com/phpstan/phpstan-src/commit/7ceb19d3b42cf4632d10c2babb0fc5a21b6c8352), https://github.com/phpstan/phpstan/issues/8880#issuecomment-1426971473 -* Fix position variance of static method parameters ([#2313](https://github.com/phpstan/phpstan-src/pull/2313)), thanks @jiripudil! -* Empty `skipCheckGenericClasses` (https://github.com/phpstan/phpstan-src/commit/28c2c79b16cac6ba6b01f1b4d211541dd49d8a77) -* Report unnecessary nullsafe property fetch inside `??` / `isset` / `empty` with different message ([#1253](https://github.com/phpstan/phpstan-src/pull/1253)), thanks @rajyan! -* Specify explicit mixed array type via `is_array` ([#1191](https://github.com/phpstan/phpstan-src/pull/1191)), thanks @herndlm! -* TooWideMethodReturnTypehintRule - always report for final methods (https://github.com/phpstan/phpstan-src/commit/c30e9a484c8245b8126cd63444607ca74d2af761) -* Move IllegalConstructorMethodCallRule and IllegalConstructorStaticCallRule to phpstan-strict-rules (https://github.com/phpstan/phpstan-src/commit/124b30f98c182193187be0b9c2e151e477429b7a, https://github.com/phpstan/phpstan-strict-rules/commit/0c82c96f2a55d8b91bbc7ee6512c94f68a206b43) -* Check invalid PHPDocs in previously unchecked statement types (https://github.com/phpstan/phpstan-src/commit/9780d352f3264aac09ac7954f691de1877db8e01) -* InvalidPHPStanDocTagRule in StubValidator (https://github.com/phpstan/phpstan-src/commit/9c2552b7e744926d1a74c1ba8fd32c64079eed61) -* CallToConstructorStatementWithoutSideEffectsRule - report class with no constructor (https://github.com/phpstan/phpstan-src/commit/b116d25a6e4ba6c09f59af6569d9e6f6fd20aff4) -* ContainerFactory - always check duplicate files (https://github.com/phpstan/phpstan-src/commit/939a715a0636ed05752659dbe7646c1f1a574765) -* Display parent class name for anonymous class like native PHP does ([#3362](https://github.com/phpstan/phpstan-src/pull/3362)), thanks @mvorisek! -* Always report static property fetch in `isset()`, not just on PHP 8.2+ ([#3476](https://github.com/phpstan/phpstan-src/pull/3476)), thanks @ondrejmirtes! -* Revert "Dumb down parameter types in some recently added stubs" (https://github.com/phpstan/phpstan-src/commit/950a491485c46068074ca3f4f6dc5b970d41465a) -* Do not apply heuristics of `Collection<...>|Foo[]` being resolved to Collection of Foo (https://github.com/phpstan/phpstan-src/commit/fff8f095988a66f298aa4037fe8e6ba98266063c) -* Collected PHP errors cannot be ignored (https://github.com/phpstan/phpstan-src/commit/1d3f4313955dc6fa5c6ce60fa58afe765964e5b0) -* Added missing rules to StubValidator (https://github.com/phpstan/phpstan-src/commit/bf19914cac1682d0eab8bf65a874ba368522311c) -* Report precise offsets in errors ([#3504](https://github.com/phpstan/phpstan-src/pull/3504)), thanks @ruudk! -* IntersectionType - always describe list as list (https://github.com/phpstan/phpstan-src/commit/f680629bc92e4dd5d7acd3bc60c9539fb047452b) -* ArrayType::describe - explicit mixed should be stated explicitly (https://github.com/phpstan/phpstan-src/commit/6cf223840f89c972551f373ade9eea16d12e143b) -* Refactor IntersectionType::describe() (https://github.com/phpstan/phpstan-src/commit/67fbfaee6585c2d47485dc2a159ee76d3ed02b35) -* Remove inefficient caching from `PhpMethodReflection` and `PhpFunctionReflection::isVariadic()` ([#3534](https://github.com/phpstan/phpstan-src/pull/3534)), thanks @staabm! -* Clean file cache from unused items (https://github.com/phpstan/phpstan-src/commit/466ad51740d629c9137a77dac28a676b71ef7197) -* Journal for used generated containers (https://github.com/phpstan/phpstan-src/commit/57c65888e6372a4056afbbacc8207d411ea8559a) -* Use named argument in error for variadic types ([#3611](https://github.com/phpstan/phpstan-src/pull/3611)), thanks @ruudk! - -Bugfixes 🐛 -===================== - -* Fix invariance composition ([#2054](https://github.com/phpstan/phpstan-src/pull/2054)), thanks @jiripudil! -* Fix checking generic `mixed` type based on config ([#2885](https://github.com/phpstan/phpstan-src/pull/2885)), thanks @schlndh! - - -Function signature fixes 🤖 -======================= - -* Countable stub with `0|positive-int` ([#1027](https://github.com/phpstan/phpstan-src/pull/1027)), thanks @staabm! -* More precise types for bcmath function parameters ([#2217](https://github.com/phpstan/phpstan-src/pull/2217)), thanks @Warxcell! -* Specify `Imagick` parameter types ([#2334](https://github.com/phpstan/phpstan-src/pull/2334)), thanks @zonuexe! -* `max()`/`min()` should expect non-empty-array ([#2163](https://github.com/phpstan/phpstan-src/pull/2163)), thanks @staabm! -* Narrow `Closure::bind` `$newScope` param ([#2817](https://github.com/phpstan/phpstan-src/pull/2817)), thanks @mvorisek! -* `error_log` errors with `message_type=2` ([#2428](https://github.com/phpstan/phpstan-src/pull/2428)), #9380, thanks @staabm! -* Update functionMap ([#2699](https://github.com/phpstan/phpstan-src/pull/2699), [#2783](https://github.com/phpstan/phpstan-src/pull/2783)), thanks @zonuexe! -* Improve image related functions signature ([#3127](https://github.com/phpstan/phpstan-src/pull/3127)), thanks @thg2k! -* Support `FILE_NO_DEFAULT_CONTEXT` in `file()` ([#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! -* Fix ftp related function signatures ([#2551](https://github.com/phpstan/phpstan-src/pull/2551)), thanks @thg2k! -* More precise `file()` flags args ([#2476](https://github.com/phpstan/phpstan-src/pull/2476), [#2482](https://github.com/phpstan/phpstan-src/pull/2482)), thanks @staabm! -* More precise `flock()` operation flags ([#2477](https://github.com/phpstan/phpstan-src/pull/2477)), thanks @staabm! -* More precise `stream_socket_client()` signature ([#2519](https://github.com/phpstan/phpstan-src/pull/2519)), thanks @staabm! -* More precise `scandir()` signature ([#2518](https://github.com/phpstan/phpstan-src/pull/2518)), thanks @staabm! -* More precise `extract()` signature ([#2517](https://github.com/phpstan/phpstan-src/pull/2517)), thanks @staabm! -* More precise `RecursiveIteratorIterator::__construct()` parameter types ([#2835](https://github.com/phpstan/phpstan-src/pull/2835)), thanks @staabm! -* Update `Locale` signatures ([#2880](https://github.com/phpstan/phpstan-src/pull/2880)), thanks @devnix! -* Improved the type of the `$mode` parameter for the `count()` ([#3190](https://github.com/phpstan/phpstan-src/pull/3190)), thanks @kuma3!* Check `filter_input*` type param type ([#2271](https://github.com/phpstan/phpstan-src/pull/2271)), thanks @herndlm! -* Change `curl_setopt` function signature based on 2nd arg ([#1719](https://github.com/phpstan/phpstan-src/pull/1719)), thanks @staabm! -* Support returning an array or a string in `count_chars()` ([#3596](https://github.com/phpstan/phpstan-src/pull/3596)), thanks @u01jmg3! -* xdebug_get_function_stack: fix signature ([#3605](https://github.com/phpstan/phpstan-src/pull/3605)), thanks @janedbal! - - -Internals 🔍 -===================== - -* Tool to make optional parameters required across the codebase (https://github.com/phpstan/phpstan-src/commit/7e366e08f96e2e4095b3f02b5487e8f9531f37bf) -* A few more MutatingScope method parameters made required (https://github.com/phpstan/phpstan-src/commit/2c4c0cde75e637ac323e81def57d4a2ace952429) -* CommandHelper::begin() parameters made required (https://github.com/phpstan/phpstan-src/commit/f17cf9ec43111cb29dd50d620fb6259c0ab0d373) -* MethodTag - constructor parameter `$templateTags` is required (https://github.com/phpstan/phpstan-src/commit/5b58f83e6d8b5044d742caed9729d00178c4a9de) -* InitializerExprTypeResolver - constructor parameter `$usePathConstantsAsConstantString` made required (https://github.com/phpstan/phpstan-src/commit/f88d9ba7f56ef6c3b783aee1c909a3422c0ef3c3) -* `PhpMethodReflectionFactory::create()` - all parameters are required (https://github.com/phpstan/phpstan-src/commit/8bfbf8f254a68e4f1b15419eb950ea677fc2916e) -* FunctionCallParametersCheck - parameters `$nodeType` and `$acceptsNamedArguments` made required (https://github.com/phpstan/phpstan-src/commit/493752737c32eb878de4dfb91817761b952348e4) -* MethodParameterComparisonHelper - parameter `$ignorable` of `compare()` method made required (https://github.com/phpstan/phpstan-src/commit/f85a500288b0b8ef9a19d405c0e3d99ab57ce797) -* Parameter `$dateTimeClass` of DateTimeModifyReturnTypeExtension constructor made required (https://github.com/phpstan/phpstan-src/commit/a8cd423e842deaa7d924580665207a4b1a373115) -* NativeFunctionReflection construct parameters made required (https://github.com/phpstan/phpstan-src/commit/64ff598cd42268d2178d02efd208afe637060978) -* Cover AccessoryArrayListType constructor with BC promise (https://github.com/phpstan/phpstan-src/commit/51de9032c6e98bff2d6eb0e5b7295720ec0276b9) -* Add `PhpVersion` parameter to various `Type` methods ([#3478](https://github.com/phpstan/phpstan-src/pull/3478)), thanks @VincentLanglet! -* Move ContainerDynamicReturnTypeExtension to build/PHPStan (https://github.com/phpstan/phpstan-src/commit/5651bec661582b2d62de1b4ae9d5f27e69e3c524) -* Renamed NewOptimizedDirectorySourceLocator to OptimizedDirectorySourceLocator (https://github.com/phpstan/phpstan-src/commit/db02a30ca11c7b9839c30e0321ed403dd14f6c73) -* Remove unneded abstraction (https://github.com/phpstan/phpstan-src/commit/f302c9069274afa63ec1b4f313ca72340699e9d8) -* Introduce native return types thanks to PHP 7.4 return type covariance (https://github.com/phpstan/phpstan-src/commit/392f090066bfc9946b4ad524ffecf3d420c23114) -* ReadWritePropertiesExtension - use ExtendedPropertyReflection in parameter type (https://github.com/phpstan/phpstan-src/commit/f0a629685de2202687b9f92bd0e1a516daf2443e) -* Declare more precise `getClass()` return types in extension interfaces ([#1754](https://github.com/phpstan/phpstan-src/pull/1754)), thanks @staabm! -* (https://github.com/phpstan/phpstan-src/commit/38cb5a315e5573231d8695df343c8ee87a8c3b2e) -* HasOffsetType - put constructor parameter type natively (https://github.com/phpstan/phpstan-src/commit/b5accb3f6bbcffc8a44934539b88903e09b6a174) -* Printer is covered by BC promise (https://github.com/phpstan/phpstan-src/commit/b0858332efc7aa2f2fde7544a2a821ba81bde13b) -* More interfaces that are not supposed to be implemented in userland (https://github.com/phpstan/phpstan-src/commit/778af2ed74ba59bfb2a69fd5b45821ccdb1107c9, https://github.com/phpstan/phpstan-src/commit/cb6ab5544a016c52f931fc390bcdf9c627819d8f) -* Refactored `FunctionCallParametersCheck::check()` parameters (https://github.com/phpstan/phpstan-src/commit/710e09c41698efb1d8d3ae31791944077dbb9cc1) -* Spread list usages in Reflection, Scope, Type ([#3530](https://github.com/phpstan/phpstan-src/pull/3530)), thanks @janedbal! -* Remove $isFinal dead-code in PhpFunctionReflection ([#3545](https://github.com/phpstan/phpstan-src/pull/3545)), thanks @staabm! -* Get rid of unnecessary `instanceof self` in `ConstantArrayType` ([#3552](https://github.com/phpstan/phpstan-src/pull/3552)), thanks @herndlm! -* test: use `bashunit -a` exit_code to check for errors ([#3533](https://github.com/phpstan/phpstan-src/pull/3533)), thanks @Chemaclass! -* Upgrade bashunit:0.18.0 for e2e tests ([#3614](https://github.com/phpstan/phpstan-src/pull/3614)), thanks @Chemaclass! -* Remove dead code ([#3575](https://github.com/phpstan/phpstan-src/pull/3575)), thanks @staabm! -* Remove dead code in ConstantConditionRuleHelper ([#3597](https://github.com/phpstan/phpstan-src/pull/3597)), thanks @staabm! From 6b52c1dda46ce625de4375f1a3d39c54aa5d6b4b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 11 Nov 2024 08:44:51 +0100 Subject: [PATCH 439/508] Update issue-bot --- issue-bot/composer.lock | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/issue-bot/composer.lock b/issue-bot/composer.lock index be0c051842..b4abdf4947 100644 --- a/issue-bot/composer.lock +++ b/issue-bot/composer.lock @@ -1403,16 +1403,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.0.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "f347f223a7235178f056f34dc104557095998614" + "reference": "72115ab2bf1e40af1f9b238938d493ba7f3221e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f347f223a7235178f056f34dc104557095998614", - "reference": "f347f223a7235178f056f34dc104557095998614", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/72115ab2bf1e40af1f9b238938d493ba7f3221e7", + "reference": "72115ab2bf1e40af1f9b238938d493ba7f3221e7", "shasum": "" }, "require": { @@ -1421,7 +1421,6 @@ "conflict": { "phpstan/phpstan-shim": "*" }, - "default-branch": true, "bin": [ "phpstan", "phpstan.phar" @@ -1458,20 +1457,20 @@ "type": "github" } ], - "time": "2024-09-30T19:33:02+00:00" + "time": "2024-11-11T07:06:55+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "2.0.x-dev", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "e208c9311872047b903511e2e03cb0df795014b0" + "reference": "a4a6a08bd4a461e516b9c3b8fdbf0f1883b34158" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/e208c9311872047b903511e2e03cb0df795014b0", - "reference": "e208c9311872047b903511e2e03cb0df795014b0", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/a4a6a08bd4a461e516b9c3b8fdbf0f1883b34158", + "reference": "a4a6a08bd4a461e516b9c3b8fdbf0f1883b34158", "shasum": "" }, "require": { @@ -1484,7 +1483,6 @@ "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^9.6" }, - "default-branch": true, "type": "phpstan-extension", "extra": { "phpstan": { @@ -1505,9 +1503,9 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.0" }, - "time": "2024-09-30T19:35:25+00:00" + "time": "2024-10-26T16:04:33+00:00" }, { "name": "psr/cache", @@ -4471,12 +4469,12 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.3" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } From 6517446a99d70c75015e6fc2990adba63a662913 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 11 Nov 2024 08:45:41 +0100 Subject: [PATCH 440/508] Upgrading guide will only be in phpstan/phpstan --- .github/workflows/phar.yml | 3 - UPGRADING.md | 338 ------------------------------------- 2 files changed, 341 deletions(-) delete mode 100644 UPGRADING.md diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index 28d8d8b36b..dcc27d6be7 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -211,9 +211,6 @@ jobs: env: GPG_ID: ${{ steps.import-gpg.outputs.fingerprint }} - - name: "cp UPGRADING.md" - run: cp phpstan-src/UPGRADING.md phpstan-dist/UPGRADING.md - - name: "Verify PHAR" working-directory: phpstan-dist run: "gpg --verify phpstan.phar.asc" diff --git a/UPGRADING.md b/UPGRADING.md deleted file mode 100644 index 1b76768ec4..0000000000 --- a/UPGRADING.md +++ /dev/null @@ -1,338 +0,0 @@ -Upgrading from PHPStan 1.x to 2.0 -================================= - -## PHP version requirements - -PHPStan now requires PHP 7.4 or newer to run. - -## Upgrading guide for end users - -The best way to get ready for upgrade to PHPStan 2.0 is to update to the **latest PHPStan 1.12 release** -and enable [**Bleeding Edge**](https://phpstan.org/blog/what-is-bleeding-edge). This will enable the new rules and behaviours that 2.0 turns on for all users. - -Also make sure to install and enable [`phpstan/phpstan-deprecation-rules`](https://github.com/phpstan/phpstan-deprecation-rules). - -Once you get to a green build with no deprecations showed on latest PHPStan 1.12.x with Bleeding Edge enabled, you can update all your related PHPStan dependencies to 2.0 in `composer.json`: - -```json -"require-dev": { - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-deprecation-rules": "^2.0", - "phpstan/phpstan-doctrine": "^2.0", - "phpstan/phpstan-nette": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpstan/phpstan-symfony": "^2.0", - "phpstan/phpstan-webmozart-assert": "^2.0", - ... -} -``` - -Don't forget to update [3rd party PHPStan extensions](https://phpstan.org/user-guide/extension-library) as well. - -After changing your `composer.json`, run `composer update 'phpstan/*' -W`. - -It's up to you whether you go through the new reported errors or if you just put them all to the [baseline](https://phpstan.org/user-guide/baseline) ;) Everyone who's on PHPStan 1.12 should be able to upgrade to PHPStan 2.0. - -### Noteworthy changes to code analysis - -* [**Enhancements in handling parameters passed by reference**](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) -* [**Validate inline PHPDoc `@var` tag type**](https://phpstan.org/blog/phpstan-1-10-comes-with-lie-detector#validate-inline-phpdoc-%40var-tag-type) -* [**List type enforced**](https://phpstan.org/blog/phpstan-1-9-0-with-phpdoc-asserts-list-type#list-type) -* **Always `true` conditions always reported**: previously reported only with phpstan-strict-rules, this is now always reported. - -### Removed option `checkMissingIterableValueType` - -It's strongly recommended to add the missing array typehints. - -If you want to continue ignoring missing typehints from arrays, add `missingType.iterableValue` error identifier to your `ignoreErrors`: - -```neon -parameters: - ignoreErrors: - - - identifier: missingType.iterableValue -``` - -### Removed option `checkGenericClassInNonGenericObjectType` - -It's strongly recommended to add the missing generic typehints. - -If you want to continue ignoring missing typehints from generics, add `missingType.generics` error identifier to your `ignoreErrors`: - -```neon -parameters: - ignoreErrors: - - - identifier: missingType.generics -``` - -### Removed `checkAlwaysTrue*` options - -These options have been removed because PHPStan now always behaves as if these were set to `true`: - -* `checkAlwaysTrueCheckTypeFunctionCall` -* `checkAlwaysTrueInstanceof` -* `checkAlwaysTrueStrictComparison` -* `checkAlwaysTrueLooseComparison` - -### Removed option `excludes_analyse` - -It has been replaced with [`excludePaths`](https://phpstan.org/user-guide/ignoring-errors#excluding-whole-files). - -### Paths in `excludePaths` and `ignoreErrors` have to be a valid file path or a fnmatch pattern - -If you are excluding a file path that might not exist but you still want to have it in `excludePaths`, append `(?)`: - -```neon -parameters: - excludePaths: - - tests/*/data/* - - src/broken - - node_modules (?) # optional path, might not exist -``` - -If you have the same situation in `ignoreErrors` (ignoring an error in a path that might not exist), use `reportUnmatchedIgnoredErrors: false`. - -```neon -parameters: - reportUnmatchedIgnoredErrors: false -``` - -Appending `(?)` in `ignoreErrors` is not supported. - -### Changes in 1st party PHPStan extensions - -* [phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine) - * Removed config parameter `searchOtherMethodsForQueryBuilderBeginning` (extension now behaves as when this was set to `true`) - * Removed config parameter `queryBuilderFastAlgorithm` (extension now behaves as when this was set to `false`) -* [phpstan-symfony](https://github.com/phpstan/phpstan-symfony) - * Removed legacy options with `_` in the name - * `container_xml_path` -> use `containerXmlPath` - * `constant_hassers` -> use `constantHassers` - * `console_application_loader` -> use `consoleApplicationLoader` - -### Minor backward compatibility breaks - -* Removed unused config parameter `cache.nodesByFileCountMax` -* Removed unused config parameter `memoryLimitFile` -* Removed unused feature toggle `disableRuntimeReflectionProvider` -* Removed unused config parameter `staticReflectionClassNamePatterns` -* Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead -* Remove `tempResultCachePath` config parameter, use `resultCachePath` instead -* `additionalConfigFiles` config parameter must be a list - -## Upgrading guide for extension developers - -> [!NOTE] -> Please switch to PHPStan 2.0 in a new major version of your extension. It's not feasible to try to support both PHPStan 1.x and PHPStan 2.x with the same extension code. -> -> You can definitely get closer to supporting PHPStan 2.0 without increasing major version by solving reported deprecations and other issues by analysing your extension code with PHPStan & phpstan-deprecation-rules & Bleeding Edge, but the final leap and solving backward incompatibilities should be done by requiring `"phpstan/phpstan": "^2.0"` in your `composer.json`, and releasing a new major version. - -### PHPStan now uses nikic/php-parser v5 - -See [UPGRADING](https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md) guide for PHP-Parser. - -The most notable change is how `throw` statement is represented. Previously, `throw` statements like `throw $e;` were represented using the `Stmt\Throw_` class, while uses inside other expressions (such as `$x ?? throw $e`) used the `Expr\Throw_` class. - -Now, `throw $e;` is represented as a `Stmt\Expression` that contains an `Expr\Throw_`. The -`Stmt\Throw_` class has been removed. - -### PHPStan now uses phpstan/phpdoc-parser v2 - -See [UPGRADING](https://github.com/phpstan/phpdoc-parser/blob/2.0.x/UPGRADING.md) guide for phpstan/phpdoc-parser. - -### Returning plain strings as errors no longer supported, use RuleErrorBuilder - -Identifiers are also required in custom rules. - -Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) - -**Before**: - -```php -return ['My error']; -``` - -**After**: - -```php -return [ - RuleErrorBuilder::message('My error') - ->identifier('my.error') - ->build(), -]; -``` - -### Deprecate various `instanceof *Type` in favour of new methods on `Type` interface - -Learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) - -### Removed deprecated `ParametersAcceptorSelector::selectSingle()` - -Use [`ParametersAcceptorSelector::selectFromArgs()`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ParametersAcceptorSelector.html#_selectFromArgs) instead. It should be used in most places where `selectSingle()` was previously used, like dynamic return type extensions. - -**Before**: - -```php -$defaultReturnType = ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); -``` - -**After**: - -```php -$defaultReturnType = ParametersAcceptorSelector::selectFromArgs( - $scope, - $functionCall->getArgs(), - $functionReflection->getVariants() -)->getReturnType(); -``` - -If you're analysing function or method body itself and you're using one of the following methods, ask for `getParameters()` and `getReturnType()` directly on the reflection object: - -* [InClassMethodNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InClassMethodNode.html) -* [InFunctionNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InFunctionNode.html) -* [FunctionReturnStatementsNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.FunctionReturnStatementsNode.html) -* [MethodReturnStatementsNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.MethodReturnStatementsNode.html) -* [Scope::getFunction()](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.Scope.html#_getFunction) - -**Before**: - -```php -$function = $node->getFunctionReflection(); -$returnType = ParametersAcceptorSelector::selectSingle($function->getVariants())->getReturnType(); -``` - -**After**: - -```php -$returnType = $node->getFunctionReflection()->getReturnType(); -``` - -### Changed `TypeSpecifier::create()` and `SpecifiedTypes` constructor parameters - -[`PHPStan\Analyser\TypeSpecifier::create()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.TypeSpecifier.html#_create) now accepts (all parameters are required): - -* `Expr $expr` -* `Type $type` -* `TypeSpecifierContext $context` -* `Scope $scope` - -If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by this method), call `setAlwaysOverwriteTypes()` and `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::create()`). These methods return a new object (SpecifiedTypes is immutable). - -[`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) constructor now accepts: - -* `array $sureTypes` -* `array $sureNotTypes` - -If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by the constructor), call `setAlwaysOverwriteTypes()` and `setRootExpr()`. These methods return a new object (SpecifiedTypes is immutable). - -### `ConstantArrayType` no longer extends `ArrayType` - -`Type::getArrays()` now returns `list`. - -Using `$type instanceof ArrayType` is [being deprecated anyway](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) so the impact of this change should be minimal. - -### Changed `TypeSpecifier::specifyTypesInCondition()` - -This method now longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable). - -### Node attributes `parent`, `previous`, `next` are no longer available - -Learn more: https://phpstan.org/blog/preprocessing-ast-for-custom-rules - -### Removed config parameter `scopeClass` - -As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtension`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.ExpressionTypeResolverExtension.html) interface instead and register it as a service. - -### Removed `PHPStan\Broker\Broker` - -Use [`PHPStan\Reflection\ReflectionProvider`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ReflectionProvider.html) instead. - -`BrokerAwareExtension` was also removed. Ask for `ReflectionProvider` in the extension constructor instead. - -Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createReflectionProvider()`. - -### List type is enabled for everyone - -Removed static methods from `AccessoryArrayListType` class: - -* `isListTypeEnabled()` -* `setListTypeEnabled()` -* `intersectWith()` - -Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::intersect($type, new AccessoryArrayListType())`. - -### Minor backward compatibility breaks - -* Classes that were previously `@final` were made `final` -* Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required -* Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required -* ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) -* `Type::getSmallerType()`, `Type::getSmallerOrEqualType()`, `Type::getGreaterType()`, `Type::getGreaterOrEqualType()`, `Type::isSmallerThan()`, `Type::isSmallerThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. -* `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. -* Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes) -* Remove `ArrayType::generalizeKeys()` -* Remove `ArrayType::count()`, use `Type::getArraySize()` instead -* Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead -* Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead -* Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead -* Remove unused `PHPStanTestCase::$useStaticReflectionProvider` -* Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead -* Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead -* Remove `AnalysisResult::getInternalErrors()`, use `getInternalErrorObjects()` instead -* Remove `ConstantReflection::getValue()`, use `getValueExpr()` instead. To get `Type` from `Expr`, use `Scope::getType()` or `InitializerExprTypeResolver::getType()` -* Remove `PropertyTag::getType()`, use `getReadableType()` / `getWritableType()` instead -* Remove `GenericTypeVariableResolver`, use [`Type::getTemplateType()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getTemplateType) instead -* Rename `Type::isClassStringType()` to `Type::isClassString()` -* Remove `Scope::isSpecified()`, use `hasExpressionType()` instead -* Remove `ConstantArrayType::isEmpty()`, use `isIterableAtLeastOnce()->no()` instead -* Remove `ConstantArrayType::getNextAutoIndex()` -* Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` - * Use `getFirstIterable*Type` and `getLastIterable*Type` instead -* Remove `ConstantArrayType::generalizeToArray()` -* Remove `ConstantArrayType::findTypeAndMethodName()`, use `findTypeAndMethodNames()` instead -* Remove `ConstantArrayType::removeLast()`, use [`Type::popArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_popArray) instead -* Remove `ConstantArrayType::removeFirst()`, use [`Type::shiftArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_shiftArray) instead -* Remove `ConstantArrayType::reverse()`, use [`Type::reverseArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_reverseArray) instead -* Remove `ConstantArrayType::chunk()`, use [`Type::chunkArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_chunkArray) instead -* Remove `ConstantArrayType::slice()`, use [`Type::sliceArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_sliceArray) instead -* Made `TypeUtils` thinner by removing methods: - * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead - * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead - * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead - * Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) - * Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead - * Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead - * Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead - * Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead - * Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead -* Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead -* Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer `bool` -* Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list`, no longer `int` -* Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead -* `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool` -* Remove `FunctionReflection::isFinal()` -* [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html) -* Remove `__set_state()` on objects that should not be serialized in cache -* Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts `string` -* `LevelsTestCase::dataTopics()` data provider made static -* `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint -* Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) -* Remove `CompoundType::isAcceptedWithReasonBy()`, `CompoundType::isAcceptedBy()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) -Remove `Type::isSuperTypeOfWithReason()`, `Type:isSuperTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) -* Remove `CompoundType::isSubTypeOfWithReasonBy()`, `CompoundType::isSubTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) -* Remove `TemplateType::isValidVarianceWithReason()`, changed `TemplateType::isValidVariance()` return type to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) -* `RuleLevelHelper::accepts()` return type changed from `bool` to [`RuleLevelHelperAcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) -* Changes around `ClassConstantReflection` - * Class `ClassConstantReflection` removed from BC promise, renamed to `RealClassConstantReflection` - * Interface `ConstantReflection` renamed to `ClassConstantReflection` - * Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection` - * Interface `GlobalConstantReflection` renamed to `ConstantReflection` -* Renamed interfaces and classes from `*WithPhpDocs` to `Extended*` - * `ParametersAcceptorWithPhpDocs` -> `ExtendedParametersAcceptor` - * `ParameterReflectionWithPhpDocs` -> `ExtendedParameterReflection` - * `FunctionVariantWithPhpDocs` -> `ExtendedFunctionVariant` -* `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null` -* Class `PHPStan\Node\ClassMethod` (accessible from `ClassMethodsNode`) is no longer an AST node - * Call `PHPStan\Node\ClassMethod::getNode()` to access the original AST node From 1f411b96eb130636d3cb3f663c29e8674fc2129a Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 11 Nov 2024 09:17:29 +0100 Subject: [PATCH 441/508] Revert "Upgrading guide will only be in phpstan/phpstan" This reverts commit 6517446a99d70c75015e6fc2990adba63a662913. --- UPGRADING.md | 338 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 UPGRADING.md diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 0000000000..1b76768ec4 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,338 @@ +Upgrading from PHPStan 1.x to 2.0 +================================= + +## PHP version requirements + +PHPStan now requires PHP 7.4 or newer to run. + +## Upgrading guide for end users + +The best way to get ready for upgrade to PHPStan 2.0 is to update to the **latest PHPStan 1.12 release** +and enable [**Bleeding Edge**](https://phpstan.org/blog/what-is-bleeding-edge). This will enable the new rules and behaviours that 2.0 turns on for all users. + +Also make sure to install and enable [`phpstan/phpstan-deprecation-rules`](https://github.com/phpstan/phpstan-deprecation-rules). + +Once you get to a green build with no deprecations showed on latest PHPStan 1.12.x with Bleeding Edge enabled, you can update all your related PHPStan dependencies to 2.0 in `composer.json`: + +```json +"require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-doctrine": "^2.0", + "phpstan/phpstan-nette": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/phpstan-symfony": "^2.0", + "phpstan/phpstan-webmozart-assert": "^2.0", + ... +} +``` + +Don't forget to update [3rd party PHPStan extensions](https://phpstan.org/user-guide/extension-library) as well. + +After changing your `composer.json`, run `composer update 'phpstan/*' -W`. + +It's up to you whether you go through the new reported errors or if you just put them all to the [baseline](https://phpstan.org/user-guide/baseline) ;) Everyone who's on PHPStan 1.12 should be able to upgrade to PHPStan 2.0. + +### Noteworthy changes to code analysis + +* [**Enhancements in handling parameters passed by reference**](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference) +* [**Validate inline PHPDoc `@var` tag type**](https://phpstan.org/blog/phpstan-1-10-comes-with-lie-detector#validate-inline-phpdoc-%40var-tag-type) +* [**List type enforced**](https://phpstan.org/blog/phpstan-1-9-0-with-phpdoc-asserts-list-type#list-type) +* **Always `true` conditions always reported**: previously reported only with phpstan-strict-rules, this is now always reported. + +### Removed option `checkMissingIterableValueType` + +It's strongly recommended to add the missing array typehints. + +If you want to continue ignoring missing typehints from arrays, add `missingType.iterableValue` error identifier to your `ignoreErrors`: + +```neon +parameters: + ignoreErrors: + - + identifier: missingType.iterableValue +``` + +### Removed option `checkGenericClassInNonGenericObjectType` + +It's strongly recommended to add the missing generic typehints. + +If you want to continue ignoring missing typehints from generics, add `missingType.generics` error identifier to your `ignoreErrors`: + +```neon +parameters: + ignoreErrors: + - + identifier: missingType.generics +``` + +### Removed `checkAlwaysTrue*` options + +These options have been removed because PHPStan now always behaves as if these were set to `true`: + +* `checkAlwaysTrueCheckTypeFunctionCall` +* `checkAlwaysTrueInstanceof` +* `checkAlwaysTrueStrictComparison` +* `checkAlwaysTrueLooseComparison` + +### Removed option `excludes_analyse` + +It has been replaced with [`excludePaths`](https://phpstan.org/user-guide/ignoring-errors#excluding-whole-files). + +### Paths in `excludePaths` and `ignoreErrors` have to be a valid file path or a fnmatch pattern + +If you are excluding a file path that might not exist but you still want to have it in `excludePaths`, append `(?)`: + +```neon +parameters: + excludePaths: + - tests/*/data/* + - src/broken + - node_modules (?) # optional path, might not exist +``` + +If you have the same situation in `ignoreErrors` (ignoring an error in a path that might not exist), use `reportUnmatchedIgnoredErrors: false`. + +```neon +parameters: + reportUnmatchedIgnoredErrors: false +``` + +Appending `(?)` in `ignoreErrors` is not supported. + +### Changes in 1st party PHPStan extensions + +* [phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine) + * Removed config parameter `searchOtherMethodsForQueryBuilderBeginning` (extension now behaves as when this was set to `true`) + * Removed config parameter `queryBuilderFastAlgorithm` (extension now behaves as when this was set to `false`) +* [phpstan-symfony](https://github.com/phpstan/phpstan-symfony) + * Removed legacy options with `_` in the name + * `container_xml_path` -> use `containerXmlPath` + * `constant_hassers` -> use `constantHassers` + * `console_application_loader` -> use `consoleApplicationLoader` + +### Minor backward compatibility breaks + +* Removed unused config parameter `cache.nodesByFileCountMax` +* Removed unused config parameter `memoryLimitFile` +* Removed unused feature toggle `disableRuntimeReflectionProvider` +* Removed unused config parameter `staticReflectionClassNamePatterns` +* Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead +* Remove `tempResultCachePath` config parameter, use `resultCachePath` instead +* `additionalConfigFiles` config parameter must be a list + +## Upgrading guide for extension developers + +> [!NOTE] +> Please switch to PHPStan 2.0 in a new major version of your extension. It's not feasible to try to support both PHPStan 1.x and PHPStan 2.x with the same extension code. +> +> You can definitely get closer to supporting PHPStan 2.0 without increasing major version by solving reported deprecations and other issues by analysing your extension code with PHPStan & phpstan-deprecation-rules & Bleeding Edge, but the final leap and solving backward incompatibilities should be done by requiring `"phpstan/phpstan": "^2.0"` in your `composer.json`, and releasing a new major version. + +### PHPStan now uses nikic/php-parser v5 + +See [UPGRADING](https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md) guide for PHP-Parser. + +The most notable change is how `throw` statement is represented. Previously, `throw` statements like `throw $e;` were represented using the `Stmt\Throw_` class, while uses inside other expressions (such as `$x ?? throw $e`) used the `Expr\Throw_` class. + +Now, `throw $e;` is represented as a `Stmt\Expression` that contains an `Expr\Throw_`. The +`Stmt\Throw_` class has been removed. + +### PHPStan now uses phpstan/phpdoc-parser v2 + +See [UPGRADING](https://github.com/phpstan/phpdoc-parser/blob/2.0.x/UPGRADING.md) guide for phpstan/phpdoc-parser. + +### Returning plain strings as errors no longer supported, use RuleErrorBuilder + +Identifiers are also required in custom rules. + +Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder) + +**Before**: + +```php +return ['My error']; +``` + +**After**: + +```php +return [ + RuleErrorBuilder::message('My error') + ->identifier('my.error') + ->build(), +]; +``` + +### Deprecate various `instanceof *Type` in favour of new methods on `Type` interface + +Learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) + +### Removed deprecated `ParametersAcceptorSelector::selectSingle()` + +Use [`ParametersAcceptorSelector::selectFromArgs()`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ParametersAcceptorSelector.html#_selectFromArgs) instead. It should be used in most places where `selectSingle()` was previously used, like dynamic return type extensions. + +**Before**: + +```php +$defaultReturnType = ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType(); +``` + +**After**: + +```php +$defaultReturnType = ParametersAcceptorSelector::selectFromArgs( + $scope, + $functionCall->getArgs(), + $functionReflection->getVariants() +)->getReturnType(); +``` + +If you're analysing function or method body itself and you're using one of the following methods, ask for `getParameters()` and `getReturnType()` directly on the reflection object: + +* [InClassMethodNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InClassMethodNode.html) +* [InFunctionNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InFunctionNode.html) +* [FunctionReturnStatementsNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.FunctionReturnStatementsNode.html) +* [MethodReturnStatementsNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.MethodReturnStatementsNode.html) +* [Scope::getFunction()](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.Scope.html#_getFunction) + +**Before**: + +```php +$function = $node->getFunctionReflection(); +$returnType = ParametersAcceptorSelector::selectSingle($function->getVariants())->getReturnType(); +``` + +**After**: + +```php +$returnType = $node->getFunctionReflection()->getReturnType(); +``` + +### Changed `TypeSpecifier::create()` and `SpecifiedTypes` constructor parameters + +[`PHPStan\Analyser\TypeSpecifier::create()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.TypeSpecifier.html#_create) now accepts (all parameters are required): + +* `Expr $expr` +* `Type $type` +* `TypeSpecifierContext $context` +* `Scope $scope` + +If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by this method), call `setAlwaysOverwriteTypes()` and `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::create()`). These methods return a new object (SpecifiedTypes is immutable). + +[`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) constructor now accepts: + +* `array $sureTypes` +* `array $sureNotTypes` + +If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by the constructor), call `setAlwaysOverwriteTypes()` and `setRootExpr()`. These methods return a new object (SpecifiedTypes is immutable). + +### `ConstantArrayType` no longer extends `ArrayType` + +`Type::getArrays()` now returns `list`. + +Using `$type instanceof ArrayType` is [being deprecated anyway](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) so the impact of this change should be minimal. + +### Changed `TypeSpecifier::specifyTypesInCondition()` + +This method now longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable). + +### Node attributes `parent`, `previous`, `next` are no longer available + +Learn more: https://phpstan.org/blog/preprocessing-ast-for-custom-rules + +### Removed config parameter `scopeClass` + +As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtension`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.ExpressionTypeResolverExtension.html) interface instead and register it as a service. + +### Removed `PHPStan\Broker\Broker` + +Use [`PHPStan\Reflection\ReflectionProvider`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ReflectionProvider.html) instead. + +`BrokerAwareExtension` was also removed. Ask for `ReflectionProvider` in the extension constructor instead. + +Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createReflectionProvider()`. + +### List type is enabled for everyone + +Removed static methods from `AccessoryArrayListType` class: + +* `isListTypeEnabled()` +* `setListTypeEnabled()` +* `intersectWith()` + +Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::intersect($type, new AccessoryArrayListType())`. + +### Minor backward compatibility breaks + +* Classes that were previously `@final` were made `final` +* Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required +* Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required +* ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties) +* `Type::getSmallerType()`, `Type::getSmallerOrEqualType()`, `Type::getGreaterType()`, `Type::getGreaterOrEqualType()`, `Type::isSmallerThan()`, `Type::isSmallerThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. +* `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument. +* Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes) +* Remove `ArrayType::generalizeKeys()` +* Remove `ArrayType::count()`, use `Type::getArraySize()` instead +* Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead +* Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead +* Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead +* Remove unused `PHPStanTestCase::$useStaticReflectionProvider` +* Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead +* Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead +* Remove `AnalysisResult::getInternalErrors()`, use `getInternalErrorObjects()` instead +* Remove `ConstantReflection::getValue()`, use `getValueExpr()` instead. To get `Type` from `Expr`, use `Scope::getType()` or `InitializerExprTypeResolver::getType()` +* Remove `PropertyTag::getType()`, use `getReadableType()` / `getWritableType()` instead +* Remove `GenericTypeVariableResolver`, use [`Type::getTemplateType()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getTemplateType) instead +* Rename `Type::isClassStringType()` to `Type::isClassString()` +* Remove `Scope::isSpecified()`, use `hasExpressionType()` instead +* Remove `ConstantArrayType::isEmpty()`, use `isIterableAtLeastOnce()->no()` instead +* Remove `ConstantArrayType::getNextAutoIndex()` +* Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type` + * Use `getFirstIterable*Type` and `getLastIterable*Type` instead +* Remove `ConstantArrayType::generalizeToArray()` +* Remove `ConstantArrayType::findTypeAndMethodName()`, use `findTypeAndMethodNames()` instead +* Remove `ConstantArrayType::removeLast()`, use [`Type::popArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_popArray) instead +* Remove `ConstantArrayType::removeFirst()`, use [`Type::shiftArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_shiftArray) instead +* Remove `ConstantArrayType::reverse()`, use [`Type::reverseArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_reverseArray) instead +* Remove `ConstantArrayType::chunk()`, use [`Type::chunkArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_chunkArray) instead +* Remove `ConstantArrayType::slice()`, use [`Type::sliceArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_sliceArray) instead +* Made `TypeUtils` thinner by removing methods: + * Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead + * Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead + * Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead + * Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) + * Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead + * Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead + * Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead + * Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead + * Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead +* Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead +* Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer `bool` +* Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list`, no longer `int` +* Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead +* `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool` +* Remove `FunctionReflection::isFinal()` +* [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html) +* Remove `__set_state()` on objects that should not be serialized in cache +* Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts `string` +* `LevelsTestCase::dataTopics()` data provider made static +* `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint +* Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) +* Remove `CompoundType::isAcceptedWithReasonBy()`, `CompoundType::isAcceptedBy()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) +Remove `Type::isSuperTypeOfWithReason()`, `Type:isSuperTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) +* Remove `CompoundType::isSubTypeOfWithReasonBy()`, `CompoundType::isSubTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) +* Remove `TemplateType::isValidVarianceWithReason()`, changed `TemplateType::isValidVariance()` return type to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html) +* `RuleLevelHelper::accepts()` return type changed from `bool` to [`RuleLevelHelperAcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html) +* Changes around `ClassConstantReflection` + * Class `ClassConstantReflection` removed from BC promise, renamed to `RealClassConstantReflection` + * Interface `ConstantReflection` renamed to `ClassConstantReflection` + * Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection` + * Interface `GlobalConstantReflection` renamed to `ConstantReflection` +* Renamed interfaces and classes from `*WithPhpDocs` to `Extended*` + * `ParametersAcceptorWithPhpDocs` -> `ExtendedParametersAcceptor` + * `ParameterReflectionWithPhpDocs` -> `ExtendedParameterReflection` + * `FunctionVariantWithPhpDocs` -> `ExtendedFunctionVariant` +* `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null` +* Class `PHPStan\Node\ClassMethod` (accessible from `ClassMethodsNode`) is no longer an AST node + * Call `PHPStan\Node\ClassMethod::getNode()` to access the original AST node From edcc9e8a875990913769cc355d2a775543da16a2 Mon Sep 17 00:00:00 2001 From: Can Vural Date: Mon, 11 Nov 2024 10:15:15 +0100 Subject: [PATCH 442/508] fix: check for existence of second arg in CountCharsFunctionDynamicReturnTypeExtension --- .../Php/CountCharsFunctionDynamicReturnTypeExtension.php | 7 +++++-- tests/PHPStan/Analyser/nsrt/count-chars-7.4.php | 1 + tests/PHPStan/Analyser/nsrt/count-chars-8.0.php | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php b/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php index cddb7e7989..e798af6bbd 100644 --- a/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/CountCharsFunctionDynamicReturnTypeExtension.php @@ -8,6 +8,7 @@ use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\ArrayType; use PHPStan\Type\Constant\ConstantBooleanType; +use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\IntegerRangeType; use PHPStan\Type\IntegerType; @@ -35,11 +36,13 @@ public function getTypeFromFunctionCall( Scope $scope, ): ?Type { - if (count($functionCall->getArgs()) < 1) { + $args = $functionCall->getArgs(); + + if (count($args) < 1) { return null; } - $modeType = $scope->getType($functionCall->getArgs()[1]->value); + $modeType = count($args) === 2 ? $scope->getType($args[1]->value) : new ConstantIntegerType(0); if (IntegerRangeType::fromInterval(0, 2)->isSuperTypeOf($modeType)->yes()) { $arrayType = new ArrayType(new IntegerType(), new IntegerType()); diff --git a/tests/PHPStan/Analyser/nsrt/count-chars-7.4.php b/tests/PHPStan/Analyser/nsrt/count-chars-7.4.php index 713d73a5e1..76e0bea581 100644 --- a/tests/PHPStan/Analyser/nsrt/count-chars-7.4.php +++ b/tests/PHPStan/Analyser/nsrt/count-chars-7.4.php @@ -8,6 +8,7 @@ class X { const ABC = 'abcdef'; function doFoo(): void { + assertType('array|false', count_chars(self::ABC)); assertType('array|false', count_chars(self::ABC, 0)); assertType('array|false', count_chars(self::ABC, 1)); assertType('array|false', count_chars(self::ABC, 2)); diff --git a/tests/PHPStan/Analyser/nsrt/count-chars-8.0.php b/tests/PHPStan/Analyser/nsrt/count-chars-8.0.php index 88a165e931..6e0af08f03 100644 --- a/tests/PHPStan/Analyser/nsrt/count-chars-8.0.php +++ b/tests/PHPStan/Analyser/nsrt/count-chars-8.0.php @@ -8,6 +8,7 @@ class Y { const ABC = 'abcdef'; function doFoo(): void { + assertType('array', count_chars(self::ABC)); assertType('array', count_chars(self::ABC, 0)); assertType('array', count_chars(self::ABC, 1)); assertType('array', count_chars(self::ABC, 2)); From 753fc4d98fe8929aa8816f454d2f9a836ccd7a6b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 11 Nov 2024 15:16:38 +0100 Subject: [PATCH 443/508] Fix resolving tentative return type --- .../Native/NativeMethodReflection.php | 2 +- src/Reflection/Php/PhpMethodReflection.php | 2 +- .../Methods/OverridingMethodRuleTest.php | 6 ++++++ .../Methods/data/simple-xml-element-child.php | 20 +++++++++++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 tests/PHPStan/Rules/Methods/data/simple-xml-element-child.php diff --git a/src/Reflection/Native/NativeMethodReflection.php b/src/Reflection/Native/NativeMethodReflection.php index 8f1e21d7c9..731d4973fe 100644 --- a/src/Reflection/Native/NativeMethodReflection.php +++ b/src/Reflection/Native/NativeMethodReflection.php @@ -81,7 +81,7 @@ public function getPrototype(): ClassMemberReflection $tentativeReturnType = null; if ($prototypeMethod->getTentativeReturnType() !== null) { - $tentativeReturnType = TypehintHelper::decideTypeFromReflection($prototypeMethod->getTentativeReturnType()); + $tentativeReturnType = TypehintHelper::decideTypeFromReflection($prototypeMethod->getTentativeReturnType(), null, $prototypeDeclaringClass); } return new MethodPrototypeReflection( diff --git a/src/Reflection/Php/PhpMethodReflection.php b/src/Reflection/Php/PhpMethodReflection.php index 53f5d80054..d32c16e75e 100644 --- a/src/Reflection/Php/PhpMethodReflection.php +++ b/src/Reflection/Php/PhpMethodReflection.php @@ -118,7 +118,7 @@ public function getPrototype(): ClassMemberReflection $tentativeReturnType = null; if ($prototypeMethod->getTentativeReturnType() !== null) { - $tentativeReturnType = TypehintHelper::decideTypeFromReflection($prototypeMethod->getTentativeReturnType()); + $tentativeReturnType = TypehintHelper::decideTypeFromReflection($prototypeMethod->getTentativeReturnType(), null, $prototypeDeclaringClass); } return new MethodPrototypeReflection( diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index 5a8b677229..6b2a5a0c37 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -812,4 +812,10 @@ public function testBug9524(): void $this->analyse([__DIR__ . '/data/bug-9524.php'], []); } + public function testSimpleXmlElementChildClass(): void + { + $this->phpVersionId = PHP_VERSION_ID; + $this->analyse([__DIR__ . '/data/simple-xml-element-child.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/simple-xml-element-child.php b/tests/PHPStan/Rules/Methods/data/simple-xml-element-child.php new file mode 100644 index 0000000000..1251bf5933 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/simple-xml-element-child.php @@ -0,0 +1,20 @@ +escapeInput($value), $namespace); + } + + private function escapeInput(?string $value): ?string + { + if ($value === null) { + return null; + } + return htmlspecialchars((string) normalizer_normalize($value), ENT_XML1, 'UTF-8'); + } +} From 2a200beec3f2edd913b2af3bf69fbb428018dd74 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 11 Nov 2024 16:22:41 +0100 Subject: [PATCH 444/508] Fix test --- tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php index 6b2a5a0c37..abbe2927ab 100644 --- a/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/OverridingMethodRuleTest.php @@ -814,6 +814,10 @@ public function testBug9524(): void public function testSimpleXmlElementChildClass(): void { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0.'); + } + $this->phpVersionId = PHP_VERSION_ID; $this->analyse([__DIR__ . '/data/simple-xml-element-child.php'], []); } From b071fc7a626639ae6caecea0327dfbeecf55e0c5 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 12 Nov 2024 00:03:28 +0000 Subject: [PATCH 445/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 23c5c46c7a..3400105a87 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#1f0dca06d54cf187adb3481a9c3e7d74af01743b", + "jetbrains/phpstorm-stubs": "dev-master#893a3bc59b8ff1b995220abcbbf76796926b7e9a", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index 4a377463ad..d4f8f73719 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8793a11aa08550fce8d98648609fda3b", + "content-hash": "66f5013e5ca645152c225e1855311a21", "packages": [ { "name": "clue/ndjson-react", @@ -1442,18 +1442,18 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "1f0dca06d54cf187adb3481a9c3e7d74af01743b" + "reference": "893a3bc59b8ff1b995220abcbbf76796926b7e9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/1f0dca06d54cf187adb3481a9c3e7d74af01743b", - "reference": "1f0dca06d54cf187adb3481a9c3e7d74af01743b", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/893a3bc59b8ff1b995220abcbbf76796926b7e9a", + "reference": "893a3bc59b8ff1b995220abcbbf76796926b7e9a", "shasum": "" }, "require-dev": { "friendsofphp/php-cs-fixer": "v3.64.0", "nikic/php-parser": "v5.3.1", - "phpdocumentor/reflection-docblock": "5.4.1", + "phpdocumentor/reflection-docblock": "5.5.1", "phpunit/phpunit": "11.4.3" }, "default-branch": true, @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-11-04T21:28:48+00:00" + "time": "2024-11-10T16:24:24+00:00" }, { "name": "nette/bootstrap", From 7eef99af807040bc3f2d91fa1bdf28329b0c65b2 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Tue, 12 Nov 2024 00:19:36 +0000 Subject: [PATCH 446/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 3400105a87..e739daa7f5 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.11", - "phpstan/php-8-stubs": "0.4.4", + "phpstan/php-8-stubs": "0.4.5", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index d4f8f73719..2d188ccc6a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "66f5013e5ca645152c225e1855311a21", + "content-hash": "92f8cc137cb93c0b9769fd3d8c10f71c", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.4", + "version": "0.4.5", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "c42f6e278d600b219b76d20f80f8455259bcd593" + "reference": "34c6f72940e784d1ccdda1b6a3249ed261f1637a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/c42f6e278d600b219b76d20f80f8455259bcd593", - "reference": "c42f6e278d600b219b76d20f80f8455259bcd593", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/34c6f72940e784d1ccdda1b6a3249ed261f1637a", + "reference": "34c6f72940e784d1ccdda1b6a3249ed261f1637a", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.4" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.5" }, - "time": "2024-11-01T00:22:02+00:00" + "time": "2024-11-12T00:19:02+00:00" }, { "name": "phpstan/phpdoc-parser", From 4edc329827908be5b617055c134740b240e21018 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 12 Nov 2024 14:28:17 +0100 Subject: [PATCH 447/508] Run integration tests again --- .github/workflows/phar.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index dcc27d6be7..adea89e232 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -103,14 +103,14 @@ jobs: - name: "Delete checksum PHAR" run: "rm tmp/phpstan.phar" -# -# integration-tests: -# if: github.event_name == 'pull_request' -# needs: compiler-tests -# uses: phpstan/phpstan/.github/workflows/integration-tests.yml@2.0.x -# with: -# ref: 2.0.x -# phar-checksum: ${{needs.compiler-tests.outputs.checksum}} + + integration-tests: + if: github.event_name == 'pull_request' + needs: compiler-tests + uses: phpstan/phpstan/.github/workflows/integration-tests.yml@2.0.x + with: + ref: 2.0.x + phar-checksum: ${{needs.compiler-tests.outputs.checksum}} extension-tests: if: github.event_name == 'pull_request' From 6787df2bc822c98527d8dce7152e79532edbc9e2 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Wed, 13 Nov 2024 00:20:00 +0000 Subject: [PATCH 448/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index e739daa7f5..2dd8549659 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.42.0.11", - "phpstan/php-8-stubs": "0.4.5", + "phpstan/php-8-stubs": "0.4.6", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index 2d188ccc6a..57ec0c62c4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "92f8cc137cb93c0b9769fd3d8c10f71c", + "content-hash": "01763204b0f17de678b17b578dd8ffbc", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.5", + "version": "0.4.6", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "34c6f72940e784d1ccdda1b6a3249ed261f1637a" + "reference": "25ba0a11dc14a02c062392786486ada62d36b66d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/34c6f72940e784d1ccdda1b6a3249ed261f1637a", - "reference": "34c6f72940e784d1ccdda1b6a3249ed261f1637a", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/25ba0a11dc14a02c062392786486ada62d36b66d", + "reference": "25ba0a11dc14a02c062392786486ada62d36b66d", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.5" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.6" }, - "time": "2024-11-12T00:19:02+00:00" + "time": "2024-11-13T00:19:28+00:00" }, { "name": "phpstan/phpdoc-parser", From 5a132f15d6296c34ef305d19bae405c101698fab Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 13 Nov 2024 09:35:48 +0100 Subject: [PATCH 449/508] Refactor ComposerPhpVersionFactory, ConstantResolver --- conf/config.neon | 1 - src/Analyser/ConstantResolver.php | 89 ++++++++++++++----- src/Analyser/ConstantResolverFactory.php | 4 +- .../ValidateIgnoredErrorsExtension.php | 4 +- src/Php/ComposerPhpVersionFactory.php | 55 ++---------- src/Testing/PHPStanTestCase.php | 4 +- tests/PHPStan/Analyser/nsrt/bug-4434.php | 20 ++--- .../Analyser/nsrt/predefined-constants.php | 4 +- 8 files changed, 97 insertions(+), 84 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index df5c15ddec..77b59a5d3b 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -345,7 +345,6 @@ services: - class: PHPStan\Php\ComposerPhpVersionFactory arguments: - phpVersion: %phpVersion% composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% - diff --git a/src/Analyser/ConstantResolver.php b/src/Analyser/ConstantResolver.php index 8176fe8abc..846188b985 100644 --- a/src/Analyser/ConstantResolver.php +++ b/src/Analyser/ConstantResolver.php @@ -3,10 +3,12 @@ namespace PHPStan\Analyser; use PhpParser\Node\Name; +use PHPStan\Php\ComposerPhpVersionFactory; use PHPStan\Php\PhpVersion; use PHPStan\Reflection\NamespaceAnswerer; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Reflection\ReflectionProvider\ReflectionProviderProvider; +use PHPStan\ShouldNotHappenException; use PHPStan\Type\Accessory\AccessoryNonFalsyStringType; use PHPStan\Type\Constant\ConstantFloatType; use PHPStan\Type\Constant\ConstantIntegerType; @@ -21,6 +23,8 @@ use PHPStan\Type\UnionType; use function array_key_exists; use function in_array; +use function is_array; +use function is_int; use function max; use function sprintf; use const INF; @@ -35,12 +39,13 @@ final class ConstantResolver /** * @param string[] $dynamicConstantNames + * @param int|array{min: int, max: int}|null $phpVersion */ public function __construct( private ReflectionProviderProvider $reflectionProviderProvider, private array $dynamicConstantNames, - private ?PhpVersion $composerMinPhpVersion, - private ?PhpVersion $composerMaxPhpVersion, + private int|array|null $phpVersion, + private ComposerPhpVersionFactory $composerPhpVersionFactory, ) { } @@ -83,15 +88,23 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type new AccessoryNonFalsyStringType(), ]); } + + $minPhpVersion = null; + $maxPhpVersion = null; + if (in_array($resolvedConstantName, ['PHP_VERSION_ID', 'PHP_MAJOR_VERSION', 'PHP_MINOR_VERSION', 'PHP_RELEASE_VERSION'], true)) { + $minPhpVersion = $this->getMinPhpVersion(); + $maxPhpVersion = $this->getMaxPhpVersion(); + } + if ($resolvedConstantName === 'PHP_MAJOR_VERSION') { $minMajor = 5; $maxMajor = null; - if ($this->composerMinPhpVersion !== null) { - $minMajor = max($minMajor, $this->composerMinPhpVersion->getMajorVersionId()); + if ($minPhpVersion !== null) { + $minMajor = max($minMajor, $minPhpVersion->getMajorVersionId()); } - if ($this->composerMaxPhpVersion !== null) { - $maxMajor = $this->composerMaxPhpVersion->getMajorVersionId(); + if ($maxPhpVersion !== null) { + $maxMajor = $maxPhpVersion->getMajorVersionId(); } return $this->createInteger($minMajor, $maxMajor); @@ -101,12 +114,12 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type $maxMinor = null; if ( - $this->composerMinPhpVersion !== null - && $this->composerMaxPhpVersion !== null - && $this->composerMaxPhpVersion->getMajorVersionId() === $this->composerMinPhpVersion->getMajorVersionId() + $minPhpVersion !== null + && $maxPhpVersion !== null + && $maxPhpVersion->getMajorVersionId() === $minPhpVersion->getMajorVersionId() ) { - $minMinor = $this->composerMinPhpVersion->getMinorVersionId(); - $maxMinor = $this->composerMaxPhpVersion->getMinorVersionId(); + $minMinor = $minPhpVersion->getMinorVersionId(); + $maxMinor = $maxPhpVersion->getMinorVersionId(); } return $this->createInteger($minMinor, $maxMinor); @@ -116,13 +129,13 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type $maxRelease = null; if ( - $this->composerMinPhpVersion !== null - && $this->composerMaxPhpVersion !== null - && $this->composerMaxPhpVersion->getMajorVersionId() === $this->composerMinPhpVersion->getMajorVersionId() - && $this->composerMaxPhpVersion->getMinorVersionId() === $this->composerMinPhpVersion->getMinorVersionId() + $minPhpVersion !== null + && $maxPhpVersion !== null + && $maxPhpVersion->getMajorVersionId() === $minPhpVersion->getMajorVersionId() + && $maxPhpVersion->getMinorVersionId() === $minPhpVersion->getMinorVersionId() ) { - $minRelease = $this->composerMinPhpVersion->getPatchVersionId(); - $maxRelease = $this->composerMaxPhpVersion->getPatchVersionId(); + $minRelease = $minPhpVersion->getPatchVersionId(); + $maxRelease = $maxPhpVersion->getPatchVersionId(); } return $this->createInteger($minRelease, $maxRelease); @@ -130,11 +143,11 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type if ($resolvedConstantName === 'PHP_VERSION_ID') { $minVersion = 50207; $maxVersion = null; - if ($this->composerMinPhpVersion !== null) { - $minVersion = max($minVersion, $this->composerMinPhpVersion->getVersionId()); + if ($minPhpVersion !== null) { + $minVersion = max($minVersion, $minPhpVersion->getVersionId()); } - if ($this->composerMaxPhpVersion !== null) { - $maxVersion = $this->composerMaxPhpVersion->getVersionId(); + if ($maxPhpVersion !== null) { + $maxVersion = $maxPhpVersion->getVersionId(); } return $this->createInteger($minVersion, $maxVersion); @@ -351,6 +364,40 @@ public function resolvePredefinedConstant(string $resolvedConstantName): ?Type return null; } + private function getMinPhpVersion(): ?PhpVersion + { + if (is_int($this->phpVersion)) { + return null; + } + + if (is_array($this->phpVersion)) { + if ($this->phpVersion['max'] < $this->phpVersion['min']) { + throw new ShouldNotHappenException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.'); + } + + return new PhpVersion($this->phpVersion['min']); + } + + return $this->composerPhpVersionFactory->getMinVersion(); + } + + private function getMaxPhpVersion(): ?PhpVersion + { + if (is_int($this->phpVersion)) { + return null; + } + + if (is_array($this->phpVersion)) { + if ($this->phpVersion['max'] < $this->phpVersion['min']) { + throw new ShouldNotHappenException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.'); + } + + return new PhpVersion($this->phpVersion['max']); + } + + return $this->composerPhpVersionFactory->getMaxVersion(); + } + public function resolveConstantType(string $constantName, Type $constantType): Type { if ($constantType->isConstantValue()->yes() && in_array($constantName, $this->dynamicConstantNames, true)) { diff --git a/src/Analyser/ConstantResolverFactory.php b/src/Analyser/ConstantResolverFactory.php index f111da14ec..5ccc516e42 100644 --- a/src/Analyser/ConstantResolverFactory.php +++ b/src/Analyser/ConstantResolverFactory.php @@ -23,8 +23,8 @@ public function create(): ConstantResolver return new ConstantResolver( $this->reflectionProviderProvider, $this->container->getParameter('dynamicConstantNames'), - $composerFactory->getMinVersion(), - $composerFactory->getMaxVersion(), + $this->container->getParameter('phpVersion'), + $composerFactory, ); } diff --git a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php index 92f0712e46..4560fde44c 100644 --- a/src/DependencyInjection/ValidateIgnoredErrorsExtension.php +++ b/src/DependencyInjection/ValidateIgnoredErrorsExtension.php @@ -12,6 +12,7 @@ use PHPStan\Command\IgnoredRegexValidator; use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider; use PHPStan\File\FileExcluder; +use PHPStan\Php\ComposerPhpVersionFactory; use PHPStan\Php\PhpVersion; use PHPStan\PhpDoc\DirectTypeNodeResolverExtensionRegistryProvider; use PHPStan\PhpDoc\TypeNodeResolver; @@ -65,7 +66,8 @@ public function loadConfiguration(): void $reflectionProviderProvider = new DirectReflectionProviderProvider($reflectionProvider); ReflectionProviderStaticAccessor::registerInstance($reflectionProvider); PhpVersionStaticAccessor::registerInstance(new PhpVersion(PHP_VERSION_ID)); - $constantResolver = new ConstantResolver($reflectionProviderProvider, [], null, null); + $composerPhpVersionFactory = new ComposerPhpVersionFactory([]); + $constantResolver = new ConstantResolver($reflectionProviderProvider, [], null, $composerPhpVersionFactory); $phpDocParserConfig = new ParserConfig([]); $ignoredRegexValidator = new IgnoredRegexValidator( diff --git a/src/Php/ComposerPhpVersionFactory.php b/src/Php/ComposerPhpVersionFactory.php index ebcf7c130e..88b81022ee 100644 --- a/src/Php/ComposerPhpVersionFactory.php +++ b/src/Php/ComposerPhpVersionFactory.php @@ -3,17 +3,10 @@ namespace PHPStan\Php; use Composer\Semver\VersionParser; -use Nette\Utils\Json; -use Nette\Utils\JsonException; use Nette\Utils\Strings; -use PHPStan\File\CouldNotReadFileException; -use PHPStan\File\FileReader; -use PHPStan\ShouldNotHappenException; +use PHPStan\Internal\ComposerHelper; use function count; use function end; -use function is_array; -use function is_file; -use function is_int; use function is_string; use function min; use function sprintf; @@ -29,11 +22,9 @@ final class ComposerPhpVersionFactory /** * @param string[] $composerAutoloaderProjectPaths - * @param int|array{min: int, max: int}|null $phpVersion */ public function __construct( private array $composerAutoloaderProjectPaths, - private int|array|null $phpVersion, ) { } @@ -42,23 +33,6 @@ private function initializeVersions(): void { $this->initialized = true; - $phpVersion = $this->phpVersion; - - if (is_int($phpVersion)) { - throw new ShouldNotHappenException(); - } - - if (is_array($phpVersion)) { - if ($phpVersion['max'] < $phpVersion['min']) { - throw new ShouldNotHappenException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.'); - } - - $this->minVersion = new PhpVersion($phpVersion['min']); - $this->maxVersion = new PhpVersion($phpVersion['max']); - - return; - } - // don't limit minVersion... PHPStan can analyze even PHP5 $this->maxVersion = new PhpVersion(PhpVersionFactory::MAX_PHP_VERSION); @@ -87,10 +61,6 @@ private function initializeVersions(): void public function getMinVersion(): ?PhpVersion { - if (is_int($this->phpVersion)) { - return null; - } - if ($this->initialized === false) { $this->initializeVersions(); } @@ -100,10 +70,6 @@ public function getMinVersion(): ?PhpVersion public function getMaxVersion(): ?PhpVersion { - if (is_int($this->phpVersion)) { - return null; - } - if ($this->initialized === false) { $this->initializeVersions(); } @@ -114,21 +80,18 @@ public function getMaxVersion(): ?PhpVersion private function getComposerRequireVersion(): ?string { $composerPhpVersion = null; + if (count($this->composerAutoloaderProjectPaths) > 0) { - $composerJsonPath = end($this->composerAutoloaderProjectPaths) . '/composer.json'; - if (is_file($composerJsonPath)) { - try { - $composerJsonContents = FileReader::read($composerJsonPath); - $composer = Json::decode($composerJsonContents, Json::FORCE_ARRAY); - $requiredVersion = $composer['require']['php'] ?? null; - if (is_string($requiredVersion)) { - $composerPhpVersion = $requiredVersion; - } - } catch (CouldNotReadFileException | JsonException) { - // pass + $composer = ComposerHelper::getComposerConfig(end($this->composerAutoloaderProjectPaths)); + if ($composer !== null) { + $requiredVersion = $composer['require']['php'] ?? null; + + if (is_string($requiredVersion)) { + $composerPhpVersion = $requiredVersion; } } } + return $composerPhpVersion; } diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index aee824bfbc..31cdfadb78 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -21,6 +21,7 @@ use PHPStan\Internal\DirectoryCreatorException; use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Parser\Parser; +use PHPStan\Php\ComposerPhpVersionFactory; use PHPStan\Php\PhpVersion; use PHPStan\PhpDoc\TypeNodeResolver; use PHPStan\PhpDoc\TypeStringResolver; @@ -137,7 +138,8 @@ public static function createScopeFactory(ReflectionProvider $reflectionProvider } $reflectionProviderProvider = new DirectReflectionProviderProvider($reflectionProvider); - $constantResolver = new ConstantResolver($reflectionProviderProvider, $dynamicConstantNames, null, null); + $composerPhpVersionFactory = $container->getByType(ComposerPhpVersionFactory::class); + $constantResolver = new ConstantResolver($reflectionProviderProvider, $dynamicConstantNames, null, $composerPhpVersionFactory); $initializerExprTypeResolver = new InitializerExprTypeResolver( $constantResolver, diff --git a/tests/PHPStan/Analyser/nsrt/bug-4434.php b/tests/PHPStan/Analyser/nsrt/bug-4434.php index a1f3bea048..7b48df20fd 100644 --- a/tests/PHPStan/Analyser/nsrt/bug-4434.php +++ b/tests/PHPStan/Analyser/nsrt/bug-4434.php @@ -10,14 +10,14 @@ class HelloWorld public function testSendEmailToLog(): void { foreach ([1] as $emailFile) { - assertType('int<5, max>', PHP_MAJOR_VERSION); - assertType('int<5, max>', \PHP_MAJOR_VERSION); + assertType('int<5, 8>', PHP_MAJOR_VERSION); + assertType('int<5, 8>', \PHP_MAJOR_VERSION); if (PHP_MAJOR_VERSION === 7) { assertType('7', PHP_MAJOR_VERSION); assertType('7', \PHP_MAJOR_VERSION); } else { - assertType('int<5, 6>|int<8, max>', PHP_MAJOR_VERSION); - assertType('int<5, 6>|int<8, max>', \PHP_MAJOR_VERSION); + assertType('8|int<5, 6>', PHP_MAJOR_VERSION); + assertType('8|int<5, 6>', \PHP_MAJOR_VERSION); } } } @@ -28,14 +28,14 @@ class HelloWorld2 public function testSendEmailToLog(): void { foreach ([1] as $emailFile) { - assertType('int<5, max>', PHP_MAJOR_VERSION); - assertType('int<5, max>', \PHP_MAJOR_VERSION); + assertType('int<5, 8>', PHP_MAJOR_VERSION); + assertType('int<5, 8>', \PHP_MAJOR_VERSION); if (PHP_MAJOR_VERSION === 100) { - assertType('100', PHP_MAJOR_VERSION); - assertType('100', \PHP_MAJOR_VERSION); + assertType('*NEVER*', PHP_MAJOR_VERSION); + assertType('*NEVER*', \PHP_MAJOR_VERSION); } else { - assertType('int<5, 99>|int<101, max>', PHP_MAJOR_VERSION); - assertType('int<5, 99>|int<101, max>', \PHP_MAJOR_VERSION); + assertType('int<5, 8>', PHP_MAJOR_VERSION); + assertType('int<5, 8>', \PHP_MAJOR_VERSION); } } } diff --git a/tests/PHPStan/Analyser/nsrt/predefined-constants.php b/tests/PHPStan/Analyser/nsrt/predefined-constants.php index 70dceda653..9d9d1b1fc5 100644 --- a/tests/PHPStan/Analyser/nsrt/predefined-constants.php +++ b/tests/PHPStan/Analyser/nsrt/predefined-constants.php @@ -4,10 +4,10 @@ // core, https://www.php.net/manual/en/reserved.constants.php assertType('non-falsy-string', PHP_VERSION); -assertType('int<5, max>', PHP_MAJOR_VERSION); +assertType('int<5, 8>', PHP_MAJOR_VERSION); assertType('int<0, max>', PHP_MINOR_VERSION); assertType('int<0, max>', PHP_RELEASE_VERSION); -assertType('int<50207, max>', PHP_VERSION_ID); +assertType('int<50207, 80499>', PHP_VERSION_ID); assertType('string', PHP_EXTRA_VERSION); assertType('0|1', PHP_ZTS); assertType('0|1', PHP_DEBUG); From 9717564bb5e229512113841c57950712e998353b Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 13 Nov 2024 12:56:50 +0100 Subject: [PATCH 450/508] Utilize phpVersion.min+max in VersionCompareFunctionDynamicReturnTypeExtension --- .github/workflows/e2e-tests.yml | 4 +++ conf/config.neon | 2 ++ .../.gitignore | 2 ++ .../composer.json | 5 ++++ .../phpstan.neon | 4 +++ .../test.php | 11 +++++++ ...pareFunctionDynamicReturnTypeExtension.php | 30 ++++++++++++++----- 7 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 e2e/composer-and-phpstan-version-config/.gitignore create mode 100644 e2e/composer-and-phpstan-version-config/composer.json create mode 100644 e2e/composer-and-phpstan-version-config/phpstan.neon create mode 100644 e2e/composer-and-phpstan-version-config/test.php diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 6d7233d38a..96505cbf9c 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -296,6 +296,10 @@ jobs: - script: | cd e2e/bug-11819 ../../bin/phpstan + - script: | + cd e2e/composer-and-phpstan-version-config + composer install --ignore-platform-reqs + ../../bin/phpstan analyze test.php --level=0 - script: | cd e2e/composer-max-version composer install diff --git a/conf/config.neon b/conf/config.neon index 77b59a5d3b..739e8247dc 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1683,6 +1683,8 @@ services: - class: PHPStan\Type\Php\VersionCompareFunctionDynamicReturnTypeExtension + arguments: + configPhpVersion: %phpVersion% tags: - phpstan.broker.dynamicFunctionReturnTypeExtension diff --git a/e2e/composer-and-phpstan-version-config/.gitignore b/e2e/composer-and-phpstan-version-config/.gitignore new file mode 100644 index 0000000000..3a9875b460 --- /dev/null +++ b/e2e/composer-and-phpstan-version-config/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/e2e/composer-and-phpstan-version-config/composer.json b/e2e/composer-and-phpstan-version-config/composer.json new file mode 100644 index 0000000000..8fe9570814 --- /dev/null +++ b/e2e/composer-and-phpstan-version-config/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php": "^7.0" + } +} diff --git a/e2e/composer-and-phpstan-version-config/phpstan.neon b/e2e/composer-and-phpstan-version-config/phpstan.neon new file mode 100644 index 0000000000..003e5e1484 --- /dev/null +++ b/e2e/composer-and-phpstan-version-config/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + phpVersion: + min: 80103 + max: 80304 diff --git a/e2e/composer-and-phpstan-version-config/test.php b/e2e/composer-and-phpstan-version-config/test.php new file mode 100644 index 0000000000..a9afaa4b65 --- /dev/null +++ b/e2e/composer-and-phpstan-version-config/test.php @@ -0,0 +1,11 @@ +', PHP_VERSION_ID); +\PHPStan\Testing\assertType('8', PHP_MAJOR_VERSION); +\PHPStan\Testing\assertType('int<1, 3>', PHP_MINOR_VERSION); +\PHPStan\Testing\assertType('int<0, max>', PHP_RELEASE_VERSION); + +\PHPStan\Testing\assertType('1', version_compare(PHP_VERSION, '7.0.0')); +\PHPStan\Testing\assertType('false', version_compare(PHP_VERSION, '7.0.0', '<')); +\PHPStan\Testing\assertType('true', version_compare(PHP_VERSION, '7.0.0', '>')); diff --git a/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php b/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php index d79ebf0706..7ca5d8bac9 100644 --- a/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/VersionCompareFunctionDynamicReturnTypeExtension.php @@ -6,6 +6,7 @@ use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; use PHPStan\Php\ComposerPhpVersionFactory; +use PHPStan\Php\PhpVersion; use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\BooleanType; use PHPStan\Type\Constant\ConstantBooleanType; @@ -16,12 +17,19 @@ use PHPStan\Type\TypeCombinator; use function array_filter; use function count; +use function is_array; use function version_compare; final class VersionCompareFunctionDynamicReturnTypeExtension implements DynamicFunctionReturnTypeExtension { - public function __construct(private ComposerPhpVersionFactory $composerPhpVersionFactory) + /** + * @param int|array{min: int, max: int}|null $configPhpVersion + */ + public function __construct( + private int|array|null $configPhpVersion, + private ComposerPhpVersionFactory $composerPhpVersionFactory, + ) { } @@ -93,13 +101,21 @@ private function getVersionStrings(Expr $expr, Scope $scope): array if ( $expr instanceof Expr\ConstFetch && $expr->name->toString() === 'PHP_VERSION' - && $this->composerPhpVersionFactory->getMinVersion() !== null - && $this->composerPhpVersionFactory->getMaxVersion() !== null ) { - return [ - new ConstantStringType($this->composerPhpVersionFactory->getMinVersion()->getVersionString()), - new ConstantStringType($this->composerPhpVersionFactory->getMaxVersion()->getVersionString()), - ]; + if (is_array($this->configPhpVersion)) { + $minVersion = new PhpVersion($this->configPhpVersion['min']); + $maxVersion = new PhpVersion($this->configPhpVersion['max']); + } else { + $minVersion = $this->composerPhpVersionFactory->getMinVersion(); + $maxVersion = $this->composerPhpVersionFactory->getMaxVersion(); + } + + if ($minVersion !== null && $maxVersion !== null) { + return [ + new ConstantStringType($minVersion->getVersionString()), + new ConstantStringType($maxVersion->getVersionString()), + ]; + } } return $scope->getType($expr)->getConstantStrings(); From f243636374fee78ec566f27d422bf114e1357ec3 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 13 Nov 2024 13:41:48 +0100 Subject: [PATCH 451/508] More details php version information in diagnose --- conf/config.neon | 1 + src/Diagnose/PHPStanDiagnoseExtension.php | 49 ++++++++++++++++++++--- src/Php/PhpVersion.php | 8 ++++ 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/conf/config.neon b/conf/config.neon index 739e8247dc..3f4414b606 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -2108,6 +2108,7 @@ services: arguments: composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% allConfigFiles: %allConfigFiles% + configPhpVersion: %phpVersion% autowired: false # Error formatters diff --git a/src/Diagnose/PHPStanDiagnoseExtension.php b/src/Diagnose/PHPStanDiagnoseExtension.php index 7c3057190c..35cb6a862e 100644 --- a/src/Diagnose/PHPStanDiagnoseExtension.php +++ b/src/Diagnose/PHPStanDiagnoseExtension.php @@ -7,6 +7,7 @@ use PHPStan\ExtensionInstaller\GeneratedConfig; use PHPStan\File\FileHelper; use PHPStan\Internal\ComposerHelper; +use PHPStan\Php\ComposerPhpVersionFactory; use PHPStan\Php\PhpVersion; use ReflectionClass; use function array_key_exists; @@ -17,6 +18,7 @@ use function explode; use function implode; use function in_array; +use function is_array; use function is_file; use function is_readable; use function sprintf; @@ -29,14 +31,17 @@ final class PHPStanDiagnoseExtension implements DiagnoseExtension { /** + * @param int|array{min: int, max: int}|null $configPhpVersion * @param string[] $composerAutoloaderProjectPaths * @param string [] $allConfigFiles */ public function __construct( private PhpVersion $phpVersion, + private int|array|null $configPhpVersion, private FileHelper $fileHelper, private array $composerAutoloaderProjectPaths, private array $allConfigFiles, + private ComposerPhpVersionFactory $composerPhpVersionFactory, ) { } @@ -48,11 +53,45 @@ public function print(Output $output): void 'PHP runtime version: %s', $phpRuntimeVersion->getVersionString(), )); - $output->writeLineFormatted(sprintf( - 'PHP version for analysis: %s (from %s)', - $this->phpVersion->getVersionString(), - $this->phpVersion->getSourceLabel(), - )); + + if ( + $this->phpVersion->getSource() === PhpVersion::SOURCE_CONFIG + && is_array($this->configPhpVersion) + ) { + $minVersion = new PhpVersion($this->configPhpVersion['min']); + $maxVersion = new PhpVersion($this->configPhpVersion['max']); + + $output->writeLineFormatted(sprintf( + 'PHP version for analysis: %s-%s (from %s)', + $minVersion->getVersionString(), + $maxVersion->getVersionString(), + $this->phpVersion->getSourceLabel(), + )); + + } else { + $minComposerPhpVersion = $this->composerPhpVersionFactory->getMinVersion(); + $maxComposerPhpVersion = $this->composerPhpVersionFactory->getMaxVersion(); + if ($minComposerPhpVersion !== null && $maxComposerPhpVersion !== null) { + if ($minComposerPhpVersion->getVersionId() !== $maxComposerPhpVersion->getVersionId()) { + $output->writeLineFormatted(sprintf( + 'PHP composer.json required version: %s-%s', + $minComposerPhpVersion->getVersionString(), + $maxComposerPhpVersion->getVersionString(), + )); + } else { + $output->writeLineFormatted(sprintf( + 'PHP composer.json required version: %s', + $minComposerPhpVersion->getVersionString(), + )); + } + } + + $output->writeLineFormatted(sprintf( + 'PHP version for analysis: %s (from %s)', + $this->phpVersion->getVersionString(), + $this->phpVersion->getSourceLabel(), + )); + } $output->writeLineFormatted(''); $output->writeLineFormatted(sprintf( diff --git a/src/Php/PhpVersion.php b/src/Php/PhpVersion.php index 83ca1245b5..8520f6488d 100644 --- a/src/Php/PhpVersion.php +++ b/src/Php/PhpVersion.php @@ -22,6 +22,14 @@ public function __construct(private int $versionId, private int $source = self:: { } + /** + * @return self::SOURCE_* + */ + public function getSource(): int + { + return $this->source; + } + public function getSourceLabel(): string { switch ($this->source) { From 65ddbcb6fe3d248076c49af0d1532d0dc4f75460 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 16 Nov 2024 12:02:35 +0100 Subject: [PATCH 452/508] Fix after merge --- src/Analyser/TypeSpecifier.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 6628c7bdb1..17032ec814 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -1903,7 +1903,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif new ConstantStringType(''), new ConstantArrayType([], []), ]; - return $this->create($exprNode, new UnionType($trueTypes), $context, false, $scope, $rootExpr); + return $this->create($exprNode, new UnionType($trueTypes), $context, $scope)->setRootExpr($expr); } if (!$context->null() && $constantType->getValue() === false) { @@ -1943,7 +1943,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif new ConstantStringType('0'), ]; } - return $this->create($exprNode, new UnionType($trueTypes), $context, false, $scope, $rootExpr); + return $this->create($exprNode, new UnionType($trueTypes), $context, $scope)->setRootExpr($expr); } if (!$context->null() && $constantType->getValue() === '') { @@ -1965,7 +1965,7 @@ public function resolveEqual(Expr\BinaryOp\Equal $expr, Scope $scope, TypeSpecif new ConstantStringType(''), ]; } - return $this->create($exprNode, new UnionType($trueTypes), $context, false, $scope, $rootExpr); + return $this->create($exprNode, new UnionType($trueTypes), $context, $scope)->setRootExpr($expr); } if ( From 30d20e6ee2dd93206aed2e26187aba0fc679d5c9 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 17 Nov 2024 16:35:34 +0100 Subject: [PATCH 453/508] FunctionCallParametersCheck: Add native parameter type --- src/Rules/FunctionCallParametersCheck.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 9704d5e82e..130dd0bef8 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -53,7 +53,6 @@ public function __construct( } /** - * @param Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $funcCall * @param 'attribute'|'callable'|'method'|'staticMethod'|'function'|'new' $nodeType * @return list */ @@ -61,7 +60,7 @@ public function check( ParametersAcceptor $parametersAcceptor, Scope $scope, bool $isBuiltin, - $funcCall, + Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $funcCall, string $nodeType, TrinaryLogic $acceptsNamedArguments, string $singleInsufficientParameterMessage, From a2eddcc71a01d00888069dd85358a091070639f1 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 19 Nov 2024 00:03:40 +0000 Subject: [PATCH 454/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 55b58e1a56..15e25f2a80 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#893a3bc59b8ff1b995220abcbbf76796926b7e9a", + "jetbrains/phpstorm-stubs": "dev-master#fda684a4826c1caf59efe1a1bf68d08c11aaddbf", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index cda1b9fb41..8ee3e675ed 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b0700d67568e34950c8009d83dee8a3c", + "content-hash": "ca308caf852aa82ffe555d1235c75efa", "packages": [ { "name": "clue/ndjson-react", @@ -1442,12 +1442,12 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "893a3bc59b8ff1b995220abcbbf76796926b7e9a" + "reference": "fda684a4826c1caf59efe1a1bf68d08c11aaddbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/893a3bc59b8ff1b995220abcbbf76796926b7e9a", - "reference": "893a3bc59b8ff1b995220abcbbf76796926b7e9a", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/fda684a4826c1caf59efe1a1bf68d08c11aaddbf", + "reference": "fda684a4826c1caf59efe1a1bf68d08c11aaddbf", "shasum": "" }, "require-dev": { @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-11-10T16:24:24+00:00" + "time": "2024-11-15T09:42:33+00:00" }, { "name": "nette/bootstrap", From 4a6565e140ddbc8965fca52159e8ef314cd482d5 Mon Sep 17 00:00:00 2001 From: Sven Reichel Date: Mon, 18 Nov 2024 11:57:27 +0100 Subject: [PATCH 455/508] 3rd parameter of htmlentities|htmlspecialchars allows null --- resources/functionMap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/functionMap.php b/resources/functionMap.php index 05268af81e..baaef68a8c 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -3957,8 +3957,8 @@ 'HRTime\StopWatch::start' => ['void'], 'HRTime\StopWatch::stop' => ['void'], 'html_entity_decode' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string'], -'htmlentities' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string', 'double_encode='=>'bool'], -'htmlspecialchars' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string', 'double_encode='=>'bool'], +'htmlentities' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string|null', 'double_encode='=>'bool'], +'htmlspecialchars' => ['string', 'string'=>'string', 'quote_style='=>'int', 'encoding='=>'string|null', 'double_encode='=>'bool'], 'htmlspecialchars_decode' => ['string', 'string'=>'string', 'quote_style='=>'int'], 'http\Env\Request::__construct' => ['void'], 'http\Env\Request::getCookie' => ['mixed', 'name='=>'string', 'type='=>'mixed', 'defval='=>'mixed', 'delete='=>'bool|false'], From 5b77fa68d623dd89408171615f50352fd7d19ff0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 19 Nov 2024 10:56:22 +0100 Subject: [PATCH 456/508] Fix test --- .../Reflection/SignatureMap/Php8SignatureMapProviderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php b/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php index 41d62d1c36..9302b20f69 100644 --- a/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php +++ b/tests/PHPStan/Reflection/SignatureMap/Php8SignatureMapProviderTest.php @@ -206,7 +206,7 @@ public function dataMethods(): array 'variadic' => false, ], ], - new UnionType([ + new BenevolentUnionType([ new ObjectType('Closure'), new NullType(), ]), From a34c2f4c688c7394d034058f59e1c6d70da3e2ed Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Tue, 19 Nov 2024 16:38:41 +0200 Subject: [PATCH 457/508] Update curl_setopt string values and allow nullable --- src/Reflection/ParametersAcceptorSelector.php | 69 +++++++++++++++---- .../CallToFunctionParametersRuleTest.php | 26 +++++-- .../Rules/Functions/data/curl_setopt.php | 6 ++ 3 files changed, 81 insertions(+), 20 deletions(-) diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index fd2f2b8ae1..82af7d4267 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -918,49 +918,91 @@ private static function getCurlOptValueType(int $curlOpt): ?Type } } + $nullableStringConstants = [ + 'CURLOPT_ACCEPT_ENCODING', + 'CURLOPT_CUSTOMREQUEST', + 'CURLOPT_DNS_INTERFACE', + 'CURLOPT_DNS_LOCAL_IP4', + 'CURLOPT_DNS_LOCAL_IP6', + 'CURLOPT_DOH_URL', + 'CURLOPT_FTP_ACCOUNT', + 'CURLOPT_FTPPORT', + 'CURLOPT_HSTS', + 'CURLOPT_KRBLEVEL', + 'CURLOPT_RANGE', + 'CURLOPT_RTSP_SESSION_ID', + 'CURLOPT_UNIX_SOCKET_PATH', + 'CURLOPT_XOAUTH2_BEARER', + ]; + foreach ($nullableStringConstants as $constName) { + if (defined($constName) && constant($constName) === $curlOpt) { + return new UnionType([ + new NullType(), + TypeCombinator::intersect( + new StringType(), + new AccessoryNonEmptyStringType(), + ), + ]); + } + } + $nonEmptyStringConstants = [ 'CURLOPT_ABSTRACT_UNIX_SOCKET', + 'CURLOPT_ALTSVC', + 'CURLOPT_AWS_SIGV4', 'CURLOPT_CAINFO', 'CURLOPT_CAPATH', 'CURLOPT_COOKIE', 'CURLOPT_COOKIEJAR', 'CURLOPT_COOKIELIST', - 'CURLOPT_CUSTOMREQUEST', 'CURLOPT_DEFAULT_PROTOCOL', - 'CURLOPT_DNS_INTERFACE', - 'CURLOPT_DNS_LOCAL_IP4', - 'CURLOPT_DNS_LOCAL_IP6', + 'CURLOPT_DNS_SERVERS', 'CURLOPT_EGDSOCKET', - 'CURLOPT_FTPPORT', + 'CURLOPT_FTP_ALTERNATIVE_TO_USER', 'CURLOPT_INTERFACE', 'CURLOPT_KEYPASSWD', 'CURLOPT_KRB4LEVEL', 'CURLOPT_LOGIN_OPTIONS', + 'CURLOPT_MAIL_AUTH', + 'CURLOPT_MAIL_FROM', + 'CURLOPT_NOPROXY', + 'CURLOPT_PASSWORD', 'CURLOPT_PINNEDPUBLICKEY', - 'CURLOPT_PROXY_SERVICE_NAME', + 'CURLOPT_PROTOCOLS_STR', 'CURLOPT_PROXY_CAINFO', 'CURLOPT_PROXY_CAPATH', 'CURLOPT_PROXY_CRLFILE', + 'CURLOPT_PROXY_ISSUERCERT', 'CURLOPT_PROXY_KEYPASSWD', 'CURLOPT_PROXY_PINNEDPUBLICKEY', + 'CURLOPT_PROXY_SERVICE_NAME', + 'CURLOPT_PROXY_SSL_CIPHER_LIST', 'CURLOPT_PROXY_SSLCERT', 'CURLOPT_PROXY_SSLCERTTYPE', - 'CURLOPT_PROXY_SSL_CIPHER_LIST', - 'CURLOPT_PROXY_TLS13_CIPHERS', 'CURLOPT_PROXY_SSLKEY', 'CURLOPT_PROXY_SSLKEYTYPE', + 'CURLOPT_PROXY_TLS13_CIPHERS', 'CURLOPT_PROXY_TLSAUTH_PASSWORD', 'CURLOPT_PROXY_TLSAUTH_TYPE', 'CURLOPT_PROXY_TLSAUTH_USERNAME', + 'CURLOPT_PROXYPASSWORD', + 'CURLOPT_PROXYUSERNAME', 'CURLOPT_PROXYUSERPWD', 'CURLOPT_RANDOM_FILE', - 'CURLOPT_RANGE', + 'CURLOPT_REDIR_PROTOCOLS_STR', 'CURLOPT_REFERER', + 'CURLOPT_REQUEST_TARGET', + 'CURLOPT_RTSP_STREAM_URI', + 'CURLOPT_RTSP_TRANSPORT', + 'CURLOPT_SASL_AUTHZID', 'CURLOPT_SERVICE_NAME', + 'CURLOPT_SOCKS5_GSSAPI_SERVICE', 'CURLOPT_SSH_HOST_PUBLIC_KEY_MD5', - 'CURLOPT_SSH_PUBLIC_KEYFILE', + 'CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256', 'CURLOPT_SSH_PRIVATE_KEYFILE', + 'CURLOPT_SSH_PUBLIC_KEYFILE', 'CURLOPT_SSL_CIPHER_LIST', + 'CURLOPT_SSL_EC_CURVES', 'CURLOPT_SSLCERT', 'CURLOPT_SSLCERTPASSWD', 'CURLOPT_SSLCERTTYPE', @@ -970,13 +1012,14 @@ private static function getCurlOptValueType(int $curlOpt): ?Type 'CURLOPT_SSLKEYPASSWD', 'CURLOPT_SSLKEYTYPE', 'CURLOPT_TLS13_CIPHERS', - 'CURLOPT_UNIX_SOCKET_PATH', + 'CURLOPT_TLSAUTH_PASSWORD', + 'CURLOPT_TLSAUTH_TYPE', + 'CURLOPT_TLSAUTH_USERNAME', + 'CURLOPT_TRANSFER_ENCODING', 'CURLOPT_URL', 'CURLOPT_USERAGENT', 'CURLOPT_USERNAME', - 'CURLOPT_PASSWORD', 'CURLOPT_USERPWD', - 'CURLOPT_XOAUTH2_BEARER', ]; foreach ($nonEmptyStringConstants as $constName) { if (defined($constName) && constant($constName) === $curlOpt) { diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index 7d28abb0fc..15213c15ea 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -1316,33 +1316,45 @@ public function testCurlSetOpt(): void 'Parameter #3 $value of function curl_setopt expects array, int given.', 17, ], + [ + 'Parameter #3 $value of function curl_setopt expects non-empty-string, null given.', + 18, + ], [ 'Parameter #3 $value of function curl_setopt expects bool, int given.', - 19, + 20, ], [ 'Parameter #3 $value of function curl_setopt expects bool, string given.', - 20, + 21, ], [ 'Parameter #3 $value of function curl_setopt expects int, string given.', - 22, + 23, ], [ 'Parameter #3 $value of function curl_setopt expects array, string given.', - 24, + 25, ], [ 'Parameter #3 $value of function curl_setopt expects resource, string given.', - 26, + 27, ], [ 'Parameter #3 $value of function curl_setopt expects array|string, int given.', - 28, + 29, + ], + [ + 'Parameter #3 $value of function curl_setopt expects non-empty-string, \'\' given.', + 31, + ], + [ + 'Parameter #3 $value of function curl_setopt expects non-empty-string|null, \'\' given.', + 32, ], [ 'Parameter #3 $value of function curl_setopt expects array, array given.', - 67, + 73, ], ]); } diff --git a/tests/PHPStan/Rules/Functions/data/curl_setopt.php b/tests/PHPStan/Rules/Functions/data/curl_setopt.php index 76d3136a2d..24987ddbc9 100644 --- a/tests/PHPStan/Rules/Functions/data/curl_setopt.php +++ b/tests/PHPStan/Rules/Functions/data/curl_setopt.php @@ -15,6 +15,7 @@ public function errors(int $i, string $s) { // expecting string curl_setopt($curl, CURLOPT_URL, $i); curl_setopt($curl, CURLOPT_HTTPHEADER, $i); + curl_setopt($curl, CURLOPT_ABSTRACT_UNIX_SOCKET, null); // expecting bool curl_setopt($curl, CURLOPT_AUTOREFERER, $i); curl_setopt($curl, CURLOPT_RETURNTRANSFER, $s); @@ -26,6 +27,9 @@ public function errors(int $i, string $s) { curl_setopt($curl, CURLOPT_FILE, $s); // expecting string or array curl_setopt($curl, CURLOPT_POSTFIELDS, $i); + // expecting non empty string + curl_setopt($curl, CURLOPT_URL, ''); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, ''); } /** @@ -41,6 +45,8 @@ public function allGood(string $url, array $header) { curl_setopt($curl, CURLOPT_AUTOREFERER, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_TIMEOUT, 10); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, null); $fp = fopen("example_homepage.txt", "w"); if ($fp === false) { From 3b47bc000091256f645c22e99d8823332a6cb43d Mon Sep 17 00:00:00 2001 From: Claude Pache Date: Tue, 19 Nov 2024 18:45:08 +0100 Subject: [PATCH 458/508] bccomp: more precise return type --- resources/functionMap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/functionMap.php b/resources/functionMap.php index baaef68a8c..2b1df1a790 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -418,7 +418,7 @@ 'bbcode_set_arg_parser' => ['bool', 'bbcode_container'=>'resource', 'bbcode_arg_parser'=>'resource'], 'bbcode_set_flags' => ['bool', 'bbcode_container'=>'resource', 'flags'=>'int', 'mode='=>'int'], 'bcadd' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], -'bccomp' => ['int', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], +'bccomp' => ['0|1|-1', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bcdiv' => ['numeric-string|null', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bcmod' => ['numeric-string|null', 'left_operand'=>'string', 'right_operand'=>'numeric-string', 'scale='=>'int'], 'bcmul' => ['numeric-string', 'left_operand'=>'numeric-string', 'right_operand'=>'numeric-string', 'scale='=>'int'], From 68d01a5f68c1e0897fd54e80c2b896ed98ae03a1 Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Tue, 19 Nov 2024 19:33:41 +0000 Subject: [PATCH 459/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 18 +++++++++--------- ...ctionEnumCaseDynamicReturnTypeExtension.php | 8 ++------ ...eflectionEnumDynamicReturnTypeExtension.php | 5 +---- .../adapter-reflection-enum-return-types.php | 9 +++++---- 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/composer.json b/composer.json index 15e25f2a80..73f1cc620f 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.42.0.11", + "ondrejmirtes/better-reflection": "6.43.0.2", "phpstan/php-8-stubs": "0.4.6", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 8ee3e675ed..d2adb5606c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ca308caf852aa82ffe555d1235c75efa", + "content-hash": "a4991601b7590d9dc65443dfb5d34d16", "packages": [ { "name": "clue/ndjson-react", @@ -2187,22 +2187,22 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.42.0.11", + "version": "6.43.0.2", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "1ff390ad28758b6baa20c9a45b17926bdd850e44" + "reference": "c34ee726f9abc5a7057b0dacdf1c0991c9090584" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/1ff390ad28758b6baa20c9a45b17926bdd850e44", - "reference": "1ff390ad28758b6baa20c9a45b17926bdd850e44", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/c34ee726f9abc5a7057b0dacdf1c0991c9090584", + "reference": "c34ee726f9abc5a7057b0dacdf1c0991c9090584", "shasum": "" }, "require": { "ext-json": "*", "jetbrains/phpstorm-stubs": "dev-master#217ed9356d07ef89109d3cd7d8c5df10aab4b0d4", - "nikic/php-parser": "^5.1.0", + "nikic/php-parser": "^5.3.1", "php": "^7.4 || ^8.0" }, "conflict": { @@ -2212,7 +2212,7 @@ "doctrine/coding-standard": "^12.0.0", "phpstan/phpstan": "^1.10.60", "phpstan/phpstan-phpunit": "^1.3.16", - "phpunit/phpunit": "^11.3.3", + "phpunit/phpunit": "^11.4.3", "rector/rector": "0.14.3" }, "suggest": { @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.42.0.11" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.43.0.2" }, - "time": "2024-10-12T09:30:53+00:00" + "time": "2024-11-19T19:32:34+00:00" }, { "name": "phpstan/php-8-stubs", diff --git a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php index d242403fb6..4e1cfbcea6 100644 --- a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php +++ b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumCaseDynamicReturnTypeExtension.php @@ -4,9 +4,7 @@ use PhpParser\Node\Expr\MethodCall; use PHPStan\Analyser\Scope; -use PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType; -use PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType; -use PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionType; use PHPStan\Php\PhpVersion; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\Constant\ConstantBooleanType; @@ -56,9 +54,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method if ($methodReflection->getName() === 'getType') { return new UnionType([ - new ObjectType(ReflectionIntersectionType::class), - new ObjectType(ReflectionNamedType::class), - new ObjectType(ReflectionUnionType::class), + new ObjectType(ReflectionType::class), new NullType(), ]); } diff --git a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php index f0e25e9296..dfa3218442 100644 --- a/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php +++ b/src/Reflection/BetterReflection/Type/AdapterReflectionEnumDynamicReturnTypeExtension.php @@ -72,10 +72,7 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method } if (in_array($methodReflection->getName(), ['getStartLine', 'getEndLine'], true)) { - return new UnionType([ - new IntegerType(), - new ConstantBooleanType(false), - ]); + return new IntegerType(); } if ($methodReflection->getName() === 'getReflectionConstant') { diff --git a/tests/PHPStan/Analyser/nsrt/adapter-reflection-enum-return-types.php b/tests/PHPStan/Analyser/nsrt/adapter-reflection-enum-return-types.php index 4002e1ce16..d21d17e739 100644 --- a/tests/PHPStan/Analyser/nsrt/adapter-reflection-enum-return-types.php +++ b/tests/PHPStan/Analyser/nsrt/adapter-reflection-enum-return-types.php @@ -5,12 +5,13 @@ use PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnum; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumBackedCase; use PHPStan\BetterReflection\Reflection\Adapter\ReflectionEnumUnitCase; +use PHPStan\BetterReflection\Reflection\Adapter\ReflectionType; use function PHPStan\Testing\assertType; function (ReflectionEnum $r, string $s): void { assertType('non-empty-string|false', $r->getFileName()); - assertType('int|false', $r->getStartLine()); - assertType('int|false', $r->getEndLine()); + assertType('int', $r->getStartLine()); + assertType('int', $r->getEndLine()); assertType('string|false', $r->getDocComment()); assertType('PHPStan\BetterReflection\Reflection\Adapter\ReflectionClassConstant|false', $r->getReflectionConstant($s)); assertType('PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass|false', $r->getParentClass()); @@ -20,10 +21,10 @@ function (ReflectionEnum $r, string $s): void { function (ReflectionEnumBackedCase $r): void { assertType('string|false', $r->getDocComment()); - assertType('PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType|PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType|PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType|null', $r->getType()); + assertType(ReflectionType::class . '|null', $r->getType()); }; function (ReflectionEnumUnitCase $r): void { assertType('string|false', $r->getDocComment()); - assertType('PHPStan\BetterReflection\Reflection\Adapter\ReflectionIntersectionType|PHPStan\BetterReflection\Reflection\Adapter\ReflectionNamedType|PHPStan\BetterReflection\Reflection\Adapter\ReflectionUnionType|null', $r->getType()); + assertType(ReflectionType::class . '|null', $r->getType()); }; From 08df07a3e247336b406cc71d5cedb3ffb8121a6b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 20 Nov 2024 09:22:26 +0100 Subject: [PATCH 460/508] Regenerate baseline --- phpstan-baseline.neon | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 141752f21b..3b47d2e5fc 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -784,7 +784,8 @@ parameters: path: src/Type/Accessory/AccessoryUppercaseStringType.php - - message: "#^Doing instanceof PHPStan\\\\Type\\\\IntersectionType is error\\-prone and deprecated\\.$#" + message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#' + identifier: phpstanApi.instanceofType count: 1 path: src/Type/Accessory/HasMethodType.php From 78ac6f229b8b0e94f00f06e185a22a438435aec7 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Wed, 20 Nov 2024 14:20:15 +0100 Subject: [PATCH 461/508] Fix subtracting enums inside `in_array` Co-authored-by: Ondrej Mirtes --- ...InArrayFunctionTypeSpecifyingExtension.php | 4 +- tests/PHPStan/Analyser/nsrt/enum-in-array.php | 187 ++++++++++++++++++ 2 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 tests/PHPStan/Analyser/nsrt/enum-in-array.php diff --git a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php index 62c022c8e1..997cfea752 100644 --- a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php @@ -110,7 +110,9 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $context->true() || ( $context->false() - && count($arrayValueType->getFiniteTypes()) === 1 + && count($arrayValueType->getFiniteTypes()) > 0 + && count($needleType->getFiniteTypes()) > 0 + && $arrayType->isIterableAtLeastOnce()->yes() ) ) { $specifiedTypes = $this->typeSpecifier->create( diff --git a/tests/PHPStan/Analyser/nsrt/enum-in-array.php b/tests/PHPStan/Analyser/nsrt/enum-in-array.php new file mode 100644 index 0000000000..ca34261bc8 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/enum-in-array.php @@ -0,0 +1,187 @@ += 8.1 + +use function PHPStan\Testing\assertType; + +enum MyEnum: string +{ + + case A = 'a'; + case B = 'b'; + case C = 'c'; + + const SET_AB = [self::A, self::B]; + const SET_C = [self::C]; + const SET_ABC = [self::A, self::B, self::C]; + + public function test1(): void + { + foreach (self::cases() as $enum) { + if (in_array($enum, MyEnum::SET_AB, true)) { + assertType('MyEnum::A|MyEnum::B', $enum); + } elseif (in_array($enum, MyEnum::SET_C, true)) { + assertType('MyEnum::C', $enum); + } else { + assertType('*NEVER*', $enum); + } + } + } + + public function test2(): void + { + foreach (self::cases() as $enum) { + if (in_array($enum, MyEnum::SET_ABC, true)) { + assertType('MyEnum::A|MyEnum::B|MyEnum::C', $enum); + } else { + assertType('*NEVER*', $enum); + } + } + } + + public function test3(): void + { + foreach (self::cases() as $enum) { + if (in_array($enum, MyEnum::SET_C, true)) { + assertType('MyEnum::C', $enum); + } else { + assertType('MyEnum::A|MyEnum::B', $enum); + } + } + } + + public function test4(): void + { + foreach ([MyEnum::C] as $enum) { + if (in_array($enum, MyEnum::SET_C, true)) { + assertType('MyEnum::C', $enum); + } else { + assertType('*NEVER*', $enum); + } + } + } + + public function testNegative1(): void + { + foreach (self::cases() as $enum) { + if (!in_array($enum, MyEnum::SET_AB, true)) { + assertType('MyEnum::C', $enum); + } else { + assertType('MyEnum::A|MyEnum::B', $enum); + } + } + } + + public function testNegative2(): void + { + foreach (self::cases() as $enum) { + if (!in_array($enum, MyEnum::SET_AB, true)) { + assertType('MyEnum::C', $enum); + } elseif (!in_array($enum, MyEnum::SET_AB, true)) { + assertType('*NEVER*', $enum); + } + } + } + + public function testNegative3(): void + { + foreach ([MyEnum::C] as $enum) { + if (!in_array($enum, MyEnum::SET_C, true)) { + assertType('*NEVER*', $enum); + } + } + } + + /** + * @param array $array + */ + public function testNegative4(MyEnum $enum, array $array): void + { + if (!in_array($enum, $array, true)) { + assertType('MyEnum', $enum); + assertType('array', $array); + } else { + assertType('MyEnum', $enum); + assertType('non-empty-array', $array); + } + } + +} + +class InArrayEnum +{ + + /** @param list $list */ + public function testPositive(MyEnum $enum, array $list): void + { + if (in_array($enum, $list, true)) { + return; + } + + assertType(MyEnum::class, $enum); + assertType('list', $list); + } + + /** @param list $list */ + public function testNegative(MyEnum $enum, array $list): void + { + if (!in_array($enum, $list, true)) { + return; + } + + assertType(MyEnum::class, $enum); + assertType('non-empty-list', $list); + } + +} + + +class InArrayOtherFiniteType { + + const SET_AB = ['a', 'b']; + const SET_C = ['c']; + const SET_ABC = ['a', 'b', 'c']; + + public function test1(): void + { + foreach (['a', 'b', 'c'] as $item) { + if (in_array($item, self::SET_AB, true)) { + assertType("'a'|'b'", $item); + } elseif (in_array($item, self::SET_C, true)) { + assertType("'c'", $item); + } else { + assertType('*NEVER*', $item); + } + } + } + + public function test2(): void + { + foreach (['a', 'b', 'c'] as $item) { + if (in_array($item, self::SET_ABC, true)) { + assertType("'a'|'b'|'c'", $item); + } else { + assertType('*NEVER*', $item); + } + } + } + + public function test3(): void + { + foreach (['a', 'b', 'c'] as $item) { + if (in_array($item, self::SET_C, true)) { + assertType("'c'", $item); + } else { + assertType("'a'|'b'", $item); + } + } + } + public function test4(): void + { + foreach (['c'] as $item) { + if (in_array($item, self::SET_C, true)) { + assertType("'c'", $item); + } else { + assertType('*NEVER*', $item); + } + } + } +} From c0bfae6a2efe3daa7df1ab08802960f0fa305ce2 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Fri, 22 Nov 2024 19:09:12 +0100 Subject: [PATCH 462/508] Refactor TryRemove/Accepts for DateTime|DateTimeImmutable and Exception|Error --- phpstan-baseline.neon | 2 +- src/Type/ObjectType.php | 34 +++++++++++++--------------------- src/Type/UnionType.php | 28 ++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 3b47d2e5fc..d3e9a54a9d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1422,7 +1422,7 @@ parameters: - message: '#^Doing instanceof PHPStan\\Type\\ObjectType is error\-prone and deprecated\. Use Type\:\:isObject\(\) or Type\:\:getObjectClassNames\(\) instead\.$#' identifier: phpstanApi.instanceofType - count: 6 + count: 3 path: src/Type/ObjectType.php - diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index a51539df05..3290fb97c7 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -5,11 +5,6 @@ use ArrayAccess; use Closure; use Countable; -use DateTime; -use DateTimeImmutable; -use DateTimeInterface; -use Error; -use Exception; use Iterator; use IteratorAggregate; use PHPStan\Analyser\OutOfClassScope; @@ -46,7 +41,6 @@ use PHPStan\Type\Traits\NonGeneralizableTypeTrait; use PHPStan\Type\Traits\NonGenericTypeTrait; use PHPStan\Type\Traits\UndecidedComparisonTypeTrait; -use Throwable; use Traversable; use function array_key_exists; use function array_map; @@ -1560,23 +1554,21 @@ private function getInterfaces(): array public function tryRemove(Type $typeToRemove): ?Type { - if ($this->getClassName() === DateTimeInterface::class) { - if ($typeToRemove instanceof ObjectType && $typeToRemove->getClassName() === DateTimeImmutable::class) { - return new ObjectType(DateTime::class); - } - - if ($typeToRemove instanceof ObjectType && $typeToRemove->getClassName() === DateTime::class) { - return new ObjectType(DateTimeImmutable::class); - } - } + if ($typeToRemove instanceof ObjectType) { + foreach (UnionType::EQUAL_UNION_CLASSES as $baseClass => $classes) { + if ($this->getClassName() !== $baseClass) { + continue; + } - if ($this->getClassName() === Throwable::class) { - if ($typeToRemove instanceof ObjectType && $typeToRemove->getClassName() === Error::class) { - return new ObjectType(Exception::class); // phpcs:ignore SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException - } + foreach ($classes as $index => $class) { + if ($typeToRemove->getClassName() === $class) { + unset($classes[$index]); - if ($typeToRemove instanceof ObjectType && $typeToRemove->getClassName() === Exception::class) { // phpcs:ignore SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException - return new ObjectType(Error::class); + return TypeCombinator::union( + ...array_map(static fn (string $objectClass): Type => new ObjectType($objectClass), $classes), + ); + } + } } } diff --git a/src/Type/UnionType.php b/src/Type/UnionType.php index 1505fa1bb2..5d7627b306 100644 --- a/src/Type/UnionType.php +++ b/src/Type/UnionType.php @@ -5,6 +5,8 @@ use DateTime; use DateTimeImmutable; use DateTimeInterface; +use Error; +use Exception; use PHPStan\Php\PhpVersion; use PHPStan\PhpDocParser\Ast\Type\TypeNode; use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; @@ -26,6 +28,7 @@ use PHPStan\Type\Generic\TemplateTypeVariance; use PHPStan\Type\Generic\TemplateUnionType; use PHPStan\Type\Traits\NonGeneralizableTypeTrait; +use Throwable; use function array_diff_assoc; use function array_fill_keys; use function array_map; @@ -45,6 +48,11 @@ class UnionType implements CompoundType use NonGeneralizableTypeTrait; + public const EQUAL_UNION_CLASSES = [ + DateTimeInterface::class => [DateTimeImmutable::class, DateTime::class], + Throwable::class => [Error::class, Exception::class], // phpcs:ignore SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException + ]; + private bool $sortedTypes = false; /** @var array */ @@ -183,14 +191,18 @@ public function getConstantStrings(): array public function accepts(Type $type, bool $strictTypes): AcceptsResult { - if ( - $type->equals(new ObjectType(DateTimeInterface::class)) - && $this->accepts( - new UnionType([new ObjectType(DateTime::class), new ObjectType(DateTimeImmutable::class)]), - $strictTypes, - )->yes() - ) { - return AcceptsResult::createYes(); + foreach (self::EQUAL_UNION_CLASSES as $baseClass => $classes) { + if (!$type->equals(new ObjectType($baseClass))) { + continue; + } + + $union = TypeCombinator::union( + ...array_map(static fn (string $objectClass): Type => new ObjectType($objectClass), $classes), + ); + if ($this->accepts($union, $strictTypes)->yes()) { + return AcceptsResult::createYes(); + } + break; } $result = AcceptsResult::createNo(); From d9082ecf3c80d8ba169f0c2b15fed20613212bf0 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 23 Nov 2024 11:23:12 +0100 Subject: [PATCH 463/508] Implement Scope->getPhpVersion() --- src/Analyser/MutatingScope.php | 11 +++ src/Analyser/Scope.php | 3 + src/Php/PhpVersions.php | 26 +++++++ src/Rules/Methods/FinalPrivateMethodRule.php | 9 +-- tests/PHPStan/Php/PhpVersionsTest.php | 68 +++++++++++++++++++ .../Methods/FinalPrivateMethodRuleTest.php | 36 ++++++++-- .../data/final-private-method-phpversions.php | 43 ++++++++++++ 7 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 src/Php/PhpVersions.php create mode 100644 tests/PHPStan/Php/PhpVersionsTest.php create mode 100644 tests/PHPStan/Rules/Methods/data/final-private-method-phpversions.php diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index b8dcee4fd8..61f16a5119 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -47,6 +47,7 @@ use PHPStan\Parser\NewAssignedToPropertyVisitor; use PHPStan\Parser\Parser; use PHPStan\Php\PhpVersion; +use PHPStan\Php\PhpVersions; use PHPStan\PhpDoc\Tag\TemplateTag; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\Callables\CallableParametersAcceptor; @@ -5721,4 +5722,14 @@ public function getIterableValueType(Type $iteratee): Type return $iteratee->getIterableValueType(); } + public function getPhpVersion(): PhpVersions + { + $versionExpr = new ConstFetch(new Name('PHP_VERSION_ID')); + if (!$this->hasExpressionType($versionExpr)->yes()) { + return new PhpVersions(new ConstantIntegerType($this->phpVersion->getVersionId())); + } + + return new PhpVersions($this->getType($versionExpr)); + } + } diff --git a/src/Analyser/Scope.php b/src/Analyser/Scope.php index a14c9d108d..bf89cbdf48 100644 --- a/src/Analyser/Scope.php +++ b/src/Analyser/Scope.php @@ -6,6 +6,7 @@ use PhpParser\Node\Expr; use PhpParser\Node\Name; use PhpParser\Node\Param; +use PHPStan\Php\PhpVersions; use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberAccessAnswerer; use PHPStan\Reflection\ClassReflection; @@ -136,4 +137,6 @@ public function filterByFalseyValue(Expr $expr): self; public function isInFirstLevelStatement(): bool; + public function getPhpVersion(): PhpVersions; + } diff --git a/src/Php/PhpVersions.php b/src/Php/PhpVersions.php new file mode 100644 index 0000000000..a85c6c4a42 --- /dev/null +++ b/src/Php/PhpVersions.php @@ -0,0 +1,26 @@ +isSuperTypeOf($this->phpVersions)->result; + } + +} diff --git a/src/Rules/Methods/FinalPrivateMethodRule.php b/src/Rules/Methods/FinalPrivateMethodRule.php index b205234dc2..7331e21bc1 100644 --- a/src/Rules/Methods/FinalPrivateMethodRule.php +++ b/src/Rules/Methods/FinalPrivateMethodRule.php @@ -5,7 +5,6 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\InClassMethodNode; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use function sprintf; @@ -14,12 +13,6 @@ final class FinalPrivateMethodRule implements Rule { - public function __construct( - private PhpVersion $phpVersion, - ) - { - } - public function getNodeType(): string { return InClassMethodNode::class; @@ -28,7 +21,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $method = $node->getMethodReflection(); - if (!$this->phpVersion->producesWarningForFinalPrivateMethods()) { + if ($scope->getPhpVersion()->producesWarningForFinalPrivateMethods()->no()) { return []; } diff --git a/tests/PHPStan/Php/PhpVersionsTest.php b/tests/PHPStan/Php/PhpVersionsTest.php new file mode 100644 index 0000000000..b1563e2eb1 --- /dev/null +++ b/tests/PHPStan/Php/PhpVersionsTest.php @@ -0,0 +1,68 @@ +assertSame( + $expected->describe(), + $phpVersions->producesWarningForFinalPrivateMethods()->describe(), + ); + } + + public function dataProducesWarningForFinalPrivateMethods(): iterable + { + yield [ + TrinaryLogic::createNo(), + new ConstantIntegerType(70400), + ]; + + yield [ + TrinaryLogic::createYes(), + new ConstantIntegerType(80000), + ]; + + yield [ + TrinaryLogic::createYes(), + new ConstantIntegerType(80100), + ]; + + yield [ + TrinaryLogic::createYes(), + IntegerRangeType::fromInterval(80000, null), + ]; + + yield [ + TrinaryLogic::createMaybe(), + IntegerRangeType::fromInterval(null, 80000), + ]; + + yield [ + TrinaryLogic::createNo(), + IntegerRangeType::fromInterval(70200, 70400), + ]; + + yield [ + TrinaryLogic::createMaybe(), + new UnionType([ + IntegerRangeType::fromInterval(70200, 70400), + IntegerRangeType::fromInterval(80200, 80400), + ]), + ]; + } + +} diff --git a/tests/PHPStan/Rules/Methods/FinalPrivateMethodRuleTest.php b/tests/PHPStan/Rules/Methods/FinalPrivateMethodRuleTest.php index 64a4b89c0f..05be45a380 100644 --- a/tests/PHPStan/Rules/Methods/FinalPrivateMethodRuleTest.php +++ b/tests/PHPStan/Rules/Methods/FinalPrivateMethodRuleTest.php @@ -5,18 +5,15 @@ use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** @extends RuleTestCase */ class FinalPrivateMethodRuleTest extends RuleTestCase { - private int $phpVersionId; - protected function getRule(): Rule { - return new FinalPrivateMethodRule( - new PhpVersion($this->phpVersionId), - ); + return new FinalPrivateMethodRule(); } public function dataRule(): array @@ -44,8 +41,35 @@ public function dataRule(): array */ public function testRule(int $phpVersion, array $errors): void { - $this->phpVersionId = $phpVersion; + $testVersion = new PhpVersion($phpVersion); + $runtimeVersion = new PhpVersion(PHP_VERSION_ID); + + if ( + $testVersion->getMajorVersionId() !== $runtimeVersion->getMajorVersionId() + || $testVersion->getMinorVersionId() !== $runtimeVersion->getMinorVersionId() + ) { + $this->markTestSkipped('Test requires PHP version ' . $testVersion->getMajorVersionId() . '.' . $testVersion->getMinorVersionId() . '.*'); + } + $this->analyse([__DIR__ . '/data/final-private-method.php'], $errors); } + public function testRulePhpVersions(): void + { + $this->analyse([__DIR__ . '/data/final-private-method-phpversions.php'], [ + [ + 'Private method FinalPrivateMethodPhpVersions\FooBarPhp8orHigher::foo() cannot be final as it is never overridden by other classes.', + 9, + ], + [ + 'Private method FinalPrivateMethodPhpVersions\FooBarPhp74OrHigher::foo() cannot be final as it is never overridden by other classes.', + 29, + ], + [ + 'Private method FinalPrivateMethodPhpVersions\FooBarBaz::foo() cannot be final as it is never overridden by other classes.', + 39, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/final-private-method-phpversions.php b/tests/PHPStan/Rules/Methods/data/final-private-method-phpversions.php new file mode 100644 index 0000000000..c9424720d1 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/final-private-method-phpversions.php @@ -0,0 +1,43 @@ += 80000) { + class FooBarPhp8orHigher + { + + final private function foo(): void + { + } + } +} + +if (PHP_VERSION_ID < 80000) { + class FooBarPhp7 + { + + final private function foo(): void + { + } + } +} + +if (PHP_VERSION_ID > 70400) { + class FooBarPhp74OrHigher + { + + final private function foo(): void + { + } + } +} + +if (PHP_VERSION_ID < 70400 || PHP_VERSION_ID >= 80100) { + class FooBarBaz + { + + final private function foo(): void + { + } + } +} From adcabb3078603f46c811c7dc460174c9df551310 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Wed, 20 Nov 2024 15:48:39 +0100 Subject: [PATCH 464/508] TooWidePropertyTypeRule: dont skip even always-read properties --- src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php b/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php index 8d77cb01b4..68a513f295 100644 --- a/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php +++ b/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php @@ -61,9 +61,6 @@ public function processNode(Node $node, Scope $scope): array continue; } foreach ($this->extensionProvider->getExtensions() as $extension) { - if ($extension->isAlwaysRead($propertyReflection, $propertyName)) { - continue 2; - } if ($extension->isAlwaysWritten($propertyReflection, $propertyName)) { continue 2; } From 993db818fa59ae4f715a94a9e938aca69e7060a6 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 24 Nov 2024 09:17:40 +0100 Subject: [PATCH 465/508] Revert "TooWidePropertyTypeRule: dont skip even always-read properties" This reverts commit adcabb3078603f46c811c7dc460174c9df551310. --- src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php b/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php index 68a513f295..8d77cb01b4 100644 --- a/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php +++ b/src/Rules/TooWideTypehints/TooWidePropertyTypeRule.php @@ -61,6 +61,9 @@ public function processNode(Node $node, Scope $scope): array continue; } foreach ($this->extensionProvider->getExtensions() as $extension) { + if ($extension->isAlwaysRead($propertyReflection, $propertyName)) { + continue 2; + } if ($extension->isAlwaysWritten($propertyReflection, $propertyName)) { continue 2; } From e3867c05576f0b08656ce83f6ac2f6503ff22f94 Mon Sep 17 00:00:00 2001 From: schlndh Date: Sun, 24 Nov 2024 09:24:08 +0100 Subject: [PATCH 466/508] Bleeding edge - check that values passed to array_sum/product are castable to number --- conf/bleedingEdge.neon | 1 + conf/config.level5.neon | 6 + conf/config.neon | 1 + conf/parametersSchema.neon | 1 + .../ParameterCastableToNumberRule.php | 84 +++++++++ .../ParameterCastableToNumberRuleTest.php | 162 ++++++++++++++++++ .../Rules/Functions/data/bug-11883.php | 14 ++ ...aram-castable-to-number-functions-enum.php | 14 ++ ...astable-to-number-functions-named-args.php | 15 ++ .../param-castable-to-number-functions.php | 45 +++++ 10 files changed, 343 insertions(+) create mode 100644 src/Rules/Functions/ParameterCastableToNumberRule.php create mode 100644 tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php create mode 100644 tests/PHPStan/Rules/Functions/data/bug-11883.php create mode 100644 tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions-enum.php create mode 100644 tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions-named-args.php create mode 100644 tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions.php diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 8e06b22fda..7227e369b3 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -1,5 +1,6 @@ parameters: featureToggles: bleedingEdge: true + checkParameterCastableToNumberFunctions: true skipCheckGenericClasses!: [] stricterFunctionMap: true diff --git a/conf/config.level5.neon b/conf/config.level5.neon index b89a6dbddf..fd3835fbf1 100644 --- a/conf/config.level5.neon +++ b/conf/config.level5.neon @@ -5,6 +5,10 @@ parameters: checkFunctionArgumentTypes: true checkArgumentsPassedByReference: true +conditionalTags: + PHPStan\Rules\Functions\ParameterCastableToNumberRule: + phpstan.rules.rule: %featureToggles.checkParameterCastableToNumberFunctions% + rules: - PHPStan\Rules\DateTimeInstantiationRule - PHPStan\Rules\Functions\CallUserFuncRule @@ -36,3 +40,5 @@ services: treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% tags: - phpstan.rules.rule + - + class: PHPStan\Rules\Functions\ParameterCastableToNumberRule diff --git a/conf/config.neon b/conf/config.neon index 4679d5f31c..ba4bbb2f62 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -22,6 +22,7 @@ parameters: tooWideThrowType: true featureToggles: bleedingEdge: false + checkParameterCastableToNumberFunctions: false skipCheckGenericClasses: [] stricterFunctionMap: false fileExtensions: diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 6c7f9c40e6..f73011dcad 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -28,6 +28,7 @@ parametersSchema: ]) featureToggles: structure([ bleedingEdge: bool(), + checkParameterCastableToNumberFunctions: bool(), skipCheckGenericClasses: listOf(string()), stricterFunctionMap: bool() ]) diff --git a/src/Rules/Functions/ParameterCastableToNumberRule.php b/src/Rules/Functions/ParameterCastableToNumberRule.php new file mode 100644 index 0000000000..640c73a440 --- /dev/null +++ b/src/Rules/Functions/ParameterCastableToNumberRule.php @@ -0,0 +1,84 @@ + + */ +final class ParameterCastableToNumberRule implements Rule +{ + + public function __construct( + private ReflectionProvider $reflectionProvider, + private ParameterCastableToStringCheck $parameterCastableToStringCheck, + ) + { + } + + public function getNodeType(): string + { + return FuncCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!($node->name instanceof Node\Name)) { + return []; + } + + if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { + return []; + } + + $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); + $functionName = $functionReflection->getName(); + + if (!in_array($functionName, ['array_sum', 'array_product'], true)) { + return []; + } + + $origArgs = $node->getArgs(); + + if (count($origArgs) !== 1) { + return []; + } + + $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs( + $scope, + $origArgs, + $functionReflection->getVariants(), + $functionReflection->getNamedArgumentsVariants(), + ); + + $errorMessage = 'Parameter %s of function %s expects an array of values castable to number, %s given.'; + $functionParameters = $parametersAcceptor->getParameters(); + $error = $this->parameterCastableToStringCheck->checkParameter( + $origArgs[0], + $scope, + $errorMessage, + static fn (Type $t) => $t->toNumber(), + $functionName, + $this->parameterCastableToStringCheck->getParameterName( + $origArgs[0], + 0, + $functionParameters[0] ?? null, + ), + ); + + return $error !== null + ? [$error] + : []; + } + +} diff --git a/tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php b/tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php new file mode 100644 index 0000000000..77b64c3a30 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php @@ -0,0 +1,162 @@ + + */ +class ParameterCastableToNumberRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + $broker = $this->createReflectionProvider(); + return new ParameterCastableToNumberRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false))); + } + + public function testRule(): void + { + $this->analyse([__DIR__ . '/data/param-castable-to-number-functions.php'], $this->hackPhp74ErrorMessages([ + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array> given.', + 20, + ], + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array given.', + 21, + ], + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array given.', + 22, + ], + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array given.', + 23, + ], + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array given.', + 24, + ], + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array given.', + 25, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array> given.', + 27, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array given.', + 28, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array given.', + 29, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array given.', + 30, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array given.', + 31, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array given.', + 32, + ], + ])); + } + + public function testNamedArguments(): void + { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0.'); + } + + $this->analyse([__DIR__ . '/data/param-castable-to-number-functions-named-args.php'], [ + [ + 'Parameter $array of function array_sum expects an array of values castable to number, array> given.', + 7, + ], + [ + 'Parameter $array of function array_product expects an array of values castable to number, array> given.', + 8, + ], + ]); + } + + public function testEnum(): void + { + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped('Test requires PHP 8.1.'); + } + + $this->analyse([__DIR__ . '/data/param-castable-to-number-functions-enum.php'], [ + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array given.', + 12, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array given.', + 13, + ], + ]); + } + + public function testBug11883(): void + { + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped('Test requires PHP 8.1.'); + } + + $this->analyse([__DIR__ . '/data/bug-11883.php'], [ + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array given.', + 13, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array given.', + 14, + ], + ]); + } + + /** + * @param list $errors + * @return list + */ + private function hackPhp74ErrorMessages(array $errors): array + { + if (PHP_VERSION_ID >= 80000) { + return $errors; + } + + return array_map(static function (array $error): array { + $error[0] = str_replace( + [ + '$array of function array_sum', + '$array of function array_product', + 'array', + ], + [ + '$input of function array_sum', + '$input of function array_product', + 'array', + ], + $error[0], + ); + + return $error; + }, $errors); + } + +} diff --git a/tests/PHPStan/Rules/Functions/data/bug-11883.php b/tests/PHPStan/Rules/Functions/data/bug-11883.php new file mode 100644 index 0000000000..a14174777b --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-11883.php @@ -0,0 +1,14 @@ += 8.1 + +namespace Bug11883; + +enum SomeEnum: int +{ + case A = 1; + case B = 2; +} + +$enums1 = [SomeEnum::A, SomeEnum::B]; + +var_dump(array_sum($enums1)); +var_dump(array_product($enums1)); diff --git a/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions-enum.php b/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions-enum.php new file mode 100644 index 0000000000..91e9f1f686 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions-enum.php @@ -0,0 +1,14 @@ += 8.1 + +namespace ParamCastableToNumberFunctionsEnum; + +enum FooEnum +{ + case A; +} + +function invalidUsages() +{ + array_sum([FooEnum::A]); + array_product([FooEnum::A]); +} diff --git a/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions-named-args.php b/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions-named-args.php new file mode 100644 index 0000000000..4fdc546062 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions-named-args.php @@ -0,0 +1,15 @@ += 8.0 + +namespace ParamCastableToNumberFunctionsNamedArgs; + +function invalidUsages() +{ + var_dump(array_sum(array: [[0]])); + var_dump(array_product(array: [[0]])); +} + +function validUsages() +{ + var_dump(array_sum(array: [1])); + var_dump(array_product(array: [1])); +} diff --git a/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions.php b/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions.php new file mode 100644 index 0000000000..9e7c5da4d2 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/param-castable-to-number-functions.php @@ -0,0 +1,45 @@ +7.7'), 5, 5.5, null])); + var_dump(array_product(['5.5', false, true, new \SimpleXMLElement('7.7'), 5, 5.5, null])); +} From 2d637dab640f194f19b2c50a565b13e331c0227c Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 24 Nov 2024 09:25:51 +0100 Subject: [PATCH 467/508] `Scope::getPhpVersion()` allows array via phpVersion min+max config --- src/Analyser/DirectInternalScopeFactory.php | 5 +++ src/Analyser/LazyInternalScopeFactory.php | 1 + src/Analyser/MutatingScope.php | 6 ++++ src/Testing/PHPStanTestCase.php | 1 + .../FinalPrivateMethodRuleConfigPhpTest.php | 34 +++++++++++++++++++ ...final-private-method-config-phpversion.php | 11 ++++++ .../data/final-private-php-version.neon | 4 +++ 7 files changed, 62 insertions(+) create mode 100644 tests/PHPStan/Rules/Methods/FinalPrivateMethodRuleConfigPhpTest.php create mode 100644 tests/PHPStan/Rules/Methods/data/final-private-method-config-phpversion.php create mode 100644 tests/PHPStan/Rules/Methods/data/final-private-php-version.neon diff --git a/src/Analyser/DirectInternalScopeFactory.php b/src/Analyser/DirectInternalScopeFactory.php index 99f4287dfe..74b43d80c9 100644 --- a/src/Analyser/DirectInternalScopeFactory.php +++ b/src/Analyser/DirectInternalScopeFactory.php @@ -19,6 +19,9 @@ final class DirectInternalScopeFactory implements InternalScopeFactory { + /** + * @param int|array{min: int, max: int}|null $configPhpVersion + */ public function __construct( private ReflectionProvider $reflectionProvider, private InitializerExprTypeResolver $initializerExprTypeResolver, @@ -31,6 +34,7 @@ public function __construct( private NodeScopeResolver $nodeScopeResolver, private RicherScopeGetTypeHelper $richerScopeGetTypeHelper, private PhpVersion $phpVersion, + private int|array|null $configPhpVersion, private ConstantResolver $constantResolver, ) { @@ -78,6 +82,7 @@ public function create( $this->constantResolver, $context, $this->phpVersion, + $this->configPhpVersion, $declareStrictTypes, $function, $namespace, diff --git a/src/Analyser/LazyInternalScopeFactory.php b/src/Analyser/LazyInternalScopeFactory.php index 79d34fb54f..ac5b757991 100644 --- a/src/Analyser/LazyInternalScopeFactory.php +++ b/src/Analyser/LazyInternalScopeFactory.php @@ -67,6 +67,7 @@ public function create( $this->container->getByType(ConstantResolver::class), $context, $this->container->getByType(PhpVersion::class), + $this->container->getParameter('phpVersion'), $declareStrictTypes, $function, $namespace, diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 61f16a5119..e7afd055e4 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -144,6 +144,7 @@ use function get_class; use function implode; use function in_array; +use function is_array; use function is_bool; use function is_numeric; use function is_string; @@ -184,6 +185,7 @@ final class MutatingScope implements Scope private static int $resolveClosureTypeDepth = 0; /** + * @param int|array{min: int, max: int}|null $configPhpVersion * @param array $expressionTypes * @param array $conditionalExpressions * @param list $inClosureBindScopeClasses @@ -207,6 +209,7 @@ public function __construct( private ConstantResolver $constantResolver, private ScopeContext $context, private PhpVersion $phpVersion, + private int|array|null $configPhpVersion, private bool $declareStrictTypes = false, private PhpFunctionFromParserNodeReflection|null $function = null, ?string $namespace = null, @@ -5726,6 +5729,9 @@ public function getPhpVersion(): PhpVersions { $versionExpr = new ConstFetch(new Name('PHP_VERSION_ID')); if (!$this->hasExpressionType($versionExpr)->yes()) { + if (is_array($this->configPhpVersion)) { + return new PhpVersions(IntegerRangeType::fromInterval($this->configPhpVersion['min'], $this->configPhpVersion['max'])); + } return new PhpVersions(new ConstantIntegerType($this->phpVersion->getVersionId())); } diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index 31cdfadb78..849fbfac11 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -163,6 +163,7 @@ public static function createScopeFactory(ReflectionProvider $reflectionProvider $container->getByType(NodeScopeResolver::class), new RicherScopeGetTypeHelper($initializerExprTypeResolver), $container->getByType(PhpVersion::class), + $container->getParameter('phpVersion'), $constantResolver, ), ); diff --git a/tests/PHPStan/Rules/Methods/FinalPrivateMethodRuleConfigPhpTest.php b/tests/PHPStan/Rules/Methods/FinalPrivateMethodRuleConfigPhpTest.php new file mode 100644 index 0000000000..dddd414b72 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/FinalPrivateMethodRuleConfigPhpTest.php @@ -0,0 +1,34 @@ + */ +class FinalPrivateMethodRuleConfigPhpTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new FinalPrivateMethodRule(); + } + + public function testRulePhpVersions(): void + { + $this->analyse([__DIR__ . '/data/final-private-method-config-phpversion.php'], [ + [ + 'Private method FinalPrivateMethodConfigPhpVersions\PhpVersionViaNEONConfg::foo() cannot be final as it is never overridden by other classes.', + 8, + ], + ]); + } + + public static function getAdditionalConfigFiles(): array + { + return [ + __DIR__ . '/data/final-private-php-version.neon', + ]; + } + +} diff --git a/tests/PHPStan/Rules/Methods/data/final-private-method-config-phpversion.php b/tests/PHPStan/Rules/Methods/data/final-private-method-config-phpversion.php new file mode 100644 index 0000000000..6880568c93 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/final-private-method-config-phpversion.php @@ -0,0 +1,11 @@ + Date: Tue, 26 Nov 2024 01:06:55 +0900 Subject: [PATCH 468/508] Last value was not recognized when passing an associative array as an argument --- src/Rules/FunctionCallParametersCheck.php | 17 +++++--- .../Rules/Classes/InstantiationRuleTest.php | 5 +++ .../PHPStan/Rules/Classes/data/bug-11815.php | 43 +++++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 tests/PHPStan/Rules/Classes/data/bug-11815.php diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index 130dd0bef8..d320c24d60 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -30,6 +30,7 @@ use function array_key_exists; use function count; use function implode; +use function in_array; use function is_int; use function is_string; use function max; @@ -128,30 +129,32 @@ public function check( if ($arg->unpack) { $arrays = $type->getConstantArrays(); if (count($arrays) > 0) { - $minKeys = null; + $maxKeys = null; foreach ($arrays as $array) { $countType = $array->getArraySize(); if ($countType instanceof ConstantIntegerType) { $keysCount = $countType->getValue(); } elseif ($countType instanceof IntegerRangeType) { - $keysCount = $countType->getMin(); + $keysCount = $countType->getMax(); if ($keysCount === null) { throw new ShouldNotHappenException(); } } else { throw new ShouldNotHappenException(); } - if ($minKeys !== null && $keysCount >= $minKeys) { + if ($maxKeys !== null && $keysCount >= $maxKeys) { continue; } - $minKeys = $keysCount; + $maxKeys = $keysCount; } - for ($j = 0; $j < $minKeys; $j++) { + for ($j = 0; $j < $maxKeys; $j++) { $types = []; $commonKey = null; + $isOptionalKey = false; foreach ($arrays as $constantArray) { + $isOptionalKey = in_array($j, $constantArray->getOptionalKeys(), true); $types[] = $constantArray->getValueTypes()[$j]; $keyType = $constantArray->getKeyTypes()[$j]; if ($commonKey === null) { @@ -165,6 +168,10 @@ public function check( $keyArgumentName = $commonKey; $hasNamedArguments = true; } + if ($isOptionalKey) { + continue; + } + $arguments[] = [ $arg->value, TypeCombinator::union(...$types), diff --git a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php index 657c47bd75..43b9091daf 100644 --- a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php +++ b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php @@ -499,4 +499,9 @@ public function testBug10248(): void $this->analyse([__DIR__ . '/data/bug-10248.php'], []); } + public function testBug11815(): void + { + $this->analyse([__DIR__ . '/data/bug-11815.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Classes/data/bug-11815.php b/tests/PHPStan/Rules/Classes/data/bug-11815.php new file mode 100644 index 0000000000..c08dccb9ea --- /dev/null +++ b/tests/PHPStan/Rules/Classes/data/bug-11815.php @@ -0,0 +1,43 @@ += 8.2 + +declare(strict_types = 1); + +class Dimensions +{ + public function __construct( + public int $width, + public int $height, + ) { + } +} + +class StoreProcessorResult +{ + public function __construct( + public string $path, + public string $mimetype, + public Dimensions $dimensions, + public int $filesize, + public true|null $identical = null, + ) { + } +} + +/** + * @return array{path: string, identical?: true} + */ +function getPath(): array +{ + $data = ['path' => 'some/path']; + if ((bool)rand(0, 1)) { + $data['identical'] = true; + } + return $data; +} + +$data = getPath(); +$data['dimensions'] = new Dimensions(100, 100); +$data['mimetype'] = 'image/png'; +$data['filesize'] = 123456; + +$dto = new StoreProcessorResult(...$data); From a0e007aee46a0a3ac56d74789f1107a87d0f5740 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 24 Nov 2024 11:26:38 +0100 Subject: [PATCH 469/508] non-capturing catch support-detection is scope php-version dependent --- src/Php/PhpVersions.php | 5 +++++ src/Rules/Exceptions/NoncapturingCatchRule.php | 7 +------ .../Rules/Exceptions/NoncapturingCatchRuleTest.php | 14 ++++++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Php/PhpVersions.php b/src/Php/PhpVersions.php index a85c6c4a42..7bdc70e3bf 100644 --- a/src/Php/PhpVersions.php +++ b/src/Php/PhpVersions.php @@ -18,6 +18,11 @@ public function __construct( { } + public function supportsNoncapturingCatches(): TrinaryLogic + { + return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result; + } + public function producesWarningForFinalPrivateMethods(): TrinaryLogic { return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result; diff --git a/src/Rules/Exceptions/NoncapturingCatchRule.php b/src/Rules/Exceptions/NoncapturingCatchRule.php index 499b62e154..a4d91a9ba2 100644 --- a/src/Rules/Exceptions/NoncapturingCatchRule.php +++ b/src/Rules/Exceptions/NoncapturingCatchRule.php @@ -4,7 +4,6 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -14,10 +13,6 @@ final class NoncapturingCatchRule implements Rule { - public function __construct(private PhpVersion $phpVersion) - { - } - public function getNodeType(): string { return Node\Stmt\Catch_::class; @@ -28,7 +23,7 @@ public function getNodeType(): string */ public function processNode(Node $node, Scope $scope): array { - if ($this->phpVersion->supportsNoncapturingCatches()) { + if ($scope->getPhpVersion()->supportsNoncapturingCatches()->yes()) { return []; } diff --git a/tests/PHPStan/Rules/Exceptions/NoncapturingCatchRuleTest.php b/tests/PHPStan/Rules/Exceptions/NoncapturingCatchRuleTest.php index 9c8181f4a3..8139960e66 100644 --- a/tests/PHPStan/Rules/Exceptions/NoncapturingCatchRuleTest.php +++ b/tests/PHPStan/Rules/Exceptions/NoncapturingCatchRuleTest.php @@ -5,6 +5,7 @@ use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -12,11 +13,9 @@ class NoncapturingCatchRuleTest extends RuleTestCase { - private PhpVersion $phpVersion; - protected function getRule(): Rule { - return new NoncapturingCatchRule($this->phpVersion); + return new NoncapturingCatchRule(); } public function dataRule(): array @@ -49,7 +48,14 @@ public function dataRule(): array */ public function testRule(int $phpVersion, array $expectedErrors): void { - $this->phpVersion = new PhpVersion($phpVersion); + $testVersion = new PhpVersion($phpVersion); + $runtimeVersion = new PhpVersion(PHP_VERSION_ID); + if ( + $testVersion->getMajorVersionId() !== $runtimeVersion->getMajorVersionId() + || $testVersion->getMinorVersionId() !== $runtimeVersion->getMinorVersionId() + ) { + $this->markTestSkipped('Test requires PHP version ' . $testVersion->getMajorVersionId() . '.' . $testVersion->getMinorVersionId() . '.*'); + } $this->analyse([ __DIR__ . '/data/noncapturing-catch.php', From d35a2f464d7756022b12acc83c994bcb39d07ac9 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 26 Nov 2024 00:03:38 +0000 Subject: [PATCH 470/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 73f1cc620f..71c48bfbc7 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#fda684a4826c1caf59efe1a1bf68d08c11aaddbf", + "jetbrains/phpstorm-stubs": "dev-master#9efcc4aa48b9c752c68de25f6240fcced0c95151", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index d2adb5606c..6a7f1ff905 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a4991601b7590d9dc65443dfb5d34d16", + "content-hash": "274e72a3422f81d92070bbbedbb9f8f5", "packages": [ { "name": "clue/ndjson-react", @@ -1442,18 +1442,18 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "fda684a4826c1caf59efe1a1bf68d08c11aaddbf" + "reference": "9efcc4aa48b9c752c68de25f6240fcced0c95151" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/fda684a4826c1caf59efe1a1bf68d08c11aaddbf", - "reference": "fda684a4826c1caf59efe1a1bf68d08c11aaddbf", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/9efcc4aa48b9c752c68de25f6240fcced0c95151", + "reference": "9efcc4aa48b9c752c68de25f6240fcced0c95151", "shasum": "" }, "require-dev": { "friendsofphp/php-cs-fixer": "v3.64.0", "nikic/php-parser": "v5.3.1", - "phpdocumentor/reflection-docblock": "5.5.1", + "phpdocumentor/reflection-docblock": "5.6.0", "phpunit/phpunit": "11.4.3" }, "default-branch": true, @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-11-15T09:42:33+00:00" + "time": "2024-11-25T11:21:35+00:00" }, { "name": "nette/bootstrap", From 96f721d40a0492e2f33a2316efaa50da0d385b0f Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Tue, 26 Nov 2024 20:00:44 +0000 Subject: [PATCH 471/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 71c48bfbc7..8963aa75c3 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.43.0.2", + "ondrejmirtes/better-reflection": "6.43.0.4", "phpstan/php-8-stubs": "0.4.6", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 6a7f1ff905..a1f8f8e83a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "274e72a3422f81d92070bbbedbb9f8f5", + "content-hash": "1866d60acbec835ca58159c3cb6c07a8", "packages": [ { "name": "clue/ndjson-react", @@ -2187,16 +2187,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.43.0.2", + "version": "6.43.0.4", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "c34ee726f9abc5a7057b0dacdf1c0991c9090584" + "reference": "6b869bb58972b7877509e8a24757b4108effcd79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/c34ee726f9abc5a7057b0dacdf1c0991c9090584", - "reference": "c34ee726f9abc5a7057b0dacdf1c0991c9090584", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/6b869bb58972b7877509e8a24757b4108effcd79", + "reference": "6b869bb58972b7877509e8a24757b4108effcd79", "shasum": "" }, "require": { @@ -2213,7 +2213,7 @@ "phpstan/phpstan": "^1.10.60", "phpstan/phpstan-phpunit": "^1.3.16", "phpunit/phpunit": "^11.4.3", - "rector/rector": "0.14.3" + "rector/rector": "1.2.10" }, "suggest": { "composer/composer": "Required to use the ComposerSourceLocator" @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.43.0.2" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.43.0.4" }, - "time": "2024-11-19T19:32:34+00:00" + "time": "2024-11-26T19:58:24+00:00" }, { "name": "phpstan/php-8-stubs", From 17da15181a75ec1bd184959185005e6e857e1220 Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Tue, 26 Nov 2024 20:52:02 +0000 Subject: [PATCH 472/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 8963aa75c3..988292f2d6 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.43.0.4", + "ondrejmirtes/better-reflection": "6.44.0.2", "phpstan/php-8-stubs": "0.4.6", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index a1f8f8e83a..d705cd728f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1866d60acbec835ca58159c3cb6c07a8", + "content-hash": "6c77a249a859b7eb74df36c091206c59", "packages": [ { "name": "clue/ndjson-react", @@ -2187,16 +2187,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.43.0.4", + "version": "6.44.0.2", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "6b869bb58972b7877509e8a24757b4108effcd79" + "reference": "50fe615bd6665bbc541b6ddb419bff11fc0718a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/6b869bb58972b7877509e8a24757b4108effcd79", - "reference": "6b869bb58972b7877509e8a24757b4108effcd79", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/50fe615bd6665bbc541b6ddb419bff11fc0718a1", + "reference": "50fe615bd6665bbc541b6ddb419bff11fc0718a1", "shasum": "" }, "require": { @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.43.0.4" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.2" }, - "time": "2024-11-26T19:58:24+00:00" + "time": "2024-11-26T20:50:48+00:00" }, { "name": "phpstan/php-8-stubs", From 1c4c1009a523a709d69cbe417580dd8aa44b4245 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Wed, 27 Nov 2024 00:21:18 +0000 Subject: [PATCH 473/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 988292f2d6..da38b8d286 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.44.0.2", - "phpstan/php-8-stubs": "0.4.6", + "phpstan/php-8-stubs": "0.4.7", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index d705cd728f..569d899634 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6c77a249a859b7eb74df36c091206c59", + "content-hash": "d934490a94126dd32923c058834ef486", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.6", + "version": "0.4.7", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "25ba0a11dc14a02c062392786486ada62d36b66d" + "reference": "794d410e0de8779afb4706d8667d2b3a11a3865a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/25ba0a11dc14a02c062392786486ada62d36b66d", - "reference": "25ba0a11dc14a02c062392786486ada62d36b66d", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/794d410e0de8779afb4706d8667d2b3a11a3865a", + "reference": "794d410e0de8779afb4706d8667d2b3a11a3865a", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.6" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.7" }, - "time": "2024-11-13T00:19:28+00:00" + "time": "2024-11-27T00:20:37+00:00" }, { "name": "phpstan/phpdoc-parser", From 5ec47623fa31f63912d904ba90693eac64b0de0c Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 27 Nov 2024 10:00:39 +0100 Subject: [PATCH 474/508] PropertyHookType should not be prefixed in BetterReflection --- compiler/build/scoper.inc.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/build/scoper.inc.php b/compiler/build/scoper.inc.php index 957cfe721d..0d0008d341 100644 --- a/compiler/build/scoper.inc.php +++ b/compiler/build/scoper.inc.php @@ -226,6 +226,13 @@ function (string $filePath, string $prefix, string $content): string { sprintf('\\\\%s', $prefix), ], '', $content); }, + function (string $filePath, string $prefix, string $content): string { + if (!str_starts_with($filePath, 'vendor/ondrejmirtes/better-reflection')) { + return $content; + } + + return str_replace(sprintf('%s\\PropertyHookType', $prefix), 'PropertyHookType', $content); + }, function (string $filePath, string $prefix, string $content): string { if ( $filePath !== 'vendor/nette/utils/src/Utils/Strings.php' From 265a39bb014534095b2f1651de27f4c10e770c09 Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Wed, 27 Nov 2024 10:50:13 +0000 Subject: [PATCH 475/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index da38b8d286..593163649e 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.44.0.2", + "ondrejmirtes/better-reflection": "6.44.0.3", "phpstan/php-8-stubs": "0.4.7", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 569d899634..a31b6c1e33 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d934490a94126dd32923c058834ef486", + "content-hash": "402089d9a3d76a9b791773a44ed74775", "packages": [ { "name": "clue/ndjson-react", @@ -2187,16 +2187,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.44.0.2", + "version": "6.44.0.3", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "50fe615bd6665bbc541b6ddb419bff11fc0718a1" + "reference": "c30607531b1ae173ea69a72c21ae598f15fef4af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/50fe615bd6665bbc541b6ddb419bff11fc0718a1", - "reference": "50fe615bd6665bbc541b6ddb419bff11fc0718a1", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/c30607531b1ae173ea69a72c21ae598f15fef4af", + "reference": "c30607531b1ae173ea69a72c21ae598f15fef4af", "shasum": "" }, "require": { @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.2" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.3" }, - "time": "2024-11-26T20:50:48+00:00" + "time": "2024-11-27T10:47:28+00:00" }, { "name": "phpstan/php-8-stubs", From 1abeeb77771fc3fece5c7196f75dfc1478840515 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 27 Nov 2024 14:01:24 +0100 Subject: [PATCH 476/508] Un-finalize Printer See https://github.com/rectorphp/rector-src/pull/6517#issuecomment-2503502706 --- build/PHPStan/Build/FinalClassRule.php | 2 ++ src/Node/Printer/Printer.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/build/PHPStan/Build/FinalClassRule.php b/build/PHPStan/Build/FinalClassRule.php index a4758648c6..10f30a8d48 100644 --- a/build/PHPStan/Build/FinalClassRule.php +++ b/build/PHPStan/Build/FinalClassRule.php @@ -6,6 +6,7 @@ use PHPStan\Analyser\Scope; use PHPStan\File\FileHelper; use PHPStan\Node\InClassNode; +use PHPStan\Node\Printer\Printer; use PHPStan\Reflection\FunctionVariant; use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\Php\DummyParameter; @@ -54,6 +55,7 @@ public function processNode(Node $node, Scope $scope): array ExtendedFunctionVariant::class, DummyParameter::class, PhpFunctionFromParserNodeReflection::class, + Printer::class, ], true)) { return []; } diff --git a/src/Node/Printer/Printer.php b/src/Node/Printer/Printer.php index 131376d66d..744c857f8f 100644 --- a/src/Node/Printer/Printer.php +++ b/src/Node/Printer/Printer.php @@ -22,7 +22,7 @@ /** * @api */ -final class Printer extends Standard +class Printer extends Standard { public function __construct() From 07d7c44d50677874086cb8796a97482d406d3442 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 27 Nov 2024 14:26:42 +0100 Subject: [PATCH 477/508] Revert "Un-finalize Printer" This reverts commit 1abeeb77771fc3fece5c7196f75dfc1478840515. --- build/PHPStan/Build/FinalClassRule.php | 2 -- src/Node/Printer/Printer.php | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/build/PHPStan/Build/FinalClassRule.php b/build/PHPStan/Build/FinalClassRule.php index 10f30a8d48..a4758648c6 100644 --- a/build/PHPStan/Build/FinalClassRule.php +++ b/build/PHPStan/Build/FinalClassRule.php @@ -6,7 +6,6 @@ use PHPStan\Analyser\Scope; use PHPStan\File\FileHelper; use PHPStan\Node\InClassNode; -use PHPStan\Node\Printer\Printer; use PHPStan\Reflection\FunctionVariant; use PHPStan\Reflection\ExtendedFunctionVariant; use PHPStan\Reflection\Php\DummyParameter; @@ -55,7 +54,6 @@ public function processNode(Node $node, Scope $scope): array ExtendedFunctionVariant::class, DummyParameter::class, PhpFunctionFromParserNodeReflection::class, - Printer::class, ], true)) { return []; } diff --git a/src/Node/Printer/Printer.php b/src/Node/Printer/Printer.php index 744c857f8f..131376d66d 100644 --- a/src/Node/Printer/Printer.php +++ b/src/Node/Printer/Printer.php @@ -22,7 +22,7 @@ /** * @api */ -class Printer extends Standard +final class Printer extends Standard { public function __construct() From fa9212fc7e68f9609dbfc5b1042ce83c5b34450d Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 27 Nov 2024 19:26:13 +0700 Subject: [PATCH 478/508] Remove shortArraySyntax definiton on Printer::construct() It seems alreayd short array syntax by default --- src/Node/Printer/Printer.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Node/Printer/Printer.php b/src/Node/Printer/Printer.php index 131376d66d..6f00bc8031 100644 --- a/src/Node/Printer/Printer.php +++ b/src/Node/Printer/Printer.php @@ -24,12 +24,6 @@ */ final class Printer extends Standard { - - public function __construct() - { - parent::__construct(['shortArraySyntax' => true]); - } - protected function pPHPStan_Node_TypeExpr(TypeExpr $expr): string // phpcs:ignore { return sprintf('__phpstanType(%s)', $expr->getExprType()->describe(VerbosityLevel::precise())); From 68803e997f4ab10c98a014e4a6d057b99e08b6b7 Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Wed, 27 Nov 2024 13:47:17 +0000 Subject: [PATCH 479/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 593163649e..684e819342 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.44.0.3", + "ondrejmirtes/better-reflection": "6.44.0.4", "phpstan/php-8-stubs": "0.4.7", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index a31b6c1e33..1f3a161391 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "402089d9a3d76a9b791773a44ed74775", + "content-hash": "ac31d4286789897fa7f8d303b33a72b0", "packages": [ { "name": "clue/ndjson-react", @@ -2187,16 +2187,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.44.0.3", + "version": "6.44.0.4", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "c30607531b1ae173ea69a72c21ae598f15fef4af" + "reference": "3865f1f8779d4e3562886ee261ccfdbf2da15650" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/c30607531b1ae173ea69a72c21ae598f15fef4af", - "reference": "c30607531b1ae173ea69a72c21ae598f15fef4af", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/3865f1f8779d4e3562886ee261ccfdbf2da15650", + "reference": "3865f1f8779d4e3562886ee261ccfdbf2da15650", "shasum": "" }, "require": { @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.3" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.4" }, - "time": "2024-11-27T10:47:28+00:00" + "time": "2024-11-27T13:45:40+00:00" }, { "name": "phpstan/php-8-stubs", From e1b1cad3c7da1ef175b039c4b1af37212d52a22f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 27 Nov 2024 15:04:32 +0100 Subject: [PATCH 480/508] Fix CS --- src/Node/Printer/Printer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Node/Printer/Printer.php b/src/Node/Printer/Printer.php index 6f00bc8031..6d9dab1062 100644 --- a/src/Node/Printer/Printer.php +++ b/src/Node/Printer/Printer.php @@ -24,6 +24,7 @@ */ final class Printer extends Standard { + protected function pPHPStan_Node_TypeExpr(TypeExpr $expr): string // phpcs:ignore { return sprintf('__phpstanType(%s)', $expr->getExprType()->describe(VerbosityLevel::precise())); From f9e84e05bf9b4e15a4b019d4e372b71ba98e42e8 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:03:11 +0000 Subject: [PATCH 481/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 684e819342..1505dfeb90 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#9efcc4aa48b9c752c68de25f6240fcced0c95151", + "jetbrains/phpstorm-stubs": "dev-master#7809499af1a5f3bdd20f1cab71717a2a9e1f8cf7", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index 1f3a161391..b40729b153 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ac31d4286789897fa7f8d303b33a72b0", + "content-hash": "c1cf63bf474629a0d7b5fea00c2ec54c", "packages": [ { "name": "clue/ndjson-react", @@ -1442,12 +1442,12 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "9efcc4aa48b9c752c68de25f6240fcced0c95151" + "reference": "7809499af1a5f3bdd20f1cab71717a2a9e1f8cf7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/9efcc4aa48b9c752c68de25f6240fcced0c95151", - "reference": "9efcc4aa48b9c752c68de25f6240fcced0c95151", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/7809499af1a5f3bdd20f1cab71717a2a9e1f8cf7", + "reference": "7809499af1a5f3bdd20f1cab71717a2a9e1f8cf7", "shasum": "" }, "require-dev": { @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-11-25T11:21:35+00:00" + "time": "2024-11-27T14:37:09+00:00" }, { "name": "nette/bootstrap", From ae2b6a709ddcd9a4260587565809bd7f1a50d2bd Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Thu, 28 Nov 2024 00:21:27 +0000 Subject: [PATCH 482/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 1505dfeb90..a9260b897c 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.44.0.4", - "phpstan/php-8-stubs": "0.4.7", + "phpstan/php-8-stubs": "0.4.8", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index b40729b153..1135a6a574 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c1cf63bf474629a0d7b5fea00c2ec54c", + "content-hash": "d1310e0c489abe492a66dced167d3f1e", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.7", + "version": "0.4.8", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "794d410e0de8779afb4706d8667d2b3a11a3865a" + "reference": "8a6278b2b9c9781cb969c4128da361b78eead604" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/794d410e0de8779afb4706d8667d2b3a11a3865a", - "reference": "794d410e0de8779afb4706d8667d2b3a11a3865a", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/8a6278b2b9c9781cb969c4128da361b78eead604", + "reference": "8a6278b2b9c9781cb969c4128da361b78eead604", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.7" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.8" }, - "time": "2024-11-27T00:20:37+00:00" + "time": "2024-11-28T00:20:48+00:00" }, { "name": "phpstan/phpdoc-parser", From c95367d52b04d524f1fb154e944ddb1ab8cab9a8 Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Thu, 28 Nov 2024 20:40:22 +0000 Subject: [PATCH 483/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index a9260b897c..912996ab0d 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.44.0.4", + "ondrejmirtes/better-reflection": "6.44.0.5", "phpstan/php-8-stubs": "0.4.8", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 1135a6a574..7441a9d501 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d1310e0c489abe492a66dced167d3f1e", + "content-hash": "53bd280e3693edf29e8871fa22ad20f7", "packages": [ { "name": "clue/ndjson-react", @@ -2187,16 +2187,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.44.0.4", + "version": "6.44.0.5", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "3865f1f8779d4e3562886ee261ccfdbf2da15650" + "reference": "b6d0a9adbe61544f6e8992611590a4e61487a638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/3865f1f8779d4e3562886ee261ccfdbf2da15650", - "reference": "3865f1f8779d4e3562886ee261ccfdbf2da15650", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/b6d0a9adbe61544f6e8992611590a4e61487a638", + "reference": "b6d0a9adbe61544f6e8992611590a4e61487a638", "shasum": "" }, "require": { @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.4" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.5" }, - "time": "2024-11-27T13:45:40+00:00" + "time": "2024-11-28T20:34:45+00:00" }, { "name": "phpstan/php-8-stubs", From 86197c9987529b5545c0a09ac6ad92581087526f Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Thu, 28 Nov 2024 21:07:43 +0000 Subject: [PATCH 484/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 912996ab0d..0f28344835 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.44.0.5", + "ondrejmirtes/better-reflection": "6.44.0.6", "phpstan/php-8-stubs": "0.4.8", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 7441a9d501..7cd32ee1ad 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "53bd280e3693edf29e8871fa22ad20f7", + "content-hash": "aa42dc6e1a7a8d5fc9844d231515e30f", "packages": [ { "name": "clue/ndjson-react", @@ -2187,16 +2187,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.44.0.5", + "version": "6.44.0.6", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "b6d0a9adbe61544f6e8992611590a4e61487a638" + "reference": "d942fd0af0214bb1250a55c2560f061b7b0c4bd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/b6d0a9adbe61544f6e8992611590a4e61487a638", - "reference": "b6d0a9adbe61544f6e8992611590a4e61487a638", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/d942fd0af0214bb1250a55c2560f061b7b0c4bd4", + "reference": "d942fd0af0214bb1250a55c2560f061b7b0c4bd4", "shasum": "" }, "require": { @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.5" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.6" }, - "time": "2024-11-28T20:34:45+00:00" + "time": "2024-11-28T21:05:45+00:00" }, { "name": "phpstan/php-8-stubs", From e6dc705b29b90dcc5f9773377c05aecbfe9fba3a Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz <80641364+jakubtobiasz@users.noreply.github.com> Date: Thu, 28 Nov 2024 23:00:31 +0100 Subject: [PATCH 485/508] Sanity checks around hooked properties in interfaces and classes --- .github/workflows/lint.yml | 2 +- Makefile | 10 ++ build/collision-detector.json | 2 +- conf/config.level0.neon | 1 + src/Node/ClassPropertyNode.php | 18 +++ src/Php/PhpVersion.php | 5 + .../Properties/PropertiesInInterfaceRule.php | 59 ++++++- src/Rules/Properties/PropertyInClassRule.php | 113 +++++++++++++ .../PropertiesInInterfaceRuleTest.php | 96 ++++++++++- .../Properties/PropertyInClassRuleTest.php | 150 ++++++++++++++++++ .../abstract-hooked-properties-in-class.php | 10 ++ ...abstract-hooked-properties-with-bodies.php | 26 +++ ...on-hooked-properties-in-abstract-class.php | 10 ++ .../data/hooked-properties-in-class.php | 11 ++ ...ked-properties-without-bodies-in-class.php | 10 ++ ...ct-hooked-properties-in-abstract-class.php | 35 ++++ ...on-abstract-hooked-properties-in-class.php | 10 ++ .../data/properties-in-interface.php | 2 + .../property-hooks-bodies-in-interface.php | 20 +++ .../data/property-hooks-in-interface.php | 10 ++ ...property-hooks-visibility-in-interface.php | 12 ++ 21 files changed, 600 insertions(+), 12 deletions(-) create mode 100644 src/Rules/Properties/PropertyInClassRule.php create mode 100644 tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php create mode 100644 tests/PHPStan/Rules/Properties/data/abstract-hooked-properties-in-class.php create mode 100644 tests/PHPStan/Rules/Properties/data/abstract-hooked-properties-with-bodies.php create mode 100644 tests/PHPStan/Rules/Properties/data/abstract-non-hooked-properties-in-abstract-class.php create mode 100644 tests/PHPStan/Rules/Properties/data/hooked-properties-in-class.php create mode 100644 tests/PHPStan/Rules/Properties/data/hooked-properties-without-bodies-in-class.php create mode 100644 tests/PHPStan/Rules/Properties/data/non-abstract-hooked-properties-in-abstract-class.php create mode 100644 tests/PHPStan/Rules/Properties/data/non-abstract-hooked-properties-in-class.php create mode 100644 tests/PHPStan/Rules/Properties/data/property-hooks-bodies-in-interface.php create mode 100644 tests/PHPStan/Rules/Properties/data/property-hooks-in-interface.php create mode 100644 tests/PHPStan/Rules/Properties/data/property-hooks-visibility-in-interface.php diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4680ddb82d..86ee004f07 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -116,7 +116,7 @@ jobs: uses: "shivammathur/setup-php@v2" with: coverage: "none" - php-version: "8.3" + php-version: "8.4" - name: "Install dependencies" run: "composer install --no-interaction --no-progress" diff --git a/Makefile b/Makefile index 3282ee2c4e..be44969c3c 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,16 @@ lint: --exclude tests/PHPStan/Rules/Classes/data/extends-readonly-class.php \ --exclude tests/PHPStan/Rules/Classes/data/instantiation-promoted-properties.php \ --exclude tests/PHPStan/Rules/Classes/data/bug-11592.php \ + --exclude tests/PHPStan/Rules/Properties/data/property-hooks-bodies-in-interface.php \ + --exclude tests/PHPStan/Rules/Properties/data/property-hooks-in-interface.php \ + --exclude tests/PHPStan/Rules/Properties/data/property-hooks-visibility-in-interface.php \ + --exclude tests/PHPStan/Rules/Properties/data/abstract-hooked-properties-in-class.php \ + --exclude tests/PHPStan/Rules/Properties/data/abstract-hooked-properties-with-bodies.php \ + --exclude tests/PHPStan/Rules/Properties/data/abstract-non-hooked-properties-in-abstract-class.php \ + --exclude tests/PHPStan/Rules/Properties/data/non-abstract-hooked-properties-in-abstract-class.php \ + --exclude tests/PHPStan/Rules/Properties/data/non-abstract-hooked-properties-in-class.php \ + --exclude tests/PHPStan/Rules/Properties/data/hooked-properties-in-class.php \ + --exclude tests/PHPStan/Rules/Properties/data/hooked-properties-without-bodies-in-class.php \ src tests cs: diff --git a/build/collision-detector.json b/build/collision-detector.json index 21228704f5..12de9af1d3 100644 --- a/build/collision-detector.json +++ b/build/collision-detector.json @@ -12,5 +12,5 @@ "../tests/notAutoloaded", "../tests/PHPStan/Rules/Functions/data/define-bug-3349.php", "../tests/PHPStan/Levels/data/stubs/function.php" - ] + ] } diff --git a/conf/config.level0.neon b/conf/config.level0.neon index d4927a56c4..8c2a23a9d4 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -96,6 +96,7 @@ rules: - PHPStan\Rules\Properties\MissingReadOnlyByPhpDocPropertyAssignRule - PHPStan\Rules\Properties\PropertiesInInterfaceRule - PHPStan\Rules\Properties\PropertyAttributesRule + - PHPStan\Rules\Properties\PropertyInClassRule - PHPStan\Rules\Properties\ReadOnlyPropertyRule - PHPStan\Rules\Properties\ReadOnlyByPhpDocPropertyRule - PHPStan\Rules\Regexp\RegularExpressionPatternRule diff --git a/src/Node/ClassPropertyNode.php b/src/Node/ClassPropertyNode.php index 3f500b62c1..c8602aef79 100644 --- a/src/Node/ClassPropertyNode.php +++ b/src/Node/ClassPropertyNode.php @@ -111,6 +111,11 @@ public function isAllowedPrivateMutation(): bool return $this->isAllowedPrivateMutation; } + public function isAbstract(): bool + { + return (bool) ($this->flags & Modifiers::ABSTRACT); + } + public function getNativeType(): ?Type { return $this->type; @@ -142,4 +147,17 @@ public function getSubNodeNames(): array return []; } + public function hasHooks(): bool + { + return $this->getHooks() !== []; + } + + /** + * @return Node\PropertyHook[] + */ + public function getHooks(): array + { + return $this->originalNode->hooks; + } + } diff --git a/src/Php/PhpVersion.php b/src/Php/PhpVersion.php index 8520f6488d..e636945cc2 100644 --- a/src/Php/PhpVersion.php +++ b/src/Php/PhpVersion.php @@ -347,6 +347,11 @@ public function supportsPregCaptureOnlyNamedGroups(): bool return $this->versionId >= 80200; } + public function supportsPropertyHooks(): bool + { + return $this->versionId >= 80400; + } + public function hasDateTimeExceptions(): bool { return $this->versionId >= 80300; diff --git a/src/Rules/Properties/PropertiesInInterfaceRule.php b/src/Rules/Properties/PropertiesInInterfaceRule.php index d9f62fa618..df5354adb3 100644 --- a/src/Rules/Properties/PropertiesInInterfaceRule.php +++ b/src/Rules/Properties/PropertiesInInterfaceRule.php @@ -5,6 +5,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\ClassPropertyNode; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -14,6 +15,10 @@ final class PropertiesInInterfaceRule implements Rule { + public function __construct(private PhpVersion $phpVersion) + { + } + public function getNodeType(): string { return ClassPropertyNode::class; @@ -25,12 +30,54 @@ public function processNode(Node $node, Scope $scope): array return []; } - return [ - RuleErrorBuilder::message('Interfaces may not include properties.') - ->nonIgnorable() - ->identifier('property.inInterface') - ->build(), - ]; + if (!$this->phpVersion->supportsPropertyHooks()) { + return [ + RuleErrorBuilder::message('Interfaces cannot include properties.') + ->nonIgnorable() + ->identifier('property.inInterface') + ->build(), + ]; + } + + if (!$node->hasHooks()) { + return [ + RuleErrorBuilder::message('Interfaces can only include hooked properties.') + ->nonIgnorable() + ->identifier('property.nonHookedInInterface') + ->build(), + ]; + } + + if (!$node->isPublic()) { + return [ + RuleErrorBuilder::message('Interfaces cannot include non-public properties.') + ->nonIgnorable() + ->identifier('property.nonPublicInInterface') + ->build(), + ]; + } + + if ($this->hasAnyHookBody($node)) { + return [ + RuleErrorBuilder::message('Interfaces cannot include property hooks with bodies.') + ->nonIgnorable() + ->identifier('property.hookBodyInInterface') + ->build(), + ]; + } + + return []; + } + + private function hasAnyHookBody(ClassPropertyNode $node): bool + { + foreach ($node->getHooks() as $hook) { + if ($hook->body !== null) { + return true; + } + } + + return false; } } diff --git a/src/Rules/Properties/PropertyInClassRule.php b/src/Rules/Properties/PropertyInClassRule.php new file mode 100644 index 0000000000..3500959541 --- /dev/null +++ b/src/Rules/Properties/PropertyInClassRule.php @@ -0,0 +1,113 @@ + + */ +final class PropertyInClassRule implements Rule +{ + + public function __construct(private PhpVersion $phpVersion) + { + } + + public function getNodeType(): string + { + return ClassPropertyNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $classReflection = $node->getClassReflection(); + + if (!$classReflection->isClass()) { + return []; + } + + if (!$this->phpVersion->supportsPropertyHooks()) { + if ($node->hasHooks()) { + return [ + RuleErrorBuilder::message('Property hooks are supported only on PHP 8.4 and later.') + ->nonIgnorable() + ->identifier('property.hooksNotSupported') + ->build(), + ]; + } + + return []; + } + + if ($node->isAbstract()) { + if (!$node->hasHooks()) { + return [ + RuleErrorBuilder::message('Only hooked properties can be declared abstract.') + ->nonIgnorable() + ->identifier('property.abstractNonHooked') + ->build(), + ]; + } + + if (!$this->isAtLeastOneHookBodyEmpty($node)) { + return [ + RuleErrorBuilder::message('Abstract properties must specify at least one abstract hook.') + ->nonIgnorable() + ->identifier('property.abstractWithoutAbstractHook') + ->build(), + ]; + } + + if (!$classReflection->isAbstract()) { + return [ + RuleErrorBuilder::message('Non-abstract classes cannot include abstract properties.') + ->nonIgnorable() + ->identifier('property.abstract') + ->build(), + ]; + } + + return []; + } + + if (!$this->doAllHooksHaveBody($node)) { + return [ + RuleErrorBuilder::message('Non-abstract properties cannot include hooks without bodies.') + ->nonIgnorable() + ->identifier('property.hookWithoutBody') + ->build(), + ]; + } + + return []; + } + + private function doAllHooksHaveBody(ClassPropertyNode $node): bool + { + foreach ($node->getHooks() as $hook) { + if ($hook->body === null) { + return false; + } + } + + return true; + } + + private function isAtLeastOneHookBodyEmpty(ClassPropertyNode $node): bool + { + foreach ($node->getHooks() as $hook) { + if ($hook->body === null) { + return true; + } + } + + return false; + } + +} diff --git a/tests/PHPStan/Rules/Properties/PropertiesInInterfaceRuleTest.php b/tests/PHPStan/Rules/Properties/PropertiesInInterfaceRuleTest.php index ecf4597d97..de425931da 100644 --- a/tests/PHPStan/Rules/Properties/PropertiesInInterfaceRuleTest.php +++ b/tests/PHPStan/Rules/Properties/PropertiesInInterfaceRuleTest.php @@ -2,8 +2,10 @@ namespace PHPStan\Rules\Properties; +use PHPStan\Php\PhpVersion; use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; +use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -13,21 +15,107 @@ class PropertiesInInterfaceRuleTest extends RuleTestCase protected function getRule(): Rule { - return new PropertiesInInterfaceRule(); + return new PropertiesInInterfaceRule(new PhpVersion(PHP_VERSION_ID)); } - public function testRule(): void + public function testPhp83AndPropertiesInInterface(): void { + if (PHP_VERSION_ID >= 80400) { + $this->markTestSkipped('Test requires PHP 8.3 or earlier.'); + } + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Property hooks cause syntax error on PHP 7.4'); + } + + $this->analyse([__DIR__ . '/data/properties-in-interface.php'], [ + [ + 'Interfaces cannot include properties.', + 7, + ], + [ + 'Interfaces cannot include properties.', + 9, + ], + [ + 'Interfaces cannot include properties.', + 11, + ], + ]); + } + + public function testPhp83AndPropertyHooksInInterface(): void + { + if (PHP_VERSION_ID >= 80400) { + $this->markTestSkipped('Test requires PHP 8.3 or earlier.'); + } + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Property hooks cause syntax error on PHP 7.4'); + } + + $this->analyse([__DIR__ . '/data/property-hooks-in-interface.php'], [ + [ + 'Interfaces cannot include properties.', + 7, + ], + [ + 'Interfaces cannot include properties.', + 9, + ], + ]); + } + + public function testPhp84AndPropertiesInInterface(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + $this->analyse([__DIR__ . '/data/properties-in-interface.php'], [ [ - 'Interfaces may not include properties.', + 'Interfaces can only include hooked properties.', + 9, + ], + [ + 'Interfaces can only include hooked properties.', + 11, + ], + ]); + } + + public function testPhp84AndNonPublicPropertyHooksInInterface(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/property-hooks-visibility-in-interface.php'], [ + [ + 'Interfaces cannot include non-public properties.', 7, ], [ - 'Interfaces may not include properties.', + 'Interfaces cannot include non-public properties.', 9, ], ]); } + public function testPhp84AndPropertyHooksWithBodiesInInterface(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/property-hooks-bodies-in-interface.php'], [ + [ + 'Interfaces cannot include property hooks with bodies.', + 7, + ], + [ + 'Interfaces cannot include property hooks with bodies.', + 13, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php b/tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php new file mode 100644 index 0000000000..0b2ca5ba09 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php @@ -0,0 +1,150 @@ + + */ +class PropertyInClassRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new PropertyInClassRule(new PhpVersion(PHP_VERSION_ID)); + } + + public function testPhpLessThan84AndHookedPropertiesInClass(): void + { + if (PHP_VERSION_ID >= 80400) { + $this->markTestSkipped('Test requires PHP 8.3 or earlier.'); + } + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Property hooks cause syntax error on PHP 7.4'); + } + + $this->analyse([__DIR__ . '/data/hooked-properties-in-class.php'], [ + [ + 'Property hooks are supported only on PHP 8.4 and later.', + 7, + ], + ]); + } + + public function testPhp84AndHookedPropertiesWithoutBodiesInClass(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/hooked-properties-without-bodies-in-class.php'], [ + [ + 'Non-abstract properties cannot include hooks without bodies.', + 7, + ], + [ + 'Non-abstract properties cannot include hooks without bodies.', + 9, + ], + ]); + } + + public function testPhp84AndNonAbstractHookedPropertiesInClass(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/non-abstract-hooked-properties-in-class.php'], [ + [ + 'Non-abstract properties cannot include hooks without bodies.', + 7, + ], + [ + 'Non-abstract properties cannot include hooks without bodies.', + 9, + ], + ]); + } + + public function testPhp84AndAbstractHookedPropertiesInClass(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/abstract-hooked-properties-in-class.php'], [ + [ + 'Non-abstract classes cannot include abstract properties.', + 7, + ], + [ + 'Non-abstract classes cannot include abstract properties.', + 9, + ], + ]); + } + + public function testPhp84AndNonAbstractHookedPropertiesInAbstractClass(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/non-abstract-hooked-properties-in-abstract-class.php'], [ + [ + 'Non-abstract properties cannot include hooks without bodies.', + 7, + ], + [ + 'Non-abstract properties cannot include hooks without bodies.', + 9, + ], + [ + 'Non-abstract properties cannot include hooks without bodies.', + 25, + ], + ]); + } + + public function testPhp84AndAbstractNonHookedPropertiesInAbstractClass(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/abstract-non-hooked-properties-in-abstract-class.php'], [ + [ + 'Only hooked properties can be declared abstract.', + 7, + ], + [ + 'Only hooked properties can be declared abstract.', + 9, + ], + ]); + } + + public function testPhp84AndAbstractHookedPropertiesWithBodies(): void + { + if (PHP_VERSION_ID < 80400) { + $this->markTestSkipped('Test requires PHP 8.4 or later.'); + } + + $this->analyse([__DIR__ . '/data/abstract-hooked-properties-with-bodies.php'], [ + [ + 'Abstract properties must specify at least one abstract hook.', + 7, + ], + [ + 'Abstract properties must specify at least one abstract hook.', + 12, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Properties/data/abstract-hooked-properties-in-class.php b/tests/PHPStan/Rules/Properties/data/abstract-hooked-properties-in-class.php new file mode 100644 index 0000000000..d035d36810 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/abstract-hooked-properties-in-class.php @@ -0,0 +1,10 @@ + $this->name; + set => $this->name = $value; + } + + public abstract string $lastName { + get => $this->lastName; + set => $this->lastName = $value; + } + + public abstract string $middleName { + get => $this->name; + set; + } + + public abstract string $familyName { + get; + set; + } +} diff --git a/tests/PHPStan/Rules/Properties/data/abstract-non-hooked-properties-in-abstract-class.php b/tests/PHPStan/Rules/Properties/data/abstract-non-hooked-properties-in-abstract-class.php new file mode 100644 index 0000000000..b34e66a886 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/abstract-non-hooked-properties-in-abstract-class.php @@ -0,0 +1,10 @@ + $this->name; + set => $this->name = $value; + } +} diff --git a/tests/PHPStan/Rules/Properties/data/hooked-properties-without-bodies-in-class.php b/tests/PHPStan/Rules/Properties/data/hooked-properties-without-bodies-in-class.php new file mode 100644 index 0000000000..dc839f0d2c --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/hooked-properties-without-bodies-in-class.php @@ -0,0 +1,10 @@ + Date: Sat, 30 Nov 2024 09:01:04 +0100 Subject: [PATCH 486/508] skip param castable to X on non-arrays Fixes bug 12146 --- src/Rules/ParameterCastableToStringCheck.php | 8 +-- ...plodeParameterCastableToStringRuleTest.php | 12 ++++- .../ParameterCastableToNumberRuleTest.php | 16 +++++- .../ParameterCastableToStringRuleTest.php | 16 +++++- .../SortParameterCastableToStringRuleTest.php | 12 ++++- .../Rules/Functions/data/bug-12146.php | 49 +++++++++++++++++++ 6 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 tests/PHPStan/Rules/Functions/data/bug-12146.php diff --git a/src/Rules/ParameterCastableToStringCheck.php b/src/Rules/ParameterCastableToStringCheck.php index 2d4dea0dbd..9753863557 100644 --- a/src/Rules/ParameterCastableToStringCheck.php +++ b/src/Rules/ParameterCastableToStringCheck.php @@ -36,11 +36,13 @@ public function checkParameter( $scope, $parameter->value, '', - static fn (Type $type): bool => !$castFn($type->getIterableValueType()) instanceof ErrorType, + static fn (Type $type): bool => $type->isArray()->yes() && !$castFn($type->getIterableValueType()) instanceof ErrorType, ); - if ($typeResult->getType() instanceof ErrorType - || !$castFn($typeResult->getType()->getIterableValueType()) instanceof ErrorType) { + if ( + ! $typeResult->getType()->isArray()->yes() + || !$castFn($typeResult->getType()->getIterableValueType()) instanceof ErrorType + ) { return null; } diff --git a/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php index 8111e9a965..65e4714487 100644 --- a/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ImplodeParameterCastableToStringRuleTest.php @@ -17,7 +17,7 @@ class ImplodeParameterCastableToStringRuleTest extends RuleTestCase protected function getRule(): Rule { $broker = $this->createReflectionProvider(); - return new ImplodeParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false))); + return new ImplodeParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, true, true, false))); } public function testNamedArguments(): void @@ -100,4 +100,14 @@ public function testBug8467a(): void $this->analyse([__DIR__ . '/../Arrays/data/bug-8467a.php'], []); } + public function testBug12146(): void + { + $this->analyse([__DIR__ . '/data/bug-12146.php'], [ + [ + 'Parameter #2 $array of function implode expects array, array given.', + 28, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php b/tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php index 77b64c3a30..e4708c5f4c 100644 --- a/tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ParameterCastableToNumberRuleTest.php @@ -19,7 +19,7 @@ class ParameterCastableToNumberRuleTest extends RuleTestCase protected function getRule(): Rule { $broker = $this->createReflectionProvider(); - return new ParameterCastableToNumberRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false))); + return new ParameterCastableToNumberRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, true, true, false))); } public function testRule(): void @@ -130,6 +130,20 @@ public function testBug11883(): void ]); } + public function testBug12146(): void + { + $this->analyse([__DIR__ . '/data/bug-12146.php'], $this->hackPhp74ErrorMessages([ + [ + 'Parameter #1 $array of function array_sum expects an array of values castable to number, array given.', + 16, + ], + [ + 'Parameter #1 $array of function array_product expects an array of values castable to number, array given.', + 22, + ], + ])); + } + /** * @param list $errors * @return list diff --git a/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php index 83b0f40567..0ac6304231 100644 --- a/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ParameterCastableToStringRuleTest.php @@ -19,7 +19,7 @@ class ParameterCastableToStringRuleTest extends RuleTestCase protected function getRule(): Rule { $broker = $this->createReflectionProvider(); - return new ParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false))); + return new ParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, true, true, false))); } public function testRule(): void @@ -196,6 +196,20 @@ public function testBug11141(): void ]); } + public function testBug12146(): void + { + $this->analyse([__DIR__ . '/data/bug-12146.php'], $this->hackParameterNames([ + [ + 'Parameter #1 $array of function array_intersect expects an array of values castable to string, array given.', + 34, + ], + [ + 'Parameter #1 $keys of function array_fill_keys expects an array of values castable to string, array given.', + 40, + ], + ])); + } + /** * @param list $errors * @return list diff --git a/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php b/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php index 8c0105a424..2fc8264821 100644 --- a/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php +++ b/tests/PHPStan/Rules/Functions/SortParameterCastableToStringRuleTest.php @@ -19,7 +19,7 @@ class SortParameterCastableToStringRuleTest extends RuleTestCase protected function getRule(): Rule { $broker = $this->createReflectionProvider(); - return new SortParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, false, false, false))); + return new SortParameterCastableToStringRule($broker, new ParameterCastableToStringCheck(new RuleLevelHelper($broker, true, false, true, true, true, false))); } public function testRule(): void @@ -145,6 +145,16 @@ public function testBug11167(): void $this->analyse([__DIR__ . '/data/bug-11167.php'], []); } + public function testBug12146(): void + { + $this->analyse([__DIR__ . '/data/bug-12146.php'], $this->hackParameterNames([ + [ + 'Parameter #1 $array of function array_unique expects an array of values castable to string, array given.', + 46, + ], + ])); + } + /** * @param list $errors * @return list diff --git a/tests/PHPStan/Rules/Functions/data/bug-12146.php b/tests/PHPStan/Rules/Functions/data/bug-12146.php new file mode 100644 index 0000000000..bd0bf858c3 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-12146.php @@ -0,0 +1,49 @@ +|array $validArrayUnion valid + * @param array|array<\stdClass> $invalidArrayUnion invalid, report + * @param ?array<\stdClass> $nullableInvalidArray invalid, but don't report because it's reported by CallToFunctionParametersRule + * @param array<\stdClass>|\SplFixedArray $arrayOrSplArray invalid, but don't report because it's reported by CallToFunctionParametersRule + * @return void + */ +function foo($mixed, $validArrayUnion, $invalidArrayUnion, $nullableInvalidArray, $arrayOrSplArray) { + var_dump(array_sum($mixed)); + var_dump(array_sum($validArrayUnion)); + var_dump(array_sum($invalidArrayUnion)); + var_dump(array_sum($nullableInvalidArray)); + var_dump(array_sum($arrayOrSplArray)); + + var_dump(array_product($mixed)); + var_dump(array_product($validArrayUnion)); + var_dump(array_product($invalidArrayUnion)); + var_dump(array_product($nullableInvalidArray)); + var_dump(array_product($arrayOrSplArray)); + + var_dump(implode(',', $mixed)); + var_dump(implode(',', $validArrayUnion)); + var_dump(implode(',', $invalidArrayUnion)); + var_dump(implode(',', $nullableInvalidArray)); + var_dump(implode(',', $arrayOrSplArray)); + + var_dump(array_intersect($mixed, [5])); + var_dump(array_intersect($validArrayUnion, [5])); + var_dump(array_intersect($invalidArrayUnion, [5])); + var_dump(array_intersect($nullableInvalidArray, [5])); + var_dump(array_intersect($arrayOrSplArray, [5])); + + var_dump(array_fill_keys($mixed, 1)); + var_dump(array_fill_keys($validArrayUnion, 1)); + var_dump(array_fill_keys($invalidArrayUnion, 1)); + var_dump(array_fill_keys($nullableInvalidArray, 1)); + var_dump(array_fill_keys($arrayOrSplArray, 1)); + + var_dump(array_unique($mixed)); + var_dump(array_unique($validArrayUnion)); + var_dump(array_unique($invalidArrayUnion)); + var_dump(array_unique($nullableInvalidArray)); + var_dump(array_unique($arrayOrSplArray)); +} From f8d27d5a803d7923a60e267cc8a78bfc2b8b9e10 Mon Sep 17 00:00:00 2001 From: phpstan-bot <79867460+phpstan-bot@users.noreply.github.com> Date: Mon, 2 Dec 2024 00:22:35 +0000 Subject: [PATCH 487/508] Update PHP 8 stubs --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 0f28344835..5e0a1f1e01 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", "ondrejmirtes/better-reflection": "6.44.0.6", - "phpstan/php-8-stubs": "0.4.8", + "phpstan/php-8-stubs": "0.4.9", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", "react/async": "^3", diff --git a/composer.lock b/composer.lock index 7cd32ee1ad..22c9a79b6e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "aa42dc6e1a7a8d5fc9844d231515e30f", + "content-hash": "db7c74816a1b1cd707c98ae62551ce35", "packages": [ { "name": "clue/ndjson-react", @@ -2258,16 +2258,16 @@ }, { "name": "phpstan/php-8-stubs", - "version": "0.4.8", + "version": "0.4.9", "source": { "type": "git", "url": "https://github.com/phpstan/php-8-stubs.git", - "reference": "8a6278b2b9c9781cb969c4128da361b78eead604" + "reference": "1857c330fea6e795af1f7435ed02a18652e7dd8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/8a6278b2b9c9781cb969c4128da361b78eead604", - "reference": "8a6278b2b9c9781cb969c4128da361b78eead604", + "url": "https://api.github.com/repos/phpstan/php-8-stubs/zipball/1857c330fea6e795af1f7435ed02a18652e7dd8c", + "reference": "1857c330fea6e795af1f7435ed02a18652e7dd8c", "shasum": "" }, "type": "library", @@ -2284,9 +2284,9 @@ "description": "PHP stubs extracted from php-src", "support": { "issues": "https://github.com/phpstan/php-8-stubs/issues", - "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.8" + "source": "https://github.com/phpstan/php-8-stubs/tree/0.4.9" }, - "time": "2024-11-28T00:20:48+00:00" + "time": "2024-12-02T00:21:59+00:00" }, { "name": "phpstan/phpdoc-parser", From 90933b318e332c88f675c8aa946cdfb5788a51fe Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Mon, 2 Dec 2024 22:54:08 +0200 Subject: [PATCH 488/508] Remove incorrect CURLOPT_ACCEPT_ENCODING alias --- src/Reflection/ParametersAcceptorSelector.php | 3 +-- .../CallToFunctionParametersRuleTest.php | 26 ++++++++++++------- .../Rules/Functions/data/curl_setopt.php | 4 +++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index 82af7d4267..703d345806 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -919,7 +919,6 @@ private static function getCurlOptValueType(int $curlOpt): ?Type } $nullableStringConstants = [ - 'CURLOPT_ACCEPT_ENCODING', 'CURLOPT_CUSTOMREQUEST', 'CURLOPT_DNS_INTERFACE', 'CURLOPT_DNS_LOCAL_IP4', @@ -1032,7 +1031,7 @@ private static function getCurlOptValueType(int $curlOpt): ?Type $stringConstants = [ 'CURLOPT_COOKIEFILE', - 'CURLOPT_ENCODING', + 'CURLOPT_ENCODING', // Alias: CURLOPT_ACCEPT_ENCODING 'CURLOPT_PRE_PROXY', 'CURLOPT_PRIVATE', 'CURLOPT_PROXY', diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index af3d4af2c3..89017fe2cf 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -1321,40 +1321,48 @@ public function testCurlSetOpt(): void 18, ], [ - 'Parameter #3 $value of function curl_setopt expects bool, int given.', + 'Parameter #3 $value of function curl_setopt expects string, int given.', + 19, + ], + [ + 'Parameter #3 $value of function curl_setopt expects string, int given.', 20, ], + [ + 'Parameter #3 $value of function curl_setopt expects bool, int given.', + 22, + ], [ 'Parameter #3 $value of function curl_setopt expects bool, string given.', - 21, + 23, ], [ 'Parameter #3 $value of function curl_setopt expects int, string given.', - 23, + 25, ], [ 'Parameter #3 $value of function curl_setopt expects array, string given.', - 25, + 27, ], [ 'Parameter #3 $value of function curl_setopt expects resource, string given.', - 27, + 29, ], [ 'Parameter #3 $value of function curl_setopt expects array|string, int given.', - 29, + 31, ], [ 'Parameter #3 $value of function curl_setopt expects non-empty-string, \'\' given.', - 31, + 33, ], [ 'Parameter #3 $value of function curl_setopt expects non-empty-string|null, \'\' given.', - 32, + 34, ], [ 'Parameter #3 $value of function curl_setopt expects array, array given.', - 73, + 77, ], ]); } diff --git a/tests/PHPStan/Rules/Functions/data/curl_setopt.php b/tests/PHPStan/Rules/Functions/data/curl_setopt.php index 24987ddbc9..bc5b8f6cea 100644 --- a/tests/PHPStan/Rules/Functions/data/curl_setopt.php +++ b/tests/PHPStan/Rules/Functions/data/curl_setopt.php @@ -16,6 +16,8 @@ public function errors(int $i, string $s) { curl_setopt($curl, CURLOPT_URL, $i); curl_setopt($curl, CURLOPT_HTTPHEADER, $i); curl_setopt($curl, CURLOPT_ABSTRACT_UNIX_SOCKET, null); + curl_setopt($curl, CURLOPT_ENCODING, $i); + curl_setopt($curl, CURLOPT_ACCEPT_ENCODING, $i); // expecting bool curl_setopt($curl, CURLOPT_AUTOREFERER, $i); curl_setopt($curl, CURLOPT_RETURNTRANSFER, $s); @@ -62,6 +64,8 @@ public function allGood(string $url, array $header) { curl_setopt($curl, CURLOPT_PRE_PROXY, ''); curl_setopt($curl, CURLOPT_PROXY, ''); curl_setopt($curl, CURLOPT_PRIVATE, ''); + curl_setopt($curl, CURLOPT_ENCODING, ''); + curl_setopt($curl, CURLOPT_ACCEPT_ENCODING, ''); } public function bug9263() { From 28dfac80bb4a05891ad4da675677c2077098d080 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 3 Dec 2024 00:03:57 +0000 Subject: [PATCH 489/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 5e0a1f1e01..c678b5998f 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#7809499af1a5f3bdd20f1cab71717a2a9e1f8cf7", + "jetbrains/phpstorm-stubs": "dev-master#bb981ec60b3838e56473a078edf7d0739ca20403", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index 22c9a79b6e..8557d36dae 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "db7c74816a1b1cd707c98ae62551ce35", + "content-hash": "ee384a5c11fbc1dd087ab8dc956b8d73", "packages": [ { "name": "clue/ndjson-react", @@ -1442,12 +1442,12 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "7809499af1a5f3bdd20f1cab71717a2a9e1f8cf7" + "reference": "bb981ec60b3838e56473a078edf7d0739ca20403" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/7809499af1a5f3bdd20f1cab71717a2a9e1f8cf7", - "reference": "7809499af1a5f3bdd20f1cab71717a2a9e1f8cf7", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/bb981ec60b3838e56473a078edf7d0739ca20403", + "reference": "bb981ec60b3838e56473a078edf7d0739ca20403", "shasum": "" }, "require-dev": { @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-11-27T14:37:09+00:00" + "time": "2024-11-27T16:45:26+00:00" }, { "name": "nette/bootstrap", From fbcad414543b6f6fae4acc2801de21bfa1348887 Mon Sep 17 00:00:00 2001 From: Jan Nedbal Date: Thu, 5 Dec 2024 12:44:05 +0100 Subject: [PATCH 490/508] Fix `fgetcsv` return type; never returns null --- resources/functionMap_php80delta.php | 1 + tests/PHPStan/Analyser/nsrt/fgetcsv-php7.php | 12 ++++++++++++ tests/PHPStan/Analyser/nsrt/fgetcsv-php8.php | 12 ++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/PHPStan/Analyser/nsrt/fgetcsv-php7.php create mode 100644 tests/PHPStan/Analyser/nsrt/fgetcsv-php8.php diff --git a/resources/functionMap_php80delta.php b/resources/functionMap_php80delta.php index bb267a5e49..879dc310e4 100644 --- a/resources/functionMap_php80delta.php +++ b/resources/functionMap_php80delta.php @@ -46,6 +46,7 @@ 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'0|1|3|4', 'destination='=>'string', 'extra_headers='=>'string'], 'explode' => ['list', 'separator'=>'non-empty-string', 'str'=>'string', 'limit='=>'int'], 'fdiv' => ['float', 'dividend'=>'float', 'divisor'=>'float'], + 'fgetcsv' => ['list|array{0: null}|false', 'fp'=>'resource', 'length='=>'0|positive-int|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'filter_input' => ['mixed', 'type'=>'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'variable_name'=>'string', 'filter='=>'int', 'options='=>'array|int'], 'filter_input_array' => ['array|false|null', 'type'=>'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'definition='=>'int|array', 'add_empty='=>'bool'], 'floor' => ['float', 'number'=>'float'], diff --git a/tests/PHPStan/Analyser/nsrt/fgetcsv-php7.php b/tests/PHPStan/Analyser/nsrt/fgetcsv-php7.php new file mode 100644 index 0000000000..8a38465040 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/fgetcsv-php7.php @@ -0,0 +1,12 @@ +|false|null', fgetcsv($resource)); // nullable when invalid argument is given (https://3v4l.org/4WmR5#v7.4.30) +} diff --git a/tests/PHPStan/Analyser/nsrt/fgetcsv-php8.php b/tests/PHPStan/Analyser/nsrt/fgetcsv-php8.php new file mode 100644 index 0000000000..fccf29931c --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/fgetcsv-php8.php @@ -0,0 +1,12 @@ += 8.0 + +declare(strict_types = 1); + +namespace TestFGetCsvPhp8; + +use function PHPStan\Testing\assertType; + +function test($resource): void +{ + assertType('list|false', fgetcsv($resource)); +} From 7b4c9afd090d89d595eb113831bc4b79b45d22e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Thu, 5 Dec 2024 12:15:02 +0100 Subject: [PATCH 491/508] Workaround bug in slevomat/coding-standard TypeNameMatchesFileName For each root namespace, the slevomat rule considers the left-most match of the given directory in the absolute path of the file. That is, for /home/user/src/phpstan-src/ the root namespace PHPStan is not assigned to /home/user/src/phpstan-src/src, but to /home/user/src, which is obviously wrong. The bug is known as slevomat/coding-standard#1249 for a long time, but yet to be fixed. To avoid issues for developers of PHPStan, we can set a basepath of "." in the PHP CodeSniffer config, which causes paths to be evaluated relative to the current directory, avoiding false-positives in the path leading up to the phpstan-src directory. --- phpcs.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpcs.xml b/phpcs.xml index 7ec0a21da2..fa9198745f 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,6 +1,7 @@ + From 9a718ee52c07c6b62c0eceac3bf170ac45740b6a Mon Sep 17 00:00:00 2001 From: Jack Worman Date: Wed, 4 Dec 2024 20:26:32 -0500 Subject: [PATCH 492/508] Fix-GH-12021 --- ...mptyStringFunctionsReturnTypeExtension.php | 30 +++++++++++++++++++ .../Analyser/nsrt/non-empty-string.php | 9 ++++++ .../Analyser/nsrt/non-falsy-string.php | 5 ++++ 3 files changed, 44 insertions(+) diff --git a/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php b/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php index 083914085a..893627aae2 100644 --- a/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php +++ b/src/Type/Php/NonEmptyStringFunctionsReturnTypeExtension.php @@ -2,17 +2,20 @@ namespace PHPStan\Type\Php; +use PhpParser\Node\Arg; use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; use PHPStan\Type\Accessory\AccessoryNonFalsyStringType; +use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\IntersectionType; use PHPStan\Type\StringType; use PHPStan\Type\Type; use function count; use function in_array; +use const ENT_SUBSTITUTE; final class NonEmptyStringFunctionsReturnTypeExtension implements DynamicFunctionReturnTypeExtension { @@ -45,6 +48,15 @@ public function getTypeFromFunctionCall( return null; } + if (in_array($functionReflection->getName(), [ + 'htmlspecialchars', + 'htmlentities', + ], true)) { + if (!$this->isSubstituteFlagSet($args, $scope)) { + return new StringType(); + } + } + $argType = $scope->getType($args[0]->value); if ($argType->isNonFalsyString()->yes()) { return new IntersectionType([ @@ -62,4 +74,22 @@ public function getTypeFromFunctionCall( return new StringType(); } + /** + * @param Arg[] $args + */ + private function isSubstituteFlagSet( + array $args, + Scope $scope, + ): bool + { + if (!isset($args[1])) { + return true; + } + $flagsType = $scope->getType($args[1]->value); + if (!$flagsType instanceof ConstantIntegerType) { + return false; + } + return (bool) ($flagsType->getValue() & ENT_SUBSTITUTE); + } + } diff --git a/tests/PHPStan/Analyser/nsrt/non-empty-string.php b/tests/PHPStan/Analyser/nsrt/non-empty-string.php index cd831db4d8..59d1af3931 100644 --- a/tests/PHPStan/Analyser/nsrt/non-empty-string.php +++ b/tests/PHPStan/Analyser/nsrt/non-empty-string.php @@ -8,6 +8,7 @@ use function strtolower; use function strtoupper; use function ucfirst; +use const ENT_SUBSTITUTE; class Foo { @@ -333,9 +334,17 @@ public function doFoo(string $s, string $nonEmpty, string $nonFalsy, int $i, boo assertType('string', ucwords($s)); assertType('non-empty-string', ucwords($nonEmpty)); assertType('string', htmlspecialchars($s)); + assertType('string', htmlspecialchars($s, ENT_SUBSTITUTE)); + assertType('string', htmlspecialchars($s, 0)); assertType('non-empty-string', htmlspecialchars($nonEmpty)); + assertType('non-empty-string', htmlspecialchars($nonEmpty, ENT_SUBSTITUTE)); + assertType('string', htmlspecialchars($nonEmpty, 0)); assertType('string', htmlentities($s)); + assertType('string', htmlentities($s, ENT_SUBSTITUTE)); + assertType('string', htmlentities($s, 0)); assertType('non-empty-string', htmlentities($nonEmpty)); + assertType('non-empty-string', htmlentities($nonEmpty, ENT_SUBSTITUTE)); + assertType('string', htmlentities($nonEmpty, 0)); assertType('string', urlencode($s)); assertType('non-empty-string', urlencode($nonEmpty)); diff --git a/tests/PHPStan/Analyser/nsrt/non-falsy-string.php b/tests/PHPStan/Analyser/nsrt/non-falsy-string.php index c5fd9fc1d8..744bdaf3b5 100644 --- a/tests/PHPStan/Analyser/nsrt/non-falsy-string.php +++ b/tests/PHPStan/Analyser/nsrt/non-falsy-string.php @@ -3,6 +3,7 @@ namespace NonFalseyString; use function PHPStan\Testing\assertType; +use const ENT_SUBSTITUTE; class Foo { /** @@ -95,7 +96,11 @@ function stringFunctions(string $s, $nonFalsey, $arrayOfNonFalsey, $nonEmptyArra assertType('non-falsy-string', ucfirst($nonFalsey)); assertType('non-falsy-string', ucwords($nonFalsey)); assertType('non-falsy-string', htmlspecialchars($nonFalsey)); + assertType('non-falsy-string', htmlspecialchars($nonFalsey, ENT_SUBSTITUTE)); + assertType('string', htmlspecialchars($nonFalsey, 0)); assertType('non-falsy-string', htmlentities($nonFalsey)); + assertType('non-falsy-string', htmlentities($nonFalsey, ENT_SUBSTITUTE)); + assertType('string', htmlentities($nonFalsey, 0)); assertType('non-falsy-string', urlencode($nonFalsey)); assertType('non-falsy-string', urldecode($nonFalsey)); From 71b25bc5c50b84433ec608284630ca8c25d97781 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 10 Dec 2024 11:47:07 +0100 Subject: [PATCH 493/508] Fix after merge --- src/Type/Php/ArrayMapFunctionReturnTypeExtension.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php b/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php index e79a889dd7..145756b971 100644 --- a/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayMapFunctionReturnTypeExtension.php @@ -168,12 +168,10 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, ); } } else { - $mappedArrayType = AccessoryArrayListType::intersectWith( - TypeCombinator::intersect(new ArrayType( - new IntegerType(), - $valueType, - ), ...TypeUtils::getAccessoryTypes($arrayType)), - ); + $mappedArrayType = TypeCombinator::intersect(new ArrayType( + new IntegerType(), + $valueType, + ), new AccessoryArrayListType(), ...TypeUtils::getAccessoryTypes($arrayType)); } if ($arrayType->isIterableAtLeastOnce()->yes()) { From e98335bd09659c4567b1259f524f6ff7b785c6e7 Mon Sep 17 00:00:00 2001 From: vindic Date: Thu, 12 Dec 2024 10:19:28 +0200 Subject: [PATCH 494/508] Fix apcu_cache_info and apcu_sma_info signatures --- resources/functionMap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/functionMap.php b/resources/functionMap.php index e2fcdaf7e6..9543cf7cd3 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -209,7 +209,7 @@ 'APCIterator::valid' => ['bool'], 'apcu_add' => ['bool', 'key'=>'string', 'var'=>'', 'ttl='=>'int'], 'apcu_add\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], -'apcu_cache_info' => ['array', 'limited='=>'bool'], +'apcu_cache_info' => ['array|false', 'limited='=>'bool'], 'apcu_cas' => ['bool', 'key'=>'string', 'old'=>'int', 'new'=>'int'], 'apcu_clear_cache' => ['bool'], 'apcu_dec' => ['int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], @@ -220,7 +220,7 @@ 'apcu_exists\'1' => ['array', 'keys'=>'string[]'], 'apcu_fetch' => ['mixed', 'key'=>'string|string[]', '&w_success='=>'bool'], 'apcu_inc' => ['int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], -'apcu_sma_info' => ['array', 'limited='=>'bool'], +'apcu_sma_info' => ['array|false', 'limited='=>'bool'], 'apcu_store' => ['bool', 'key'=>'string', 'var='=>'', 'ttl='=>'int'], 'apcu_store\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'APCuIterator::__construct' => ['void', 'search='=>'string|string[]|null', 'format='=>'int', 'chunk_size='=>'int', 'list='=>'int'], From e7e80934023abc94a4f4bb9066ba6d6db26f6cde Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 12 Dec 2024 09:53:14 +0100 Subject: [PATCH 495/508] Make these benevolent --- resources/functionMap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/functionMap.php b/resources/functionMap.php index 9543cf7cd3..b49b97178c 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -209,7 +209,7 @@ 'APCIterator::valid' => ['bool'], 'apcu_add' => ['bool', 'key'=>'string', 'var'=>'', 'ttl='=>'int'], 'apcu_add\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], -'apcu_cache_info' => ['array|false', 'limited='=>'bool'], +'apcu_cache_info' => ['__benevolent|false>', 'limited='=>'bool'], 'apcu_cas' => ['bool', 'key'=>'string', 'old'=>'int', 'new'=>'int'], 'apcu_clear_cache' => ['bool'], 'apcu_dec' => ['int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], @@ -220,7 +220,7 @@ 'apcu_exists\'1' => ['array', 'keys'=>'string[]'], 'apcu_fetch' => ['mixed', 'key'=>'string|string[]', '&w_success='=>'bool'], 'apcu_inc' => ['int', 'key'=>'string', 'step='=>'int', '&w_success='=>'bool', 'ttl='=>'int'], -'apcu_sma_info' => ['array|false', 'limited='=>'bool'], +'apcu_sma_info' => ['__benevolent', 'limited='=>'bool'], 'apcu_store' => ['bool', 'key'=>'string', 'var='=>'', 'ttl='=>'int'], 'apcu_store\'1' => ['array', 'values'=>'array', 'unused='=>'', 'ttl='=>'int'], 'APCuIterator::__construct' => ['void', 'search='=>'string|string[]|null', 'format='=>'int', 'chunk_size='=>'int', 'list='=>'int'], From 627ad2a75c564ce81793f1a25056d73421a11351 Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Thu, 12 Dec 2024 12:44:39 +0000 Subject: [PATCH 496/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index c678b5998f..166ac44388 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.44.0.6", + "ondrejmirtes/better-reflection": "6.46.0.0", "phpstan/php-8-stubs": "0.4.9", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 8557d36dae..f619dbd9c9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ee384a5c11fbc1dd087ab8dc956b8d73", + "content-hash": "9dad77eea28263a8f7daa01a1b3dd47a", "packages": [ { "name": "clue/ndjson-react", @@ -2187,16 +2187,16 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.44.0.6", + "version": "6.46.0.0", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "d942fd0af0214bb1250a55c2560f061b7b0c4bd4" + "reference": "242b3e1cdb59a81585be5722b6c44ae44c74c671" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/d942fd0af0214bb1250a55c2560f061b7b0c4bd4", - "reference": "d942fd0af0214bb1250a55c2560f061b7b0c4bd4", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/242b3e1cdb59a81585be5722b6c44ae44c74c671", + "reference": "242b3e1cdb59a81585be5722b6c44ae44c74c671", "shasum": "" }, "require": { @@ -2212,7 +2212,7 @@ "doctrine/coding-standard": "^12.0.0", "phpstan/phpstan": "^1.10.60", "phpstan/phpstan-phpunit": "^1.3.16", - "phpunit/phpunit": "^11.4.3", + "phpunit/phpunit": "^11.5.1", "rector/rector": "1.2.10" }, "suggest": { @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.44.0.6" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.46.0.0" }, - "time": "2024-11-28T21:05:45+00:00" + "time": "2024-12-12T12:40:29+00:00" }, { "name": "phpstan/php-8-stubs", From 0edf18d140c5b640a63317c3017088322a566180 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 12 Dec 2024 20:06:47 +0100 Subject: [PATCH 497/508] Added `strictRulesInstalled` parameter --- conf/config.neon | 1 + conf/parametersSchema.neon | 1 + 2 files changed, 2 insertions(+) diff --git a/conf/config.neon b/conf/config.neon index 9b382375c3..40e57d400d 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -51,6 +51,7 @@ parameters: checkTooWideReturnTypesInProtectedAndPublicMethods: false checkUninitializedProperties: false checkDynamicProperties: false + strictRulesInstalled: false deprecationRulesInstalled: false inferPrivatePropertyTypeFromConstructor: false reportMaybes: false diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index f73011dcad..3dbe4e87ec 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -57,6 +57,7 @@ parametersSchema: checkTooWideReturnTypesInProtectedAndPublicMethods: bool() checkUninitializedProperties: bool() checkDynamicProperties: bool() + strictRulesInstalled: bool() deprecationRulesInstalled: bool() inferPrivatePropertyTypeFromConstructor: bool() From 5d07949d88c8554bad583f8e5584fdb7534d737c Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Sun, 15 Dec 2024 13:32:32 +0100 Subject: [PATCH 498/508] Remove incorrect doc leftover from 1.x --- src/Type/Type.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Type/Type.php b/src/Type/Type.php index 8021baae62..0badf2930c 100644 --- a/src/Type/Type.php +++ b/src/Type/Type.php @@ -64,13 +64,6 @@ public function getConstantArrays(): array; /** @return list */ public function getConstantStrings(): array; - /** - * This is like accepts() but gives reasons - * why the type was not/might not be accepted in some non-intuitive scenarios. - * - * In PHPStan 2.0 this method will be removed and the return type of accepts() - * will change to AcceptsResult. - */ public function accepts(Type $type, bool $strictTypes): AcceptsResult; public function isSuperTypeOf(Type $type): IsSuperTypeOfResult; From de0553c5f03685f235f484433e8d439b3a2b2cb0 Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Sun, 15 Dec 2024 12:56:23 +0000 Subject: [PATCH 499/508] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 166ac44388..8670cde3ee 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#bb981ec60b3838e56473a078edf7d0739ca20403", + "jetbrains/phpstorm-stubs": "dev-master#0e82bdfe850c71857ee4ee3501ed82a9fc5d043c", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.4", diff --git a/composer.lock b/composer.lock index f619dbd9c9..265045a14f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9dad77eea28263a8f7daa01a1b3dd47a", + "content-hash": "3f90069e33e3f9bd4610862a5a5aed2e", "packages": [ { "name": "clue/ndjson-react", @@ -1442,12 +1442,12 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "bb981ec60b3838e56473a078edf7d0739ca20403" + "reference": "0e82bdfe850c71857ee4ee3501ed82a9fc5d043c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/bb981ec60b3838e56473a078edf7d0739ca20403", - "reference": "bb981ec60b3838e56473a078edf7d0739ca20403", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/0e82bdfe850c71857ee4ee3501ed82a9fc5d043c", + "reference": "0e82bdfe850c71857ee4ee3501ed82a9fc5d043c", "shasum": "" }, "require-dev": { @@ -1482,7 +1482,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-11-27T16:45:26+00:00" + "time": "2024-12-14T08:03:12+00:00" }, { "name": "nette/bootstrap", From 202dd81d113dd8262977fc32c895386e38bda166 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 20 Dec 2024 10:00:02 +0100 Subject: [PATCH 500/508] Readonly classes cannot be combined with `#[AllowDynamicProperties]` + check trait attributes --- Makefile | 2 + conf/config.level0.neon | 1 + src/Rules/Classes/ClassAttributesRule.php | 32 ++++++- src/Rules/Traits/TraitAttributesRule.php | 51 ++++++++++ .../Rules/Classes/ClassAttributesRuleTest.php | 24 +++++ .../PHPStan/Rules/Classes/data/bug-12281.php | 16 ++++ .../Rules/Traits/TraitAttributesRuleTest.php | 96 +++++++++++++++++++ tests/PHPStan/Rules/Traits/data/bug-12011.php | 26 +++++ tests/PHPStan/Rules/Traits/data/bug-12281.php | 19 ++++ .../Rules/Traits/data/trait-attributes.php | 30 ++++++ 10 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 src/Rules/Traits/TraitAttributesRule.php create mode 100644 tests/PHPStan/Rules/Classes/data/bug-12281.php create mode 100644 tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php create mode 100644 tests/PHPStan/Rules/Traits/data/bug-12011.php create mode 100644 tests/PHPStan/Rules/Traits/data/bug-12281.php create mode 100644 tests/PHPStan/Rules/Traits/data/trait-attributes.php diff --git a/Makefile b/Makefile index ad6075e3bf..d8566bfdb0 100644 --- a/Makefile +++ b/Makefile @@ -87,6 +87,8 @@ lint: --exclude tests/PHPStan/Rules/Properties/data/non-abstract-hooked-properties-in-class.php \ --exclude tests/PHPStan/Rules/Properties/data/hooked-properties-in-class.php \ --exclude tests/PHPStan/Rules/Properties/data/hooked-properties-without-bodies-in-class.php \ + --exclude tests/PHPStan/Rules/Classes/data/bug-12281.php \ + --exclude tests/PHPStan/Rules/Traits/data/bug-12281.php \ src tests cs: diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 3964727b8d..c84cf8f5f7 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -103,6 +103,7 @@ rules: - PHPStan\Rules\Regexp\RegularExpressionPatternRule - PHPStan\Rules\Traits\ConflictingTraitConstantsRule - PHPStan\Rules\Traits\ConstantsInTraitsRule + - PHPStan\Rules\Traits\TraitAttributesRule - PHPStan\Rules\Types\InvalidTypesInUnionRule - PHPStan\Rules\Variables\UnsetRule - PHPStan\Rules\Whitespace\FileWhitespaceRule diff --git a/src/Rules/Classes/ClassAttributesRule.php b/src/Rules/Classes/ClassAttributesRule.php index afe9786db0..190be4331b 100644 --- a/src/Rules/Classes/ClassAttributesRule.php +++ b/src/Rules/Classes/ClassAttributesRule.php @@ -8,6 +8,9 @@ use PHPStan\Node\InClassNode; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\Rule; +use PHPStan\Rules\RuleErrorBuilder; +use function count; +use function sprintf; /** * @implements Rule @@ -28,12 +31,39 @@ public function processNode(Node $node, Scope $scope): array { $classLikeNode = $node->getOriginalNode(); - return $this->attributesCheck->check( + $errors = $this->attributesCheck->check( $scope, $classLikeNode->attrGroups, Attribute::TARGET_CLASS, 'class', ); + + $classReflection = $node->getClassReflection(); + if ( + $classReflection->isReadOnly() + || $classReflection->isEnum() + || $classReflection->isInterface() + ) { + $typeName = 'readonly class'; + $identifier = 'class.allowDynamicPropertiesReadonly'; + if ($classReflection->isEnum()) { + $typeName = 'enum'; + $identifier = 'enum.allowDynamicProperties'; + } + if ($classReflection->isInterface()) { + $typeName = 'interface'; + $identifier = 'interface.allowDynamicProperties'; + } + + if (count($classReflection->getNativeReflection()->getAttributes('AllowDynamicProperties')) > 0) { + $errors[] = RuleErrorBuilder::message(sprintf('Attribute class AllowDynamicProperties cannot be used with %s.', $typeName)) + ->identifier($identifier) + ->nonIgnorable() + ->build(); + } + } + + return $errors; } } diff --git a/src/Rules/Traits/TraitAttributesRule.php b/src/Rules/Traits/TraitAttributesRule.php new file mode 100644 index 0000000000..2b9fa768d0 --- /dev/null +++ b/src/Rules/Traits/TraitAttributesRule.php @@ -0,0 +1,51 @@ + + */ +final class TraitAttributesRule implements Rule +{ + + public function __construct( + private AttributesCheck $attributesCheck, + ) + { + } + + public function getNodeType(): string + { + return InTraitNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $originalNode = $node->getOriginalNode(); + $errors = $this->attributesCheck->check( + $scope, + $originalNode->attrGroups, + Attribute::TARGET_CLASS, + 'class', + ); + + if (count($node->getTraitReflection()->getNativeReflection()->getAttributes('AllowDynamicProperties')) > 0) { + $errors[] = RuleErrorBuilder::message('Attribute class AllowDynamicProperties cannot be used with trait.') + ->identifier('trait.allowDynamicProperties') + ->nonIgnorable() + ->build(); + } + + return $errors; + } + +} diff --git a/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php b/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php index 1d72b629a8..18e7c7a1fd 100644 --- a/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php @@ -167,4 +167,28 @@ public function testBug12011(): void ]); } + public function testBug12281(): void + { + if (PHP_VERSION_ID < 80200) { + $this->markTestSkipped('Test requires PHP 8.2.'); + } + + $this->checkExplicitMixed = true; + $this->checkImplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-12281.php'], [ + [ + 'Attribute class AllowDynamicProperties cannot be used with readonly class.', + 05, + ], + [ + 'Attribute class AllowDynamicProperties cannot be used with enum.', + 12, + ], + [ + 'Attribute class AllowDynamicProperties cannot be used with interface.', + 15, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Classes/data/bug-12281.php b/tests/PHPStan/Rules/Classes/data/bug-12281.php new file mode 100644 index 0000000000..293d9e5e41 --- /dev/null +++ b/tests/PHPStan/Rules/Classes/data/bug-12281.php @@ -0,0 +1,16 @@ += 8.2 + +namespace Bug12281; + +#[\AllowDynamicProperties] +readonly class BlogData { /* … */ } + +/** @readonly */ +#[\AllowDynamicProperties] +class BlogDataPhpdoc { /* … */ } + +#[\AllowDynamicProperties] +enum BlogDataEnum { /* … */ } + +#[\AllowDynamicProperties] +interface BlogDataInterface { /* … */ } diff --git a/tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php b/tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php new file mode 100644 index 0000000000..a3be5ead04 --- /dev/null +++ b/tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php @@ -0,0 +1,96 @@ + + */ +class TraitAttributesRuleTest extends RuleTestCase +{ + + private bool $checkExplicitMixed = false; + + private bool $checkImplicitMixed = false; + + protected function getRule(): Rule + { + $reflectionProvider = $this->createReflectionProvider(); + return new TraitAttributesRule( + new AttributesCheck( + $reflectionProvider, + new FunctionCallParametersCheck( + new RuleLevelHelper($reflectionProvider, true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), + new NullsafeCheck(), + new PhpVersion(80000), + new UnresolvableTypeHelper(), + new PropertyReflectionFinder(), + true, + true, + true, + true, + ), + new ClassNameCheck( + new ClassCaseSensitivityCheck($reflectionProvider, false), + new ClassForbiddenNameCheck(self::getContainer()), + ), + true, + ), + ); + } + + public function testRule(): void + { + $this->analyse([__DIR__ . '/data/trait-attributes.php'], [ + [ + 'Attribute class TraitAttributes\AbstractAttribute is abstract.', + 8, + ], + [ + 'Attribute class TraitAttributes\MyTargettedAttribute does not have the class target.', + 20, + ], + ]); + } + + public function testBug12011(): void + { + if (PHP_VERSION_ID < 80300) { + $this->markTestSkipped('Test requires PHP 8.3.'); + } + + $this->checkExplicitMixed = true; + $this->checkImplicitMixed = true; + + $this->analyse([__DIR__ . '/data/bug-12011.php'], [ + [ + 'Parameter #1 $name of attribute class Bug12011Trait\Table constructor expects string|null, int given.', + 8, + ], + ]); + } + + public function testBug12281(): void + { + $this->analyse([__DIR__ . '/data/bug-12281.php'], [ + [ + 'Attribute class AllowDynamicProperties cannot be used with trait.', + 11, + ], + ]); + } + +} diff --git a/tests/PHPStan/Rules/Traits/data/bug-12011.php b/tests/PHPStan/Rules/Traits/data/bug-12011.php new file mode 100644 index 0000000000..32b09d38d3 --- /dev/null +++ b/tests/PHPStan/Rules/Traits/data/bug-12011.php @@ -0,0 +1,26 @@ += 8.3 + +namespace Bug12011Trait; + +use Attribute; + + +#[Table(self::TABLE_NAME)] +trait MyTrait +{ + private const int TABLE_NAME = 1; +} + +class X { + use MyTrait; +} + +#[Attribute(Attribute::TARGET_CLASS)] +final class Table +{ + public function __construct( + public readonly string|null $name = null, + public readonly string|null $schema = null, + ) { + } +} diff --git a/tests/PHPStan/Rules/Traits/data/bug-12281.php b/tests/PHPStan/Rules/Traits/data/bug-12281.php new file mode 100644 index 0000000000..da7d088f1a --- /dev/null +++ b/tests/PHPStan/Rules/Traits/data/bug-12281.php @@ -0,0 +1,19 @@ += 8.2 + +namespace Bug12281Traits; + +#[\AllowDynamicProperties] +enum BlogDataEnum { /* … */ } // reported by ClassAttributesRule + +#[\AllowDynamicProperties] +interface BlogDataInterface { /* … */ } // reported by ClassAttributesRule + +#[\AllowDynamicProperties] +trait BlogDataTrait { /* … */ } + +class Uses +{ + + use BlogDataTrait; + +} diff --git a/tests/PHPStan/Rules/Traits/data/trait-attributes.php b/tests/PHPStan/Rules/Traits/data/trait-attributes.php new file mode 100644 index 0000000000..67906a2dfe --- /dev/null +++ b/tests/PHPStan/Rules/Traits/data/trait-attributes.php @@ -0,0 +1,30 @@ + Date: Fri, 20 Dec 2024 10:04:20 +0100 Subject: [PATCH 501/508] Named argument detection is scope-PHP version dependent --- src/Analyser/MutatingScope.php | 6 ++-- src/Php/PhpVersions.php | 5 +++ src/Rules/FunctionCallParametersCheck.php | 4 +-- .../Analyser/Bug9307CallMethodsRuleTest.php | 4 +-- .../nsrt/bug-2600-php-version-scope.php | 26 ++++++++++++++ .../Rules/Classes/ClassAttributesRuleTest.php | 2 -- .../ClassConstantAttributesRuleTest.php | 2 -- .../ForbiddenNameCheckExtensionRuleTest.php | 3 +- .../Rules/Classes/InstantiationRuleTest.php | 11 ++++-- .../EnumCases/EnumCaseAttributesRuleTest.php | 2 -- .../ArrowFunctionAttributesRuleTest.php | 2 -- .../Rules/Functions/CallCallablesRuleTest.php | 6 ++-- .../CallToFunctionParametersRuleTest.php | 13 +++---- .../Rules/Functions/CallUserFuncRuleTest.php | 3 +- .../Functions/ClosureAttributesRuleTest.php | 2 -- .../Functions/FunctionAttributesRuleTest.php | 2 -- .../Functions/ParamAttributesRuleTest.php | 2 -- .../Rules/Methods/CallMethodsRuleTest.php | 30 ++++++++++++---- .../Methods/CallStaticMethodsRuleTest.php | 6 ++-- .../Methods/MethodAttributesRuleTest.php | 7 ---- ...llow-named-arguments-php-version-scope.php | 35 +++++++++++++++++++ .../Properties/PropertyAttributesRuleTest.php | 2 -- 22 files changed, 119 insertions(+), 56 deletions(-) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-2600-php-version-scope.php create mode 100644 tests/PHPStan/Rules/Methods/data/disallow-named-arguments-php-version-scope.php diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index aa143cc3af..832c73b1c0 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3139,7 +3139,7 @@ private function enterFunctionLike( $paramExprString = '$' . $parameter->getName(); if ($parameter->isVariadic()) { - if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()->yes()) { + if (!$this->getPhpVersion()->supportsNamedArguments()->no() && $functionReflection->acceptsNamedArguments()->yes()) { $parameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $parameterType); } else { $parameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $parameterType), new AccessoryArrayListType()); @@ -3154,7 +3154,7 @@ private function enterFunctionLike( $nativeParameterType = $parameter->getNativeType(); if ($parameter->isVariadic()) { - if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()->yes()) { + if (!$this->getPhpVersion()->supportsNamedArguments()->no() && $functionReflection->acceptsNamedArguments()->yes()) { $nativeParameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $nativeParameterType); } else { $nativeParameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $nativeParameterType), new AccessoryArrayListType()); @@ -3629,7 +3629,7 @@ public function getFunctionType($type, bool $isNullable, bool $isVariadic): Type ); } if ($isVariadic) { - if ($this->phpVersion->supportsNamedArguments()) { + if (!$this->getPhpVersion()->supportsNamedArguments()->no()) { return new ArrayType(new UnionType([new IntegerType(), new StringType()]), $this->getFunctionType( $type, false, diff --git a/src/Php/PhpVersions.php b/src/Php/PhpVersions.php index 7bdc70e3bf..74474b28b0 100644 --- a/src/Php/PhpVersions.php +++ b/src/Php/PhpVersions.php @@ -28,4 +28,9 @@ public function producesWarningForFinalPrivateMethods(): TrinaryLogic return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result; } + public function supportsNamedArguments(): TrinaryLogic + { + return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result; + } + } diff --git a/src/Rules/FunctionCallParametersCheck.php b/src/Rules/FunctionCallParametersCheck.php index c39da64ce1..50371ab23c 100644 --- a/src/Rules/FunctionCallParametersCheck.php +++ b/src/Rules/FunctionCallParametersCheck.php @@ -6,7 +6,6 @@ use PhpParser\Node\Expr; use PHPStan\Analyser\MutatingScope; use PHPStan\Analyser\Scope; -use PHPStan\Php\PhpVersion; use PHPStan\Reflection\ExtendedParameterReflection; use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\ParametersAcceptor; @@ -42,7 +41,6 @@ final class FunctionCallParametersCheck public function __construct( private RuleLevelHelper $ruleLevelHelper, private NullsafeCheck $nullsafeCheck, - private PhpVersion $phpVersion, private UnresolvableTypeHelper $unresolvableTypeHelper, private PropertyReflectionFinder $propertyReflectionFinder, private bool $checkArgumentTypes, @@ -201,7 +199,7 @@ public function check( ]; } - if ($hasNamedArguments && !$this->phpVersion->supportsNamedArguments() && !(bool) $funcCall->getAttribute('isAttribute', false)) { + if ($hasNamedArguments && !$scope->getPhpVersion()->supportsNamedArguments()->yes() && !(bool) $funcCall->getAttribute('isAttribute', false)) { $errors[] = RuleErrorBuilder::message('Named arguments are supported only on PHP 8.0 and later.') ->identifier('argument.namedNotSupported') ->line($funcCall->getStartLine()) diff --git a/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php b/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php index a49a650286..ff1be83109 100644 --- a/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php +++ b/tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Analyser; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\FunctionCallParametersCheck; use PHPStan\Rules\Methods\CallMethodsRule; use PHPStan\Rules\Methods\MethodCallCheck; @@ -12,7 +11,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; -use const PHP_VERSION_ID; /** * @extends RuleTestCase @@ -26,7 +24,7 @@ protected function getRule(): Rule $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false); return new CallMethodsRule( new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true), - new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion(PHP_VERSION_ID), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), + new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), ); } diff --git a/tests/PHPStan/Analyser/nsrt/bug-2600-php-version-scope.php b/tests/PHPStan/Analyser/nsrt/bug-2600-php-version-scope.php new file mode 100644 index 0000000000..bf13358857 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-2600-php-version-scope.php @@ -0,0 +1,26 @@ + 7.4 + +namespace Bug2600PhpVersionScope; + +use function PHPStan\Testing\assertType; + +if (PHP_VERSION_ID >= 80000) { + class Foo8 { + /** + * @param mixed $x + */ + public function doBaz(...$x) { + assertType('array', $x); + } + } +} else { + class Foo9 { + /** + * @param mixed $x + */ + public function doBaz(...$x) { + assertType('list', $x); + } + } + +} diff --git a/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php b/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php index 18e7c7a1fd..d4a9dc96d5 100644 --- a/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Classes; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -35,7 +34,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, diff --git a/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php b/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php index d5787f8344..64b9783877 100644 --- a/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Classes; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -30,7 +29,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, diff --git a/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php b/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php index 4907d1d7ec..5286e079fc 100644 --- a/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php +++ b/tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Classes; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; use PHPStan\Rules\ClassNameCheck; @@ -26,7 +25,7 @@ protected function getRule(): Rule $reflectionProvider = $this->createReflectionProvider(); return new InstantiationRule( $reflectionProvider, - new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), diff --git a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php index 43b9091daf..e4155ce55b 100644 --- a/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php +++ b/tests/PHPStan/Rules/Classes/InstantiationRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Classes; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; use PHPStan\Rules\ClassNameCheck; @@ -26,7 +25,7 @@ protected function getRule(): Rule $reflectionProvider = $this->createReflectionProvider(); return new InstantiationRule( $reflectionProvider, - new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), new ClassNameCheck( new ClassCaseSensitivityCheck($reflectionProvider, true), new ClassForbiddenNameCheck(self::getContainer()), @@ -290,6 +289,10 @@ public function testBug4056(): void public function testNamedArguments(): void { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0'); + } + $this->analyse([__DIR__ . '/data/instantiation-named-arguments.php'], [ [ 'Missing parameter $j (int) in call to InstantiationNamedArguments\Foo constructor.', @@ -501,6 +504,10 @@ public function testBug10248(): void public function testBug11815(): void { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0'); + } + $this->analyse([__DIR__ . '/data/bug-11815.php'], []); } diff --git a/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php b/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php index 52428ced2b..d61265e3e7 100644 --- a/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php +++ b/tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\EnumCases; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -30,7 +29,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), - new PhpVersion(80100), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, diff --git a/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php index af9266b7e5..1be1cfae69 100644 --- a/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ArrowFunctionAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Functions; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -30,7 +29,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, diff --git a/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php b/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php index 31a92a4f92..a8ffcaf800 100644 --- a/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Functions; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\FunctionCallParametersCheck; use PHPStan\Rules\NullsafeCheck; use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper; @@ -27,7 +26,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( $ruleLevelHelper, new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, @@ -158,6 +156,10 @@ public function testRule(): void public function testNamedArguments(): void { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0'); + } + $this->analyse([__DIR__ . '/data/callables-named-arguments.php'], [ [ 'Missing parameter $j (int) in call to closure.', diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php index 89017fe2cf..a6513f03cb 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Functions; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\FunctionCallParametersCheck; use PHPStan\Rules\NullsafeCheck; use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper; @@ -28,7 +27,7 @@ protected function getRule(): Rule $broker = $this->createReflectionProvider(); return new CallToFunctionParametersRule( $broker, - new FunctionCallParametersCheck(new RuleLevelHelper($broker, true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), + new FunctionCallParametersCheck(new RuleLevelHelper($broker, true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), ); } @@ -477,6 +476,10 @@ public function testGenericFunction(): void public function testNamedArguments(): void { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0'); + } + $errors = [ [ 'Missing parameter $j (int) in call to function FunctionNamedArguments\foo.', @@ -491,12 +494,6 @@ public function testNamedArguments(): void 14, ], ]; - if (PHP_VERSION_ID < 80000) { - $errors[] = [ - 'Missing parameter $arr1 (array) in call to function array_merge.', - 14, - ]; - } require_once __DIR__ . '/data/named-arguments-define.php'; $this->analyse([__DIR__ . '/data/named-arguments.php'], $errors); diff --git a/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php b/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php index f4eb4c2c6e..ccff7cb19d 100644 --- a/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallUserFuncRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Functions; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\FunctionCallParametersCheck; use PHPStan\Rules\NullsafeCheck; use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper; @@ -21,7 +20,7 @@ class CallUserFuncRuleTest extends RuleTestCase protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); - return new CallUserFuncRule($reflectionProvider, new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true)); + return new CallUserFuncRule($reflectionProvider, new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false), new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true)); } public function testRule(): void diff --git a/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php index dbab699a2b..41cc608457 100644 --- a/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ClosureAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Functions; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -30,7 +29,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, diff --git a/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php index 6d028b1b96..1961e8e81c 100644 --- a/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/FunctionAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Functions; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -30,7 +29,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, diff --git a/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php b/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php index 842d0513a1..678738ac50 100644 --- a/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ParamAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Functions; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -30,7 +29,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index bd20b469b8..0da6911a43 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Methods; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\FunctionCallParametersCheck; use PHPStan\Rules\NullsafeCheck; use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper; @@ -28,15 +27,13 @@ class CallMethodsRuleTest extends RuleTestCase private bool $checkImplicitMixed = false; - private int $phpVersion = PHP_VERSION_ID; - protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); $ruleLevelHelper = new RuleLevelHelper($reflectionProvider, $this->checkNullables, $this->checkThisOnly, $this->checkUnionTypes, $this->checkExplicitMixed, $this->checkImplicitMixed, false); return new CallMethodsRule( new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true), - new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion($this->phpVersion), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), + new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true), ); } @@ -1822,12 +1819,29 @@ public function testDisallowNamedArguments(): void ]); } + public function testDisallowNamedArgumentsInPhpVersionScope(): void + { + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + + $this->analyse([__DIR__ . '/data/disallow-named-arguments-php-version-scope.php'], [ + [ + 'Named arguments are supported only on PHP 8.0 and later.', + 26, + ], + ]); + } + public function testNamedArguments(): void { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0'); + } + $this->checkThisOnly = false; $this->checkNullables = true; $this->checkUnionTypes = true; - $this->phpVersion = 80000; $this->analyse([__DIR__ . '/data/named-arguments.php'], [ [ @@ -2104,7 +2118,11 @@ public function testBug4800(): void $this->checkThisOnly = false; $this->checkNullables = true; $this->checkUnionTypes = true; - $this->phpVersion = 80000; + + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0'); + } + $this->analyse([__DIR__ . '/data/bug-4800.php'], [ [ 'Missing parameter $bar (string) in call to method Bug4800\HelloWorld2::a().', diff --git a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php index 80d61e299e..51210125cf 100644 --- a/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Methods; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; use PHPStan\Rules\ClassNameCheck; @@ -47,7 +46,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( $ruleLevelHelper, new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, @@ -414,6 +412,10 @@ public function testNamedArguments(): void { $this->checkThisOnly = false; + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0'); + } + $this->analyse([__DIR__ . '/data/static-method-named-arguments.php'], [ [ 'Missing parameter $j (int) in call to static method StaticMethodNamedArguments\Foo::doFoo().', diff --git a/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php b/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php index ef5ca25aef..c87aabde90 100644 --- a/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Methods; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -21,8 +20,6 @@ class MethodAttributesRuleTest extends RuleTestCase { - private int $phpVersion; - protected function getRule(): Rule { $reflectionProvider = $this->createReflectionProvider(); @@ -32,7 +29,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), - new PhpVersion($this->phpVersion), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, @@ -51,8 +47,6 @@ protected function getRule(): Rule public function testRule(): void { - $this->phpVersion = 80000; - $this->analyse([__DIR__ . '/data/method-attributes.php'], [ [ 'Attribute class MethodAttributes\Foo does not have the method target.', @@ -63,7 +57,6 @@ public function testRule(): void public function testBug5898(): void { - $this->phpVersion = 70400; $this->analyse([__DIR__ . '/data/bug-5898.php'], []); } diff --git a/tests/PHPStan/Rules/Methods/data/disallow-named-arguments-php-version-scope.php b/tests/PHPStan/Rules/Methods/data/disallow-named-arguments-php-version-scope.php new file mode 100644 index 0000000000..174fef244d --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/disallow-named-arguments-php-version-scope.php @@ -0,0 +1,35 @@ += 80000) { + class Foo + { + + public function doFoo(): void + { + $this->doBar(i: 1); + } + + public function doBar(int $i): void + { + + } + + } +} else { + class FooBar + { + + public function doFoo(): void + { + $this->doBar(i: 1); + } + + public function doBar(int $i): void + { + + } + + } +} diff --git a/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php b/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php index 02b75d1007..6f4a6121ec 100644 --- a/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/PropertyAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Properties; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -29,7 +28,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, From c5df243d3eeae15822c32780523cb5dda2bda59b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 20 Dec 2024 10:12:43 +0100 Subject: [PATCH 502/508] Fix test --- tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php b/tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php index a3be5ead04..fb35b438a0 100644 --- a/tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php +++ b/tests/PHPStan/Rules/Traits/TraitAttributesRuleTest.php @@ -2,7 +2,6 @@ namespace PHPStan\Rules\Traits; -use PHPStan\Php\PhpVersion; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\ClassCaseSensitivityCheck; use PHPStan\Rules\ClassForbiddenNameCheck; @@ -35,7 +34,6 @@ protected function getRule(): Rule new FunctionCallParametersCheck( new RuleLevelHelper($reflectionProvider, true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false), new NullsafeCheck(), - new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, @@ -54,6 +52,10 @@ protected function getRule(): Rule public function testRule(): void { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0.'); + } + $this->analyse([__DIR__ . '/data/trait-attributes.php'], [ [ 'Attribute class TraitAttributes\AbstractAttribute is abstract.', @@ -85,6 +87,10 @@ public function testBug12011(): void public function testBug12281(): void { + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped('Test requires PHP 8.1.'); + } + $this->analyse([__DIR__ . '/data/bug-12281.php'], [ [ 'Attribute class AllowDynamicProperties cannot be used with trait.', From 90e48fa876696f221874a2766c2bf3fc1bea0ec0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Fri, 20 Dec 2024 10:16:44 +0100 Subject: [PATCH 503/508] Attributes rules use `In*Node` virtual nodes for more precise Scope --- src/Rules/Functions/ArrowFunctionAttributesRule.php | 7 ++++--- src/Rules/Functions/ClosureAttributesRule.php | 7 ++++--- src/Rules/Functions/FunctionAttributesRule.php | 7 ++++--- src/Rules/Methods/MethodAttributesRule.php | 7 ++++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Rules/Functions/ArrowFunctionAttributesRule.php b/src/Rules/Functions/ArrowFunctionAttributesRule.php index b849f968aa..67af9eb5e0 100644 --- a/src/Rules/Functions/ArrowFunctionAttributesRule.php +++ b/src/Rules/Functions/ArrowFunctionAttributesRule.php @@ -5,11 +5,12 @@ use Attribute; use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\Node\InArrowFunctionNode; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\Rule; /** - * @implements Rule + * @implements Rule */ final class ArrowFunctionAttributesRule implements Rule { @@ -20,14 +21,14 @@ public function __construct(private AttributesCheck $attributesCheck) public function getNodeType(): string { - return Node\Expr\ArrowFunction::class; + return InArrowFunctionNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->attributesCheck->check( $scope, - $node->attrGroups, + $node->getOriginalNode()->attrGroups, Attribute::TARGET_FUNCTION, 'function', ); diff --git a/src/Rules/Functions/ClosureAttributesRule.php b/src/Rules/Functions/ClosureAttributesRule.php index 841ae2f46c..fc206e19d4 100644 --- a/src/Rules/Functions/ClosureAttributesRule.php +++ b/src/Rules/Functions/ClosureAttributesRule.php @@ -5,11 +5,12 @@ use Attribute; use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\Node\InClosureNode; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\Rule; /** - * @implements Rule + * @implements Rule */ final class ClosureAttributesRule implements Rule { @@ -20,14 +21,14 @@ public function __construct(private AttributesCheck $attributesCheck) public function getNodeType(): string { - return Node\Expr\Closure::class; + return InClosureNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->attributesCheck->check( $scope, - $node->attrGroups, + $node->getOriginalNode()->attrGroups, Attribute::TARGET_FUNCTION, 'function', ); diff --git a/src/Rules/Functions/FunctionAttributesRule.php b/src/Rules/Functions/FunctionAttributesRule.php index 153c222091..9c5ad24d73 100644 --- a/src/Rules/Functions/FunctionAttributesRule.php +++ b/src/Rules/Functions/FunctionAttributesRule.php @@ -5,11 +5,12 @@ use Attribute; use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\Node\InFunctionNode; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\Rule; /** - * @implements Rule + * @implements Rule */ final class FunctionAttributesRule implements Rule { @@ -20,14 +21,14 @@ public function __construct(private AttributesCheck $attributesCheck) public function getNodeType(): string { - return Node\Stmt\Function_::class; + return InFunctionNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->attributesCheck->check( $scope, - $node->attrGroups, + $node->getOriginalNode()->attrGroups, Attribute::TARGET_FUNCTION, 'function', ); diff --git a/src/Rules/Methods/MethodAttributesRule.php b/src/Rules/Methods/MethodAttributesRule.php index fefc7bac89..433931baf3 100644 --- a/src/Rules/Methods/MethodAttributesRule.php +++ b/src/Rules/Methods/MethodAttributesRule.php @@ -5,11 +5,12 @@ use Attribute; use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\Node\InClassMethodNode; use PHPStan\Rules\AttributesCheck; use PHPStan\Rules\Rule; /** - * @implements Rule + * @implements Rule */ final class MethodAttributesRule implements Rule { @@ -20,14 +21,14 @@ public function __construct(private AttributesCheck $attributesCheck) public function getNodeType(): string { - return Node\Stmt\ClassMethod::class; + return InClassMethodNode::class; } public function processNode(Node $node, Scope $scope): array { return $this->attributesCheck->check( $scope, - $node->attrGroups, + $node->getOriginalNode()->attrGroups, Attribute::TARGET_METHOD, 'method', ); From f6c556f625078b39caff3d67fafd6ae49957333e Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 20 Dec 2024 10:24:48 +0100 Subject: [PATCH 504/508] Scope: use `scope->getConstant` instead --- src/Analyser/MutatingScope.php | 40 +++++++++++------ src/Php/PhpVersions.php | 5 +++ .../PHPStan/Analyser/ScopePhpVersionTest.php | 43 +++++++++++++++++++ .../Analyser/data/scope-constants-global.php | 9 ++++ .../data/scope-constants-namespace.php | 9 ++++ 5 files changed, 93 insertions(+), 13 deletions(-) create mode 100644 tests/PHPStan/Analyser/ScopePhpVersionTest.php create mode 100644 tests/PHPStan/Analyser/data/scope-constants-global.php create mode 100644 tests/PHPStan/Analyser/data/scope-constants-namespace.php diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 832c73b1c0..f883c95578 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -610,12 +610,7 @@ public function hasConstant(Name $name): bool return $this->fileHasCompilerHaltStatementCalls(); } - if (!$name->isFullyQualified() && $this->getNamespace() !== null) { - if ($this->hasExpressionType(new ConstFetch(new FullyQualified([$this->getNamespace(), $name->toString()])))->yes()) { - return true; - } - } - if ($this->hasExpressionType(new ConstFetch(new FullyQualified($name->toString())))->yes()) { + if ($this->getGlobalConstantType($name) !== null) { return true; } @@ -5686,6 +5681,25 @@ private function getConstantTypes(): array return $constantTypes; } + private function getGlobalConstantType(Name $name): ?Type + { + $fetches = []; + if (!$name->isFullyQualified() && $this->getNamespace() !== null) { + $fetches[] = new ConstFetch(new FullyQualified([$this->getNamespace(), $name->toString()])); + } + + $fetches[] = new ConstFetch(new FullyQualified($name->toString())); + $fetches[] = new ConstFetch($name); + + foreach ($fetches as $constFetch) { + if ($this->hasExpressionType($constFetch)->yes()) { + return $this->getType($constFetch); + } + } + + return null; + } + /** * @return array */ @@ -5728,15 +5742,15 @@ public function getIterableValueType(Type $iteratee): Type public function getPhpVersion(): PhpVersions { - $versionExpr = new ConstFetch(new Name('PHP_VERSION_ID')); - if (!$this->hasExpressionType($versionExpr)->yes()) { - if (is_array($this->configPhpVersion)) { - return new PhpVersions(IntegerRangeType::fromInterval($this->configPhpVersion['min'], $this->configPhpVersion['max'])); - } - return new PhpVersions(new ConstantIntegerType($this->phpVersion->getVersionId())); + $constType = $this->getGlobalConstantType(new Name('PHP_VERSION_ID')); + if ($constType !== null) { + return new PhpVersions($constType); } - return new PhpVersions($this->getType($versionExpr)); + if (is_array($this->configPhpVersion)) { + return new PhpVersions(IntegerRangeType::fromInterval($this->configPhpVersion['min'], $this->configPhpVersion['max'])); + } + return new PhpVersions(new ConstantIntegerType($this->phpVersion->getVersionId())); } } diff --git a/src/Php/PhpVersions.php b/src/Php/PhpVersions.php index 74474b28b0..229dccb72d 100644 --- a/src/Php/PhpVersions.php +++ b/src/Php/PhpVersions.php @@ -18,6 +18,11 @@ public function __construct( { } + public function getType(): Type + { + return $this->phpVersions; + } + public function supportsNoncapturingCatches(): TrinaryLogic { return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result; diff --git a/tests/PHPStan/Analyser/ScopePhpVersionTest.php b/tests/PHPStan/Analyser/ScopePhpVersionTest.php new file mode 100644 index 0000000000..fac3b8a066 --- /dev/null +++ b/tests/PHPStan/Analyser/ScopePhpVersionTest.php @@ -0,0 +1,43 @@ +', + __DIR__ . '/data/scope-constants-global.php', + ], + [ + 'int<80000, 80499>', + __DIR__ . '/data/scope-constants-namespace.php', + ], + ]; + } + + /** + * @dataProvider dataTestPhpVersion + */ + public function testPhpVersion(string $expected, string $file): void + { + self::processFile($file, function (Node $node, Scope $scope) use ($expected): void { + if (!($node instanceof Exit_)) { + return; + } + $this->assertSame( + $expected, + $scope->getPhpVersion()->getType()->describe(VerbosityLevel::precise()), + ); + }); + } + +} diff --git a/tests/PHPStan/Analyser/data/scope-constants-global.php b/tests/PHPStan/Analyser/data/scope-constants-global.php new file mode 100644 index 0000000000..56eba41c9a --- /dev/null +++ b/tests/PHPStan/Analyser/data/scope-constants-global.php @@ -0,0 +1,9 @@ + Date: Fri, 20 Dec 2024 14:52:28 +0100 Subject: [PATCH 505/508] Bleeding edge - UnusedFunctionParametersCheck: report precise line --- conf/bleedingEdge.neon | 1 + conf/config.neon | 3 ++ conf/parametersSchema.neon | 1 + .../UnusedConstructorParametersRule.php | 7 ++-- src/Rules/Functions/UnusedClosureUsesRule.php | 9 +---- src/Rules/UnusedFunctionParametersCheck.php | 35 +++++++++++++------ .../UnusedConstructorParametersRuleTest.php | 20 ++++++++++- .../Functions/UnusedClosureUsesRuleTest.php | 6 ++-- 8 files changed, 55 insertions(+), 27 deletions(-) diff --git a/conf/bleedingEdge.neon b/conf/bleedingEdge.neon index 7227e369b3..76dd0d8904 100644 --- a/conf/bleedingEdge.neon +++ b/conf/bleedingEdge.neon @@ -4,3 +4,4 @@ parameters: checkParameterCastableToNumberFunctions: true skipCheckGenericClasses!: [] stricterFunctionMap: true + reportPreciseLineForUnusedFunctionParameter: true diff --git a/conf/config.neon b/conf/config.neon index 40e57d400d..d77e889531 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -25,6 +25,7 @@ parameters: checkParameterCastableToNumberFunctions: false skipCheckGenericClasses: [] stricterFunctionMap: false + reportPreciseLineForUnusedFunctionParameter: false fileExtensions: - php checkAdvancedIsset: false @@ -1043,6 +1044,8 @@ services: - class: PHPStan\Rules\UnusedFunctionParametersCheck + arguments: + reportExactLine: %featureToggles.reportPreciseLineForUnusedFunctionParameter% - class: PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 3dbe4e87ec..f7328f7863 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -31,6 +31,7 @@ parametersSchema: checkParameterCastableToNumberFunctions: bool(), skipCheckGenericClasses: listOf(string()), stricterFunctionMap: bool() + reportPreciseLineForUnusedFunctionParameter: bool() ]) fileExtensions: listOf(string()) checkAdvancedIsset: bool() diff --git a/src/Rules/Classes/UnusedConstructorParametersRule.php b/src/Rules/Classes/UnusedConstructorParametersRule.php index e42a60d5f7..8b38392470 100644 --- a/src/Rules/Classes/UnusedConstructorParametersRule.php +++ b/src/Rules/Classes/UnusedConstructorParametersRule.php @@ -15,7 +15,6 @@ use function array_map; use function array_values; use function count; -use function is_string; use function sprintf; use function strtolower; @@ -56,11 +55,11 @@ public function processNode(Node $node, Scope $scope): array return $this->check->getUnusedParameters( $scope, - array_map(static function (Param $parameter): string { - if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { + array_map(static function (Param $parameter): Variable { + if (!$parameter->var instanceof Variable) { throw new ShouldNotHappenException(); } - return $parameter->var->name; + return $parameter->var; }, array_values(array_filter($originalNode->params, static fn (Param $parameter): bool => $parameter->flags === 0))), $originalNode->stmts, $message, diff --git a/src/Rules/Functions/UnusedClosureUsesRule.php b/src/Rules/Functions/UnusedClosureUsesRule.php index c019d69240..ed9639e41f 100644 --- a/src/Rules/Functions/UnusedClosureUsesRule.php +++ b/src/Rules/Functions/UnusedClosureUsesRule.php @@ -6,10 +6,8 @@ use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\UnusedFunctionParametersCheck; -use PHPStan\ShouldNotHappenException; use function array_map; use function count; -use function is_string; /** * @implements Rule @@ -34,12 +32,7 @@ public function processNode(Node $node, Scope $scope): array return $this->check->getUnusedParameters( $scope, - array_map(static function (Node\ClosureUse $use): string { - if (!is_string($use->var->name)) { - throw new ShouldNotHappenException(); - } - return $use->var->name; - }, $node->uses), + array_map(static fn (Node\ClosureUse $use): Node\Expr\Variable => $use->var, $node->uses), $node->stmts, 'Anonymous function has an unused use $%s.', 'closure.unusedUse', diff --git a/src/Rules/UnusedFunctionParametersCheck.php b/src/Rules/UnusedFunctionParametersCheck.php index 4fbe76d20d..628041a032 100644 --- a/src/Rules/UnusedFunctionParametersCheck.php +++ b/src/Rules/UnusedFunctionParametersCheck.php @@ -3,11 +3,13 @@ namespace PHPStan\Rules; use PhpParser\Node; +use PhpParser\Node\Expr\Variable; use PHPStan\Analyser\Scope; use PHPStan\Reflection\ReflectionProvider; +use PHPStan\ShouldNotHappenException; use PHPStan\Type\Constant\ConstantStringType; -use function array_fill_keys; -use function array_keys; +use function array_combine; +use function array_map; use function array_merge; use function is_array; use function is_string; @@ -16,25 +18,34 @@ final class UnusedFunctionParametersCheck { - public function __construct(private ReflectionProvider $reflectionProvider) + public function __construct( + private ReflectionProvider $reflectionProvider, + private bool $reportExactLine, + ) { } /** - * @param string[] $parameterNames + * @param Variable[] $parameterVars * @param Node[] $statements * @param 'constructor.unusedParameter'|'closure.unusedUse' $identifier * @return list */ public function getUnusedParameters( Scope $scope, - array $parameterNames, + array $parameterVars, array $statements, string $unusedParameterMessage, string $identifier, ): array { - $unusedParameters = array_fill_keys($parameterNames, true); + $parameterNames = array_map(static function (Variable $variable): string { + if (!is_string($variable->name)) { + throw new ShouldNotHappenException(); + } + return $variable->name; + }, $parameterVars); + $unusedParameters = array_combine($parameterNames, $parameterVars); foreach ($this->getUsedVariables($scope, $statements) as $variableName) { if (!isset($unusedParameters[$variableName])) { continue; @@ -43,10 +54,12 @@ public function getUnusedParameters( unset($unusedParameters[$variableName]); } $errors = []; - foreach (array_keys($unusedParameters) as $name) { - $errors[] = RuleErrorBuilder::message( - sprintf($unusedParameterMessage, $name), - )->identifier($identifier)->build(); + foreach ($unusedParameters as $name => $variable) { + $errorBuilder = RuleErrorBuilder::message(sprintf($unusedParameterMessage, $name))->identifier($identifier); + if ($this->reportExactLine) { + $errorBuilder->line($variable->getStartLine()); + } + $errors[] = $errorBuilder->build(); } return $errors; @@ -66,7 +79,7 @@ private function getUsedVariables(Scope $scope, $node): array return $scope->getDefinedVariables(); } } - if ($node instanceof Node\Expr\Variable && is_string($node->name) && $node->name !== 'this') { + if ($node instanceof Variable && is_string($node->name) && $node->name !== 'this') { return [$node->name]; } if ($node instanceof Node\ClosureUse && is_string($node->var->name)) { diff --git a/tests/PHPStan/Rules/Classes/UnusedConstructorParametersRuleTest.php b/tests/PHPStan/Rules/Classes/UnusedConstructorParametersRuleTest.php index b6530920df..beb402c267 100644 --- a/tests/PHPStan/Rules/Classes/UnusedConstructorParametersRuleTest.php +++ b/tests/PHPStan/Rules/Classes/UnusedConstructorParametersRuleTest.php @@ -12,15 +12,19 @@ class UnusedConstructorParametersRuleTest extends RuleTestCase { + private bool $reportExactLine = true; + protected function getRule(): Rule { return new UnusedConstructorParametersRule(new UnusedFunctionParametersCheck( $this->createReflectionProvider(), + $this->reportExactLine, )); } - public function testUnusedConstructorParameters(): void + public function testUnusedConstructorParametersNoExactLine(): void { + $this->reportExactLine = false; $this->analyse([__DIR__ . '/data/unused-constructor-parameters.php'], [ [ 'Constructor of class UnusedConstructorParameters\Foo has an unused parameter $unusedParameter.', @@ -33,6 +37,20 @@ public function testUnusedConstructorParameters(): void ]); } + public function testUnusedConstructorParameters(): void + { + $this->analyse([__DIR__ . '/data/unused-constructor-parameters.php'], [ + [ + 'Constructor of class UnusedConstructorParameters\Foo has an unused parameter $unusedParameter.', + 19, + ], + [ + 'Constructor of class UnusedConstructorParameters\Foo has an unused parameter $anotherUnusedParameter.', + 20, + ], + ]); + } + public function testPromotedProperties(): void { $this->analyse([__DIR__ . '/data/unused-constructor-parameters-promoted-properties.php'], []); diff --git a/tests/PHPStan/Rules/Functions/UnusedClosureUsesRuleTest.php b/tests/PHPStan/Rules/Functions/UnusedClosureUsesRuleTest.php index 0d033268d8..38a555afda 100644 --- a/tests/PHPStan/Rules/Functions/UnusedClosureUsesRuleTest.php +++ b/tests/PHPStan/Rules/Functions/UnusedClosureUsesRuleTest.php @@ -14,7 +14,7 @@ class UnusedClosureUsesRuleTest extends RuleTestCase protected function getRule(): Rule { - return new UnusedClosureUsesRule(new UnusedFunctionParametersCheck($this->createReflectionProvider())); + return new UnusedClosureUsesRule(new UnusedFunctionParametersCheck($this->createReflectionProvider(), true)); } public function testUnusedClosureUses(): void @@ -22,11 +22,11 @@ public function testUnusedClosureUses(): void $this->analyse([__DIR__ . '/data/unused-closure-uses.php'], [ [ 'Anonymous function has an unused use $unused.', - 3, + 6, ], [ 'Anonymous function has an unused use $anotherUnused.', - 3, + 7, ], [ 'Anonymous function has an unused use $usedInClosureUse.', From 72b31c081c52682736318d62a09b60f740d9ce41 Mon Sep 17 00:00:00 2001 From: ondrejmirtes Date: Fri, 20 Dec 2024 19:31:57 +0000 Subject: [PATCH 506/508] Update BetterReflection --- composer.json | 2 +- composer.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 8670cde3ee..30dfc158c3 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "nette/utils": "^3.2.5", "nikic/php-parser": "^5.3.0", "ondram/ci-detector": "^3.4.0", - "ondrejmirtes/better-reflection": "6.46.0.0", + "ondrejmirtes/better-reflection": "6.49.0.0", "phpstan/php-8-stubs": "0.4.9", "phpstan/phpdoc-parser": "2.0.0", "psr/http-message": "^1.1", diff --git a/composer.lock b/composer.lock index 265045a14f..731974732a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3f90069e33e3f9bd4610862a5a5aed2e", + "content-hash": "7887860dff8af8b2ff60352d573b1aba", "packages": [ { "name": "clue/ndjson-react", @@ -2187,21 +2187,21 @@ }, { "name": "ondrejmirtes/better-reflection", - "version": "6.46.0.0", + "version": "6.49.0.0", "source": { "type": "git", "url": "https://github.com/ondrejmirtes/BetterReflection.git", - "reference": "242b3e1cdb59a81585be5722b6c44ae44c74c671" + "reference": "11abb6b4c9c8b29ee2730a3307ebae77b17fa94d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/242b3e1cdb59a81585be5722b6c44ae44c74c671", - "reference": "242b3e1cdb59a81585be5722b6c44ae44c74c671", + "url": "https://api.github.com/repos/ondrejmirtes/BetterReflection/zipball/11abb6b4c9c8b29ee2730a3307ebae77b17fa94d", + "reference": "11abb6b4c9c8b29ee2730a3307ebae77b17fa94d", "shasum": "" }, "require": { "ext-json": "*", - "jetbrains/phpstorm-stubs": "dev-master#217ed9356d07ef89109d3cd7d8c5df10aab4b0d4", + "jetbrains/phpstorm-stubs": "dev-master#b61d4a5f40c3940be440d85355fef4e2416b8527", "nikic/php-parser": "^5.3.1", "php": "^7.4 || ^8.0" }, @@ -2252,9 +2252,9 @@ ], "description": "Better Reflection - an improved code reflection API", "support": { - "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.46.0.0" + "source": "https://github.com/ondrejmirtes/BetterReflection/tree/6.49.0.0" }, - "time": "2024-12-12T12:40:29+00:00" + "time": "2024-12-20T19:27:15+00:00" }, { "name": "phpstan/php-8-stubs", From 46b98196c0643eeb3b0eb3c5e91e10099e00f5c1 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 21 Dec 2024 15:55:41 +0100 Subject: [PATCH 507/508] Prepare for 2.1.x-dev --- .github/workflows/apiref.yml | 4 ++-- .github/workflows/issue-bot.yml | 4 ++-- .github/workflows/pr-base-on-previous-branch.yml | 4 ++-- .github/workflows/update-phpstorm-stubs.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/apiref.yml b/.github/workflows/apiref.yml index 7700ceb911..24ba44284b 100644 --- a/.github/workflows/apiref.yml +++ b/.github/workflows/apiref.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: push: branches: - - "2.0.x" + - "2.1.x" paths: - 'src/**' - 'composer.lock' @@ -14,7 +14,7 @@ on: - '.github/workflows/apiref.yml' env: - COMPOSER_ROOT_VERSION: "2.0.x-dev" + COMPOSER_ROOT_VERSION: "2.1.x-dev" concurrency: group: apigen-${{ github.ref }} # will be canceled on subsequent pushes in branch diff --git a/.github/workflows/issue-bot.yml b/.github/workflows/issue-bot.yml index c3d3488fea..3165350af2 100644 --- a/.github/workflows/issue-bot.yml +++ b/.github/workflows/issue-bot.yml @@ -11,7 +11,7 @@ on: - 'changelog-generator/**' push: branches: - - "2.0.x" + - "2.1.x" paths-ignore: - 'compiler/**' - 'apigen/**' @@ -164,7 +164,7 @@ jobs: - name: "Evaluate results - push" working-directory: "issue-bot" - if: "github.repository_owner == 'phpstan' && github.ref == 'refs/heads/2.0.x'" + if: "github.repository_owner == 'phpstan' && github.ref == 'refs/heads/2.1.x'" env: GITHUB_PAT: ${{ secrets.PHPSTAN_BOT_TOKEN }} PHPSTAN_SRC_COMMIT_BEFORE: ${{ github.event.before }} diff --git a/.github/workflows/pr-base-on-previous-branch.yml b/.github/workflows/pr-base-on-previous-branch.yml index 7c2f57188d..34ef71bb83 100644 --- a/.github/workflows/pr-base-on-previous-branch.yml +++ b/.github/workflows/pr-base-on-previous-branch.yml @@ -7,7 +7,7 @@ on: types: - opened branches: - - '2.1.x' + - '2.2.x' jobs: @@ -19,6 +19,6 @@ jobs: - name: Comment PR uses: peter-evans/create-or-update-comment@v4 with: - body: "You've opened the pull request against the latest branch 2.1.x. PHPStan 2.1 is not going to be released for months. If your code is relevant on 2.0.x and you want it to be released sooner, please rebase your pull request and change its target to 2.0.x." + body: "You've opened the pull request against the latest branch 2.2.x. PHPStan 2.2 is not going to be released for months. If your code is relevant on 2.1.x and you want it to be released sooner, please rebase your pull request and change its target to 2.1.x." token: ${{ secrets.PHPSTAN_BOT_TOKEN }} issue-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/update-phpstorm-stubs.yml b/.github/workflows/update-phpstorm-stubs.yml index 320b4eba1b..396be1c0be 100644 --- a/.github/workflows/update-phpstorm-stubs.yml +++ b/.github/workflows/update-phpstorm-stubs.yml @@ -16,7 +16,7 @@ jobs: - name: "Checkout" uses: actions/checkout@v4 with: - ref: 2.0.x + ref: 2.1.x fetch-depth: '0' token: ${{ secrets.PHPSTAN_BOT_TOKEN }} - name: "Install PHP" From da80fc77d0f4190c0d6773ce6c93c844486f87ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=BD=C3=A1=C4=8Dek?= Date: Sat, 9 Nov 2024 19:03:17 +0100 Subject: [PATCH 508/508] Introduce isDeprecated to CallableParametersAcceptor --- src/Analyser/MutatingScope.php | 3 +++ .../Callables/CallableParametersAcceptor.php | 2 ++ .../Callables/FunctionCallableVariant.php | 5 +++++ .../ExtendedCallableFunctionVariant.php | 6 ++++++ .../GenericParametersAcceptorResolver.php | 1 + src/Reflection/InaccessibleMethod.php | 5 +++++ src/Reflection/ParametersAcceptorSelector.php | 4 ++++ .../ResolvedFunctionVariantWithCallable.php | 6 ++++++ src/Reflection/TrivialParametersAcceptor.php | 5 +++++ src/Rules/RuleLevelHelper.php | 2 ++ src/Type/CallableType.php | 15 +++++++++++++++ src/Type/ClosureType.php | 12 ++++++++++++ src/Type/ClosureTypeFactory.php | 17 ++++++++++++++++- ...reFromCallableDynamicReturnTypeExtension.php | 1 + 14 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index f883c95578..e6e9dc15ab 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -1342,6 +1342,7 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu $cachedClosureData['invalidateExpressions'], $cachedClosureData['usedVariables'], TrinaryLogic::createYes(), + TrinaryLogic::createNo(), ); } if (self::$resolveClosureTypeDepth >= 2) { @@ -1557,6 +1558,7 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu $invalidateExpressions, $usedVariables, TrinaryLogic::createYes(), + TrinaryLogic::createNo(), ); } elseif ($node instanceof New_) { if ($node->class instanceof Name) { @@ -2552,6 +2554,7 @@ private function createFirstClassCallable( [], [], $acceptsNamedArguments, + $variant->isDeprecated(), ); } diff --git a/src/Reflection/Callables/CallableParametersAcceptor.php b/src/Reflection/Callables/CallableParametersAcceptor.php index 25ff7d770c..d5042193e3 100644 --- a/src/Reflection/Callables/CallableParametersAcceptor.php +++ b/src/Reflection/Callables/CallableParametersAcceptor.php @@ -19,6 +19,8 @@ public function getThrowPoints(): array; public function isPure(): TrinaryLogic; + public function isDeprecated(): TrinaryLogic; + public function acceptsNamedArguments(): TrinaryLogic; /** diff --git a/src/Reflection/Callables/FunctionCallableVariant.php b/src/Reflection/Callables/FunctionCallableVariant.php index 71ea905c52..28d8d17771 100644 --- a/src/Reflection/Callables/FunctionCallableVariant.php +++ b/src/Reflection/Callables/FunctionCallableVariant.php @@ -135,6 +135,11 @@ public function isPure(): TrinaryLogic return $certainCount > 0 ? TrinaryLogic::createNo() : TrinaryLogic::createMaybe(); } + public function isDeprecated(): TrinaryLogic + { + return $this->function->isDeprecated(); + } + public function getImpurePoints(): array { if ($this->impurePoints !== null) { diff --git a/src/Reflection/ExtendedCallableFunctionVariant.php b/src/Reflection/ExtendedCallableFunctionVariant.php index 5e2d3a9c10..8239ec81b9 100644 --- a/src/Reflection/ExtendedCallableFunctionVariant.php +++ b/src/Reflection/ExtendedCallableFunctionVariant.php @@ -32,6 +32,7 @@ public function __construct( ?TemplateTypeVarianceMap $callSiteVarianceMap, private array $throwPoints, private TrinaryLogic $isPure, + private TrinaryLogic $isDeprecated, private array $impurePoints, private array $invalidateExpressions, private array $usedVariables, @@ -60,6 +61,11 @@ public function isPure(): TrinaryLogic return $this->isPure; } + public function isDeprecated(): TrinaryLogic + { + return $this->isDeprecated; + } + public function getImpurePoints(): array { return $this->impurePoints; diff --git a/src/Reflection/GenericParametersAcceptorResolver.php b/src/Reflection/GenericParametersAcceptorResolver.php index e680908c32..47b1c75524 100644 --- a/src/Reflection/GenericParametersAcceptorResolver.php +++ b/src/Reflection/GenericParametersAcceptorResolver.php @@ -123,6 +123,7 @@ public static function resolve(array $argTypes, ParametersAcceptor $parametersAc $result, $originalParametersAcceptor->getThrowPoints(), $originalParametersAcceptor->isPure(), + $originalParametersAcceptor->isDeprecated(), $originalParametersAcceptor->getImpurePoints(), $originalParametersAcceptor->getInvalidateExpressions(), $originalParametersAcceptor->getUsedVariables(), diff --git a/src/Reflection/InaccessibleMethod.php b/src/Reflection/InaccessibleMethod.php index 037f4e8137..063433c924 100644 --- a/src/Reflection/InaccessibleMethod.php +++ b/src/Reflection/InaccessibleMethod.php @@ -62,6 +62,11 @@ public function isPure(): TrinaryLogic return TrinaryLogic::createMaybe(); } + public function isDeprecated(): TrinaryLogic + { + return $this->methodReflection->isDeprecated(); + } + public function getImpurePoints(): array { return [ diff --git a/src/Reflection/ParametersAcceptorSelector.php b/src/Reflection/ParametersAcceptorSelector.php index 703d345806..d51c00f86c 100644 --- a/src/Reflection/ParametersAcceptorSelector.php +++ b/src/Reflection/ParametersAcceptorSelector.php @@ -611,6 +611,7 @@ public static function combineAcceptors(array $acceptors): ExtendedParametersAcc $callableOccurred = false; $throwPoints = []; $isPure = TrinaryLogic::createNo(); + $isDeprecated = TrinaryLogic::createNo(); $impurePoints = []; $invalidateExpressions = []; $usedVariables = []; @@ -627,6 +628,7 @@ public static function combineAcceptors(array $acceptors): ExtendedParametersAcc $callableOccurred = true; $throwPoints = array_merge($throwPoints, $acceptor->getThrowPoints()); $isPure = $isPure->or($acceptor->isPure()); + $isDeprecated = $isDeprecated->or($acceptor->isDeprecated()); $impurePoints = array_merge($impurePoints, $acceptor->getImpurePoints()); $invalidateExpressions = array_merge($invalidateExpressions, $acceptor->getInvalidateExpressions()); $usedVariables = array_merge($usedVariables, $acceptor->getUsedVariables()); @@ -729,6 +731,7 @@ public static function combineAcceptors(array $acceptors): ExtendedParametersAcc null, $throwPoints, $isPure, + $isDeprecated, $impurePoints, $invalidateExpressions, $usedVariables, @@ -765,6 +768,7 @@ private static function wrapAcceptor(ParametersAcceptor $acceptor): ExtendedPara TemplateTypeVarianceMap::createEmpty(), $acceptor->getThrowPoints(), $acceptor->isPure(), + $acceptor->isDeprecated(), $acceptor->getImpurePoints(), $acceptor->getInvalidateExpressions(), $acceptor->getUsedVariables(), diff --git a/src/Reflection/ResolvedFunctionVariantWithCallable.php b/src/Reflection/ResolvedFunctionVariantWithCallable.php index 7dbd382405..68d9d87414 100644 --- a/src/Reflection/ResolvedFunctionVariantWithCallable.php +++ b/src/Reflection/ResolvedFunctionVariantWithCallable.php @@ -24,6 +24,7 @@ public function __construct( private ResolvedFunctionVariant $parametersAcceptor, private array $throwPoints, private TrinaryLogic $isPure, + private TrinaryLogic $isDeprecated, private array $impurePoints, private array $invalidateExpressions, private array $usedVariables, @@ -97,6 +98,11 @@ public function isPure(): TrinaryLogic return $this->isPure; } + public function isDeprecated(): TrinaryLogic + { + return $this->isDeprecated; + } + public function getImpurePoints(): array { return $this->impurePoints; diff --git a/src/Reflection/TrivialParametersAcceptor.php b/src/Reflection/TrivialParametersAcceptor.php index ea6b278145..8c7e3e9a6a 100644 --- a/src/Reflection/TrivialParametersAcceptor.php +++ b/src/Reflection/TrivialParametersAcceptor.php @@ -72,6 +72,11 @@ public function isPure(): TrinaryLogic return TrinaryLogic::createMaybe(); } + public function isDeprecated(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + public function getImpurePoints(): array { return [ diff --git a/src/Rules/RuleLevelHelper.php b/src/Rules/RuleLevelHelper.php index 416583546f..9ad1805c77 100644 --- a/src/Rules/RuleLevelHelper.php +++ b/src/Rules/RuleLevelHelper.php @@ -91,6 +91,7 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType): $acceptedType->getResolvedTemplateTypeMap(), $acceptedType->getTemplateTags(), $acceptedType->isPure(), + $acceptedType->isDeprecated(), ); } @@ -112,6 +113,7 @@ private function transformAcceptedType(Type $acceptingType, Type $acceptedType): $acceptedType->getInvalidateExpressions(), $acceptedType->getUsedVariables(), $acceptedType->acceptsNamedArguments(), + $acceptedType->isDeprecated(), ); } diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index fe6e412ad2..9ea353c5d6 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -65,6 +65,8 @@ class CallableType implements CompoundType, CallableParametersAcceptor private TrinaryLogic $isPure; + private TrinaryLogic $isDeprecated; + /** * @api * @param list|null $parameters @@ -78,6 +80,7 @@ public function __construct( ?TemplateTypeMap $resolvedTemplateTypeMap = null, private array $templateTags = [], ?TrinaryLogic $isPure = null, + ?TrinaryLogic $isDeprecated = null, ) { $this->parameters = $parameters ?? []; @@ -86,6 +89,7 @@ public function __construct( $this->templateTypeMap = $templateTypeMap ?? TemplateTypeMap::createEmpty(); $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap ?? TemplateTypeMap::createEmpty(); $this->isPure = $isPure ?? TrinaryLogic::createMaybe(); + $this->isDeprecated = $isDeprecated ?? TrinaryLogic::createNo(); } /** @@ -101,6 +105,14 @@ public function isPure(): TrinaryLogic return $this->isPure; } + public function isDeprecated(): TrinaryLogic + { + return $this->isDeprecated; + } + + /** + * @return list + */ public function getReferencedClasses(): array { $classes = []; @@ -231,6 +243,7 @@ function (): string { $this->resolvedTemplateTypeMap, $this->templateTags, $this->isPure, + $this->isDeprecated, ); return $printer->print($selfWithoutParameterNames->toPhpDocNode()); @@ -445,6 +458,7 @@ public function traverse(callable $cb): Type $this->resolvedTemplateTypeMap, $this->templateTags, $this->isPure, + $this->isDeprecated, ); } @@ -495,6 +509,7 @@ public function traverseSimultaneously(Type $right, callable $cb): Type $this->resolvedTemplateTypeMap, $this->templateTags, $this->isPure, + $this->isDeprecated, ); } diff --git a/src/Type/ClosureType.php b/src/Type/ClosureType.php index a76aa90596..03caa373d5 100644 --- a/src/Type/ClosureType.php +++ b/src/Type/ClosureType.php @@ -79,6 +79,8 @@ class ClosureType implements TypeWithClassName, CallableParametersAcceptor private TrinaryLogic $acceptsNamedArguments; + private TrinaryLogic $isDeprecated; + /** * @api * @param list|null $parameters @@ -101,6 +103,7 @@ public function __construct( private array $invalidateExpressions = [], private array $usedVariables = [], ?TrinaryLogic $acceptsNamedArguments = null, + ?TrinaryLogic $isDeprecated = null, ) { if ($acceptsNamedArguments === null) { @@ -116,6 +119,7 @@ public function __construct( $this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap ?? TemplateTypeMap::createEmpty(); $this->callSiteVarianceMap = $callSiteVarianceMap ?? TemplateTypeVarianceMap::createEmpty(); $this->impurePoints = $impurePoints ?? [new SimpleImpurePoint('functionCall', 'call to an unknown Closure', false)]; + $this->isDeprecated = $isDeprecated ?? TrinaryLogic::createNo(); } /** @@ -150,6 +154,11 @@ public function isPure(): TrinaryLogic return $certainCount > 0 ? TrinaryLogic::createNo() : TrinaryLogic::createMaybe(); } + public function isDeprecated(): TrinaryLogic + { + return $this->isDeprecated; + } + public function getClassName(): string { return $this->objectType->getClassName(); @@ -262,6 +271,7 @@ function (): string { $this->impurePoints, $this->invalidateExpressions, $this->usedVariables, + $this->isDeprecated, ); return $printer->print($selfWithoutParameterNames->toPhpDocNode()); @@ -584,6 +594,7 @@ public function traverse(callable $cb): Type $this->invalidateExpressions, $this->usedVariables, $this->acceptsNamedArguments, + $this->isDeprecated, ); } @@ -634,6 +645,7 @@ public function traverseSimultaneously(Type $right, callable $cb): Type $this->invalidateExpressions, $this->usedVariables, $this->acceptsNamedArguments, + $this->isDeprecated, ); } diff --git a/src/Type/ClosureTypeFactory.php b/src/Type/ClosureTypeFactory.php index fb36d04c44..b5c7983288 100644 --- a/src/Type/ClosureTypeFactory.php +++ b/src/Type/ClosureTypeFactory.php @@ -18,6 +18,7 @@ use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\PassedByReference; use PHPStan\ShouldNotHappenException; +use PHPStan\TrinaryLogic; use ReflectionFunction; use function array_map; use function count; @@ -113,7 +114,21 @@ public function getDefaultValue(): ?Type }, $betterReflectionFunction->getParameters()); - return new ClosureType($parameters, TypehintHelper::decideTypeFromReflection(ReflectionType::fromTypeOrNull($betterReflectionFunction->getReturnType())), $betterReflectionFunction->isVariadic()); + return new ClosureType( + $parameters, + TypehintHelper::decideTypeFromReflection(ReflectionType::fromTypeOrNull($betterReflectionFunction->getReturnType())), + $betterReflectionFunction->isVariadic(), + null, + null, + null, + [], + [], + null, + [], + [], + null, + TrinaryLogic::createFromBoolean($betterReflectionFunction->isDeprecated()), + ); } } diff --git a/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php b/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php index d579157160..f8421d109e 100644 --- a/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php +++ b/src/Type/Php/ClosureFromCallableDynamicReturnTypeExtension.php @@ -54,6 +54,7 @@ public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, $variant->getInvalidateExpressions(), $variant->getUsedVariables(), $variant->acceptsNamedArguments(), + $variant->isDeprecated(), ); }