diff --git a/.composer-require-checker.json b/.composer-require-checker.json index 183841e09f9..2f2afcdcd4d 100644 --- a/.composer-require-checker.json +++ b/.composer-require-checker.json @@ -14,7 +14,9 @@ "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", - "T_NULLSAFE_OBJECT_OPERATOR" + "T_NULLSAFE_OBJECT_OPERATOR", + "T_READONLY", + "T_ENUM" ], "php-core-extensions" : [ "dom", "mbstring", "Phar", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88e7955db15..64b674e20d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,16 +17,11 @@ jobs: - operating-system: 'ubuntu-20.04' php-version: '7.2' - job-description: 'with Sf ^3' - execute-flex-with-symfony-version: '^3' # Explicit check for Sf 3.x compatibility - - - operating-system: 'ubuntu-20.04' - php-version: '7.3' job-description: 'with Sf ^4' execute-flex-with-symfony-version: '^4' # Explicit check for Sf 4.x compatibility - operating-system: 'ubuntu-20.04' - php-version: '7.4' + php-version: '7.3' job-description: 'with Sf ^5' execute-flex-with-symfony-version: '^5' # Explicit check for Sf 5.x compatibility @@ -109,9 +104,9 @@ jobs: composer update --optimize-autoloader --no-interaction --no-progress ${{ matrix.composer-flags }} composer info -D - - name: Execute migration rules + - name: Execute migration rules # we want to execute migration rules BEFORE we gonna run tests and self-fixing, so we know that our codebase is future-ready if: matrix.execute-migration-rules == 'yes' - run: php php-cs-fixer fix --rules @PHP80Migration,@PHP80Migration:risky -q + run: php php-cs-fixer fix --config .php-cs-fixer.php-highest.php -q - name: Disable time limit for tests when collecting coverage if: matrix.calculate-code-coverage == 'yes' @@ -129,9 +124,9 @@ jobs: COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: php vendor/bin/php-coveralls --verbose - - name: Run PHP CS Fixer for PHP 7.0 types - if: matrix.php-version == '7.1' # we run on lowest supported version, we running it on higher would falsy expect more changes, eg `mixed` type on PHP 8 - run: php php-cs-fixer fix --diff --dry-run -v --config .php-cs-fixer.php70types.php + - name: Run PHP CS Fixer for PHP 7.1 types + if: matrix.php-version == '7.1' # we run on lowest supported version, running it on higher would falsy expect more changes, eg `mixed` type on PHP 8 + run: php php-cs-fixer fix --diff --dry-run -v --config .php-cs-fixer.php-lowest.php - name: Run PHP CS Fixer env: diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 6c4889c902e..998e341702e 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -36,12 +36,14 @@ $config ->setRiskyAllowed(true) ->setRules([ + '@PHP71Migration' => true, '@PHP71Migration:risky' => true, '@PHPUnit75Migration:risky' => true, '@PhpCsFixer' => true, '@PhpCsFixer:risky' => true, 'general_phpdoc_annotation_remove' => ['annotations' => ['expectedDeprecation']], // one should use PHPUnit built-in method instead 'header_comment' => ['header' => $header], + 'modernize_strpos' => true, // needs PHP 8+ or polyfill ]) ->setFinder($finder) ; diff --git a/.php-cs-fixer.php-highest.php b/.php-cs-fixer.php-highest.php new file mode 100644 index 00000000000..b3971965f39 --- /dev/null +++ b/.php-cs-fixer.php-highest.php @@ -0,0 +1,27 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +if (PHP_VERSION_ID <= 80001 || PHP_VERSION_ID >= 80100) { + fwrite(STDERR, "PHP CS Fixer's config for PHP-HIGHEST can be executed only on highest supported PHP version - 8.0.*.\n"); + fwrite(STDERR, "Running it on lower PHP version would prevent calling migration rules.\n"); + exit(1); +} + +$config = require '.php-cs-fixer.dist.php'; + +$config->setRules(array_merge($config->getRules(), [ + '@PHP80Migration' => true, + '@PHP80Migration:risky' => true, + 'heredoc_indentation' => false, +])); + +return $config; diff --git a/.php-cs-fixer.php70types.php b/.php-cs-fixer.php-lowest.php similarity index 70% rename from .php-cs-fixer.php70types.php rename to .php-cs-fixer.php-lowest.php index f8e0a0115f6..3d914f59083 100644 --- a/.php-cs-fixer.php70types.php +++ b/.php-cs-fixer.php-lowest.php @@ -10,6 +10,12 @@ * with this source code in the file LICENSE. */ +if (PHP_VERSION_ID <= 70103 || PHP_VERSION_ID >= 70200) { + fwrite(STDERR, "PHP CS Fixer's config for PHP-LOWEST can be executed only on lowest supported PHP version - 7.1.*.\n"); + fwrite(STDERR, "Running it on higher PHP version would falsy expect more changes, eg `mixed` type on PHP 8.\n"); + exit(1); +} + $config = require '.php-cs-fixer.dist.php'; $config->getFinder()->notPath([ diff --git a/CHANGELOG.md b/CHANGELOG.md index 711540d3dcc..e6222b2dab2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,48 @@ CHANGELOG for PHP CS Fixer This file contains changelogs for stable releases only. +Changelog for v3.1.0 +-------------------- + +* feature #5572 PhpdocToCommentFixer - Add `ignored_tags` option (VincentLanglet) +* feature #5588 NoAliasFunctionsFixer - Add more function aliases (danog) +* feature #5704 ClassAttributesSeparationFixer - Introduce `only_if_meta` spacing option (paulbalandan) +* feature #5734 TypesSpacesFixer - Introduction (kubawerlos) +* feature #5745 EmptyLoopBodyFixer - introduction (SpacePossum, keradus) +* feature #5751 Extract DeclareParenthesesFixer from BracesFixer (julienfalque, keradus) +* feature #5877 ClassDefinitionFixer - PSR12 for anonymous class (SpacePossum) +* minor #5875 EmptyLoopBodyFixer - NoTrailingWhitespaceFixer - priority test (SpacePossum) +* minor #5914 Deprecate ClassKeywordRemoveFixer (kubawerlos) + +Changelog for v3.0.3 +-------------------- + +* bug #4927 PhpdocAlignFixer - fix for whitespace in type (kubawerlos) +* bug #5720 NoUnusedImportsFixer - Fix undetected unused imports when type mismatch (julienfalque, SpacePossum) +* bug #5806 DoctrineAnnotationFixer - Add template to ignored_tags (akalineskou) +* bug #5849 PhpdocTagTypeFixer - must not remove inlined tags within other tags (boesing) +* bug #5853 BracesFixer - handle alternative short foreach with if (SpacePossum) +* bug #5855 GlobalNamespaceImportFixer - fix for attributes imported as constants (kubawerlos) +* bug #5881 SelfUpdateCommand - fix link to UPGRADE docs (keradus) +* bug #5884 CurlyBraceTransformer - fix handling dynamic property with string with variable (kubawerlos, keradus) +* bug #5912 TypeAlternationTransformer - fix for "callable" type (kubawerlos) +* bug #5913 SingleSpaceAfterConstructFixer - improve comma handling (keradus) +* minor #5829 DX: Fix SCA with PHPMD (paulbalandan) +* minor #5838 PHP7 - use spaceship (SpacePossum, keradus) +* minor #5848 Docs: update PhpStorm integration link (keradus) +* minor #5856 Add AttributeAnalyzer (kubawerlos) +* minor #5857 DX: PHPMD - exclude fixtures (keradus) +* minor #5859 Various fixes (kubawerlos) +* minor #5864 DX: update dev tools (kubawerlos) +* minor #5876 AttributeTransformerTest - add more tests (SpacePossum) +* minor #5879 Update UPGRADE-v3.md adding relative links (shakaran, keradus) +* minor #5882 Docs: don't use v2 for installation example (keradus) +* minor #5883 Docs: typo (brianteeman, keradus) +* minor #5890 DX: use PHP 8.1 polyfill (keradus) +* minor #5902 Remove references to PHP 7.0 in tests (only removing lines) (kubawerlos) +* minor #5905 DX: Use "yield from" in tests (kubawerlos, keradus) +* minor #5917 Use `@PHP71Migration` rules (kubawerlos, keradus) + Changelog for v3.0.2 -------------------- diff --git a/UPGRADE-v3.md b/UPGRADE-v3.md index 6ff787919b2..dd27c882d0e 100644 --- a/UPGRADE-v3.md +++ b/UPGRADE-v3.md @@ -157,8 +157,8 @@ Code BC changes - class `Token` is now `final` - class `Tokens` is now `final` -- method `create` of class `Config` has been removed, use the constructor -- method `create` of class `RuleSet` has been removed, use the constructor +- method `create` of class `Config` has been removed, [use the constructor](./doc/config.rst) +- method `create` of class `RuleSet` has been removed, [use the constructor](./doc/custom_rules.rst) ### BC breaks; common internal classes diff --git a/composer.json b/composer.json index 2f8600d42da..f83e227f1b6 100644 --- a/composer.json +++ b/composer.json @@ -26,13 +26,15 @@ "symfony/filesystem": "^4.4.20 || ^5.0", "symfony/finder": "^4.4.20 || ^5.0", "symfony/options-resolver": "^4.4.20 || ^5.0", - "symfony/polyfill-php72": "^1.22", + "symfony/polyfill-php72": "^1.23", + "symfony/polyfill-php80": "^1.23", + "symfony/polyfill-php81": "^1.23", "symfony/process": "^4.4.20 || ^5.0", "symfony/stopwatch": "^4.4.20 || ^5.0" }, "require-dev": { "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^1.4", + "keradus/cli-executor": "^1.5", "mikey179/vfsstream": "^1.6.8", "php-coveralls/php-coveralls": "^2.4.3", "php-cs-fixer/accessible-object": "^1.1", diff --git a/dev-tools/.gitignore b/dev-tools/.gitignore index 46fd5bdc227..dce02ead080 100644 --- a/dev-tools/.gitignore +++ b/dev-tools/.gitignore @@ -1,3 +1,4 @@ /composer.lock /bin/ +/phpstan/cache/ /vendor/ diff --git a/dev-tools/composer.json b/dev-tools/composer.json index 7c4695137a2..5b5e584bbce 100644 --- a/dev-tools/composer.json +++ b/dev-tools/composer.json @@ -9,7 +9,7 @@ "maglnet/composer-require-checker": "2.0.0", "mi-schi/phpmd-extension": "^4.3", "phpmd/phpmd": "^2.10.2", - "phpstan/phpstan": "0.12.92", + "phpstan/phpstan": "0.12.96", "phpstan/phpstan-phpunit": "0.12.21" }, "config": { diff --git a/doc/ruleSets/PHP80MigrationRisky.rst b/doc/ruleSets/PHP80MigrationRisky.rst index 6942647a890..d5b9f874b87 100644 --- a/doc/ruleSets/PHP80MigrationRisky.rst +++ b/doc/ruleSets/PHP80MigrationRisky.rst @@ -8,6 +8,7 @@ Rules ----- - `@PHP74Migration:risky <./PHP74MigrationRisky.rst>`_ +- `modernize_strpos <./../rules/alias/modernize_strpos.rst>`_ - `no_alias_functions <./../rules/alias/no_alias_functions.rst>`_ config: ``['sets' => ['@all']]`` diff --git a/doc/ruleSets/PHP81Migration.rst b/doc/ruleSets/PHP81Migration.rst new file mode 100644 index 00000000000..8b2b592cb72 --- /dev/null +++ b/doc/ruleSets/PHP81Migration.rst @@ -0,0 +1,11 @@ +============================ +Rule set ``@PHP81Migration`` +============================ + +Rules to improve code for PHP 8.1 compatibility. + +Rules +----- + +- `@PHP80Migration <./PHP80Migration.rst>`_ +- `octal_notation <./../rules/basic/octal_notation.rst>`_ diff --git a/doc/ruleSets/PSR12.rst b/doc/ruleSets/PSR12.rst index ce4856bad54..2595a1b0299 100644 --- a/doc/ruleSets/PSR12.rst +++ b/doc/ruleSets/PSR12.rst @@ -12,6 +12,9 @@ Rules - `braces <./../rules/basic/braces.rst>`_ config: ``['allow_single_line_anonymous_class_with_empty_body' => true]`` +- `class_definition <./../rules/class_notation/class_definition.rst>`_ + config: + ``['space_before_parenthesis' => true]`` - `compact_nullable_typehint <./../rules/whitespace/compact_nullable_typehint.rst>`_ - `declare_equal_normalize <./../rules/language_construct/declare_equal_normalize.rst>`_ - `lowercase_cast <./../rules/cast_notation/lowercase_cast.rst>`_ diff --git a/doc/ruleSets/PhpCsFixer.rst b/doc/ruleSets/PhpCsFixer.rst index 3edd8678de3..6b35c813b91 100644 --- a/doc/ruleSets/PhpCsFixer.rst +++ b/doc/ruleSets/PhpCsFixer.rst @@ -30,7 +30,7 @@ Rules ``['strategy' => 'new_line_for_chained_calls']`` - `no_extra_blank_lines <./../rules/whitespace/no_extra_blank_lines.rst>`_ config: - ``['tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']]`` + ``['tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use']]`` - `no_null_property_initialization <./../rules/class_notation/no_null_property_initialization.rst>`_ - `no_superfluous_elseif <./../rules/control_structure/no_superfluous_elseif.rst>`_ - `no_useless_else <./../rules/control_structure/no_useless_else.rst>`_ diff --git a/doc/ruleSets/Symfony.rst b/doc/ruleSets/Symfony.rst index ee27a504204..69c504cbef4 100644 --- a/doc/ruleSets/Symfony.rst +++ b/doc/ruleSets/Symfony.rst @@ -27,6 +27,10 @@ Rules - `clean_namespace <./../rules/namespace_notation/clean_namespace.rst>`_ - `concat_space <./../rules/operator/concat_space.rst>`_ - `echo_tag_syntax <./../rules/php_tag/echo_tag_syntax.rst>`_ +- `empty_loop_body <./../rules/control_structure/empty_loop_body.rst>`_ + config: + ``['style' => 'braces']`` +- `empty_loop_condition <./../rules/control_structure/empty_loop_condition.rst>`_ - `fully_qualified_strict_types <./../rules/import/fully_qualified_strict_types.rst>`_ - `function_typehint_space <./../rules/function_notation/function_typehint_space.rst>`_ - `general_phpdoc_tag_rename <./../rules/phpdoc/general_phpdoc_tag_rename.rst>`_ @@ -34,6 +38,7 @@ Rules ``['replacements' => ['inheritDocs' => 'inheritDoc']]`` - `include <./../rules/control_structure/include.rst>`_ - `increment_style <./../rules/operator/increment_style.rst>`_ +- `integer_literal_case <./../rules/casing/integer_literal_case.rst>`_ - `lambda_not_used_import <./../rules/function_notation/lambda_not_used_import.rst>`_ - `linebreak_after_opening_tag <./../rules/php_tag/linebreak_after_opening_tag.rst>`_ - `magic_constant_casing <./../rules/casing/magic_constant_casing.rst>`_ @@ -52,7 +57,7 @@ Rules - `no_empty_statement <./../rules/semicolon/no_empty_statement.rst>`_ - `no_extra_blank_lines <./../rules/whitespace/no_extra_blank_lines.rst>`_ config: - ``['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']]`` + ``['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use']]`` - `no_leading_namespace_whitespace <./../rules/namespace_notation/no_leading_namespace_whitespace.rst>`_ - `no_mixed_echo_print <./../rules/alias/no_mixed_echo_print.rst>`_ - `no_multiline_whitespace_around_double_arrow <./../rules/array_notation/no_multiline_whitespace_around_double_arrow.rst>`_ @@ -119,6 +124,7 @@ Rules - `switch_continue_to_break <./../rules/control_structure/switch_continue_to_break.rst>`_ - `trailing_comma_in_multiline <./../rules/control_structure/trailing_comma_in_multiline.rst>`_ - `trim_array_spaces <./../rules/array_notation/trim_array_spaces.rst>`_ +- `types_spaces <./../rules/whitespace/types_spaces.rst>`_ - `unary_operator_spaces <./../rules/operator/unary_operator_spaces.rst>`_ - `whitespace_after_comma_in_array <./../rules/array_notation/whitespace_after_comma_in_array.rst>`_ - `yoda_style <./../rules/control_structure/yoda_style.rst>`_ diff --git a/doc/ruleSets/index.rst b/doc/ruleSets/index.rst index c0a9d0c0845..6f6b8e0857b 100644 --- a/doc/ruleSets/index.rst +++ b/doc/ruleSets/index.rst @@ -13,6 +13,7 @@ List of Available Rule sets - `@PHP74Migration:risky <./PHP74MigrationRisky.rst>`_ - `@PHP80Migration <./PHP80Migration.rst>`_ - `@PHP80Migration:risky <./PHP80MigrationRisky.rst>`_ +- `@PHP81Migration <./PHP81Migration.rst>`_ - `@PHPUnit30Migration:risky <./PHPUnit30MigrationRisky.rst>`_ - `@PHPUnit32Migration:risky <./PHPUnit32MigrationRisky.rst>`_ - `@PHPUnit35Migration:risky <./PHPUnit35MigrationRisky.rst>`_ diff --git a/doc/rules/alias/modernize_strpos.rst b/doc/rules/alias/modernize_strpos.rst new file mode 100644 index 00000000000..51f270a3d7f --- /dev/null +++ b/doc/rules/alias/modernize_strpos.rst @@ -0,0 +1,39 @@ +========================= +Rule ``modernize_strpos`` +========================= + +Replace ``strpos()`` calls with ``str_starts_with()`` or ``str_contains()`` if +possible. + +.. warning:: Using this rule is risky. + + Risky if ``strpos``, ``str_starts_with`` or ``str_contains`` functions are + overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + `_ rule set will enable the ``modernize_strpos`` rule. diff --git a/doc/rules/array_notation/array_syntax.rst b/doc/rules/array_notation/array_syntax.rst index d0f00c65f08..6f27f8a50b9 100644 --- a/doc/rules/array_notation/array_syntax.rst +++ b/doc/rules/array_notation/array_syntax.rst @@ -68,6 +68,9 @@ The rule is part of the following rule sets: @PHP80Migration Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the default config. +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the default config. + @PhpCsFixer Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``array_syntax`` rule with the default config. diff --git a/doc/rules/array_notation/no_whitespace_before_comma_in_array.rst b/doc/rules/array_notation/no_whitespace_before_comma_in_array.rst index cac0987947d..15d55610664 100644 --- a/doc/rules/array_notation/no_whitespace_before_comma_in_array.rst +++ b/doc/rules/array_notation/no_whitespace_before_comma_in_array.rst @@ -68,6 +68,11 @@ The rule is part of the following rule sets: ``['after_heredoc' => true]`` +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``no_whitespace_before_comma_in_array`` rule with the config below: + + ``['after_heredoc' => true]`` + @PhpCsFixer Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_whitespace_before_comma_in_array`` rule with the default config. diff --git a/doc/rules/array_notation/normalize_index_brace.rst b/doc/rules/array_notation/normalize_index_brace.rst index 6886082e9b2..53a741b3269 100644 --- a/doc/rules/array_notation/normalize_index_brace.rst +++ b/doc/rules/array_notation/normalize_index_brace.rst @@ -29,6 +29,9 @@ The rule is part of the following rule sets: @PHP80Migration Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``normalize_index_brace`` rule. +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``normalize_index_brace`` rule. + @PhpCsFixer Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``normalize_index_brace`` rule. diff --git a/doc/rules/basic/octal_notation.rst b/doc/rules/basic/octal_notation.rst new file mode 100644 index 00000000000..5b2d1f6e747 --- /dev/null +++ b/doc/rules/basic/octal_notation.rst @@ -0,0 +1,26 @@ +======================= +Rule ``octal_notation`` +======================= + +Literal octal must be in ``0o`` notation. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -`_ rule set will enable the ``octal_notation`` rule. diff --git a/doc/rules/casing/integer_literal_case.rst b/doc/rules/casing/integer_literal_case.rst new file mode 100644 index 00000000000..bf9a21c9b5c --- /dev/null +++ b/doc/rules/casing/integer_literal_case.rst @@ -0,0 +1,32 @@ +============================= +Rule ``integer_literal_case`` +============================= + +Integer literals must be in correct case. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + `_ rule set will enable the ``integer_literal_case`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``integer_literal_case`` rule. diff --git a/doc/rules/cast_notation/no_unset_cast.rst b/doc/rules/cast_notation/no_unset_cast.rst index f972fb8e451..3ae4f9bd7a7 100644 --- a/doc/rules/cast_notation/no_unset_cast.rst +++ b/doc/rules/cast_notation/no_unset_cast.rst @@ -26,6 +26,9 @@ The rule is part of the following rule sets: @PHP80Migration Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``no_unset_cast`` rule. +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``no_unset_cast`` rule. + @PhpCsFixer Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_unset_cast`` rule. diff --git a/doc/rules/cast_notation/short_scalar_cast.rst b/doc/rules/cast_notation/short_scalar_cast.rst index e470fb356d8..47b4dc098e0 100644 --- a/doc/rules/cast_notation/short_scalar_cast.rst +++ b/doc/rules/cast_notation/short_scalar_cast.rst @@ -58,6 +58,9 @@ The rule is part of the following rule sets: @PHP80Migration Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``short_scalar_cast`` rule. +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``short_scalar_cast`` rule. + @PSR12 Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``short_scalar_cast`` rule. diff --git a/doc/rules/class_notation/class_attributes_separation.rst b/doc/rules/class_notation/class_attributes_separation.rst index 32ad8be710b..b6643c63a4f 100644 --- a/doc/rules/class_notation/class_attributes_separation.rst +++ b/doc/rules/class_notation/class_attributes_separation.rst @@ -16,7 +16,7 @@ Dictionary of ``const|method|property|trait_import`` => Allowed types: ``array`` -Default value: ``['const' => 'one', 'method' => 'one', 'property' => 'one', 'trait_import' => 'one']`` +Default value: ``['const' => 'one', 'method' => 'one', 'property' => 'one', 'trait_import' => 'none']`` Examples -------- @@ -55,9 +55,9 @@ With configuration: ``['elements' => ['property' => 'one']]``. +++ New ['property' => 'only_if_meta']]``. -.. code-block:: diff - - --- Original - +++ New - ['property' => 'only_if_meta']]``. - .. code-block:: diff --- Original diff --git a/doc/rules/class_notation/class_definition.rst b/doc/rules/class_notation/class_definition.rst index f9a50bdd67f..630cf6c1128 100644 --- a/doc/rules/class_notation/class_definition.rst +++ b/doc/rules/class_notation/class_definition.rst @@ -35,6 +35,16 @@ Allowed types: ``bool`` Default value: ``false`` +``space_before_parenthesis`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether there should be a single space after the parenthesis of anonymous class +(PSR12) or not. + +Allowed types: ``bool`` + +Default value: ``false`` + Examples -------- @@ -64,21 +74,10 @@ Example #1 { } -Example #2 -~~~~~~~~~~ - -*Default* configuration. - -.. code-block:: diff - - --- Original - +++ New - true]``. @@ -95,7 +94,7 @@ With configuration: ``['single_line' => true]``. +class Foo extends Bar implements Baz, BarBaz {} -Example #4 +Example #3 ~~~~~~~~~~ With configuration: ``['single_item_single_line' => true]``. @@ -112,7 +111,7 @@ With configuration: ``['single_item_single_line' => true]``. +class Foo extends Bar implements Baz {} -Example #5 +Example #4 ~~~~~~~~~~ With configuration: ``['multi_line_extends_each_single_line' => true]``. @@ -130,13 +129,28 @@ With configuration: ``['multi_line_extends_each_single_line' => true]``. + FooBarBaz {} +Example #5 +~~~~~~~~~~ + +With configuration: ``['space_before_parenthesis' => true]``. + +.. code-block:: diff + + --- Original + +++ New + `_ rule set will enable the ``class_definition`` rule with the default config. + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``class_definition`` rule with the config below: + + ``['space_before_parenthesis' => true]`` @PSR2 Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``class_definition`` rule with the default config. diff --git a/doc/rules/class_notation/visibility_required.rst b/doc/rules/class_notation/visibility_required.rst index 9f33855f0f6..cf01f40adeb 100644 --- a/doc/rules/class_notation/visibility_required.rst +++ b/doc/rules/class_notation/visibility_required.rst @@ -77,6 +77,9 @@ The rule is part of the following rule sets: @PHP80Migration Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``visibility_required`` rule with the default config. +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``visibility_required`` rule with the default config. + @PSR12 Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``visibility_required`` rule with the default config. diff --git a/doc/rules/control_structure/control_structure_continuation_position.rst b/doc/rules/control_structure/control_structure_continuation_position.rst new file mode 100644 index 00000000000..63b486b9861 --- /dev/null +++ b/doc/rules/control_structure/control_structure_continuation_position.rst @@ -0,0 +1,56 @@ +================================================ +Rule ``control_structure_continuation_position`` +================================================ + +Control structure continuation keyword must be on the configured line. + +Configuration +------------- + +``position`` +~~~~~~~~~~~~ + +the position of the keyword that continues the control structure. + +Allowed values: ``'next_line'``, ``'same_line'`` + +Default value: ``'same_line'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + 'next_line']``. + +.. code-block:: diff + + --- Original + +++ New + 'braces']``. Rule sets --------- -The rule is part of the following rule set: +The rule is part of the following rule sets: @PhpCsFixer Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``empty_loop_body`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``empty_loop_body`` rule with the config below: + + ``['style' => 'braces']`` diff --git a/doc/rules/control_structure/empty_loop_condition.rst b/doc/rules/control_structure/empty_loop_condition.rst new file mode 100644 index 00000000000..86bd5bf9d9b --- /dev/null +++ b/doc/rules/control_structure/empty_loop_condition.rst @@ -0,0 +1,67 @@ +============================= +Rule ``empty_loop_condition`` +============================= + +Empty loop-condition must be in configured style. + +Configuration +------------- + +``style`` +~~~~~~~~~ + +Style of empty loop-condition. + +Allowed values: ``'for'``, ``'while'`` + +Default value: ``'while'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + 'for']``. + +.. code-block:: diff + + --- Original + +++ New + `_ rule set will enable the ``empty_loop_condition`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``empty_loop_condition`` rule with the default config. diff --git a/doc/rules/control_structure/no_alternative_syntax.rst b/doc/rules/control_structure/no_alternative_syntax.rst index f91a6981fae..32a6f36f262 100644 --- a/doc/rules/control_structure/no_alternative_syntax.rst +++ b/doc/rules/control_structure/no_alternative_syntax.rst @@ -4,12 +4,26 @@ Rule ``no_alternative_syntax`` Replace control structure alternative syntax to use braces. +Configuration +------------- + +``fix_non_monolithic_code`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to also fix code with inline HTML. + +Allowed types: ``bool`` + +Default value: ``true`` + Examples -------- Example #1 ~~~~~~~~~~ +*Default* configuration. + .. code-block:: diff --- Original @@ -21,35 +35,17 @@ Example #1 Example #2 ~~~~~~~~~~ -.. code-block:: diff - - --- Original - +++ New - true]``. .. code-block:: diff --- Original +++ New - + + + Lorem ipsum. + - + + Rule sets --------- @@ -57,7 +53,7 @@ Rule sets The rule is part of the following rule sets: @PhpCsFixer - Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_alternative_syntax`` rule. + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_alternative_syntax`` rule with the default config. @Symfony - Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_alternative_syntax`` rule. + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_alternative_syntax`` rule with the default config. diff --git a/doc/rules/control_structure/no_unneeded_control_parentheses.rst b/doc/rules/control_structure/no_unneeded_control_parentheses.rst index e7c9a7e4117..e8cb6e32849 100644 --- a/doc/rules/control_structure/no_unneeded_control_parentheses.rst +++ b/doc/rules/control_structure/no_unneeded_control_parentheses.rst @@ -12,7 +12,7 @@ Configuration List of control statements to fix. -Allowed types: ``array`` +Allowed values: a subset of ``['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield', 'yield_from']`` Default value: ``['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield']`` diff --git a/doc/rules/control_structure/trailing_comma_in_multiline.rst b/doc/rules/control_structure/trailing_comma_in_multiline.rst index ca12d7d94e8..ece2a1ab42f 100644 --- a/doc/rules/control_structure/trailing_comma_in_multiline.rst +++ b/doc/rules/control_structure/trailing_comma_in_multiline.rst @@ -118,6 +118,11 @@ The rule is part of the following rule sets: ``['after_heredoc' => true]`` +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``trailing_comma_in_multiline`` rule with the config below: + + ``['after_heredoc' => true]`` + @PhpCsFixer Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``trailing_comma_in_multiline`` rule with the default config. diff --git a/doc/rules/doctrine_annotation/doctrine_annotation_array_assignment.rst b/doc/rules/doctrine_annotation/doctrine_annotation_array_assignment.rst index 999dc8bf03e..f5c9a580d8b 100644 --- a/doc/rules/doctrine_annotation/doctrine_annotation_array_assignment.rst +++ b/doc/rules/doctrine_annotation/doctrine_annotation_array_assignment.rst @@ -14,7 +14,7 @@ List of tags that must not be treated as Doctrine Annotations. Allowed types: ``array`` -Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'fix', 'FIXME', 'fixme', 'override']`` +Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'template', 'fix', 'FIXME', 'fixme', 'override']`` ``operator`` ~~~~~~~~~~~~ diff --git a/doc/rules/doctrine_annotation/doctrine_annotation_braces.rst b/doc/rules/doctrine_annotation/doctrine_annotation_braces.rst index 8852b7798cb..850925bdedd 100644 --- a/doc/rules/doctrine_annotation/doctrine_annotation_braces.rst +++ b/doc/rules/doctrine_annotation/doctrine_annotation_braces.rst @@ -14,7 +14,7 @@ List of tags that must not be treated as Doctrine Annotations. Allowed types: ``array`` -Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'fix', 'FIXME', 'fixme', 'override']`` +Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'template', 'fix', 'FIXME', 'fixme', 'override']`` ``syntax`` ~~~~~~~~~~ diff --git a/doc/rules/doctrine_annotation/doctrine_annotation_indentation.rst b/doc/rules/doctrine_annotation/doctrine_annotation_indentation.rst index 62f8d32bf70..708c30509ee 100644 --- a/doc/rules/doctrine_annotation/doctrine_annotation_indentation.rst +++ b/doc/rules/doctrine_annotation/doctrine_annotation_indentation.rst @@ -14,7 +14,7 @@ List of tags that must not be treated as Doctrine Annotations. Allowed types: ``array`` -Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'fix', 'FIXME', 'fixme', 'override']`` +Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'template', 'fix', 'FIXME', 'fixme', 'override']`` ``indent_mixed_lines`` ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/rules/doctrine_annotation/doctrine_annotation_spaces.rst b/doc/rules/doctrine_annotation/doctrine_annotation_spaces.rst index 9eb706e9dfd..4cbad2ebdbb 100644 --- a/doc/rules/doctrine_annotation/doctrine_annotation_spaces.rst +++ b/doc/rules/doctrine_annotation/doctrine_annotation_spaces.rst @@ -21,7 +21,7 @@ List of tags that must not be treated as Doctrine Annotations. Allowed types: ``array`` -Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'fix', 'FIXME', 'fixme', 'override']`` +Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'template', 'fix', 'FIXME', 'fixme', 'override']`` ``around_parentheses`` ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/rules/function_notation/method_argument_space.rst b/doc/rules/function_notation/method_argument_space.rst index e6ffc9a80c2..15c2bb9f5cd 100644 --- a/doc/rules/function_notation/method_argument_space.rst +++ b/doc/rules/function_notation/method_argument_space.rst @@ -224,6 +224,11 @@ The rule is part of the following rule sets: ``['after_heredoc' => true]`` +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``method_argument_space`` rule with the config below: + + ``['after_heredoc' => true]`` + @PSR12 Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``method_argument_space`` rule with the config below: diff --git a/doc/rules/function_notation/phpdoc_to_param_type.rst b/doc/rules/function_notation/phpdoc_to_param_type.rst index d5ebf26293c..a176e966d64 100644 --- a/doc/rules/function_notation/phpdoc_to_param_type.rst +++ b/doc/rules/function_notation/phpdoc_to_param_type.rst @@ -40,30 +40,17 @@ Example #1 +++ New false]``. .. code-block:: diff diff --git a/doc/rules/function_notation/phpdoc_to_return_type.rst b/doc/rules/function_notation/phpdoc_to_return_type.rst index 72885bdc93d..2ea166cb253 100644 --- a/doc/rules/function_notation/phpdoc_to_return_type.rst +++ b/doc/rules/function_notation/phpdoc_to_return_type.rst @@ -41,27 +41,16 @@ Example #1 false]``. @@ -94,7 +83,7 @@ With configuration: ``['scalar_types' => false]``. /** @return string */ function bar() {} -Example #5 +Example #4 ~~~~~~~~~~ *Default* configuration. diff --git a/doc/rules/import/ordered_imports.rst b/doc/rules/import/ordered_imports.rst index f3d49cb3221..20d91fe0b19 100644 --- a/doc/rules/import/ordered_imports.rst +++ b/doc/rules/import/ordered_imports.rst @@ -39,8 +39,11 @@ Example #1 --- Original +++ New 'length']``. Example #3 ~~~~~~~~~~ -*Default* configuration. - -.. code-block:: diff - - --- Original - +++ New - 'length', 'imports_order' => ['const', 'class', 'function']]``. .. code-block:: diff @@ -99,7 +86,7 @@ With configuration: ``['sort_algorithm' => 'length', 'imports_order' => ['const' use function CCC\AA; -use function DDD; -Example #5 +Example #4 ~~~~~~~~~~ With configuration: ``['sort_algorithm' => 'alpha', 'imports_order' => ['const', 'class', 'function']]``. @@ -122,7 +109,7 @@ With configuration: ``['sort_algorithm' => 'alpha', 'imports_order' => ['const', use function DDD; -use function CCC\AA; -Example #6 +Example #5 ~~~~~~~~~~ With configuration: ``['sort_algorithm' => 'none', 'imports_order' => ['const', 'class', 'function']]``. diff --git a/doc/rules/index.rst b/doc/rules/index.rst index 823c12d6f11..64a4ce9748f 100644 --- a/doc/rules/index.rst +++ b/doc/rules/index.rst @@ -13,6 +13,8 @@ Alias Replace deprecated ``ereg`` regular expression functions with ``preg``. - `mb_str_functions <./alias/mb_str_functions.rst>`_ *(risky)* Replace non multibyte-safe functions with corresponding mb function. +- `modernize_strpos <./alias/modernize_strpos.rst>`_ *(risky)* + Replace ``strpos()`` calls with ``str_starts_with()`` or ``str_contains()`` if possible. - `no_alias_functions <./alias/no_alias_functions.rst>`_ *(risky)* Master functions shall be used instead of aliases. - `no_alias_language_construct_call <./alias/no_alias_language_construct_call.rst>`_ @@ -53,6 +55,8 @@ Basic PHP code MUST use only UTF-8 without BOM (remove BOM). - `non_printable_character <./basic/non_printable_character.rst>`_ *(risky)* Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other invisible unicode symbols. +- `octal_notation <./basic/octal_notation.rst>`_ + Literal octal must be in ``0o`` notation. - `psr_autoloading <./basic/psr_autoloading.rst>`_ *(risky)* Classes must be in a path that matches their namespace, be at least one namespace deep and the class name should match the file name. @@ -61,6 +65,8 @@ Casing - `constant_case <./casing/constant_case.rst>`_ The PHP constants ``true``, ``false``, and ``null`` MUST be written using the correct casing. +- `integer_literal_case <./casing/integer_literal_case.rst>`_ + Integer literals must be in correct case. - `lowercase_keywords <./casing/lowercase_keywords.rst>`_ PHP keywords MUST be in lower case. - `lowercase_static_reference <./casing/lowercase_static_reference.rst>`_ @@ -161,10 +167,14 @@ Constant Notation Control Structure ----------------- +- `control_structure_continuation_position <./control_structure/control_structure_continuation_position.rst>`_ + Control structure continuation keyword must be on the configured line. - `elseif <./control_structure/elseif.rst>`_ The keyword ``elseif`` should be used instead of ``else if`` so that all control keywords look like single words. - `empty_loop_body <./control_structure/empty_loop_body.rst>`_ Empty loop-body must be in configured style. +- `empty_loop_condition <./control_structure/empty_loop_condition.rst>`_ + Empty loop-condition must be in configured style. - `include <./control_structure/include.rst>`_ Include/Require and file path should be divided with a single space. File path should not be placed under brackets. - `no_alternative_syntax <./control_structure/no_alternative_syntax.rst>`_ @@ -277,7 +287,7 @@ Import Language Construct ------------------ -- `class_keyword_remove <./language_construct/class_keyword_remove.rst>`_ +- `class_keyword_remove <./language_construct/class_keyword_remove.rst>`_ *(deprecated)* Converts ``::class`` keywords to FQCN strings. - `combine_consecutive_issets <./language_construct/combine_consecutive_issets.rst>`_ Using ``isset($var) &&`` multiple times should be done in one call. @@ -285,6 +295,8 @@ Language Construct Calling ``unset`` on multiple items should be done in one call. - `declare_equal_normalize <./language_construct/declare_equal_normalize.rst>`_ Equal sign in declare statement should be surrounded by spaces or not following configuration. +- `declare_parentheses <./language_construct/declare_parentheses.rst>`_ + There must not be spaces around ``declare`` statement parentheses. - `dir_constant <./language_construct/dir_constant.rst>`_ *(risky)* Replaces ``dirname(__FILE__)`` expression with equivalent ``__DIR__`` constant. - `error_suppression <./language_construct/error_suppression.rst>`_ *(risky)* @@ -565,3 +577,5 @@ Whitespace Remove trailing whitespace at the end of blank lines. - `single_blank_line_at_eof <./whitespace/single_blank_line_at_eof.rst>`_ A PHP file without end tag must always end with a single empty line feed. +- `types_spaces <./whitespace/types_spaces.rst>`_ + A single space or none should be around union type operator. diff --git a/doc/rules/language_construct/class_keyword_remove.rst b/doc/rules/language_construct/class_keyword_remove.rst index efcb8b68811..d59a7e51340 100644 --- a/doc/rules/language_construct/class_keyword_remove.rst +++ b/doc/rules/language_construct/class_keyword_remove.rst @@ -2,6 +2,8 @@ Rule ``class_keyword_remove`` ============================= +.. warning:: This rule is deprecated and will be removed on next major version. + Converts ``::class`` keywords to FQCN strings. Examples diff --git a/doc/rules/language_construct/declare_parentheses.rst b/doc/rules/language_construct/declare_parentheses.rst new file mode 100644 index 00000000000..6b63b9369a8 --- /dev/null +++ b/doc/rules/language_construct/declare_parentheses.rst @@ -0,0 +1,18 @@ +============================ +Rule ``declare_parentheses`` +============================ + +There must not be spaces around ``declare`` statement parentheses. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -`_ rule set will enable the ``list_syntax`` rule with the default config. + +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``list_syntax`` rule with the default config. diff --git a/doc/rules/namespace_notation/clean_namespace.rst b/doc/rules/namespace_notation/clean_namespace.rst index 255444dc78b..52fc1694acd 100644 --- a/doc/rules/namespace_notation/clean_namespace.rst +++ b/doc/rules/namespace_notation/clean_namespace.rst @@ -37,6 +37,9 @@ The rule is part of the following rule sets: @PHP80Migration Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``clean_namespace`` rule. +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``clean_namespace`` rule. + @PhpCsFixer Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``clean_namespace`` rule. diff --git a/doc/rules/operator/ternary_to_null_coalescing.rst b/doc/rules/operator/ternary_to_null_coalescing.rst index 38d4f6c00bf..40ba724c10b 100644 --- a/doc/rules/operator/ternary_to_null_coalescing.rst +++ b/doc/rules/operator/ternary_to_null_coalescing.rst @@ -37,3 +37,6 @@ The rule is part of the following rule sets: @PHP80Migration Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``ternary_to_null_coalescing`` rule. + +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``ternary_to_null_coalescing`` rule. diff --git a/doc/rules/phpdoc/no_superfluous_phpdoc_tags.rst b/doc/rules/phpdoc/no_superfluous_phpdoc_tags.rst index 771067cf4ef..133e0a1e3fd 100644 --- a/doc/rules/phpdoc/no_superfluous_phpdoc_tags.rst +++ b/doc/rules/phpdoc/no_superfluous_phpdoc_tags.rst @@ -54,8 +54,10 @@ Example #1 /** - * @param Bar $bar - * @param mixed $baz + * + - * @return Baz */ - public function doFoo(Bar $bar, $baz) {} + public function doFoo(Bar $bar, $baz): Baz {} } Example #2 @@ -79,26 +81,6 @@ With configuration: ``['allow_mixed' => true]``. Example #3 ~~~~~~~~~~ -*Default* configuration. - -.. code-block:: diff - - --- Original - +++ New - true]``. .. code-block:: diff @@ -114,7 +96,7 @@ With configuration: ``['remove_inheritdoc' => true]``. public function doFoo(Bar $bar, $baz) {} } -Example #5 +Example #4 ~~~~~~~~~~ With configuration: ``['allow_unused_params' => true]``. diff --git a/doc/rules/whitespace/heredoc_indentation.rst b/doc/rules/whitespace/heredoc_indentation.rst index 27f3f2f9b7e..a0695f6e6a9 100644 --- a/doc/rules/whitespace/heredoc_indentation.rst +++ b/doc/rules/whitespace/heredoc_indentation.rst @@ -87,3 +87,6 @@ The rule is part of the following rule sets: @PHP80Migration Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``heredoc_indentation`` rule with the default config. + +@PHP81Migration + Using the `@PHP81Migration <./../../ruleSets/PHP81Migration.rst>`_ rule set will enable the ``heredoc_indentation`` rule with the default config. diff --git a/doc/rules/whitespace/no_extra_blank_lines.rst b/doc/rules/whitespace/no_extra_blank_lines.rst index 8f85be5b624..28ccf0b2cc4 100644 --- a/doc/rules/whitespace/no_extra_blank_lines.rst +++ b/doc/rules/whitespace/no_extra_blank_lines.rst @@ -198,24 +198,6 @@ With configuration: ``['tokens' => ['use']]``. Example #11 ~~~~~~~~~~~ -With configuration: ``['tokens' => ['use_trait']]``. - -.. code-block:: diff - - --- Original - +++ New - ['switch', 'case', 'default']]``. .. code-block:: diff @@ -240,9 +222,9 @@ The rule is part of the following rule sets: @PhpCsFixer Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_extra_blank_lines`` rule with the config below: - ``['tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']]`` + ``['tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use']]`` @Symfony Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_extra_blank_lines`` rule with the config below: - ``['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']]`` + ``['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use']]`` diff --git a/doc/rules/whitespace/types_spaces.rst b/doc/rules/whitespace/types_spaces.rst new file mode 100644 index 00000000000..7fc086d345c --- /dev/null +++ b/doc/rules/whitespace/types_spaces.rst @@ -0,0 +1,80 @@ +===================== +Rule ``types_spaces`` +===================== + +A single space or none should be around union type operator. + +Configuration +------------- + +``space`` +~~~~~~~~~ + +spacing to apply around union type operator. + +Allowed values: ``'none'``, ``'single'`` + +Default value: ``'none'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + 'single']``. + +.. code-block:: diff + + --- Original + +++ New + `_ rule set will enable the ``types_spaces`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``types_spaces`` rule with the default config. diff --git a/doc/usage.rst b/doc/usage.rst index c369141ab8c..01e4f6da647 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -133,7 +133,7 @@ The ``--config`` option can be used, like in the ``fix`` command, to tell from w $ php php-cs-fixer.phar list-files --config=.php-cs-fixer.dist.php -The output is build in a form that its easy to use in combination with ``xargs`` command in a linux pipe. +The output is built in a form that its easy to use in combination with ``xargs`` command in a linux pipe. This can be useful e.g. in situations where the caching mechanism might not be available (CI, Docker) and distribute fixing across several processes might speedup the process. diff --git a/logo.md b/logo.md index b08e6a818dd..16fc6d14e0e 100644 --- a/logo.md +++ b/logo.md @@ -1,3 +1,3 @@ -The logo is © 2010-2014 Sensio Labs. +The logo is © 2010-2021 Sensio Labs. Original resolution can be found at https://github.com/PHP-CS-Fixer/logo . diff --git a/php-cs-fixer b/php-cs-fixer index fd9e6011c89..7d1749c8304 100755 --- a/php-cs-fixer +++ b/php-cs-fixer @@ -21,22 +21,22 @@ if (defined('HHVM_VERSION_ID')) { } else { exit(1); } +} elseif (!defined('PHP_VERSION_ID')) { // PHP_VERSION_ID is available as of PHP 5.2.7 + fwrite(STDERR, 'PHP version no supported, please update. Current PHP version: '.PHP_VERSION.".\n"); + + exit(1); +} elseif (\PHP_VERSION_ID === 80000) { + fwrite(STDERR, "PHP CS Fixer is not able run on PHP 8.0.0 due to bug in PHP tokenizer (https://bugs.php.net/bug.php?id=80462).\n"); + fwrite(STDERR, "Update PHP version to unblock execution.\n"); + + exit(1); } elseif ( - !defined('PHP_VERSION_ID') - || \PHP_VERSION_ID === 80000 - || \PHP_VERSION_ID < 70103 + \PHP_VERSION_ID < 70103 || \PHP_VERSION_ID >= 80100 ) { fwrite(STDERR, "PHP needs to be a minimum version of PHP 7.1.3 and maximum version of PHP 8.0.*.\n"); fwrite(STDERR, 'Current PHP version: '.PHP_VERSION.".\n"); - if (defined('PHP_VERSION_ID') && \PHP_VERSION_ID === 80000) { - fwrite(STDERR, "PHP CS Fixer is not able run on PHP 8.0.0 due to bug in PHP tokenizer (https://bugs.php.net/bug.php?id=80462).\n"); - fwrite(STDERR, "Update PHP version to unblock execution.\n"); - - exit(1); - } - if (getenv('PHP_CS_FIXER_IGNORE_ENV')) { fwrite(STDERR, "Ignoring environment requirements because `PHP_CS_FIXER_IGNORE_ENV` is set. Execution may be unstable.\n"); } else { diff --git a/phpstan.neon b/phpstan.neon index 5c1c6d3c8d8..b5838764885 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -10,4 +10,9 @@ parameters: - tests excludePaths: - tests/Fixtures + ignoreErrors: + - '/^Class [a-zA-Z\\]+ extends @final class PhpCsFixer\\(ConfigurationException\\InvalidConfigurationException|ConfigurationException\\InvalidFixerConfigurationException|Tokenizer\\Tokens)\.$/' + - '/^Unsafe call to private method [a-zA-Z\\]+::[a-zA-Z]+\(\) through static::\.$/' + - '/^\$this\(PhpCsFixer\\Tokenizer\\Tokens\) does not accept PhpCsFixer\\Tokenizer\\Token\|null\.$/' tipsOfTheDay: false + tmpDir: dev-tools/phpstan/cache diff --git a/src/AbstractDoctrineAnnotationFixer.php b/src/AbstractDoctrineAnnotationFixer.php index dfa4bc16e9c..857067e1c2f 100644 --- a/src/AbstractDoctrineAnnotationFixer.php +++ b/src/AbstractDoctrineAnnotationFixer.php @@ -79,7 +79,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn return new FixerConfigurationResolver([ (new FixerOptionBuilder('ignored_tags', 'List of tags that must not be treated as Doctrine Annotations.')) ->setAllowedTypes(['array']) - ->setAllowedValues([static function (array $values) { + ->setAllowedValues([static function (array $values): bool { foreach ($values as $value) { if (!\is_string($value)) { return false; @@ -192,6 +192,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn // PHPStan 'phpstan', + 'template', // other 'fix', @@ -217,7 +218,13 @@ private function nextElementAcceptsDoctrineAnnotations(Tokens $tokens, int $inde return true; } - while ($tokens[$index]->isGivenKind([T_PUBLIC, T_PROTECTED, T_PRIVATE, T_FINAL, T_ABSTRACT, T_NS_SEPARATOR, T_STRING, CT::T_NULLABLE_TYPE])) { + $modifierKinds = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_FINAL, T_ABSTRACT, T_NS_SEPARATOR, T_STRING, CT::T_NULLABLE_TYPE]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $modifierKinds[] = T_READONLY; + } + + while ($tokens[$index]->isGivenKind($modifierKinds)) { $index = $tokens->getNextMeaningfulToken($index); } diff --git a/src/AbstractFopenFlagFixer.php b/src/AbstractFopenFlagFixer.php index 5010cc877e1..e9d7a120cef 100644 --- a/src/AbstractFopenFlagFixer.php +++ b/src/AbstractFopenFlagFixer.php @@ -19,8 +19,6 @@ /** * @internal - * - * @author SpacePossum */ abstract class AbstractFopenFlagFixer extends AbstractFunctionReferenceFixer { diff --git a/src/AbstractFunctionReferenceFixer.php b/src/AbstractFunctionReferenceFixer.php index 9e81193a34a..a1c57d9541d 100644 --- a/src/AbstractFunctionReferenceFixer.php +++ b/src/AbstractFunctionReferenceFixer.php @@ -41,7 +41,7 @@ public function isRisky(): bool protected function find(string $functionNameToSearch, Tokens $tokens, int $start = 0, ?int $end = null): ?array { // make interface consistent with findSequence - $end = null === $end ? $tokens->count() : $end; + $end = $end ?? $tokens->count(); // find raw sequence which we can analyse for context $candidateSequence = [[T_STRING, $functionNameToSearch], '(']; @@ -52,7 +52,7 @@ protected function find(string $functionNameToSearch, Tokens $tokens, int $start } // translate results for humans - list($functionName, $openParenthesis) = array_keys($matches); + [$functionName, $openParenthesis] = array_keys($matches); $functionsAnalyzer = new FunctionsAnalyzer(); diff --git a/src/AbstractLinesBeforeNamespaceFixer.php b/src/AbstractLinesBeforeNamespaceFixer.php index 0c6cf6ba7c2..3fdd94f7f92 100644 --- a/src/AbstractLinesBeforeNamespaceFixer.php +++ b/src/AbstractLinesBeforeNamespaceFixer.php @@ -22,7 +22,7 @@ * This abstract fixer is responsible for ensuring that a certain number of * lines prefix a namespace declaration. * - * @author Graham Campbell + * @author Graham Campbell * * @internal */ @@ -48,7 +48,7 @@ protected function fixLinesBeforeNamespace(Tokens $tokens, int $index, int $expe if ($token->isGivenKind(T_OPEN_TAG)) { $openingToken = $token; $openingTokenIndex = $index - $i; - $newlineInOpening = false !== strpos($token->getContent(), "\n"); + $newlineInOpening = str_contains($token->getContent(), "\n"); if ($newlineInOpening) { ++$precedingNewlines; } diff --git a/src/AbstractNoUselessElseFixer.php b/src/AbstractNoUselessElseFixer.php index 338d709ae68..7aeebb76676 100644 --- a/src/AbstractNoUselessElseFixer.php +++ b/src/AbstractNoUselessElseFixer.php @@ -16,9 +16,6 @@ use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ abstract class AbstractNoUselessElseFixer extends AbstractFixer { /** @@ -37,7 +34,7 @@ protected function isSuperfluousElse(Tokens $tokens, int $index): bool do { // Check if all 'if', 'else if ' and 'elseif' blocks above this 'else' always end, // if so this 'else' is overcomplete. - list($previousBlockStart, $previousBlockEnd) = $this->getPreviousBlock($tokens, $previousBlockStart); + [$previousBlockStart, $previousBlockEnd] = $this->getPreviousBlock($tokens, $previousBlockStart); // short 'if' detection $previous = $previousBlockEnd; diff --git a/src/AbstractPhpdocToTypeDeclarationFixer.php b/src/AbstractPhpdocToTypeDeclarationFixer.php index 465d52684d2..57bb41806d4 100644 --- a/src/AbstractPhpdocToTypeDeclarationFixer.php +++ b/src/AbstractPhpdocToTypeDeclarationFixer.php @@ -182,7 +182,7 @@ protected function getCommonTypeFromAnnotation(Annotation $annotation, bool $isR return null; } - if ($isNullable && (\PHP_VERSION_ID < 70100 || 'void' === $commonType)) { + if ($isNullable && 'void' === $commonType) { return null; } diff --git a/src/AbstractPhpdocTypesFixer.php b/src/AbstractPhpdocTypesFixer.php index 46bf4cb3cac..844ef7e2943 100644 --- a/src/AbstractPhpdocTypesFixer.php +++ b/src/AbstractPhpdocTypesFixer.php @@ -22,7 +22,7 @@ /** * This abstract fixer provides a base for fixers to fix types in PHPDoc. * - * @author Graham Campbell + * @author Graham Campbell * * @internal */ @@ -120,10 +120,9 @@ private function normalizeTypes(array $types): array */ private function normalizeType(string $type): string { - if ('[]' === substr($type, -2)) { - return $this->normalizeType(substr($type, 0, -2)).'[]'; - } - - return $this->normalize($type); + return str_ends_with($type, '[]') + ? $this->normalizeType(substr($type, 0, -2)).'[]' + : $this->normalize($type) + ; } } diff --git a/src/Cache/FileHandler.php b/src/Cache/FileHandler.php index 0f8833f4f9f..1a4727e0fe3 100644 --- a/src/Cache/FileHandler.php +++ b/src/Cache/FileHandler.php @@ -99,7 +99,7 @@ public function write(CacheInterface $cache): void $error = error_get_last(); throw new IOException( - sprintf('Failed to write file "%s", "%s".', $this->file, isset($error['message']) ? $error['message'] : 'no reason available'), + sprintf('Failed to write file "%s", "%s".', $this->file, $error['message'] ?? 'no reason available'), 0, null, $this->file diff --git a/src/ConfigurationException/InvalidConfigurationException.php b/src/ConfigurationException/InvalidConfigurationException.php index 9356b6098df..ab1185f09b8 100644 --- a/src/ConfigurationException/InvalidConfigurationException.php +++ b/src/ConfigurationException/InvalidConfigurationException.php @@ -19,8 +19,6 @@ /** * Exceptions of this type are thrown on misconfiguration of the Fixer. * - * @author SpacePossum - * * @internal * @final Only internal extending this class is supported */ @@ -30,7 +28,7 @@ public function __construct(string $message, ?int $code = null, ?\Throwable $pre { parent::__construct( $message, - null === $code ? FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_CONFIG : $code, + $code ?? FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_CONFIG, $previous ); } diff --git a/src/ConfigurationException/InvalidFixerConfigurationException.php b/src/ConfigurationException/InvalidFixerConfigurationException.php index b62ad0dd94e..0750eee86a9 100644 --- a/src/ConfigurationException/InvalidFixerConfigurationException.php +++ b/src/ConfigurationException/InvalidFixerConfigurationException.php @@ -19,8 +19,6 @@ /** * Exception thrown by Fixers on misconfiguration. * - * @author SpacePossum - * * @internal * @final Only internal extending this class is supported */ diff --git a/src/Console/Application.php b/src/Console/Application.php index df86d7d2ec3..e0d06302664 100644 --- a/src/Console/Application.php +++ b/src/Console/Application.php @@ -39,8 +39,8 @@ */ final class Application extends BaseApplication { - public const VERSION = '3.1.0-DEV'; - public const VERSION_CODENAME = ''; + public const VERSION = '3.2.0-DEV'; + public const VERSION_CODENAME = 'River'; /** * @var ToolInfo diff --git a/src/Console/Command/DescribeCommand.php b/src/Console/Command/DescribeCommand.php index ba013159966..4fa4e01cb5f 100644 --- a/src/Console/Command/DescribeCommand.php +++ b/src/Console/Command/DescribeCommand.php @@ -41,7 +41,6 @@ /** * @author Dariusz Rumiński - * @author SpacePossum * * @internal */ @@ -193,7 +192,14 @@ private function describeRule(OutputInterface $output, string $name): void $line = '* '.OutputFormatter::escape($option->getName()).''; $allowed = HelpCommand::getDisplayableAllowedValues($option); - if (null !== $allowed) { + if (null === $allowed) { + $allowed = array_map( + static function (string $type): string { + return ''.$type.''; + }, + $option->getAllowedTypes() + ); + } else { foreach ($allowed as &$value) { if ($value instanceof AllowedValueSubset) { $value = 'a subset of '.HelpCommand::toString($value->getAllowedValues()).''; @@ -201,18 +207,9 @@ private function describeRule(OutputInterface $output, string $name): void $value = ''.HelpCommand::toString($value).''; } } - } else { - $allowed = array_map( - static function (string $type) { - return ''.$type.''; - }, - $option->getAllowedTypes() - ); } - if (null !== $allowed) { - $line .= ' ('.implode(', ', $allowed).')'; - } + $line .= ' ('.implode(', ', $allowed).')'; $description = Preg::replace('/(`.+?`)/', '$1', OutputFormatter::escape($option->getDescription())); $line .= ': '.lcfirst(Preg::replace('/\.$/', '', $description)).'; '; @@ -245,7 +242,7 @@ static function (string $type) { } /** @var CodeSampleInterface[] $codeSamples */ - $codeSamples = array_filter($definition->getCodeSamples(), static function (CodeSampleInterface $codeSample) { + $codeSamples = array_filter($definition->getCodeSamples(), static function (CodeSampleInterface $codeSample): bool { if ($codeSample instanceof VersionSpecificCodeSampleInterface) { return $codeSample->isSuitableFor(\PHP_VERSION_ID); } @@ -278,7 +275,7 @@ static function (string $type) { $configuration = $codeSample->getConfiguration(); if ($fixer instanceof ConfigurableFixerInterface) { - $fixer->configure(null === $configuration ? [] : $configuration); + $fixer->configure($configuration ?? []); } $file = $codeSample instanceof FileSpecificCodeSampleInterface @@ -421,7 +418,7 @@ private function replaceRstLinks(string $content): string static function (array $matches) { return Preg::replaceCallback( '/`(.*)<(.*)>`_/', - static function (array $matches) { + static function (array $matches): string { return $matches[1].'('.$matches[2].')'; }, $matches[1] diff --git a/src/Console/Command/DescribeNameNotFoundException.php b/src/Console/Command/DescribeNameNotFoundException.php index b5a5355b610..8ddab2a308f 100644 --- a/src/Console/Command/DescribeNameNotFoundException.php +++ b/src/Console/Command/DescribeNameNotFoundException.php @@ -15,8 +15,6 @@ namespace PhpCsFixer\Console\Command; /** - * @author SpacePossum - * * @internal */ final class DescribeNameNotFoundException extends \InvalidArgumentException diff --git a/src/Console/Command/HelpCommand.php b/src/Console/Command/HelpCommand.php index 280d8e09aa5..a5f22047c21 100644 --- a/src/Console/Command/HelpCommand.php +++ b/src/Console/Command/HelpCommand.php @@ -25,7 +25,6 @@ /** * @author Fabien Potencier * @author Dariusz Rumiński - * @author SpacePossum * * @internal */ @@ -55,11 +54,11 @@ public static function getDisplayableAllowedValues(FixerOptionInterface $option) $allowed = $option->getAllowedValues(); if (null !== $allowed) { - $allowed = array_filter($allowed, static function ($value) { + $allowed = array_filter($allowed, static function ($value): bool { return !($value instanceof \Closure); }); - usort($allowed, static function ($valueA, $valueB) { + usort($allowed, static function ($valueA, $valueB): int { if ($valueA instanceof AllowedValueSubset) { return -1; } @@ -106,7 +105,7 @@ private static function arrayToString(array $value): string return '[]'; } - $isHash = static::isHash($value); + $isHash = !array_is_list($value); $str = '['; foreach ($value as $k => $v) { @@ -122,19 +121,4 @@ private static function arrayToString(array $value): string return substr($str, 0, -2).']'; } - - private static function isHash(array $array): bool - { - $i = 0; - - foreach ($array as $k => $v) { - if ($k !== $i) { - return true; - } - - ++$i; - } - - return false; - } } diff --git a/src/Console/Command/SelfUpdateCommand.php b/src/Console/Command/SelfUpdateCommand.php index 5b242a71bf0..2039b04b643 100644 --- a/src/Console/Command/SelfUpdateCommand.php +++ b/src/Console/Command/SelfUpdateCommand.php @@ -29,7 +29,6 @@ * @author Stephane PY * @author Grégoire Pineau * @author Dariusz Rumiński - * @author SpacePossum * * @internal */ diff --git a/src/Console/ConfigurationResolver.php b/src/Console/ConfigurationResolver.php index ea2df2eb31e..3be2fd0b930 100644 --- a/src/Console/ConfigurationResolver.php +++ b/src/Console/ConfigurationResolver.php @@ -23,6 +23,7 @@ use PhpCsFixer\Cache\Signature; use PhpCsFixer\ConfigInterface; use PhpCsFixer\ConfigurationException\InvalidConfigurationException; +use PhpCsFixer\Console\Command\HelpCommand; use PhpCsFixer\Console\Report\FixReport\ReporterFactory; use PhpCsFixer\Console\Report\FixReport\ReporterInterface; use PhpCsFixer\Differ\DifferInterface; @@ -330,12 +331,12 @@ public function getFixers(): array if (false === $this->getRiskyAllowed()) { $riskyFixers = array_map( - static function (FixerInterface $fixer) { + static function (FixerInterface $fixer): string { return $fixer->getName(); }, array_filter( $this->fixers, - static function (FixerInterface $fixer) { + static function (FixerInterface $fixer): bool { return $fixer->isRisky(); } ) @@ -374,7 +375,7 @@ public function getPath(): array $this->path = $this->options['path']; } else { $this->path = array_map( - static function (string $rawPath) use ($cwd, $filesystem) { + static function (string $rawPath) use ($cwd, $filesystem): string { $path = trim($rawPath); if ('' === $path) { @@ -591,9 +592,7 @@ private function createFixerFactory(): FixerFactory private function getFormat(): string { if (null === $this->format) { - $this->format = null === $this->options['format'] - ? $this->getConfig()->getFormat() - : $this->options['format']; + $this->format = $this->options['format'] ?? $this->getConfig()->getFormat(); } return $this->format; @@ -677,6 +676,7 @@ private function validateRules(array $rules): void * @see RuleSet::resolveSet() */ $ruleSet = []; + foreach ($rules as $key => $value) { if (\is_int($key)) { throw new InvalidConfigurationException(sprintf('Missing value for "%s" rule/set.', $value)); @@ -684,6 +684,7 @@ private function validateRules(array $rules): void $ruleSet[$key] = true; } + $ruleSet = new RuleSet($ruleSet); /** @var string[] $configuredFixers */ @@ -692,7 +693,7 @@ private function validateRules(array $rules): void $fixers = $this->createFixerFactory()->getFixers(); /** @var string[] $availableFixers */ - $availableFixers = array_map(static function (FixerInterface $fixer) { + $availableFixers = array_map(static function (FixerInterface $fixer): string { return $fixer->getName(); }, $fixers); @@ -702,19 +703,89 @@ private function validateRules(array $rules): void ); if (\count($unknownFixers)) { - $matcher = new WordMatcher($availableFixers); + $renamedRules = [ + 'blank_line_before_return' => [ + 'new_name' => 'blank_line_before_statement', + 'config' => ['statements' => ['return']], + ], + 'final_static_access' => [ + 'new_name' => 'self_static_accessor', + ], + 'hash_to_slash_comment' => [ + 'new_name' => 'single_line_comment_style', + 'config' => ['comment_types' => ['hash']], + ], + 'lowercase_constants' => [ + 'new_name' => 'constant_case', + 'config' => ['case' => 'lower'], + ], + 'no_extra_consecutive_blank_lines' => [ + 'new_name' => 'no_extra_blank_lines', + ], + 'no_multiline_whitespace_before_semicolons' => [ + 'new_name' => 'multiline_whitespace_before_semicolons', + ], + 'no_short_echo_tag' => [ + 'new_name' => 'echo_tag_syntax', + 'config' => ['format' => 'long'], + ], + 'php_unit_ordered_covers' => [ + 'new_name' => 'phpdoc_order_by_value', + 'config' => ['annotations' => ['covers']], + ], + 'phpdoc_inline_tag' => [ + 'new_name' => 'general_phpdoc_tag_rename, phpdoc_inline_tag_normalizer and phpdoc_tag_type', + ], + 'pre_increment' => [ + 'new_name' => 'increment_style', + 'config' => ['style' => 'pre'], + ], + 'psr0' => [ + 'new_name' => 'psr_autoloading', + 'config' => ['dir' => 'x'], + ], + 'psr4' => [ + 'new_name' => 'psr_autoloading', + ], + 'silenced_deprecation_error' => [ + 'new_name' => 'error_suppression', + ], + 'trailing_comma_in_multiline_array' => [ + 'new_name' => 'trailing_comma_in_multiline', + 'config' => ['elements' => ['arrays']], + ], + ]; $message = 'The rules contain unknown fixers: '; + $hasOldRule = false; + foreach ($unknownFixers as $unknownFixer) { - $alternative = $matcher->match($unknownFixer); - $message .= sprintf( - '"%s"%s, ', - $unknownFixer, - null === $alternative ? '' : ' (did you mean "'.$alternative.'"?)' - ); + if (isset($renamedRules[$unknownFixer])) { // Check if present as old renamed rule + $hasOldRule = true; + $message .= sprintf( + '"%s" is renamed (did you mean "%s"?%s), ', + $unknownFixer, + $renamedRules[$unknownFixer]['new_name'], + isset($renamedRules[$unknownFixer]['config']) ? ' (note: use configuration "'.HelpCommand::toString($renamedRules[$unknownFixer]['config']).'")' : '' + ); + } else { // Go to normal matcher if it is not a renamed rule + $matcher = new WordMatcher($availableFixers); + $alternative = $matcher->match($unknownFixer); + $message .= sprintf( + '"%s"%s, ', + $unknownFixer, + null === $alternative ? '' : ' (did you mean "'.$alternative.'"?)' + ); + } + } + + $message = substr($message, 0, -2).'.'; + + if ($hasOldRule) { + $message .= "\nFor more info about updating see: https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v3.0.0/UPGRADE-v3.md#renamed-ruless."; } - throw new InvalidConfigurationException(substr($message, 0, -2).'.'); + throw new InvalidConfigurationException($message); } foreach ($fixers as $fixer) { @@ -802,7 +873,7 @@ static function (string $path) { return new \CallbackFilterIterator( new \IteratorIterator($nestedFinder), - static function (\SplFileInfo $current) use ($pathsByType) { + static function (\SplFileInfo $current) use ($pathsByType): bool { $currentRealPath = $current->getRealPath(); if (\in_array($currentRealPath, $pathsByType['file'], true)) { @@ -810,7 +881,7 @@ static function (\SplFileInfo $current) use ($pathsByType) { } foreach ($pathsByType['dir'] as $path) { - if (0 === strpos($currentRealPath, $path)) { + if (str_starts_with($currentRealPath, $path)) { return true; } } diff --git a/src/Console/Output/ErrorOutput.php b/src/Console/Output/ErrorOutput.php index df7a5e77cf1..3d716364342 100644 --- a/src/Console/Output/ErrorOutput.php +++ b/src/Console/Output/ErrorOutput.php @@ -21,8 +21,6 @@ use Symfony\Component\Console\Output\OutputInterface; /** - * @author SpacePossum - * * @internal */ final class ErrorOutput diff --git a/src/Console/Report/FixReport/JsonReporter.php b/src/Console/Report/FixReport/JsonReporter.php index e99146dd01c..d637ee7de95 100644 --- a/src/Console/Report/FixReport/JsonReporter.php +++ b/src/Console/Report/FixReport/JsonReporter.php @@ -54,17 +54,11 @@ public function generate(ReportSummary $reportSummary): string $json = [ 'files' => $jFiles, - ]; - - if (null !== $reportSummary->getTime()) { - $json['time'] = [ + 'time' => [ 'total' => round($reportSummary->getTime() / 1000, 3), - ]; - } - - if (null !== $reportSummary->getMemory()) { - $json['memory'] = round($reportSummary->getMemory() / 1024 / 1024, 3); - } + ], + 'memory' => round($reportSummary->getMemory() / 1024 / 1024, 3), + ]; $json = json_encode($json); diff --git a/src/Console/Report/FixReport/JunitReporter.php b/src/Console/Report/FixReport/JunitReporter.php index 759754d49c1..114d3df86ef 100644 --- a/src/Console/Report/FixReport/JunitReporter.php +++ b/src/Console/Report/FixReport/JunitReporter.php @@ -47,13 +47,13 @@ public function generate(ReportSummary $reportSummary): string $testsuite = $testsuites->appendChild($dom->createElement('testsuite')); $testsuite->setAttribute('name', 'PHP CS Fixer'); - if (\count($reportSummary->getChanged())) { + if (\count($reportSummary->getChanged()) > 0) { $this->createFailedTestCases($dom, $testsuite, $reportSummary); } else { $this->createSuccessTestCase($dom, $testsuite); } - if ($reportSummary->getTime()) { + if ($reportSummary->getTime() > 0) { $testsuite->setAttribute( 'time', sprintf( diff --git a/src/Console/Report/ListSetsReport/JsonReporter.php b/src/Console/Report/ListSetsReport/JsonReporter.php index be95b0cf40c..2046939717d 100644 --- a/src/Console/Report/ListSetsReport/JsonReporter.php +++ b/src/Console/Report/ListSetsReport/JsonReporter.php @@ -38,7 +38,7 @@ public function generate(ReportSummary $reportSummary): string { $sets = $reportSummary->getSets(); - usort($sets, function (RuleSetDescriptionInterface $a, RuleSetDescriptionInterface $b) { + usort($sets, static function (RuleSetDescriptionInterface $a, RuleSetDescriptionInterface $b): int { return strcmp($a->getName(), $b->getName()); }); diff --git a/src/Console/Report/ListSetsReport/ReporterFactory.php b/src/Console/Report/ListSetsReport/ReporterFactory.php index 96ce3d556ea..5e2f277515a 100644 --- a/src/Console/Report/ListSetsReport/ReporterFactory.php +++ b/src/Console/Report/ListSetsReport/ReporterFactory.php @@ -54,10 +54,7 @@ public function registerBuiltInReporters(): self return $this; } - /** - * @return $this - */ - public function registerReporter(ReporterInterface $reporter) + public function registerReporter(ReporterInterface $reporter): self { $format = $reporter->getFormat(); diff --git a/src/Console/Report/ListSetsReport/TextReporter.php b/src/Console/Report/ListSetsReport/TextReporter.php index a3d6cd53200..0caddef57f7 100644 --- a/src/Console/Report/ListSetsReport/TextReporter.php +++ b/src/Console/Report/ListSetsReport/TextReporter.php @@ -38,7 +38,7 @@ public function generate(ReportSummary $reportSummary): string { $sets = $reportSummary->getSets(); - usort($sets, function (RuleSetDescriptionInterface $a, RuleSetDescriptionInterface $b) { + usort($sets, static function (RuleSetDescriptionInterface $a, RuleSetDescriptionInterface $b): int { return strcmp($a->getName(), $b->getName()); }); diff --git a/src/Console/WarningsDetector.php b/src/Console/WarningsDetector.php index 9d168ba250b..cc8165a8119 100644 --- a/src/Console/WarningsDetector.php +++ b/src/Console/WarningsDetector.php @@ -41,7 +41,7 @@ public function __construct(ToolInfoInterface $toolInfo) public function detectOldMajor(): void { - // @TODO 3.99 to be activated with new MAJOR release + // @TODO 3.99 to be activated with new MAJOR release 4.0 // $currentMajorVersion = \intval(explode('.', Application::VERSION)[0], 10); // $nextMajorVersion = $currentMajorVersion + 1; // $this->warnings[] = "You are running PHP CS Fixer v{$currentMajorVersion}, which is not maintained anymore. Please update to v{$nextMajorVersion}."; diff --git a/src/Differ/DiffConsoleFormatter.php b/src/Differ/DiffConsoleFormatter.php index e756dad8c21..887af335903 100644 --- a/src/Differ/DiffConsoleFormatter.php +++ b/src/Differ/DiffConsoleFormatter.php @@ -54,7 +54,7 @@ public function format(string $diff, string $lineTemplate = '%s'): string implode( PHP_EOL, array_map( - static function (string $line) use ($isDecorated, $lineTemplate) { + static function (string $line) use ($isDecorated, $lineTemplate): string { if ($isDecorated) { $count = 0; $line = Preg::replaceCallback( @@ -63,7 +63,7 @@ static function (string $line) use ($isDecorated, $lineTemplate) { '/^(\-.*)/', '/^(@.*)/', ], - static function (array $matches) { + static function (array $matches): string { if ('+' === $matches[0][0]) { $colour = 'green'; } elseif ('-' === $matches[0][0]) { diff --git a/src/Differ/UnifiedDiffer.php b/src/Differ/UnifiedDiffer.php index b2b37c55753..fa2233b3139 100644 --- a/src/Differ/UnifiedDiffer.php +++ b/src/Differ/UnifiedDiffer.php @@ -18,9 +18,6 @@ use PhpCsFixer\Diff\Output\StrictUnifiedDiffOutputBuilder; use PhpCsFixer\Preg; -/** - * @author SpacePossum - */ final class UnifiedDiffer implements DifferInterface { /** diff --git a/src/DocBlock/Annotation.php b/src/DocBlock/Annotation.php index b1f5dce0af6..5d4376427ef 100644 --- a/src/DocBlock/Annotation.php +++ b/src/DocBlock/Annotation.php @@ -21,7 +21,7 @@ /** * This represents an entire annotation from a docblock. * - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński * * @final @@ -163,11 +163,9 @@ public function getTag(): Tag } /** - * @return TypeExpression - * * @internal */ - public function getTypeExpression() + public function getTypeExpression(): TypeExpression { return new TypeExpression($this->getTypesContent(), $this->namespace, $this->namespaceUses); } @@ -224,7 +222,7 @@ public function setTypes(array $types): void */ public function getNormalizedTypes(): array { - $normalized = array_map(static function (string $type) { + $normalized = array_map(static function (string $type): string { return strtolower($type); }, $this->getTypes()); diff --git a/src/DocBlock/DocBlock.php b/src/DocBlock/DocBlock.php index 4d00a17def2..e73fd6a81f5 100644 --- a/src/DocBlock/DocBlock.php +++ b/src/DocBlock/DocBlock.php @@ -23,7 +23,7 @@ * * It internally splits it up into "lines" that we can manipulate. * - * @author Graham Campbell + * @author Graham Campbell * * @final */ @@ -86,7 +86,7 @@ public function getLines(): array */ public function getLine(int $pos): ?Line { - return isset($this->lines[$pos]) ? $this->lines[$pos] : null; + return $this->lines[$pos] ?? null; } /** @@ -161,7 +161,7 @@ public function makeSingleLine(): void $usefulLines = array_filter( $this->lines, - static function (Line $line) { + static function (Line $line): bool { return $line->containsUsefulContent(); } ); @@ -182,7 +182,7 @@ public function getAnnotation(int $pos): ?Annotation { $annotations = $this->getAnnotations(); - return isset($annotations[$pos]) ? $annotations[$pos] : null; + return $annotations[$pos] ?? null; } /** @@ -253,9 +253,9 @@ private function getSingleLineDocBlockEntry(Line $line): string $lineString = str_replace('*/', '', $lineString); $lineString = trim($lineString); - if ('/**' === substr($lineString, 0, 3)) { + if (str_starts_with($lineString, '/**')) { $lineString = substr($lineString, 3); - } elseif ('*' === substr($lineString, 0, 1)) { + } elseif (str_starts_with($lineString, '*')) { $lineString = substr($lineString, 1); } diff --git a/src/DocBlock/Line.php b/src/DocBlock/Line.php index 8b369ffc09e..d54c53da6f9 100644 --- a/src/DocBlock/Line.php +++ b/src/DocBlock/Line.php @@ -19,7 +19,7 @@ /** * This represents a line of a docblock. * - * @author Graham Campbell + * @author Graham Campbell * * @final */ @@ -81,7 +81,7 @@ public function containsATag(): bool */ public function isTheStart(): bool { - return false !== strpos($this->content, '/**'); + return str_contains($this->content, '/**'); } /** @@ -89,7 +89,7 @@ public function isTheStart(): bool */ public function isTheEnd(): bool { - return false !== strpos($this->content, '*/'); + return str_contains($this->content, '*/'); } /** diff --git a/src/DocBlock/Tag.php b/src/DocBlock/Tag.php index 999ea486ffe..225e3036288 100644 --- a/src/DocBlock/Tag.php +++ b/src/DocBlock/Tag.php @@ -19,7 +19,7 @@ /** * This represents a tag, as defined by the proposed PSR PHPDoc standard. * - * @author Graham Campbell + * @author Graham Campbell * * @final */ diff --git a/src/DocBlock/TagComparator.php b/src/DocBlock/TagComparator.php index e9a3092a9a7..c49761a6181 100644 --- a/src/DocBlock/TagComparator.php +++ b/src/DocBlock/TagComparator.php @@ -18,7 +18,7 @@ * This class is responsible for comparing tags to see if they should be kept * together, or kept apart. * - * @author Graham Campbell + * @author Graham Campbell * * @final */ diff --git a/src/DocBlock/TypeExpression.php b/src/DocBlock/TypeExpression.php index 66738cbd3c0..3fe50196db9 100644 --- a/src/DocBlock/TypeExpression.php +++ b/src/DocBlock/TypeExpression.php @@ -150,13 +150,13 @@ public function getTypes(): array public function getCommonType(): ?string { $aliases = [ - 'true' => 'bool', - 'false' => 'bool', 'boolean' => 'bool', - 'integer' => 'int', + 'callback' => 'callable', 'double' => 'float', + 'false' => 'bool', + 'integer' => 'int', 'real' => 'float', - 'callback' => 'callable', + 'true' => 'bool', ]; $mainType = null; @@ -211,29 +211,25 @@ private function getParentType(string $type1, string $type2): ?string $types = implode('|', $types); $parents = [ - 'array|iterable' => 'iterable', 'array|Traversable' => 'iterable', + 'array|iterable' => 'iterable', 'iterable|Traversable' => 'iterable', 'self|static' => 'self', ]; - if (isset($parents[$types])) { - return $parents[$types]; - } - - return null; + return $parents[$types] ?? null; } private function normalize(string $type): string { $aliases = [ - 'true' => 'bool', - 'false' => 'bool', 'boolean' => 'bool', - 'integer' => 'int', + 'callback' => 'callable', 'double' => 'float', + 'false' => 'bool', + 'integer' => 'int', 'real' => 'float', - 'callback' => 'callable', + 'true' => 'bool', ]; if (isset($aliases[$type])) { @@ -241,18 +237,19 @@ private function normalize(string $type): string } if (\in_array($type, [ - 'void', - 'null', + 'array', 'bool', - 'int', + 'callable', 'float', - 'string', - 'array', + 'int', 'iterable', + 'mixed', + 'never', + 'null', 'object', - 'callable', 'resource', - 'mixed', + 'string', + 'void', ], true)) { return $type; } @@ -265,7 +262,7 @@ private function normalize(string $type): string return $matches[1]; } - if (0 === strpos($type, '\\')) { + if (str_starts_with($type, '\\')) { return substr($type, 1); } diff --git a/src/Doctrine/Annotation/Tokens.php b/src/Doctrine/Annotation/Tokens.php index fcbf04be503..d2c579b6fa9 100644 --- a/src/Doctrine/Annotation/Tokens.php +++ b/src/Doctrine/Annotation/Tokens.php @@ -248,7 +248,7 @@ public function insertAt(int $index, Token $token): void $this->setSize($this->getSize() + 1); for ($i = $this->getSize() - 1; $i > $index; --$i) { - $this[$i] = isset($this[$i - 1]) ? $this[$i - 1] : new Token(); + $this[$i] = $this[$i - 1] ?? new Token(); } $this[$index] = $token; diff --git a/src/Documentation/DocumentationGenerator.php b/src/Documentation/DocumentationGenerator.php index ae8e66279f6..457441a54fa 100644 --- a/src/Documentation/DocumentationGenerator.php +++ b/src/Documentation/DocumentationGenerator.php @@ -77,7 +77,7 @@ public function generateFixersDocumentationIndex(array $fixers): string 'Phpdoc' => 'PHPDoc', ]; - usort($fixers, function (FixerInterface $a, FixerInterface $b) { + usort($fixers, static function (FixerInterface $a, FixerInterface $b): int { return strcmp(\get_class($a), \get_class($b)); }); @@ -90,11 +90,7 @@ public function generateFixersDocumentationIndex(array $fixers): string $currentGroup = null; foreach ($fixers as $fixer) { $namespace = Preg::replace('/^.*\\\\(.+)\\\\.+Fixer$/', '$1', \get_class($fixer)); - if (isset($overrideGroups[$namespace])) { - $group = $overrideGroups[$namespace]; - } else { - $group = Preg::replace('/(?<=[[:lower:]])(?=[[:upper:]])/', ' ', $namespace); - } + $group = $overrideGroups[$namespace] ?? Preg::replace('/(?<=[[:lower:]])(?=[[:upper:]])/', ' ', $namespace); if ($group !== $currentGroup) { $underline = str_repeat('-', \strlen($group)); @@ -135,7 +131,7 @@ public function getFixerDocumentationFilePath(FixerInterface $fixer): string { return $this->getFixersDocumentationDirectoryPath().'/'.Preg::replaceCallback( '/^.*\\\\(.+)\\\\(.+)Fixer$/', - function (array $matches) { + static function (array $matches): string { return Utils::camelCaseToUnderscore($matches[1]).'/'.Utils::camelCaseToUnderscore($matches[2]); }, \get_class($fixer) @@ -228,8 +224,15 @@ public function generateFixerDocumentation(FixerInterface $fixer): string } $allowed = HelpCommand::getDisplayableAllowedValues($option); - $allowedKind = 'Allowed values'; - if (null !== $allowed) { + + if (null === $allowed) { + $allowedKind = 'Allowed types'; + $allowed = array_map(static function ($value): string { + return '``'.$value.'``'; + }, $option->getAllowedTypes()); + } else { + $allowedKind = 'Allowed values'; + foreach ($allowed as &$value) { if ($value instanceof AllowedValueSubset) { $value = 'a subset of ``'.HelpCommand::toString($value->getAllowedValues()).'``'; @@ -237,17 +240,10 @@ public function generateFixerDocumentation(FixerInterface $fixer): string $value = '``'.HelpCommand::toString($value).'``'; } } - } else { - $allowedKind = 'Allowed types'; - $allowed = array_map(function ($value) { - return '``'.$value.'``'; - }, $option->getAllowedTypes()); } - if (null !== $allowed) { - $allowed = implode(', ', $allowed); - $optionInfo .= "\n\n{$allowedKind}: {$allowed}"; - } + $allowed = implode(', ', $allowed); + $optionInfo .= "\n\n{$allowedKind}: {$allowed}"; if ($option->hasDefault()) { $default = HelpCommand::toString($option->getDefault()); diff --git a/src/Error/ErrorsManager.php b/src/Error/ErrorsManager.php index b2b83081a2d..2d70a3e6d63 100644 --- a/src/Error/ErrorsManager.php +++ b/src/Error/ErrorsManager.php @@ -35,7 +35,7 @@ final class ErrorsManager */ public function getInvalidErrors(): array { - return array_filter($this->errors, static function (Error $error) { + return array_filter($this->errors, static function (Error $error): bool { return Error::TYPE_INVALID === $error->getType(); }); } @@ -47,7 +47,7 @@ public function getInvalidErrors(): array */ public function getExceptionErrors(): array { - return array_filter($this->errors, static function (Error $error) { + return array_filter($this->errors, static function (Error $error): bool { return Error::TYPE_EXCEPTION === $error->getType(); }); } @@ -59,7 +59,7 @@ public function getExceptionErrors(): array */ public function getLintErrors(): array { - return array_filter($this->errors, static function (Error $error) { + return array_filter($this->errors, static function (Error $error): bool { return Error::TYPE_LINT === $error->getType(); }); } diff --git a/src/Fixer/Alias/ArrayPushFixer.php b/src/Fixer/Alias/ArrayPushFixer.php index b4923b8870b..43f4ae4f3a1 100644 --- a/src/Fixer/Alias/ArrayPushFixer.php +++ b/src/Fixer/Alias/ArrayPushFixer.php @@ -15,18 +15,14 @@ namespace PhpCsFixer\Fixer\Alias; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class ArrayPushFixer extends AbstractFixer { /** @@ -36,7 +32,7 @@ public function getDefinition(): FixerDefinitionInterface { return new FixerDefinition( 'Converts simple usages of `array_push($x, $y);` to `$x[] = $y;`.', - [new VersionSpecificCodeSample("= 70000 && $tokens->isTokenKindFound(T_STRING) && $tokens->count() > 7; + return $tokens->isTokenKindFound(T_STRING) && $tokens->count() > 7; } /** diff --git a/src/Fixer/Alias/EregToPregFixer.php b/src/Fixer/Alias/EregToPregFixer.php index 1cfc7e8dde8..8fc64c5f11f 100644 --- a/src/Fixer/Alias/EregToPregFixer.php +++ b/src/Fixer/Alias/EregToPregFixer.php @@ -87,9 +87,9 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void foreach (self::$functions as $map) { // the sequence is the function name, followed by "(" and a quoted string $seq = [[T_STRING, $map[0]], '(', [T_CONSTANT_ENCAPSED_STRING]]; - $currIndex = 0; - while (null !== $currIndex) { + + do { $match = $tokens->findSequence($seq, $currIndex, $end, false); // did we find a match? @@ -112,6 +112,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // ensure the first parameter is just a string (e.g. has nothing appended) $next = $tokens->getNextMeaningfulToken($match[2]); + if (null === $next || !$tokens[$next]->equalsAny([',', ')'])) { continue; } @@ -131,7 +132,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // modify function and argument $tokens[$match[0]] = new Token([T_STRING, $map[1]]); $tokens[$match[2]] = new Token([T_CONSTANT_ENCAPSED_STRING, $quote.$preg.$quote]); - } + } while (null !== $currIndex); } } @@ -160,10 +161,10 @@ private function checkPreg(string $pattern): bool */ private function getBestDelimiter(string $pattern): string { - // try do find something that's not used + // try to find something that's not used $delimiters = []; foreach (self::$delimiters as $k => $d) { - if (false === strpos($pattern, $d)) { + if (!str_contains($pattern, $d)) { return $d; } @@ -171,7 +172,7 @@ private function getBestDelimiter(string $pattern): string } // return the least used delimiter, using the position in the list as a tie breaker - uasort($delimiters, static function (array $a, array $b) { + uasort($delimiters, static function (array $a, array $b): int { if ($a[0] === $b[0]) { return $a[1] <=> $b[1]; } diff --git a/src/Fixer/Alias/MbStrFunctionsFixer.php b/src/Fixer/Alias/MbStrFunctionsFixer.php index e37cb961238..730e361ef88 100644 --- a/src/Fixer/Alias/MbStrFunctionsFixer.php +++ b/src/Fixer/Alias/MbStrFunctionsFixer.php @@ -57,7 +57,7 @@ public function __construct() $this->functions = array_filter( self::$functionsMap, - static function (array $mapping) { + static function (array $mapping): bool { return \function_exists($mapping['alternativeName']) && (new \ReflectionFunction($mapping['alternativeName']))->isInternal(); } ); @@ -109,7 +109,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $argumentsAnalyzer = new ArgumentsAnalyzer(); foreach ($this->functions as $functionIdentity => $functionReplacement) { $currIndex = 0; - while (null !== $currIndex) { + do { // try getting function reference and translate boundaries for humans $boundaries = $this->find($functionIdentity, $tokens, $currIndex, $tokens->count() - 1); if (null === $boundaries) { @@ -117,7 +117,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue 2; } - list($functionName, $openParenthesis, $closeParenthesis) = $boundaries; + [$functionName, $openParenthesis, $closeParenthesis] = $boundaries; $count = $argumentsAnalyzer->countArguments($tokens, $openParenthesis, $closeParenthesis); if (!\in_array($count, $functionReplacement['argumentCount'], true)) { continue 2; @@ -127,7 +127,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $currIndex = $openParenthesis; $tokens[$functionName] = new Token([T_STRING, $functionReplacement['alternativeName']]); - } + } while (null !== $currIndex); } } } diff --git a/src/Fixer/Alias/ModernizeStrposFixer.php b/src/Fixer/Alias/ModernizeStrposFixer.php new file mode 100644 index 00000000000..aee4ea76747 --- /dev/null +++ b/src/Fixer/Alias/ModernizeStrposFixer.php @@ -0,0 +1,217 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Alexander M. Turek + */ +final class ModernizeStrposFixer extends AbstractFixer +{ + private const REPLACEMENTS = [ + [ + 'operator' => [T_IS_IDENTICAL, '==='], + 'operand' => [T_LNUMBER, '0'], + 'replacement' => [T_STRING, 'str_starts_with'], + 'negate' => false, + ], + [ + 'operator' => [T_IS_NOT_IDENTICAL, '!=='], + 'operand' => [T_LNUMBER, '0'], + 'replacement' => [T_STRING, 'str_starts_with'], + 'negate' => true, + ], + [ + 'operator' => [T_IS_NOT_IDENTICAL, '!=='], + 'operand' => [T_STRING, 'false'], + 'replacement' => [T_STRING, 'str_contains'], + 'negate' => false, + ], + [ + 'operator' => [T_IS_IDENTICAL, '==='], + 'operand' => [T_STRING, 'false'], + 'replacement' => [T_STRING, 'str_contains'], + 'negate' => true, + ], + ]; + + public function getDefinition(): FixerDefinitionInterface + { + return new FixerDefinition( + 'Replace `strpos()` calls with `str_starts_with()` or `str_contains()` if possible.', + [ + new CodeSample( + 'isTokenKindFound(T_STRING) && $tokens->isAnyTokenKindsFound([T_IS_IDENTICAL, T_IS_NOT_IDENTICAL]); + } + + public function isRisky(): bool + { + return true; + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens): void + { + $functionsAnalyzer = new FunctionsAnalyzer(); + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + for ($index = \count($tokens) - 1; $index > 0; --$index) { + // find candidate function call + if (!$tokens[$index]->equals([T_STRING, 'strpos'], false) || !$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + continue; + } + + // assert called with 2 arguments + $openIndex = $tokens->getNextMeaningfulToken($index); + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); + $arguments = $argumentsAnalyzer->getArguments($tokens, $openIndex, $closeIndex); + + if (2 !== \count($arguments)) { + continue; + } + + // check if part condition and fix if needed + $compareTokens = $this->getCompareTokens($tokens, $index, -1); // look behind + + if (null === $compareTokens) { + $compareTokens = $this->getCompareTokens($tokens, $closeIndex, 1); // look ahead + } + + if (null !== $compareTokens) { + $this->fixCall($tokens, $index, $compareTokens); + } + } + } + + private function fixCall(Tokens $tokens, int $functionIndex, array $operatorIndexes): void + { + foreach (self::REPLACEMENTS as $replacement) { + if (!$tokens[$operatorIndexes['operator_index']]->equals($replacement['operator'])) { + continue; + } + + if (!$tokens[$operatorIndexes['operand_index']]->equals($replacement['operand'], false)) { + continue; + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($operatorIndexes['operator_index']); + $tokens->clearTokenAndMergeSurroundingWhitespace($operatorIndexes['operand_index']); + $tokens->clearTokenAndMergeSurroundingWhitespace($functionIndex); + + if ($replacement['negate']) { + $tokens->insertAt($functionIndex, new Token('!')); + ++$functionIndex; + } + + $tokens->insertAt($functionIndex, new Token($replacement['replacement'])); + + break; + } + } + + private function getCompareTokens(Tokens $tokens, int $offsetIndex, int $direction): ?array + { + $operatorIndex = $tokens->getMeaningfulTokenSibling($offsetIndex, $direction); + + if (null === $operatorIndex) { + return null; + } + + $operandIndex = $tokens->getMeaningfulTokenSibling($operatorIndex, $direction); + + if (null === $operandIndex) { + return null; + } + + $operand = $tokens[$operandIndex]; + + if (!$operand->equals([T_LNUMBER, '0']) && !$operand->equals([T_STRING, 'false'], false)) { + return null; + } + + if (!$tokens[$operatorIndex]->isGivenKind([T_IS_IDENTICAL, T_IS_NOT_IDENTICAL])) { + return null; + } + + $precedenceTokenIndex = $tokens->getMeaningfulTokenSibling($operandIndex, $direction); + + if (null !== $precedenceTokenIndex && $this->isOfHigherPrecedence($tokens[$precedenceTokenIndex])) { + return null; + } + + return ['operator_index' => $operatorIndex, 'operand_index' => $operandIndex]; + } + + private function isOfHigherPrecedence(Token $token): bool + { + static $operatorsPerId = [ + T_DEC => true, // -- + T_INC => true, // ++ + T_INSTANCEOF => true, // instanceof + T_IS_GREATER_OR_EQUAL => true, // >= + T_IS_SMALLER_OR_EQUAL => true, // <= + T_POW => true, // ** + T_SL => true, // << + T_SR => true, // >> + ]; + + static $operatorsPerContent = [ + '!', + '%', + '*', + '+', + '-', + '.', + '/', + '<', + '>', + '~', + ]; + + return isset($operatorsPerId[$token->getId()]) || $token->equalsAny($operatorsPerContent); + } +} diff --git a/src/Fixer/Alias/NoAliasFunctionsFixer.php b/src/Fixer/Alias/NoAliasFunctionsFixer.php index f4d866fbc2d..d67e7786725 100644 --- a/src/Fixer/Alias/NoAliasFunctionsFixer.php +++ b/src/Fixer/Alias/NoAliasFunctionsFixer.php @@ -36,11 +36,10 @@ final class NoAliasFunctionsFixer extends AbstractFixer implements ConfigurableF { private const SETS = [ '@internal' => [ - 'dir' => 'getdir', 'diskfreespace' => 'disk_free_space', - 'checkdnsrr' => 'dns_check_record', - 'getmxrr' => 'dns_get_mx', + 'dns_check_record' => 'checkdnsrr', + 'dns_get_mx' => 'getmxrr', 'session_commit' => 'session_write_close', @@ -84,14 +83,8 @@ final class NoAliasFunctionsFixer extends AbstractFixer implements ConfigurableF 'imap_scanmailbox' => 'imap_listscan', ], - '@snmp' => [ - 'snmpwalkoid' => 'snmprealwalk', - 'snmp_set_oid_numeric_print' => 'snmp_set_oid_output_format', - ], - '@ldap' => [ 'ldap_close' => 'ldap_unbind', - 'ldap_get_values' => 'ldap_get_values_len', 'ldap_modify' => 'ldap_mod_replace', ], @@ -170,6 +163,7 @@ public function configure(array $configuration): void parent::configure($configuration); $this->aliases = []; + foreach ($this->configuration['sets'] as $set) { if ('@all' === $set) { $this->aliases = array_merge(...array_values(self::SETS)); @@ -265,6 +259,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void foreach ($tokens->findGivenKind(T_STRING) as $index => $token) { // check mapping hit $tokenContent = strtolower($token->getContent()); + if (!isset($this->aliases[$tokenContent])) { continue; } @@ -281,7 +276,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } if (\is_array($this->aliases[$tokenContent])) { - list($alias, $numberOfArguments) = $this->aliases[$tokenContent]; + [$alias, $numberOfArguments] = $this->aliases[$tokenContent]; $count = $argumentsAnalyzer->countArguments($tokens, $openParenthesis, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis)); @@ -316,16 +311,16 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn '@pcntl' => 'PCNTL functions', '@pg' => 'pg functions', '@posix' => 'POSIX functions', - '@snmp' => 'SNMP functions', + '@snmp' => 'SNMP functions', // @TODO Remove on next major 4.0 as this set is now empty '@sodium' => 'libsodium functions', '@time' => 'time functions', ]; - $list = ''; + $list = "List of sets to fix. Defined sets are:\n\n"; + foreach ($sets as $set => $description) { $list .= sprintf("* `%s` (%s)\n", $set, $description); } - $list = sprintf("List of sets to fix. Defined sets are:\n\n%s", $list); return new FixerConfigurationResolver([ (new FixerOptionBuilder('sets', $list)) diff --git a/src/Fixer/Alias/NoAliasLanguageConstructCallFixer.php b/src/Fixer/Alias/NoAliasLanguageConstructCallFixer.php index 41eab1c99a4..357fa22830c 100644 --- a/src/Fixer/Alias/NoAliasLanguageConstructCallFixer.php +++ b/src/Fixer/Alias/NoAliasLanguageConstructCallFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NoAliasLanguageConstructCallFixer extends AbstractFixer { /** diff --git a/src/Fixer/Alias/NoMixedEchoPrintFixer.php b/src/Fixer/Alias/NoMixedEchoPrintFixer.php index 0e899a4b910..46782415371 100644 --- a/src/Fixer/Alias/NoMixedEchoPrintFixer.php +++ b/src/Fixer/Alias/NoMixedEchoPrintFixer.php @@ -28,7 +28,6 @@ /** * @author Sullivan Senechal - * @author SpacePossum */ final class NoMixedEchoPrintFixer extends AbstractFixer implements ConfigurableFixerInterface { diff --git a/src/Fixer/Alias/PowToExponentiationFixer.php b/src/Fixer/Alias/PowToExponentiationFixer.php index 8e3836f00c7..f71020e6b15 100644 --- a/src/Fixer/Alias/PowToExponentiationFixer.php +++ b/src/Fixer/Alias/PowToExponentiationFixer.php @@ -23,9 +23,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class PowToExponentiationFixer extends AbstractFunctionReferenceFixer { /** diff --git a/src/Fixer/Alias/RandomApiMigrationFixer.php b/src/Fixer/Alias/RandomApiMigrationFixer.php index d88d1f6157c..a4772bcae37 100644 --- a/src/Fixer/Alias/RandomApiMigrationFixer.php +++ b/src/Fixer/Alias/RandomApiMigrationFixer.php @@ -103,7 +103,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $currIndex = 0; - while (null !== $currIndex) { + do { // try getting function reference and translate boundaries for humans $boundaries = $this->find($functionIdentity, $tokens, $currIndex, $tokens->count() - 1); @@ -112,7 +112,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue 2; } - list($functionName, $openParenthesis, $closeParenthesis) = $boundaries; + [$functionName, $openParenthesis, $closeParenthesis] = $boundaries; $count = $argumentsAnalyzer->countArguments($tokens, $openParenthesis, $closeParenthesis); if (!\in_array($count, $functionReplacement['argumentCount'], true)) { @@ -135,7 +135,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $currIndex += 6; } - } + } while (null !== $currIndex); } } @@ -147,7 +147,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn return new FixerConfigurationResolver([ (new FixerOptionBuilder('replacements', 'Mapping between replaced functions with the new ones.')) ->setAllowedTypes(['array']) - ->setAllowedValues([static function (array $value) { + ->setAllowedValues([static function (array $value): bool { foreach ($value as $functionName => $replacement) { if (!\array_key_exists($functionName, self::$argumentCounts)) { throw new InvalidOptionsException(sprintf( diff --git a/src/Fixer/Alias/SetTypeToCastFixer.php b/src/Fixer/Alias/SetTypeToCastFixer.php index ed568384133..5ecc2bd291e 100644 --- a/src/Fixer/Alias/SetTypeToCastFixer.php +++ b/src/Fixer/Alias/SetTypeToCastFixer.php @@ -22,9 +22,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class SetTypeToCastFixer extends AbstractFunctionReferenceFixer { /** diff --git a/src/Fixer/ArrayNotation/ArraySyntaxFixer.php b/src/Fixer/ArrayNotation/ArraySyntaxFixer.php index 28d44494407..c3d070de3f3 100644 --- a/src/Fixer/ArrayNotation/ArraySyntaxFixer.php +++ b/src/Fixer/ArrayNotation/ArraySyntaxFixer.php @@ -22,8 +22,6 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -32,7 +30,6 @@ * @author Gregor Harlan * @author Sebastiaan Stok * @author Dariusz Rumiński - * @author SpacePossum */ final class ArraySyntaxFixer extends AbstractFixer implements ConfigurableFixerInterface { @@ -65,9 +62,8 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'PHP arrays should be declared using the configured syntax.', [ - new VersionSpecificCodeSample( - " * @author Dariusz Rumiński - * @author Graham Campbell + * @author Graham Campbell */ final class NoMultilineWhitespaceAroundDoubleArrowFixer extends AbstractFixer { diff --git a/src/Fixer/ArrayNotation/TrimArraySpacesFixer.php b/src/Fixer/ArrayNotation/TrimArraySpacesFixer.php index 00f0d114c86..d2e19bfb7ac 100644 --- a/src/Fixer/ArrayNotation/TrimArraySpacesFixer.php +++ b/src/Fixer/ArrayNotation/TrimArraySpacesFixer.php @@ -88,7 +88,7 @@ private static function fixArray(Tokens $tokens, int $index): void !$nextNonWhitespaceToken->isComment() || $nextNonWhitespaceIndex === $prevNonWhitespaceIndex || $tokenAfterNextNonWhitespaceToken->isWhitespace(" \t") - || '/*' === substr($nextNonWhitespaceToken->getContent(), 0, 2) + || str_starts_with($nextNonWhitespaceToken->getContent(), '/*') ) ) { $tokens->clearAt($nextIndex); diff --git a/src/Fixer/Basic/BracesFixer.php b/src/Fixer/Basic/BracesFixer.php index b1940f937e8..f0dd9824caa 100644 --- a/src/Fixer/Basic/BracesFixer.php +++ b/src/Fixer/Basic/BracesFixer.php @@ -14,8 +14,10 @@ namespace PhpCsFixer\Fixer\Basic; -use PhpCsFixer\AbstractFixer; +use PhpCsFixer\AbstractProxyFixer; use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ControlStructure\ControlStructureContinuationPositionFixer; +use PhpCsFixer\Fixer\LanguageConstruct\DeclareParenthesesFixer; use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; @@ -35,7 +37,7 @@ * * @author Dariusz Rumiński */ -final class BracesFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface +final class BracesFixer extends AbstractProxyFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface { /** * @internal @@ -47,6 +49,11 @@ final class BracesFixer extends AbstractFixer implements ConfigurableFixerInterf */ public const LINE_SAME = 'same'; + /** + * @var null|ControlStructureContinuationPositionFixer + */ + private $controlStructureContinuationPositionFixer; + /** * {@inheritdoc} */ @@ -137,6 +144,17 @@ public function getPriority(): int return 35; } + public function configure(array $configuration = null): void + { + parent::configure($configuration); + + $this->getControlStructureContinuationPositionFixer()->configure([ + 'position' => self::LINE_NEXT === $this->configuration['position_after_control_structures'] + ? ControlStructureContinuationPositionFixer::NEXT_LINE + : ControlStructureContinuationPositionFixer::SAME_LINE, + ]); + } + /** * {@inheritdoc} */ @@ -153,9 +171,10 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $this->fixCommentBeforeBrace($tokens); $this->fixMissingControlBraces($tokens); $this->fixIndents($tokens); - $this->fixControlContinuationBraces($tokens); $this->fixSpaceAroundToken($tokens); $this->fixDoWhile($tokens); + + parent::applyFix($file, $tokens); } /** @@ -187,6 +206,14 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ]); } + protected function createProxyFixers(): array + { + return [ + $this->getControlStructureContinuationPositionFixer(), + new DeclareParenthesesFixer(), + ]; + } + private function fixCommentBeforeBrace(Tokens $tokens): void { $tokensAnalyzer = new TokensAnalyzer($tokens); @@ -210,7 +237,7 @@ private function fixCommentBeforeBrace(Tokens $tokens): void $commentIndex = $tokens->getNextNonWhitespace($prevIndex); $commentToken = $tokens[$commentIndex]; - if (!$commentToken->isGivenKind(T_COMMENT) || 0 === strpos($commentToken->getContent(), '/*')) { + if (!$commentToken->isGivenKind(T_COMMENT) || str_starts_with($commentToken->getContent(), '/*')) { continue; } @@ -245,34 +272,6 @@ private function fixCommentBeforeBrace(Tokens $tokens): void } } - private function fixControlContinuationBraces(Tokens $tokens): void - { - $controlContinuationTokens = $this->getControlContinuationTokens(); - - for ($index = \count($tokens) - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind($controlContinuationTokens)) { - continue; - } - - $prevIndex = $tokens->getPrevNonWhitespace($index); - $prevToken = $tokens[$prevIndex]; - - if (!$prevToken->equals('}')) { - continue; - } - - $tokens->ensureWhitespaceAtIndex( - $index - 1, - 1, - self::LINE_NEXT === $this->configuration['position_after_control_structures'] ? - $this->whitespacesConfig->getLineEnding().WhitespacesAnalyzer::detectIndent($tokens, $index) - : ' ' - ); - } - } - private function fixDoWhile(Tokens $tokens): void { for ($index = \count($tokens) - 1; 0 <= $index; --$index) { @@ -303,7 +302,7 @@ private function fixIndents(Tokens $tokens): void $controlTokens = $this->getControlTokens(); $indentTokens = array_filter( array_merge($classyAndFunctionTokens, $controlTokens), - static function (int $item) { + static function (int $item): bool { return T_SWITCH !== $item; } ); @@ -600,7 +599,7 @@ static function (int $item) { if ( !$isAnonymousClass && $tokens[$closingParenthesisIndex - 1]->isWhitespace() - && false !== strpos($tokens[$closingParenthesisIndex - 1]->getContent(), "\n") + && str_contains($tokens[$closingParenthesisIndex - 1]->getContent(), "\n") ) { if (!$tokens[$startBraceIndex - 2]->isComment()) { $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); @@ -659,9 +658,9 @@ private function fixMissingControlBraces(Tokens $tokens): void continue; } - // do not add for short 'if' followed by alternative loop, - // for example: if ($a) while ($b): ? > X < ?php endwhile; ? > - if ($tokenAfterParenthesis->isGivenKind([T_FOR, T_FOREACH, T_SWITCH, T_WHILE])) { + // do not add for 'short if' followed by alternative loop, for example: if ($a) while ($b): ? > X < ?php endwhile; ? > + // or 'short if' after an alternative loop, for example: foreach ($arr as $index => $item) if ($item): + if ($tokenAfterParenthesis->isGivenKind([T_FOR, T_FOREACH, T_SWITCH, T_WHILE, T_IF])) { $tokenAfterParenthesisBlockEnd = $tokens->findBlockEnd( // go to ')' Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextMeaningfulToken($nextAfterParenthesisEndIndex) @@ -697,8 +696,10 @@ private function fixSpaceAroundToken(Tokens $tokens): void // Declare tokens don't follow the same rules are other control statements if ($token->isGivenKind(T_DECLARE)) { - $this->fixDeclareStatement($tokens, $index); - } elseif ($token->isGivenKind($controlTokens) || $token->isGivenKind(CT::T_USE_LAMBDA)) { + continue; // delegated to DeclareParenthesesFixer + } + + if ($token->isGivenKind($controlTokens) || $token->isGivenKind(CT::T_USE_LAMBDA)) { $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($index); if (!$tokens[$nextNonWhitespaceIndex]->equals(':')) { @@ -869,37 +870,6 @@ private function getFinalControlContinuationTokensForOpeningToken(int $openingTo return []; } - private function fixDeclareStatement(Tokens $tokens, int $index): void - { - $tokens->removeTrailingWhitespace($index); - - $startParenthesisIndex = $tokens->getNextTokenOfKind($index, ['(']); - $tokens->removeTrailingWhitespace($startParenthesisIndex); - - $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); - $tokens->removeLeadingWhitespace($endParenthesisIndex); - - $startBraceIndex = $tokens->getNextTokenOfKind($endParenthesisIndex, [';', '{']); - $startBraceToken = $tokens[$startBraceIndex]; - - if ($startBraceToken->equals('{')) { - $this->fixSingleLineWhitespaceForDeclare($tokens, $startBraceIndex); - } - } - - private function fixSingleLineWhitespaceForDeclare(Tokens $tokens, int $startBraceIndex): void - { - // fix single-line whitespace before { - // eg: `declare(ticks=1){` => `declare(ticks=1) {` - // eg: `declare(ticks=1) {` => `declare(ticks=1) {` - if ( - !$tokens[$startBraceIndex - 1]->isWhitespace() - || $tokens[$startBraceIndex - 1]->isWhitespace(" \t") - ) { - $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); - } - } - private function ensureWhitespaceAtIndexAndIndentMultilineComment(Tokens $tokens, int $index, string $whitespace): void { if ($tokens[$index]->isWhitespace()) { @@ -918,8 +888,8 @@ private function ensureWhitespaceAtIndexAndIndentMultilineComment(Tokens $tokens $previousToken->isWhitespace() && 1 === Preg::match('/\R$/', $previousToken->getContent()) && ( - (0 === strpos($nextTokenContent, '//'.$this->whitespacesConfig->getIndent()) || '//' === $nextTokenContent) - || (0 === strpos($nextTokenContent, '#'.$this->whitespacesConfig->getIndent()) || '#' === $nextTokenContent) + (str_starts_with($nextTokenContent, '//'.$this->whitespacesConfig->getIndent()) || '//' === $nextTokenContent) + || (str_starts_with($nextTokenContent, '#'.$this->whitespacesConfig->getIndent()) || '#' === $nextTokenContent) ) ) { return; @@ -941,7 +911,7 @@ private function ensureWhitespaceAtIndexAndIndentMultilineComment(Tokens $tokens private function isMultilined(Tokens $tokens, int $startParenthesisIndex, int $endParenthesisIndex): bool { for ($i = $startParenthesisIndex; $i < $endParenthesisIndex; ++$i) { - if (false !== strpos($tokens[$i]->getContent(), "\n")) { + if (str_contains($tokens[$i]->getContent(), "\n")) { return true; } } @@ -963,7 +933,7 @@ private function isCommentWithFixableIndentation(Tokens $tokens, int $index): bo return false; } - if (0 === strpos($tokens[$index]->getContent(), '/*')) { + if (str_starts_with($tokens[$index]->getContent(), '/*')) { return true; } @@ -1009,7 +979,7 @@ private function getSiblingContinuousSingleLineComment(Tokens $tokens, int $inde if (null === $siblingIndex) { return null; } - } while (0 === strpos($tokens[$siblingIndex]->getContent(), '/*')); + } while (str_starts_with($tokens[$siblingIndex]->getContent(), '/*')); $newLines = 0; for ($i = min($siblingIndex, $index) + 1, $max = max($siblingIndex, $index); $i < $max; ++$i) { @@ -1024,4 +994,13 @@ private function getSiblingContinuousSingleLineComment(Tokens $tokens, int $inde return $siblingIndex; } + + private function getControlStructureContinuationPositionFixer(): ControlStructureContinuationPositionFixer + { + if (null === $this->controlStructureContinuationPositionFixer) { + $this->controlStructureContinuationPositionFixer = new ControlStructureContinuationPositionFixer(); + } + + return $this->controlStructureContinuationPositionFixer; + } } diff --git a/src/Fixer/Basic/EncodingFixer.php b/src/Fixer/Basic/EncodingFixer.php index 4e256e51f55..50044e3aa6a 100644 --- a/src/Fixer/Basic/EncodingFixer.php +++ b/src/Fixer/Basic/EncodingFixer.php @@ -37,7 +37,7 @@ public function __construct() { parent::__construct(); - $this->BOM = pack('CCC', 0xef, 0xbb, 0xbf); + $this->BOM = pack('CCC', 0xEF, 0xBB, 0xBF); } /** diff --git a/src/Fixer/Basic/NonPrintableCharacterFixer.php b/src/Fixer/Basic/NonPrintableCharacterFixer.php index 12be23d8085..3df6fefdbaf 100644 --- a/src/Fixer/Basic/NonPrintableCharacterFixer.php +++ b/src/Fixer/Basic/NonPrintableCharacterFixer.php @@ -19,16 +19,12 @@ use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; -use PhpCsFixer\FixerConfiguration\InvalidOptionsForEnvException; use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Preg; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -use Symfony\Component\OptionsResolver\Options; /** * Removes Zero-width space (ZWSP), Non-breaking space (NBSP) and other invisible unicode symbols. @@ -73,9 +69,8 @@ public function getDefinition(): FixerDefinitionInterface new CodeSample( ' false] ), ], @@ -109,13 +104,6 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn (new FixerOptionBuilder('use_escape_sequences_in_strings', 'Whether characters should be replaced with escape sequences in strings.')) ->setAllowedTypes(['bool']) ->setDefault(true) - ->setNormalizer(static function (Options $options, $value) { - if (\PHP_VERSION_ID < 70000 && $value) { - throw new InvalidOptionsForEnvException('Escape sequences require PHP 7.0+.'); - } - - return $value; - }) ->getOption(), ]); } @@ -128,7 +116,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $replacements = []; $escapeSequences = []; - foreach ($this->symbolsReplace as $character => list($replacement, $codepoint)) { + foreach ($this->symbolsReplace as $character => [$replacement, $codepoint]) { $replacements[$character] = $replacement; $escapeSequences[$character] = '\u{'.$codepoint.'}'; } @@ -151,7 +139,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ($previousToken->isGivenKind(T_START_HEREDOC)) { $previousTokenContent = $previousToken->getContent(); - if (false !== strpos($previousTokenContent, '\'')) { + if (str_contains($previousTokenContent, '\'')) { $tokens[$index - 1] = new Token([T_START_HEREDOC, str_replace('\'', '', $previousTokenContent)]); $stringTypeChanged = true; } diff --git a/src/Fixer/Basic/OctalNotationFixer.php b/src/Fixer/Basic/OctalNotationFixer.php new file mode 100644 index 00000000000..1e6755f3e4f --- /dev/null +++ b/src/Fixer/Basic/OctalNotationFixer.php @@ -0,0 +1,74 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Basic; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class OctalNotationFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition(): FixerDefinitionInterface + { + return new FixerDefinition( + 'Literal octal must be in `0o` notation.', + [ + new VersionSpecificCodeSample( + "= 80100 && $tokens->isTokenKindFound(T_LNUMBER); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens): void + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_LNUMBER)) { + continue; + } + + $content = $token->getContent(); + + if (1 !== Preg::match('#^0\d+$#', $content)) { + continue; + } + + $tokens[$index] = 1 === Preg::match('#^0+$#', $content) + ? new Token([T_LNUMBER, '0']) + : new Token([T_LNUMBER, '0o'.substr($content, 1)]) + ; + } + } +} diff --git a/src/Fixer/Basic/PsrAutoloadingFixer.php b/src/Fixer/Basic/PsrAutoloadingFixer.php index 4f79089a70b..0b3ebeb3af1 100644 --- a/src/Fixer/Basic/PsrAutoloadingFixer.php +++ b/src/Fixer/Basic/PsrAutoloadingFixer.php @@ -26,12 +26,13 @@ use PhpCsFixer\StdinFileInfo; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; /** * @author Jordi Boggiano * @author Dariusz Rumiński * @author Bram Gotink - * @author Graham Campbell + * @author Graham Campbell * @author Kuba Werłos */ final class PsrAutoloadingFixer extends AbstractFixer implements ConfigurableFixerInterface @@ -131,7 +132,7 @@ public function supports(\SplFileInfo $file): bool return false; } - // ignore stubs/fixtures, since they are typically containing invalid files for various reasons + // ignore stubs/fixtures, since they typically contain invalid files for various reasons return !Preg::match('{[/\\\\](stub|fixture)s?[/\\\\]}i', $file->getRealPath()); } @@ -153,7 +154,9 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn */ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { - if (null !== $this->configuration['dir'] && 0 !== strpos($file->getRealPath(), $this->configuration['dir'])) { + $tokenAnalyzer = new TokensAnalyzer($tokens); + + if (null !== $this->configuration['dir'] && !str_starts_with($file->getRealPath(), $this->configuration['dir'])) { return; } @@ -172,10 +175,9 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $namespaceStartIndex = $tokens->getNextMeaningfulToken($index); $namespaceEndIndex = $tokens->getNextTokenOfKind($namespaceStartIndex, [';']); - $namespace = trim($tokens->generatePartialCode($namespaceStartIndex, $namespaceEndIndex - 1)); } elseif ($token->isClassy()) { - if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NEW)) { + if ($tokenAnalyzer->isAnonymousClass($index)) { continue; } @@ -208,6 +210,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $configuredDir = realpath($this->configuration['dir']); $fileDir = \dirname($file->getRealPath()); + if (\strlen($configuredDir) >= \strlen($fileDir)) { return; } @@ -230,7 +233,6 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void private function calculateClassyName(\SplFileInfo $file, ?string $namespace, string $currentName): string { $name = $file->getBasename('.php'); - $maxNamespace = $this->calculateMaxNamespace($file, $namespace); if (null !== $this->configuration['dir']) { @@ -241,9 +243,11 @@ private function calculateClassyName(\SplFileInfo $file, ?string $namespace, str foreach ($namespaceParts as $namespacePart) { $nameCandidate = sprintf('%s_%s', $namespacePart, $name); + if (strtolower($nameCandidate) !== strtolower(substr($currentName, -\strlen($nameCandidate)))) { break; } + $name = $nameCandidate; } @@ -254,6 +258,7 @@ private function calculateMaxNamespace(\SplFileInfo $file, ?string $namespace): { if (null === $this->configuration['dir']) { $root = \dirname($file->getRealPath()); + while ($root !== \dirname($root)) { $root = \dirname($root); } @@ -274,9 +279,11 @@ private function calculateMaxNamespace(\SplFileInfo $file, ?string $namespace): if (!isset($namespaceAccordingToFileLocationPartsReversed[$key])) { break; } + if (strtolower($namespaceParte) !== strtolower($namespaceAccordingToFileLocationPartsReversed[$key])) { break; } + unset($namespaceAccordingToFileLocationPartsReversed[$key]); } diff --git a/src/Fixer/Casing/IntegerLiteralCaseFixer.php b/src/Fixer/Casing/IntegerLiteralCaseFixer.php new file mode 100644 index 00000000000..5d262ffef14 --- /dev/null +++ b/src/Fixer/Casing/IntegerLiteralCaseFixer.php @@ -0,0 +1,69 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Casing; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class IntegerLiteralCaseFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition(): FixerDefinitionInterface + { + return new FixerDefinition( + 'Integer literals must be in correct case.', + [ + new CodeSample( + "isTokenKindFound(T_LNUMBER); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens): void + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_LNUMBER)) { + continue; + } + + $content = $token->getContent(); + + if (1 !== Preg::match('#^0[bxoBXO][0-9a-fA-F]+$#', $content)) { + continue; + } + + $newContent = '0'.strtolower($content[1]).strtoupper(substr($content, 2)); + + if ($content === $newContent) { + continue; + } + + $tokens[$index] = new Token([T_LNUMBER, $newContent]); + } + } +} diff --git a/src/Fixer/Casing/LowercaseStaticReferenceFixer.php b/src/Fixer/Casing/LowercaseStaticReferenceFixer.php index 085296d1961..770e66a1c5e 100644 --- a/src/Fixer/Casing/LowercaseStaticReferenceFixer.php +++ b/src/Fixer/Casing/LowercaseStaticReferenceFixer.php @@ -18,8 +18,7 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -55,7 +54,7 @@ public function baz3(PaRent $x) } } '), - new VersionSpecificCodeSample( + new CodeSample( 'getPrevMeaningfulToken($index); - if ($tokens[$prevIndex]->isGivenKind([T_CONST, T_DOUBLE_COLON, T_FUNCTION, T_NAMESPACE, T_NS_SEPARATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC]) || $tokens[$prevIndex]->isObjectOperator()) { + if ($tokens[$prevIndex]->isGivenKind([T_CONST, T_DOUBLE_COLON, T_FUNCTION, T_NAMESPACE, T_NS_SEPARATOR]) || $tokens[$prevIndex]->isObjectOperator()) { continue; } $nextIndex = $tokens->getNextMeaningfulToken($index); - if ($tokens[$nextIndex]->isGivenKind([T_FUNCTION, T_NS_SEPARATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC])) { + if ($tokens[$nextIndex]->isGivenKind([T_FUNCTION, T_NS_SEPARATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_STRING, CT::T_NULLABLE_TYPE])) { continue; } diff --git a/src/Fixer/Casing/MagicMethodCasingFixer.php b/src/Fixer/Casing/MagicMethodCasingFixer.php index 45979c8a241..b0611219dbd 100644 --- a/src/Fixer/Casing/MagicMethodCasingFixer.php +++ b/src/Fixer/Casing/MagicMethodCasingFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class MagicMethodCasingFixer extends AbstractFixer { private static $magicNames = [ @@ -116,7 +113,8 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } $content = $tokens[$index]->getContent(); - if ('__' !== substr($content, 0, 2)) { + + if (!str_starts_with($content, '__')) { continue; // cheap look ahead } diff --git a/src/Fixer/Casing/NativeFunctionCasingFixer.php b/src/Fixer/Casing/NativeFunctionCasingFixer.php index db9e4fe9345..cf0f68da348 100644 --- a/src/Fixer/Casing/NativeFunctionCasingFixer.php +++ b/src/Fixer/Casing/NativeFunctionCasingFixer.php @@ -18,13 +18,10 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NativeFunctionCasingFixer extends AbstractFixer { /** @@ -61,6 +58,8 @@ public function isCandidate(Tokens $tokens): bool */ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { + $functionsAnalyzer = new FunctionsAnalyzer(); + static $nativeFunctionNames = null; if (null === $nativeFunctionNames) { @@ -69,30 +68,10 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { // test if we are at a function all - if (!$tokens[$index]->isGivenKind(T_STRING)) { - continue; - } - - $next = $tokens->getNextMeaningfulToken($index); - if (!$tokens[$next]->equals('(')) { - $index = $next; - + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { continue; } - $functionNamePrefix = $tokens->getPrevMeaningfulToken($index); - if ($tokens[$functionNamePrefix]->isGivenKind([T_DOUBLE_COLON, T_NEW, T_FUNCTION, CT::T_RETURN_REF]) || $tokens[$functionNamePrefix]->isObjectOperator()) { - continue; - } - - if ($tokens[$functionNamePrefix]->isGivenKind(T_NS_SEPARATOR)) { - // skip if the call is to a constructor or to a function in a namespace other than the default - $prev = $tokens->getPrevMeaningfulToken($functionNamePrefix); - if ($tokens[$prev]->isGivenKind([T_STRING, T_NEW])) { - continue; - } - } - // test if the function call is to a native PHP function $lower = strtolower($tokens[$index]->getContent()); if (!\array_key_exists($lower, $nativeFunctionNames)) { @@ -100,7 +79,6 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } $tokens[$index] = new Token([T_STRING, $nativeFunctionNames[$lower]]); - $index = $next; } } diff --git a/src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php b/src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php index 32da7ea37b1..3d2bddecd80 100644 --- a/src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php +++ b/src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php @@ -25,9 +25,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer { /** @@ -45,6 +42,7 @@ final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer * object PHP 7.2 * static PHP 8.0 (return type only) * mixed PHP 8.0 + * never PHP 8.1 * * @var array */ @@ -65,27 +63,23 @@ public function __construct() 'self' => true, ]; - if (\PHP_VERSION_ID >= 70000) { - $this->hints = array_merge( - $this->hints, - [ - 'bool' => true, - 'float' => true, - 'int' => true, - 'string' => true, - ] - ); - } + $this->hints = array_merge( + $this->hints, + [ + 'bool' => true, + 'float' => true, + 'int' => true, + 'string' => true, + ] + ); - if (\PHP_VERSION_ID >= 70100) { - $this->hints = array_merge( - $this->hints, - [ - 'iterable' => true, - 'void' => true, - ] - ); - } + $this->hints = array_merge( + $this->hints, + [ + 'iterable' => true, + 'void' => true, + ] + ); if (\PHP_VERSION_ID >= 70200) { $this->hints = array_merge($this->hints, ['object' => true]); @@ -96,6 +90,10 @@ public function __construct() $this->hints = array_merge($this->hints, ['mixed' => true]); } + if (\PHP_VERSION_ID >= 80100) { + $this->hints = array_merge($this->hints, ['never' => true]); + } + $this->functionsAnalyzer = new FunctionsAnalyzer(); } @@ -108,13 +106,11 @@ public function getDefinition(): FixerDefinitionInterface 'Native type hints for functions should use the correct case.', [ new CodeSample("count() - 1; $index >= 0; --$index) { if ($tokens[$index]->isGivenKind(T_FUNCTION)) { - if (\PHP_VERSION_ID >= 70000) { - $this->fixFunctionReturnType($tokens, $index); - } - + $this->fixFunctionReturnType($tokens, $index); $this->fixFunctionArgumentTypes($tokens, $index); } } diff --git a/src/Fixer/CastNotation/LowercaseCastFixer.php b/src/Fixer/CastNotation/LowercaseCastFixer.php index a3f501af891..f0e30ce2d0e 100644 --- a/src/Fixer/CastNotation/LowercaseCastFixer.php +++ b/src/Fixer/CastNotation/LowercaseCastFixer.php @@ -22,9 +22,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class LowercaseCastFixer extends AbstractFixer { /** diff --git a/src/Fixer/CastNotation/ModernizeTypesCastingFixer.php b/src/Fixer/CastNotation/ModernizeTypesCastingFixer.php index 2ebb286a626..e645149c59d 100644 --- a/src/Fixer/CastNotation/ModernizeTypesCastingFixer.php +++ b/src/Fixer/CastNotation/ModernizeTypesCastingFixer.php @@ -76,15 +76,17 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void foreach ($replacement as $functionIdentity => $newToken) { $currIndex = 0; - while (null !== $currIndex) { + + do { // try getting function reference and translate boundaries for humans $boundaries = $this->find($functionIdentity, $tokens, $currIndex, $tokens->count() - 1); + if (null === $boundaries) { // next function search, as current one not found continue 2; } - list($functionName, $openParenthesis, $closeParenthesis) = $boundaries; + [$functionName, $openParenthesis, $closeParenthesis] = $boundaries; // analysing cursor shift $currIndex = $openParenthesis; @@ -96,6 +98,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $paramContentEnd = $closeParenthesis; $commaCandidate = $tokens->getPrevMeaningfulToken($paramContentEnd); + if ($tokens[$commaCandidate]->equals(',')) { $tokens->removeTrailingWhitespace($commaCandidate); $tokens->clearAt($commaCandidate); @@ -104,6 +107,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // check if something complex passed as an argument and preserve parenthesises then $countParamTokens = 0; + for ($paramContentIndex = $openParenthesis + 1; $paramContentIndex < $paramContentEnd; ++$paramContentIndex) { //not a space, means some sensible token if (!$tokens[$paramContentIndex]->isGivenKind(T_WHITESPACE)) { @@ -111,14 +115,15 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } } - $preserveParenthesises = $countParamTokens > 1; + $preserveParentheses = $countParamTokens > 1; $afterCloseParenthesisIndex = $tokens->getNextMeaningfulToken($closeParenthesis); $afterCloseParenthesisToken = $tokens[$afterCloseParenthesisIndex]; - $wrapInParenthesises = $afterCloseParenthesisToken->equalsAny(['[', '{']) || $afterCloseParenthesisToken->isGivenKind(T_POW); + $wrapInParentheses = $afterCloseParenthesisToken->equalsAny(['[', '{']) || $afterCloseParenthesisToken->isGivenKind(T_POW); // analyse namespace specification (root one or none) and decide what to do $prevTokenIndex = $tokens->getPrevMeaningfulToken($functionName); + if ($tokens[$prevTokenIndex]->isGivenKind(T_NS_SEPARATOR)) { // get rid of root namespace when it used $tokens->removeTrailingWhitespace($prevTokenIndex); @@ -130,11 +135,12 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void new Token($newToken), new Token([T_WHITESPACE, ' ']), ]; - if ($wrapInParenthesises) { + + if ($wrapInParentheses) { array_unshift($replacementSequence, new Token('(')); } - if (!$preserveParenthesises) { + if (!$preserveParentheses) { // closing parenthesis removed with leading spaces $tokens->removeLeadingWhitespace($closeParenthesis); $tokens->clearAt($closeParenthesis); @@ -148,7 +154,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $tokens->removeTrailingWhitespace($functionName); } - if ($wrapInParenthesises) { + if ($wrapInParentheses) { $tokens->insertAt($closeParenthesis, new Token(')')); } @@ -156,7 +162,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // nested transformations support $currIndex = $functionName; - } + } while (null !== $currIndex); } } } diff --git a/src/Fixer/CastNotation/NoShortBoolCastFixer.php b/src/Fixer/CastNotation/NoShortBoolCastFixer.php index dbe032add6b..d802d49526d 100644 --- a/src/Fixer/CastNotation/NoShortBoolCastFixer.php +++ b/src/Fixer/CastNotation/NoShortBoolCastFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NoShortBoolCastFixer extends AbstractFixer { /** diff --git a/src/Fixer/CastNotation/NoUnsetCastFixer.php b/src/Fixer/CastNotation/NoUnsetCastFixer.php index 79d6c242a78..c75f8ba429b 100644 --- a/src/Fixer/CastNotation/NoUnsetCastFixer.php +++ b/src/Fixer/CastNotation/NoUnsetCastFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NoUnsetCastFixer extends AbstractFixer { /** diff --git a/src/Fixer/CastNotation/ShortScalarCastFixer.php b/src/Fixer/CastNotation/ShortScalarCastFixer.php index d7758480200..983effde72e 100644 --- a/src/Fixer/CastNotation/ShortScalarCastFixer.php +++ b/src/Fixer/CastNotation/ShortScalarCastFixer.php @@ -22,9 +22,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class ShortScalarCastFixer extends AbstractFixer { /** diff --git a/src/Fixer/ClassNotation/ClassAttributesSeparationFixer.php b/src/Fixer/ClassNotation/ClassAttributesSeparationFixer.php index eb441b2fc33..d4c70625900 100644 --- a/src/Fixer/ClassNotation/ClassAttributesSeparationFixer.php +++ b/src/Fixer/ClassNotation/ClassAttributesSeparationFixer.php @@ -36,31 +36,26 @@ * Make sure there is one blank line above and below class elements. * * The exception is when an element is the first or last item in a 'classy'. - * - * @author SpacePossum */ final class ClassAttributesSeparationFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface { - private const SPACING_NONE = 'none'; + /** + * @internal + */ + public const SPACING_NONE = 'none'; - private const SPACING_ONE = 'one'; + /** + * @internal + */ + public const SPACING_ONE = 'one'; private const SPACING_ONLY_IF_META = 'only_if_meta'; - private const SUPPORTED_SPACINGS = [self::SPACING_NONE, self::SPACING_ONE, self::SPACING_ONLY_IF_META]; - - private const SUPPORTED_TYPES = ['const', 'method', 'property', 'trait_import']; - /** * @var array */ private $classElementTypes = []; - /** - * @var array - */ - private $possibleMetadataKinds = []; - /** * {@inheritdoc} */ @@ -73,12 +68,6 @@ public function configure(array $configuration): void foreach ($this->configuration['elements'] as $elementType => $spacing) { $this->classElementTypes[$elementType] = $spacing; } - - $this->possibleMetadataKinds = [T_DOC_COMMENT]; - if (\defined('T_ATTRIBUTE')) { - // @todo remove check when PHP 8.0+ is required - $this->possibleMetadataKinds[] = T_ATTRIBUTE; - } } /** @@ -107,7 +96,7 @@ protected function bar() new CodeSample( ' ['property' => self::SPACING_ONLY_IF_META]] - ), - new VersionSpecificCodeSample( - 'getElementsByClass($tokens) as $class) { + $elements = $class['elements']; + $elementCount = \count($elements); - foreach (array_reverse($tokensAnalyzer->getClassyElements(), true) as $index => $element) { - if (!isset($this->classElementTypes[$element['type']])) { - continue; // not configured to be fixed + if (0 === $elementCount) { + continue; } - $spacing = $this->classElementTypes[$element['type']]; - - if ($element['classIndex'] !== $class) { - $class = $element['classIndex']; - $classStart = $tokens->getNextTokenOfKind($class, ['{']); - $classEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classStart); + if (isset($this->classElementTypes[$elements[0]['type']])) { + $this->fixSpaceBelowClassElement($tokens, $class); + $this->fixSpaceAboveClassElement($tokens, $class, 0); } - if ('method' === $element['type'] && !$tokens[$class]->isGivenKind(T_INTERFACE)) { - // method of class or trait - $attributes = $tokensAnalyzer->getMethodAttributes($index); - - $methodEnd = true === $attributes['abstract'] - ? $tokens->getNextTokenOfKind($index, [';']) - : $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $tokens->getNextTokenOfKind($index, ['{'])) - ; - - $this->fixSpaceBelowClassMethod($tokens, $classEnd, $methodEnd, $spacing); - $this->fixSpaceAboveClassElement($tokens, $classStart, $index, $spacing); - - continue; + for ($index = 1; $index < $elementCount; ++$index) { + if (isset($this->classElementTypes[$elements[$index]['type']])) { + $this->fixSpaceAboveClassElement($tokens, $class, $index); + } } - - // `const`, `property` or `method` of an `interface` - $this->fixSpaceBelowClassElement($tokens, $classEnd, $tokens->getNextTokenOfKind($index, [';']), $spacing); - $this->fixSpaceAboveClassElement($tokens, $classStart, $index, $spacing); } } @@ -248,26 +204,30 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void protected function createConfigurationDefinition(): FixerConfigurationResolverInterface { return new FixerConfigurationResolver([ - (new FixerOptionBuilder('elements', sprintf('Dictionary of `%s` => `%s` values.', implode('|', self::SUPPORTED_TYPES), implode('|', self::SUPPORTED_SPACINGS)))) + (new FixerOptionBuilder('elements', 'Dictionary of `const|method|property|trait_import` => `none|one|only_if_meta` values.')) ->setAllowedTypes(['array']) - ->setAllowedValues([static function (array $option) { + ->setAllowedValues([static function (array $option): bool { foreach ($option as $type => $spacing) { - if (!\in_array($type, self::SUPPORTED_TYPES, true)) { + $supportedTypes = ['const', 'method', 'property', 'trait_import']; + + if (!\in_array($type, $supportedTypes, true)) { throw new InvalidOptionsException( sprintf( 'Unexpected element type, expected any of "%s", got "%s".', - implode('", "', self::SUPPORTED_TYPES), + implode('", "', $supportedTypes), \gettype($type).'#'.$type ) ); } - if (!\in_array($spacing, self::SUPPORTED_SPACINGS, true)) { + $supportedSpacings = [self::SPACING_NONE, self::SPACING_ONE, self::SPACING_ONLY_IF_META]; + + if (!\in_array($spacing, $supportedSpacings, true)) { throw new InvalidOptionsException( sprintf( 'Unexpected spacing for element type "%s", expected any of "%s", got "%s".', $spacing, - implode('", "', self::SUPPORTED_SPACINGS), + implode('", "', $supportedSpacings), \is_object($spacing) ? \get_class($spacing) : (null === $spacing ? 'null' : \gettype($spacing).'#'.$spacing) ) ); @@ -280,197 +240,132 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn 'const' => self::SPACING_ONE, 'method' => self::SPACING_ONE, 'property' => self::SPACING_ONE, - 'trait_import' => self::SPACING_ONE, + 'trait_import' => self::SPACING_NONE, ]) ->getOption(), ]); } - /** - * Fix spacing below an element of a class, interface or trait. - * - * Deals with comments, PHPDocs and spaces above the element with respect to the position of the - * element within the class, interface or trait. - */ - private function fixSpaceBelowClassElement(Tokens $tokens, int $classEndIndex, int $elementEndIndex, string $spacing): void - { - for ($nextNotWhite = $elementEndIndex + 1;; ++$nextNotWhite) { - if (($tokens[$nextNotWhite]->isComment() || $tokens[$nextNotWhite]->isWhitespace()) && false === strpos($tokens[$nextNotWhite]->getContent(), "\n")) { - continue; - } - - break; - } - - if ($tokens[$nextNotWhite]->isWhitespace()) { - $nextNotWhite = $tokens->getNextNonWhitespace($nextNotWhite); - } - - $functionIndex = $tokens->getTokenNotOfKindsSibling($nextNotWhite - 1, 1, [T_ABSTRACT, T_FINAL, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_WHITESPACE, T_COMMENT, T_DOC_COMMENT]); - - if ($tokens[$functionIndex]->isGivenKind(T_FUNCTION)) { - $this->correctLineBreaks($tokens, $elementEndIndex, $nextNotWhite, 2); - - return; - } - - $reqLineCount = $this->determineRequiredLineCount($tokens, $nextNotWhite, $classEndIndex, $spacing); - - $this->correctLineBreaks($tokens, $elementEndIndex, $nextNotWhite, $reqLineCount); - } - - /** - * Fix spacing below a method of a class or trait. - * - * Deals with comments, PHPDocs and spaces above the method with respect to the position of the - * method within the class or trait. - */ - private function fixSpaceBelowClassMethod(Tokens $tokens, int $classEndIndex, int $elementEndIndex, string $spacing): void - { - $nextNotWhite = $tokens->getNextNonWhitespace($elementEndIndex); - $reqLineCount = $this->determineRequiredLineCount($tokens, $nextNotWhite, $classEndIndex, $spacing); - - $this->correctLineBreaks($tokens, $elementEndIndex, $nextNotWhite, $reqLineCount); - } - /** * Fix spacing above an element of a class, interface or trait. * * Deals with comments, PHPDocs and spaces above the element with respect to the position of the * element within the class, interface or trait. - * - * @param int $classStartIndex index of the class Token the element is in - * @param int $elementIndex index of the element to fix */ - private function fixSpaceAboveClassElement(Tokens $tokens, int $classStartIndex, int $elementIndex, string $spacing): void + private function fixSpaceAboveClassElement(Tokens $tokens, array $class, int $elementIndex): void { - static $methodAttr = [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_ABSTRACT, T_FINAL, T_STATIC, T_STRING, T_NS_SEPARATOR, T_VAR, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, CT::T_TYPE_ALTERNATION]; - - $nonWhiteAbove = null; + $element = $class['elements'][$elementIndex]; + $elementAboveEnd = isset($class['elements'][$elementIndex + 1]) ? $class['elements'][$elementIndex + 1]['end'] : 0; + $nonWhiteAbove = $tokens->getPrevNonWhitespace($element['start']); - // find out where the element definition starts - $firstElementAttributeIndex = $elementIndex; + // element is directly after class open brace + if ($nonWhiteAbove === $class['open']) { + $this->correctLineBreaks($tokens, $nonWhiteAbove, $element['start'], 1); - for ($i = $elementIndex; $i > $classStartIndex; --$i) { - $nonWhiteAbove = $tokens->getPrevNonWhitespace($i); - - if (null !== $nonWhiteAbove && $tokens[$nonWhiteAbove]->isGivenKind($methodAttr)) { - $firstElementAttributeIndex = $nonWhiteAbove; - } else { - break; - } + return; } // deal with comments above an element if ($tokens[$nonWhiteAbove]->isGivenKind(T_COMMENT)) { - if (1 === $firstElementAttributeIndex - $nonWhiteAbove) { - // no white space found between comment and element start - $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 1); + // check if the comment belongs to the previous element + if ($elementAboveEnd === $nonWhiteAbove) { + $this->correctLineBreaks($tokens, $nonWhiteAbove, $element['start'], $this->determineRequiredLineCount($tokens, $class, $elementIndex)); return; } - // $tokens[$nonWhiteAbove + 1] is always a white space token here - if (substr_count($tokens[$nonWhiteAbove + 1]->getContent(), "\n") > 1) { - // more than one line break, always bring it back to 2 line breaks between the element start and what is above it - $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 2); + // more than one line break, always bring it back to 2 line breaks between the element start and what is above it + if ($tokens[$nonWhiteAbove + 1]->isWhitespace() && substr_count($tokens[$nonWhiteAbove + 1]->getContent(), "\n") > 1) { + $this->correctLineBreaks($tokens, $nonWhiteAbove, $element['start'], 2); return; } // there are 2 cases: - if ($tokens[$nonWhiteAbove - 1]->isWhitespace() && substr_count($tokens[$nonWhiteAbove - 1]->getContent(), "\n") > 0) { + if ( + 1 === $element['start'] - $nonWhiteAbove + || $tokens[$nonWhiteAbove - 1]->isWhitespace() && substr_count($tokens[$nonWhiteAbove - 1]->getContent(), "\n") > 0 + || $tokens[$nonWhiteAbove + 1]->isWhitespace() && substr_count($tokens[$nonWhiteAbove + 1]->getContent(), "\n") > 0 + ) { // 1. The comment is meant for the element (although not a PHPDoc), // make sure there is one line break between the element and the comment... - $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 1); + $this->correctLineBreaks($tokens, $nonWhiteAbove, $element['start'], 1); // ... and make sure there is blank line above the comment (with the exception when it is directly after a class opening) - $nonWhiteAbove = $this->findCommentBlockStart($tokens, $nonWhiteAbove); + $nonWhiteAbove = $this->findCommentBlockStart($tokens, $nonWhiteAbove, $elementAboveEnd); $nonWhiteAboveComment = $tokens->getPrevNonWhitespace($nonWhiteAbove); - $this->correctLineBreaks($tokens, $nonWhiteAboveComment, $nonWhiteAbove, $nonWhiteAboveComment === $classStartIndex ? 1 : 2); + $this->correctLineBreaks($tokens, $nonWhiteAboveComment, $nonWhiteAbove, $nonWhiteAboveComment === $class['open'] ? 1 : 2); } else { // 2. The comment belongs to the code above the element, // make sure there is a blank line above the element (i.e. 2 line breaks) - $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 2); + $this->correctLineBreaks($tokens, $nonWhiteAbove, $element['start'], 2); } return; } - // deal with element with a PHPDoc above it - if ($tokens[$nonWhiteAbove]->isGivenKind(T_DOC_COMMENT)) { - // there should be one linebreak between the element and the PHPDoc above it - $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 1); - - // there should be one blank line between the PHPDoc and whatever is above (with the exception when it is directly after a class opening) - $nonWhiteAbovePHPDoc = $tokens->getPrevNonWhitespace($nonWhiteAbove); - $reqLineCount = $nonWhiteAbovePHPDoc === $classStartIndex ? 1 : 2; + // deal with element with a PHPDoc/attribute above it + if ($tokens[$nonWhiteAbove]->isGivenKind([T_DOC_COMMENT, CT::T_ATTRIBUTE_CLOSE])) { + // there should be one linebreak between the element and the attribute above it + $this->correctLineBreaks($tokens, $nonWhiteAbove, $element['start'], 1); - if ($tokens[$nonWhiteAbovePHPDoc]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { - // PHPDocs can have attributes adjacent to them, so adjust our comparison points - list($nonWhiteAbove, $nonWhiteAbovePHPDoc, $reqLineCount) = $this->getAttributePhpdocSequenceOffset($tokens, $nonWhiteAbovePHPDoc, $classStartIndex); - } + // make sure there is blank line above the comment (with the exception when it is directly after a class opening) + $nonWhiteAbove = $this->findCommentBlockStart($tokens, $nonWhiteAbove, $elementAboveEnd); + $nonWhiteAboveComment = $tokens->getPrevNonWhitespace($nonWhiteAbove); - $this->correctLineBreaks($tokens, $nonWhiteAbovePHPDoc, $nonWhiteAbove, $reqLineCount); + $this->correctLineBreaks($tokens, $nonWhiteAboveComment, $nonWhiteAbove, $nonWhiteAboveComment === $class['open'] ? 1 : 2); return; } - // deal with element with an attribute above it - if ($tokens[$nonWhiteAbove]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { - // there should be one linebreak between the element and the attribute above it - $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 1); - - // make sure there is blank line above the attribute comment - // with the exception when it is directly after a class opening or has an adjacent PHPDoc - list($nonWhiteAbove, $nonWhiteAboveComment, $reqLineCount) = $this->getAttributePhpdocSequenceOffset($tokens, $nonWhiteAbove, $classStartIndex); + $this->correctLineBreaks($tokens, $nonWhiteAbove, $element['start'], $this->determineRequiredLineCount($tokens, $class, $elementIndex)); + } - $this->correctLineBreaks($tokens, $nonWhiteAboveComment, $nonWhiteAbove, $reqLineCount); + private function determineRequiredLineCount(Tokens $tokens, array $class, int $elementIndex): int + { + $type = $class['elements'][$elementIndex]['type']; + $spacing = $this->classElementTypes[$type]; - return; + if (self::SPACING_ONE === $spacing) { + return 2; } - $reqLineCount = $this->determineRequiredLineCount($tokens, $nonWhiteAbove, $classStartIndex, $spacing); + if (self::SPACING_NONE === $spacing) { + if (!isset($class['elements'][$elementIndex + 1])) { + return 1; + } - $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, $reqLineCount); - } + $aboveElement = $class['elements'][$elementIndex + 1]; - /** - * @return array - */ - private function getAttributePhpdocSequenceOffset(Tokens $tokens, int $attributeCloseIndex, int $classStartIndex): array - { - $attributeStartIndex = $this->findAttributeBlockStart($tokens, $attributeCloseIndex); - $nonWhiteAboveAttribute = $tokens->getNonWhitespaceSibling($attributeStartIndex, -1); - $reqLineCount = $nonWhiteAboveAttribute === $classStartIndex || $tokens[$nonWhiteAboveAttribute]->isGivenKind(T_DOC_COMMENT) ? 1 : 2; + if ($aboveElement['type'] !== $type) { + return 2; + } - return [$attributeStartIndex, $nonWhiteAboveAttribute, $reqLineCount]; - } + $aboveElementDocCandidateIndex = $tokens->getPrevNonWhitespace($aboveElement['start']); - private function determineRequiredLineCount(Tokens $tokens, int $notWhiteIndex, int $classStartOrEndIndex, string $spacing): int - { - // if the two indices are equal, this means the index is either at the - // start or end of the class and no additional line breaks are needed - if ($notWhiteIndex === $classStartOrEndIndex) { - return 1; + return $tokens[$aboveElementDocCandidateIndex]->isGivenKind([T_DOC_COMMENT, CT::T_ATTRIBUTE_CLOSE]) ? 2 : 1; } - if (self::SPACING_NONE === $spacing) { - return 1; - } + if (self::SPACING_ONLY_IF_META === $spacing) { + $aboveElementDocCandidateIndex = $tokens->getPrevNonWhitespace($class['elements'][$elementIndex]['start']); - if (self::SPACING_ONE === $spacing) { - return 2; + return $tokens[$aboveElementDocCandidateIndex]->isGivenKind([T_DOC_COMMENT, CT::T_ATTRIBUTE_CLOSE]) ? 2 : 1; } - if (self::SPACING_ONLY_IF_META === $spacing && $tokens[$notWhiteIndex]->isGivenKind($this->possibleMetadataKinds)) { - return 2; - } + throw new \RuntimeException(sprintf('Unknown spacing "%s".', $spacing)); + } + + private function fixSpaceBelowClassElement(Tokens $tokens, array $class): void + { + $element = $class['elements'][0]; - return 1; + // if this is last element fix; fix to the class end `}` here if appropriate + if ($class['close'] === $tokens->getNextNonWhitespace($element['end'])) { + $this->correctLineBreaks($tokens, $element['end'], $class['close'], 1); + } } - private function correctLineBreaks(Tokens $tokens, int $startIndex, int $endIndex, int $reqLineCount = 2): void + private function correctLineBreaks(Tokens $tokens, int $startIndex, int $endIndex, int $reqLineCount): void { $lineEnding = $this->whitespacesConfig->getLineEnding(); @@ -524,22 +419,26 @@ private function correctLineBreaks(Tokens $tokens, int $startIndex, int $endInde } } - private function getLineBreakCount(Tokens $tokens, int $whiteSpaceStartIndex, int $whiteSpaceEndIndex): int + private function getLineBreakCount(Tokens $tokens, int $startIndex, int $endIndex): int { $lineCount = 0; - for ($i = $whiteSpaceStartIndex; $i < $whiteSpaceEndIndex; ++$i) { + for ($i = $startIndex; $i < $endIndex; ++$i) { $lineCount += substr_count($tokens[$i]->getContent(), "\n"); } return $lineCount; } - private function findCommentBlockStart(Tokens $tokens, int $commentIndex): int + private function findCommentBlockStart(Tokens $tokens, int $start, int $elementAboveEnd): int { - $start = $commentIndex; + for ($i = $start; $i > $elementAboveEnd; --$i) { + if ($tokens[$i]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { + $start = $i = $tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $i); + + continue; + } - for ($i = $commentIndex - 1; $i > 0; --$i) { if ($tokens[$i]->isComment()) { $start = $i; @@ -554,25 +453,125 @@ private function findCommentBlockStart(Tokens $tokens, int $commentIndex): int return $start; } - /** - * @param int $index attribute close index - */ - private function findAttributeBlockStart(Tokens $tokens, int $index): int + private function getElementsByClass(Tokens $tokens): \Generator { - $start = $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $index); + $tokensAnalyzer = new TokensAnalyzer($tokens); + $class = $classIndex = false; + $elements = $tokensAnalyzer->getClassyElements(); - for ($i = $index - 1; $i > 0; --$i) { - if ($tokens[$i]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { - $start = $i = $tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $i); + for (end($elements);; prev($elements)) { + $index = key($elements); - continue; + if (null === $index) { + break; } - if (!$tokens[$i]->isWhitespace() || $this->getLineBreakCount($tokens, $i, $i + 1) > 1) { + $element = current($elements); + $element['index'] = $index; + + if ($element['classIndex'] !== $classIndex) { + if (false !== $class) { + yield $class; + } + + $classIndex = $element['classIndex']; + $classOpen = $tokens->getNextTokenOfKind($classIndex, ['{']); + $classEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classOpen); + $class = [ + 'index' => $classIndex, + 'open' => $classOpen, + 'close' => $classEnd, + 'elements' => [], + ]; + } + + unset($element['classIndex']); + $element['start'] = $this->getFirstTokenIndexOfClassElement($tokens, $class, $element); + $element['end'] = $this->getLastTokenIndexOfClassElement($tokens, $class, $element, $tokensAnalyzer); + + $class['elements'][] = $element; // reset the key by design + } + + if (false !== $class) { + yield $class; + } + } + + private function getFirstTokenIndexOfClassElement(Tokens $tokens, array $class, array $element): int + { + $modifierTypes = [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_ABSTRACT, T_FINAL, T_STATIC, T_STRING, T_NS_SEPARATOR, T_VAR, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, CT::T_TYPE_ALTERNATION]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $modifierTypes[] = T_READONLY; + } + + $firstElementAttributeIndex = $element['index']; + + do { + $nonWhiteAbove = $tokens->getPrevMeaningfulToken($firstElementAttributeIndex); + + if (null !== $nonWhiteAbove && $tokens[$nonWhiteAbove]->isGivenKind($modifierTypes)) { + $firstElementAttributeIndex = $nonWhiteAbove; + } else { break; } + } while ($firstElementAttributeIndex > $class['open']); + + return $firstElementAttributeIndex; + } + + // including trailing single line comments if belonging to the class element + private function getLastTokenIndexOfClassElement(Tokens $tokens, array $class, array $element, TokensAnalyzer $tokensAnalyzer): int + { + // find last token of the element + if ('method' === $element['type'] && !$tokens[$class['index']]->isGivenKind(T_INTERFACE)) { + $attributes = $tokensAnalyzer->getMethodAttributes($element['index']); + + if (true === $attributes['abstract']) { + $elementEndIndex = $tokens->getNextTokenOfKind($element['index'], [';']); + } else { + $elementEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $tokens->getNextTokenOfKind($element['index'], ['{'])); + } + } elseif ('trait_import' === $element['type']) { + $elementEndIndex = $element['index']; + + do { + $elementEndIndex = $tokens->getNextMeaningfulToken($elementEndIndex); + } while ($tokens[$elementEndIndex]->isGivenKind([T_STRING, T_NS_SEPARATOR]) || $tokens[$elementEndIndex]->equals(',')); + + if (!$tokens[$elementEndIndex]->equals(';')) { + $elementEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $tokens->getNextTokenOfKind($element['index'], ['{'])); + } + } else { // const or property + $elementEndIndex = $tokens->getNextTokenOfKind($element['index'], [';']); } - return $start; + $singleLineElement = true; + + for ($i = $element['index'] + 1; $i < $elementEndIndex; ++$i) { + if (str_contains($tokens[$i]->getContent(), "\n")) { + $singleLineElement = false; + + break; + } + } + + if ($singleLineElement) { + while (true) { + $nextToken = $tokens[$elementEndIndex + 1]; + + if (($nextToken->isComment() || $nextToken->isWhitespace()) && !str_contains($nextToken->getContent(), "\n")) { + ++$elementEndIndex; + } else { + break; + } + } + + if ($tokens[$elementEndIndex]->isWhitespace()) { + $elementEndIndex = $tokens->getPrevNonWhitespace($elementEndIndex); + } + } + + return $elementEndIndex; } } diff --git a/src/Fixer/ClassNotation/ClassDefinitionFixer.php b/src/Fixer/ClassNotation/ClassDefinitionFixer.php index 38d9cd04e88..1ed02a79411 100644 --- a/src/Fixer/ClassNotation/ClassDefinitionFixer.php +++ b/src/Fixer/ClassNotation/ClassDefinitionFixer.php @@ -23,16 +23,12 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\TokensAnalyzer; /** * Fixer for part of the rules defined in PSR2 ¶4.1 Extends and Implements and PSR12 ¶8. Anonymous Classes. - * - * @author SpacePossum */ final class ClassDefinitionFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface { @@ -58,14 +54,9 @@ final class Foo extends Bar implements Baz, BarBaz trait Foo { } -' - ), - new VersionSpecificCodeSample( - ' true] ), + new CodeSample( + ' true] + ), ] ); } @@ -149,6 +146,10 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ->setAllowedTypes(['bool']) ->setDefault(false) ->getOption(), + (new FixerOptionBuilder('space_before_parenthesis', 'Whether there should be a single space after the parenthesis of anonymous class (PSR12) or not.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), ]); } @@ -182,6 +183,7 @@ private function fixClassyDefinition(Tokens $tokens, int $classyIndex): void // PSR12: anonymous class curly brace on same line if not multi line implements. $classDefInfo['open'] = $this->fixClassyDefinitionOpenSpacing($tokens, $classDefInfo); + if ($classDefInfo['implements']) { $end = $classDefInfo['implements']['start']; } elseif ($classDefInfo['extends']) { @@ -191,11 +193,7 @@ private function fixClassyDefinition(Tokens $tokens, int $classyIndex): void } // 4.1 The extends and implements keywords MUST be declared on the same line as the class name. - $this->makeClassyDefinitionSingleLine( - $tokens, - $classDefInfo['anonymousClass'] ? $tokens->getPrevMeaningfulToken($classyIndex) : $classDefInfo['start'], - $end - ); + $this->makeClassyDefinitionSingleLine($tokens, $classDefInfo['start'], $end); } private function fixClassyDefinitionExtends(Tokens $tokens, int $classOpenIndex, array $classExtendsInfo): array @@ -249,7 +247,8 @@ private function fixClassyDefinitionOpenSpacing(Tokens $tokens, array $classDefI } $openIndex = $tokens->getNextTokenOfKind($classDefInfo['classy'], ['{']); - if (' ' !== $spacing && false !== strpos($tokens[$openIndex - 1]->getContent(), "\n")) { + + if (' ' !== $spacing && str_contains($tokens[$openIndex - 1]->getContent(), "\n")) { return $openIndex; } @@ -269,9 +268,6 @@ private function fixClassyDefinitionOpenSpacing(Tokens $tokens, array $classDefI private function getClassyDefinitionInfo(Tokens $tokens, int $classyIndex): array { $openIndex = $tokens->getNextTokenOfKind($classyIndex, ['{']); - $prev = $tokens->getPrevMeaningfulToken($classyIndex); - $startIndex = $tokens[$prev]->isGivenKind([T_FINAL, T_ABSTRACT]) ? $prev : $classyIndex; - $extends = false; $implements = false; $anonymousClass = false; @@ -288,6 +284,13 @@ private function getClassyDefinitionInfo(Tokens $tokens, int $classyIndex): arra } } + if ($anonymousClass) { + $startIndex = $tokens->getPrevMeaningfulToken($classyIndex); // go to "new" for anonymous class + } else { + $prev = $tokens->getPrevMeaningfulToken($classyIndex); + $startIndex = $tokens[$prev]->isGivenKind([T_FINAL, T_ABSTRACT]) ? $prev : $classyIndex; + } + return [ 'start' => $startIndex, 'classy' => $classyIndex, @@ -304,6 +307,7 @@ private function getClassyInheritanceInfo(Tokens $tokens, int $startIndex, strin ++$startIndex; $endIndex = $tokens->getNextTokenOfKind($startIndex, ['{', [T_IMPLEMENTS], [T_EXTENDS]]); $endIndex = $tokens[$endIndex]->equals('{') ? $tokens->getPrevNonWhitespace($endIndex) : $endIndex; + for ($i = $startIndex; $i < $endIndex; ++$i) { if ($tokens[$i]->equals(',')) { ++$implementsInfo[$label]; @@ -311,7 +315,7 @@ private function getClassyInheritanceInfo(Tokens $tokens, int $startIndex, strin continue; } - if (!$implementsInfo['multiLine'] && false !== strpos($tokens[$i]->getContent(), "\n")) { + if (!$implementsInfo['multiLine'] && str_contains($tokens[$i]->getContent(), "\n")) { $implementsInfo['multiLine'] = true; } } @@ -323,14 +327,13 @@ private function makeClassyDefinitionSingleLine(Tokens $tokens, int $startIndex, { for ($i = $endIndex; $i >= $startIndex; --$i) { if ($tokens[$i]->isWhitespace()) { - $prevNonWhite = $tokens->getPrevNonWhitespace($i); - $nextNonWhite = $tokens->getNextNonWhitespace($i); - - if ($tokens[$prevNonWhite]->isComment() || $tokens[$nextNonWhite]->isComment()) { - $content = $tokens[$prevNonWhite]->getContent(); - if (!('#' === $content || '//' === substr($content, 0, 2))) { - $content = $tokens[$nextNonWhite]->getContent(); - if (!('#' === $content || '//' === substr($content, 0, 2))) { + if ($tokens[$i - 1]->isComment() || $tokens[$i + 1]->isComment()) { + $content = $tokens[$i - 1]->getContent(); + + if (!('#' === $content || str_starts_with($content, '//'))) { + $content = $tokens[$i + 1]->getContent(); + + if (!('#' === $content || str_starts_with($content, '//'))) { $tokens[$i] = new Token([T_WHITESPACE, ' ']); } } @@ -338,7 +341,17 @@ private function makeClassyDefinitionSingleLine(Tokens $tokens, int $startIndex, continue; } - if (!$tokens[$i - 1]->equals(',') && $tokens[$i + 1]->equalsAny([',', '(', ')']) || $tokens[$i - 1]->equals('(')) { + if ($tokens[$i - 1]->isGivenKind(T_CLASS) && $tokens[$i + 1]->equals('(')) { + if (true === $this->configuration['space_before_parenthesis']) { + $tokens[$i] = new Token([T_WHITESPACE, ' ']); + } else { + $tokens->clearAt($i); + } + + continue; + } + + if (!$tokens[$i - 1]->equals(',') && $tokens[$i + 1]->equalsAny([',', ')']) || $tokens[$i - 1]->equals('(')) { $tokens->clearAt($i); continue; @@ -355,11 +368,17 @@ private function makeClassyDefinitionSingleLine(Tokens $tokens, int $startIndex, continue; } + if ($this->configuration['space_before_parenthesis'] && $tokens[$i]->isGivenKind(T_CLASS) && !$tokens[$i + 1]->isWhitespace()) { + $tokens->insertAt($i + 1, new Token([T_WHITESPACE, ' '])); + + continue; + } + if (!$tokens[$i]->isComment()) { continue; } - if (!$tokens[$i + 1]->isWhitespace() && !$tokens[$i + 1]->isComment() && false === strpos($tokens[$i]->getContent(), "\n")) { + if (!$tokens[$i + 1]->isWhitespace() && !$tokens[$i + 1]->isComment() && !str_contains($tokens[$i]->getContent(), "\n")) { $tokens->insertAt($i + 1, new Token([T_WHITESPACE, ' '])); } @@ -374,6 +393,7 @@ private function makeClassyInheritancePartMultiLine(Tokens $tokens, int $startIn for ($i = $endIndex; $i > $startIndex; --$i) { $previousInterfaceImplementingIndex = $tokens->getPrevTokenOfKind($i, [',', [T_IMPLEMENTS], [T_EXTENDS]]); $breakAtIndex = $tokens->getNextMeaningfulToken($previousInterfaceImplementingIndex); + // make the part of a ',' or 'implements' single line $this->makeClassyDefinitionSingleLine( $tokens, @@ -383,8 +403,9 @@ private function makeClassyInheritancePartMultiLine(Tokens $tokens, int $startIn // make sure the part is on its own line $isOnOwnLine = false; + for ($j = $breakAtIndex; $j > $previousInterfaceImplementingIndex; --$j) { - if (false !== strpos($tokens[$j]->getContent(), "\n")) { + if (str_contains($tokens[$j]->getContent(), "\n")) { $isOnOwnLine = true; break; diff --git a/src/Fixer/ClassNotation/FinalInternalClassFixer.php b/src/Fixer/ClassNotation/FinalInternalClassFixer.php index d70ff5dcbb6..dfe3941ae89 100644 --- a/src/Fixer/ClassNotation/FinalInternalClassFixer.php +++ b/src/Fixer/ClassNotation/FinalInternalClassFixer.php @@ -27,11 +27,11 @@ use PhpCsFixer\Preg; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; use Symfony\Component\OptionsResolver\Options; /** * @author Dariusz Rumiński - * @author SpacePossum */ final class FinalInternalClassFixer extends AbstractFixer implements ConfigurableFixerInterface { @@ -106,8 +106,10 @@ public function isRisky(): bool */ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { + $tokensAnalyzer = new TokensAnalyzer($tokens); + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { - if (!$tokens[$index]->isGivenKind(T_CLASS) || !$this->isClassCandidate($tokens, $index)) { + if (!$tokens[$index]->isGivenKind(T_CLASS) || $tokensAnalyzer->isAnonymousClass($index) || !$this->isClassCandidate($tokens, $index)) { continue; } @@ -183,7 +185,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn */ private function isClassCandidate(Tokens $tokens, int $index): bool { - if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind([T_ABSTRACT, T_FINAL, T_NEW])) { + if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind([T_ABSTRACT, T_FINAL])) { return false; // ignore class; it is abstract or already final } @@ -202,7 +204,7 @@ private function isClassCandidate(Tokens $tokens, int $index): bool } $tag = strtolower(substr(array_shift($matches), 1)); foreach ($this->configuration['annotation_exclude'] as $tagStart => $true) { - if (0 === strpos($tag, $tagStart)) { + if (str_starts_with($tag, $tagStart)) { return false; // ignore class: class-level PHPDoc contains tag that has been excluded through configuration } } diff --git a/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php b/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php index b0d96a59ab0..e25dd001281 100644 --- a/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php +++ b/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php @@ -122,8 +122,10 @@ private function fixClass(Tokens $tokens, int $classOpenIndex, int $classCloseIn if (!$tokens[$index]->isGivenKind(T_PUBLIC)) { continue; } + $nextIndex = $tokens->getNextMeaningfulToken($index); $nextToken = $tokens[$nextIndex]; + if ($nextToken->isGivenKind(T_STATIC)) { $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); $nextToken = $tokens[$nextIndex]; @@ -133,6 +135,7 @@ private function fixClass(Tokens $tokens, int $classOpenIndex, int $classCloseIn if (!$nextToken->isGivenKind(T_FUNCTION)) { continue; } + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); $nextToken = $tokens[$nextIndex]; @@ -143,11 +146,13 @@ private function fixClass(Tokens $tokens, int $classOpenIndex, int $classCloseIn $prevIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $tokens[$prevIndex]; + if ($prevToken->isGivenKind(T_STATIC)) { $index = $prevIndex; $prevIndex = $tokens->getPrevMeaningfulToken($index); $prevToken = $tokens[$prevIndex]; } + // skip abstract or already final methods if ($prevToken->isGivenKind([T_ABSTRACT, T_FINAL])) { $index = $prevIndex; diff --git a/src/Fixer/ClassNotation/NoNullPropertyInitializationFixer.php b/src/Fixer/ClassNotation/NoNullPropertyInitializationFixer.php index 01adc32731e..176a2a675bd 100644 --- a/src/Fixer/ClassNotation/NoNullPropertyInitializationFixer.php +++ b/src/Fixer/ClassNotation/NoNullPropertyInitializationFixer.php @@ -130,7 +130,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ($tokens[$index]->equals([T_STRING, 'null'], false)) { for ($i = $varTokenIndex + 1; $i <= $index; ++$i) { if ( - !($tokens[$i]->isWhitespace() && false !== strpos($tokens[$i]->getContent(), "\n")) + !($tokens[$i]->isWhitespace() && str_contains($tokens[$i]->getContent(), "\n")) && !$tokens[$i]->isComment() ) { $tokens->clearAt($i); diff --git a/src/Fixer/ClassNotation/NoPhp4ConstructorFixer.php b/src/Fixer/ClassNotation/NoPhp4ConstructorFixer.php index 14ee1b25d63..433bfa07690 100644 --- a/src/Fixer/ClassNotation/NoPhp4ConstructorFixer.php +++ b/src/Fixer/ClassNotation/NoPhp4ConstructorFixer.php @@ -87,7 +87,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void for ($i = 0; $i < $numClasses; ++$i) { $index = $classes[$i]; - // is it an an anonymous class definition? + // is it an anonymous class definition? if ($tokensAnalyzer->isAnonymousClass($index)) { continue; } @@ -109,6 +109,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // the index points to the { of a block-namespace $nspEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $nspIndex); + if ($index < $nspEnd) { // the class is inside a block namespace, skip other classes that might be in it for ($j = $i + 1; $j < $numClasses; ++$j) { @@ -167,7 +168,8 @@ private function fixConstructor(Tokens $tokens, string $className, int $classSta } // does the PHP4-constructor only call $this->__construct($args, ...)? - list($sequences, $case) = $this->getWrapperMethodSequence($tokens, '__construct', $php4['startIndex'], $php4['bodyIndex']); + [$sequences, $case] = $this->getWrapperMethodSequence($tokens, '__construct', $php4['startIndex'], $php4['bodyIndex']); + foreach ($sequences as $seq) { if (null !== $tokens->findSequence($seq, $php4['bodyIndex'] - 1, $php4['endIndex'], $case)) { // good, delete it! @@ -180,7 +182,8 @@ private function fixConstructor(Tokens $tokens, string $className, int $classSta } // does __construct only call the PHP4-constructor (with the same args)? - list($sequences, $case) = $this->getWrapperMethodSequence($tokens, $className, $php4['startIndex'], $php4['bodyIndex']); + [$sequences, $case] = $this->getWrapperMethodSequence($tokens, $className, $php4['startIndex'], $php4['bodyIndex']); + foreach ($sequences as $seq) { if (null !== $tokens->findSequence($seq, $php5['bodyIndex'] - 1, $php5['endIndex'], $case)) { // that was a weird choice, but we can safely delete it and... @@ -316,6 +319,7 @@ private function getWrapperMethodSequence(Tokens $tokens, string $method, int $s // parse method parameters, if any $index = $startIndex; + while (true) { // find the next variable name $index = $tokens->getNextTokenOfKind($index, [[T_VARIABLE]]); @@ -382,6 +386,7 @@ private function findFunction(Tokens $tokens, string $name, int $startIndex, int $modifiers = []; $prevBlock = $tokens->getPrevMeaningfulToken($function[0]); + while (null !== $prevBlock && $tokens[$prevBlock]->isGivenKind($possibleModifiers)) { $modifiers[$tokens[$prevBlock]->getId()] = $prevBlock; $prevBlock = $tokens->getPrevMeaningfulToken($prevBlock); diff --git a/src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php b/src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php index dadc06d1b8f..eec3ef50650 100644 --- a/src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php +++ b/src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php @@ -23,6 +23,7 @@ use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; /** * @author Filippo Tessarotto @@ -90,17 +91,20 @@ public function isRisky(): bool */ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { - $tokensCount = \count($tokens); - for ($index = 0; $index < $tokensCount; ++$index) { - if (!$tokens[$index]->isGivenKind(T_CLASS)) { + foreach ($this->getClassMethods($tokens) as $element) { + $index = $element['method_final_index']; + + if ($element['class_is_final']) { + $this->clearFinal($tokens, $index); + continue; } - $classOpen = $tokens->getNextTokenOfKind($index, ['{']); - $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; - $classIsFinal = $prevToken->isGivenKind(T_FINAL); + if (!$element['method_is_private'] || false === $this->configuration['private_methods'] || $element['method_is_constructor']) { + continue; + } - $this->fixClass($tokens, $classOpen, $classIsFinal); + $this->clearFinal($tokens, $index); } } @@ -117,54 +121,67 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ]); } - private function fixClass(Tokens $tokens, int $classOpenIndex, bool $classIsFinal): void + private function getClassMethods(Tokens $tokens): \Generator { - $tokensCount = \count($tokens); + $tokensAnalyzer = new TokensAnalyzer($tokens); + $modifierKinds = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_FINAL, T_ABSTRACT, T_STATIC]; - for ($index = $classOpenIndex + 1; $index < $tokensCount; ++$index) { - // Class end - if ($tokens[$index]->equals('}')) { - return; - } + $classesAreFinal = []; + $elements = $tokensAnalyzer->getClassyElements(); - // Skip method content - if ($tokens[$index]->equals('{')) { - $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + for (end($elements);; prev($elements)) { + $index = key($elements); - continue; + if (null === $index) { + break; } - if (!$tokens[$index]->isGivenKind(T_FINAL)) { - continue; + $element = current($elements); + + if ('method' !== $element['type']) { + continue; // not a method } - if (!$classIsFinal && (!$this->isPrivateMethodOtherThanConstructor($tokens, $index, $classOpenIndex) || !$this->configuration['private_methods'])) { - continue; + $classIndex = $element['classIndex']; + + if (!\array_key_exists($classIndex, $classesAreFinal)) { + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($classIndex)]; + $classesAreFinal[$classIndex] = $prevToken->isGivenKind(T_FINAL); } - $tokens->clearAt($index); + $element['class_is_final'] = $classesAreFinal[$classIndex]; + $element['method_is_constructor'] = '__construct' === strtolower($tokens[$tokens->getNextMeaningfulToken($index)]->getContent()); + $element['method_final_index'] = null; + $element['method_is_private'] = false; - ++$index; + $previous = $index; - if ($tokens[$index]->isWhitespace()) { - $tokens->clearAt($index); - } + do { + $previous = $tokens->getPrevMeaningfulToken($previous); + + if ($tokens[$previous]->isGivenKind(T_PRIVATE)) { + $element['method_is_private'] = true; + } elseif ($tokens[$previous]->isGivenKind(T_FINAL)) { + $element['method_final_index'] = $previous; + } + } while ($tokens[$previous]->isGivenKind($modifierKinds)); + + yield $element; } } - private function isPrivateMethodOtherThanConstructor(Tokens $tokens, int $index, int $classOpenIndex): bool + private function clearFinal(Tokens $tokens, ?int $index): void { - $index = max($classOpenIndex + 1, $tokens->getPrevTokenOfKind($index, [';', '{', '}'])); - $private = false; + if (null === $index) { + return; + } - while (!$tokens[$index]->isGivenKind(T_FUNCTION)) { - if ($tokens[$index]->isGivenKind(T_PRIVATE)) { - $private = true; - } + $tokens->clearAt($index); - $index = $tokens->getNextMeaningfulToken($index); - } + ++$index; - return $private && '__construct' !== strtolower($tokens[$tokens->getNextMeaningfulToken($index)]->getContent()); + if ($tokens[$index]->isWhitespace()) { + $tokens->clearAt($index); + } } } diff --git a/src/Fixer/ClassNotation/OrderedClassElementsFixer.php b/src/Fixer/ClassNotation/OrderedClassElementsFixer.php index 61084b37362..5108ca2aa61 100644 --- a/src/Fixer/ClassNotation/OrderedClassElementsFixer.php +++ b/src/Fixer/ClassNotation/OrderedClassElementsFixer.php @@ -401,11 +401,10 @@ private function detectElementType(Tokens $tokens, int $index) return ['phpunit', strtolower($nameToken->getContent())]; } - if ('__' === substr($nameToken->getContent(), 0, 2)) { - return 'magic'; - } - - return 'method'; + return str_starts_with($nameToken->getContent(), '__') + ? 'magic' + : 'method' + ; } private function findElementEnd(Tokens $tokens, int $index): int @@ -471,7 +470,7 @@ private function sortElements(array $elements): array } unset($element); - usort($elements, function (array $a, array $b) { + usort($elements, function (array $a, array $b): int { if ($a['position'] === $b['position']) { return $this->sortGroupElements($a, $b); } diff --git a/src/Fixer/ClassNotation/OrderedInterfacesFixer.php b/src/Fixer/ClassNotation/OrderedInterfacesFixer.php index 63aaa5393ae..702bba0829b 100644 --- a/src/Fixer/ClassNotation/OrderedInterfacesFixer.php +++ b/src/Fixer/ClassNotation/OrderedInterfacesFixer.php @@ -180,7 +180,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $interfaces[$interfaceIndex]['originalIndex'] = $interfaceIndex; } - usort($interfaces, function (array $first, array $second) { + usort($interfaces, function (array $first, array $second): int { $score = self::ORDER_LENGTH === $this->configuration[self::OPTION_ORDER] ? \strlen($first['normalized']) - \strlen($second['normalized']) : strcasecmp($first['normalized'], $second['normalized']); diff --git a/src/Fixer/ClassNotation/OrderedTraitsFixer.php b/src/Fixer/ClassNotation/OrderedTraitsFixer.php index 33653ff5120..9602ec3afe4 100644 --- a/src/Fixer/ClassNotation/OrderedTraitsFixer.php +++ b/src/Fixer/ClassNotation/OrderedTraitsFixer.php @@ -157,9 +157,6 @@ private function sortMultipleTraitsInStatement(Tokens $use): void */ private function sort(Tokens $tokens, array $elements): void { - /** - * @return string - */ $toTraitName = static function (Tokens $use): string { $string = ''; @@ -177,7 +174,7 @@ private function sort(Tokens $tokens, array $elements): void }; $sortedElements = $elements; - uasort($sortedElements, static function (Tokens $useA, Tokens $useB) use ($toTraitName) { + uasort($sortedElements, static function (Tokens $useA, Tokens $useB) use ($toTraitName): int { return strcasecmp($toTraitName($useA), $toTraitName($useB)); }); diff --git a/src/Fixer/ClassNotation/ProtectedToPrivateFixer.php b/src/Fixer/ClassNotation/ProtectedToPrivateFixer.php index 63f2e453724..b04c5eacf67 100644 --- a/src/Fixer/ClassNotation/ProtectedToPrivateFixer.php +++ b/src/Fixer/ClassNotation/ProtectedToPrivateFixer.php @@ -21,10 +21,10 @@ use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; /** * @author Filippo Tessarotto - * @author SpacePossum */ final class ProtectedToPrivateFixer extends AbstractFixer { @@ -76,58 +76,76 @@ public function isCandidate(Tokens $tokens): bool */ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { - $end = \count($tokens) - 3; // min. number of tokens to form a class candidate to fix - for ($index = 0; $index < $end; ++$index) { - if (!$tokens[$index]->isGivenKind(T_CLASS)) { - continue; - } + $tokensAnalyzer = new TokensAnalyzer($tokens); + $modifierKinds = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_FINAL, T_ABSTRACT, T_NS_SEPARATOR, T_STRING, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, T_STATIC, CT::T_TYPE_ALTERNATION]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $modifierKinds[] = T_READONLY; + } + + $classesCandidate = []; - $classOpen = $tokens->getNextTokenOfKind($index, ['{']); - $classClose = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classOpen); + foreach ($tokensAnalyzer->getClassyElements() as $index => $element) { + $classIndex = $element['classIndex']; - if (!$this->skipClass($tokens, $index, $classOpen, $classClose)) { - $this->fixClass($tokens, $classOpen, $classClose); + if (!\array_key_exists($classIndex, $classesCandidate)) { + $classesCandidate[$classIndex] = $this->isClassCandidate($tokens, $classIndex); } - $index = $classClose; - } - } + if (false === $classesCandidate[$classIndex]) { + continue; // not "final" class, "extends", is "anonymous" or uses trait + } - private function fixClass(Tokens $tokens, int $classOpenIndex, int $classCloseIndex): void - { - for ($index = $classOpenIndex + 1; $index < $classCloseIndex; ++$index) { - if ($tokens[$index]->equals('{')) { - $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + $previous = $index; + $isProtected = false; + $isFinal = false; + + do { + $previous = $tokens->getPrevMeaningfulToken($previous); + if ($tokens[$previous]->isGivenKind(T_PROTECTED)) { + $isProtected = $previous; + } elseif ($tokens[$previous]->isGivenKind(T_FINAL)) { + $isFinal = $previous; + } + } while ($tokens[$previous]->isGivenKind($modifierKinds)); + + if (false === $isProtected) { continue; } - if (!$tokens[$index]->isGivenKind(T_PROTECTED)) { - continue; + if ($isFinal && 'const' === $element['type']) { + continue; // Final constants cannot be private } - $tokens[$index] = new Token([T_PRIVATE, 'private']); + $element['protected_index'] = $isProtected; + $tokens[$element['protected_index']] = new Token([T_PRIVATE, 'private']); } } - /** - * Decide whether or not skip the fix for given class. - */ - private function skipClass(Tokens $tokens, int $classIndex, int $classOpenIndex, int $classCloseIndex): bool + private function isClassCandidate(Tokens $tokens, int $classIndex): bool { $prevToken = $tokens[$tokens->getPrevMeaningfulToken($classIndex)]; + if (!$prevToken->isGivenKind(T_FINAL)) { - return true; + return false; } - for ($index = $classIndex; $index < $classOpenIndex; ++$index) { - if ($tokens[$index]->isGivenKind(T_EXTENDS)) { - return true; - } + $classNameIndex = $tokens->getNextMeaningfulToken($classIndex); // move to class name as anonymous class is never "final" + $classExtendsIndex = $tokens->getNextMeaningfulToken($classNameIndex); // move to possible "extends" + + if ($tokens[$classExtendsIndex]->isGivenKind(T_EXTENDS)) { + return false; + } + + if (!$tokens->isTokenKindFound(CT::T_USE_TRAIT)) { + return true; // cheap test } - $useIndex = $tokens->getNextTokenOfKind($classIndex, [[CT::T_USE_TRAIT]]); + $classOpenIndex = $tokens->getNextTokenOfKind($classNameIndex, ['{']); + $classCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classOpenIndex); + $useIndex = $tokens->getNextTokenOfKind($classOpenIndex, [[CT::T_USE_TRAIT]]); - return $useIndex && $useIndex < $classCloseIndex; + return null === $useIndex || $useIndex > $classCloseIndex; } } diff --git a/src/Fixer/ClassNotation/SelfStaticAccessorFixer.php b/src/Fixer/ClassNotation/SelfStaticAccessorFixer.php index b46e63f166c..0c66ca6d6c3 100644 --- a/src/Fixer/ClassNotation/SelfStaticAccessorFixer.php +++ b/src/Fixer/ClassNotation/SelfStaticAccessorFixer.php @@ -18,8 +18,6 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\TokensAnalyzer; @@ -79,7 +77,7 @@ public function isBar() } ' ), - new VersionSpecificCodeSample( + new CodeSample( 'tokensAnalyzer = $tokensAnalyzer = new TokensAnalyzer($tokens); + $this->tokensAnalyzer = new TokensAnalyzer($tokens); $classIndex = $tokens->getNextTokenOfKind(0, [[T_CLASS]]); while (null !== $classIndex) { if ( - $tokens[$tokens->getPrevMeaningfulToken($classIndex)]->isGivenKind(T_FINAL) - || $tokensAnalyzer->isAnonymousClass($classIndex) + $this->tokensAnalyzer->isAnonymousClass($classIndex) + || $tokens[$tokens->getPrevMeaningfulToken($classIndex)]->isGivenKind(T_FINAL) ) { $classIndex = $this->fixClass($tokens, $classIndex); } diff --git a/src/Fixer/ClassNotation/SingleClassElementPerStatementFixer.php b/src/Fixer/ClassNotation/SingleClassElementPerStatementFixer.php index 4451a44df3e..db7811fec9c 100644 --- a/src/Fixer/ClassNotation/SingleClassElementPerStatementFixer.php +++ b/src/Fixer/ClassNotation/SingleClassElementPerStatementFixer.php @@ -34,7 +34,6 @@ * Fixer for rules defined in PSR2 ¶4.2. * * @author Javier Spagnoletti - * @author SpacePossum * @author Dariusz Rumiński */ final class SingleClassElementPerStatementFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface @@ -162,8 +161,10 @@ private function fixElement(Tokens $tokens, string $type, int $index): void private function expandElement(Tokens $tokens, string $type, int $startIndex, int $endIndex): void { $divisionContent = null; + if ($tokens[$startIndex - 1]->isWhitespace()) { $divisionContent = $tokens[$startIndex - 1]->getContent(); + if (Preg::match('#(\n|\r\n)#', $divisionContent, $matches)) { $divisionContent = $matches[0].trim($divisionContent, "\r\n"); } @@ -190,6 +191,7 @@ private function expandElement(Tokens $tokens, string $type, int $startIndex, in } $tokens[$i] = new Token(';'); + if ($tokens[$i + 1]->isWhitespace()) { $tokens->clearAt($i + 1); } @@ -210,12 +212,17 @@ private function expandElement(Tokens $tokens, string $type, int $startIndex, in private function getModifiersSequences(Tokens $tokens, string $type, int $startIndex, int $endIndex): array { if ('property' === $type) { - $tokenKinds = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_VAR, T_STRING, T_NS_SEPARATOR, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT]; + $tokenKinds = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_VAR, T_STRING, T_NS_SEPARATOR, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, CT::T_TYPE_ALTERNATION]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $tokenKinds[] = T_READONLY; + } } else { $tokenKinds = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_CONST]; } $sequence = []; + for ($i = $startIndex; $i < $endIndex - 1; ++$i) { if ($tokens[$i]->isComment()) { continue; diff --git a/src/Fixer/ClassNotation/SingleTraitInsertPerStatementFixer.php b/src/Fixer/ClassNotation/SingleTraitInsertPerStatementFixer.php index 06b9fe384f2..095cf449bbf 100644 --- a/src/Fixer/ClassNotation/SingleTraitInsertPerStatementFixer.php +++ b/src/Fixer/ClassNotation/SingleTraitInsertPerStatementFixer.php @@ -23,9 +23,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class SingleTraitInsertPerStatementFixer extends AbstractFixer { public function getDefinition(): FixerDefinitionInterface diff --git a/src/Fixer/ClassNotation/VisibilityRequiredFixer.php b/src/Fixer/ClassNotation/VisibilityRequiredFixer.php index cf823632d1b..c8fd622624e 100644 --- a/src/Fixer/ClassNotation/VisibilityRequiredFixer.php +++ b/src/Fixer/ClassNotation/VisibilityRequiredFixer.php @@ -23,8 +23,6 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -34,7 +32,6 @@ * Fixer for rules defined in PSR2 ¶4.3, ¶4.5. * * @author Dariusz Rumiński - * @author SpacePossum */ final class VisibilityRequiredFixer extends AbstractFixer implements ConfigurableFixerInterface { @@ -59,14 +56,13 @@ function A() } ' ), - new VersionSpecificCodeSample( + new CodeSample( ' ['const']] ), ] @@ -101,33 +97,42 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { $tokensAnalyzer = new TokensAnalyzer($tokens); + $propertyTypeDeclarationKinds = [T_STRING, T_NS_SEPARATOR, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, CT::T_TYPE_ALTERNATION]; + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $propertyReadOnlyType = T_READONLY; + $propertyTypeDeclarationKinds[] = T_READONLY; + } else { + $propertyReadOnlyType = -999; + } + + $expectedKindsGeneric = [T_ABSTRACT, T_FINAL, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_STATIC, T_VAR]; + $expectedKindsPropertyKinds = array_merge($expectedKindsGeneric, $propertyTypeDeclarationKinds); + foreach (array_reverse($tokensAnalyzer->getClassyElements(), true) as $index => $element) { if (!\in_array($element['type'], $this->configuration['elements'], true)) { continue; } - if (\PHP_VERSION_ID < 70100 && 'const' === $element['type']) { - continue; - } - $abstractFinalIndex = null; $visibilityIndex = null; $staticIndex = null; $typeIndex = null; + $readOnlyIndex = null; $prevIndex = $tokens->getPrevMeaningfulToken($index); - $expectedKinds = [T_ABSTRACT, T_FINAL, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_STATIC, T_VAR]; - - if ('property' === $element['type']) { - $expectedKinds = array_merge($expectedKinds, $propertyTypeDeclarationKinds); - } + $expectedKinds = 'property' === $element['type'] + ? $expectedKindsPropertyKinds + : $expectedKindsGeneric + ; while ($tokens[$prevIndex]->isGivenKind($expectedKinds)) { if ($tokens[$prevIndex]->isGivenKind([T_ABSTRACT, T_FINAL])) { $abstractFinalIndex = $prevIndex; } elseif ($tokens[$prevIndex]->isGivenKind(T_STATIC)) { $staticIndex = $prevIndex; + } elseif ($tokens[$prevIndex]->isGivenKind($propertyReadOnlyType)) { + $readOnlyIndex = $prevIndex; } elseif ($tokens[$prevIndex]->isGivenKind($propertyTypeDeclarationKinds)) { $typeIndex = $prevIndex; } else { @@ -145,11 +150,13 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - if (null !== $staticIndex) { - if ($this->isKeywordPlacedProperly($tokens, $staticIndex, $index)) { - $index = $staticIndex; + $swapIndex = $staticIndex ?? $readOnlyIndex; // "static" property cannot be "readonly", so there can always be at most one swap + + if (null !== $swapIndex) { + if ($this->isKeywordPlacedProperly($tokens, $swapIndex, $index)) { + $index = $swapIndex; } else { - $this->moveTokenAndEnsureSingleSpaceFollows($tokens, $staticIndex, $index); + $this->moveTokenAndEnsureSingleSpaceFollows($tokens, $swapIndex, $index); } } @@ -186,8 +193,8 @@ private function isKeywordPlacedProperly(Tokens $tokens, int $keywordIndex, int private function moveTokenAndEnsureSingleSpaceFollows(Tokens $tokens, int $fromIndex, int $toIndex): void { $tokens->insertAt($toIndex, [$tokens[$fromIndex], new Token([T_WHITESPACE, ' '])]); - $tokens->clearAt($fromIndex); + if ($tokens[$fromIndex + 1]->isWhitespace()) { $tokens->clearAt($fromIndex + 1); } diff --git a/src/Fixer/ClassUsage/DateTimeImmutableFixer.php b/src/Fixer/ClassUsage/DateTimeImmutableFixer.php index fc611a09275..1d0610ea2fc 100644 --- a/src/Fixer/ClassUsage/DateTimeImmutableFixer.php +++ b/src/Fixer/ClassUsage/DateTimeImmutableFixer.php @@ -18,6 +18,7 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -60,6 +61,12 @@ public function isRisky(): bool */ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { + $functionsAnalyzer = new FunctionsAnalyzer(); + $functionMap = [ + 'date_create' => 'date_create_immutable', + 'date_create_from_format' => 'date_create_immutable_from_format', + ]; + $isInNamespace = false; $isImported = false; // e.g. use DateTime; @@ -72,12 +79,15 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - if ($token->isGivenKind(T_USE) && $isInNamespace) { + if ($isInNamespace && $token->isGivenKind(T_USE)) { $nextIndex = $tokens->getNextMeaningfulToken($index); + if ('datetime' !== strtolower($tokens[$nextIndex]->getContent())) { continue; } + $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); + if ($tokens[$nextNextIndex]->equals(';')) { $isImported = true; } @@ -92,6 +102,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->isGivenKind(T_FUNCTION)) { continue; } @@ -101,10 +112,12 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ('datetime' === $lowercaseContent) { $this->fixClassUsage($tokens, $index, $isInNamespace, $isImported); $limit = $tokens->count(); // update limit, as fixing class usage may insert new token - } elseif ('date_create' === $lowercaseContent) { - $this->fixFunctionUsage($tokens, $index, 'date_create_immutable'); - } elseif ('date_create_from_format' === $lowercaseContent) { - $this->fixFunctionUsage($tokens, $index, 'date_create_immutable_from_format'); + + continue; + } + + if (isset($functionMap[$lowercaseContent]) && $functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + $tokens[$index] = new Token([T_STRING, $functionMap[$lowercaseContent]]); } } } @@ -142,20 +155,4 @@ private function fixClassUsage(Tokens $tokens, int $index, bool $isInNamespace, } } } - - private function fixFunctionUsage(Tokens $tokens, int $index, string $replacement): void - { - $prevIndex = $tokens->getPrevMeaningfulToken($index); - if ($tokens[$prevIndex]->isGivenKind([T_DOUBLE_COLON, T_NEW]) || $tokens[$prevIndex]->isObjectOperator()) { - return; - } - if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { - $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); - if ($tokens[$prevPrevIndex]->isGivenKind([T_NEW, T_STRING])) { - return; - } - } - - $tokens[$index] = new Token([T_STRING, $replacement]); - } } diff --git a/src/Fixer/Comment/CommentToPhpdocFixer.php b/src/Fixer/Comment/CommentToPhpdocFixer.php index 0eff6cadeb7..b887b18757a 100644 --- a/src/Fixer/Comment/CommentToPhpdocFixer.php +++ b/src/Fixer/Comment/CommentToPhpdocFixer.php @@ -91,7 +91,7 @@ public function configure(array $configuration): void parent::configure($configuration); $this->ignoredTags = array_map( - static function (string $tag) { + static function (string $tag): string { return strtolower($tag); }, $this->configuration['ignored_tags'] @@ -150,7 +150,7 @@ private function isCommentCandidate(Tokens $tokens, array $indices): bool { return array_reduce( $indices, - function (bool $carry, int $index) use ($tokens) { + function (bool $carry, int $index) use ($tokens): bool { if ($carry) { return true; } @@ -206,7 +206,7 @@ private function fixCommentMultiLine(Tokens $tokens, array $indices): void if (!$tokens[$index]->isComment()) { continue; } - if (false !== strpos($tokens[$index]->getContent(), '*/')) { + if (str_contains($tokens[$index]->getContent(), '*/')) { return; } $message = $this->getMessage($tokens[$index]->getContent()); @@ -227,10 +227,10 @@ private function fixCommentMultiLine(Tokens $tokens, array $indices): void private function getMessage(string $content): string { - if (0 === strpos($content, '#')) { + if (str_starts_with($content, '#')) { return substr($content, 1); } - if (0 === strpos($content, '//')) { + if (str_starts_with($content, '//')) { return substr($content, 2); } diff --git a/src/Fixer/Comment/HeaderCommentFixer.php b/src/Fixer/Comment/HeaderCommentFixer.php index 53d32ba1082..2eadbfe7ccf 100644 --- a/src/Fixer/Comment/HeaderCommentFixer.php +++ b/src/Fixer/Comment/HeaderCommentFixer.php @@ -31,7 +31,6 @@ /** * @author Antonio J. García Lagar - * @author SpacePossum */ final class HeaderCommentFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface { @@ -204,12 +203,12 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn return new FixerConfigurationResolver([ (new FixerOptionBuilder('header', 'Proper header content.')) ->setAllowedTypes(['string']) - ->setNormalizer(static function (Options $options, $value) use ($fixerName) { + ->setNormalizer(static function (Options $options, string $value) use ($fixerName): string { if ('' === trim($value)) { return ''; } - if (false !== strpos($value, '*/')) { + if (str_contains($value, '*/')) { throw new InvalidFixerConfigurationException($fixerName, 'Cannot use \'*/\' in header.'); } @@ -436,7 +435,7 @@ private function removeHeader(Tokens $tokens, int $index): void } $nextIndex = $index + 1; - $nextToken = isset($tokens[$nextIndex]) ? $tokens[$nextIndex] : null; + $nextToken = $tokens[$nextIndex] ?? null; if (!$newlineRemoved && null !== $nextToken && $nextToken->isWhitespace()) { $content = Preg::replace('/^\R/', '', $nextToken->getContent()); diff --git a/src/Fixer/Comment/MultilineCommentOpeningClosingFixer.php b/src/Fixer/Comment/MultilineCommentOpeningClosingFixer.php index 7e32153f785..d27585ea0b1 100644 --- a/src/Fixer/Comment/MultilineCommentOpeningClosingFixer.php +++ b/src/Fixer/Comment/MultilineCommentOpeningClosingFixer.php @@ -75,7 +75,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ( !$token->isGivenKind(T_DOC_COMMENT) - && !($token->isGivenKind(T_COMMENT) && 0 === strpos($originalContent, '/*')) + && !($token->isGivenKind(T_COMMENT) && str_starts_with($originalContent, '/*')) ) { continue; } diff --git a/src/Fixer/Comment/NoEmptyCommentFixer.php b/src/Fixer/Comment/NoEmptyCommentFixer.php index dde77e79ff3..396fba4be04 100644 --- a/src/Fixer/Comment/NoEmptyCommentFixer.php +++ b/src/Fixer/Comment/NoEmptyCommentFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Preg; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NoEmptyCommentFixer extends AbstractFixer { private const TYPE_HASH = 1; @@ -72,7 +69,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - list($blockStart, $index, $isEmpty) = $this->getCommentBlock($tokens, $index); + [$blockStart, $index, $isEmpty] = $this->getCommentBlock($tokens, $index); if (false === $isEmpty) { continue; } diff --git a/src/Fixer/Comment/NoTrailingWhitespaceInCommentFixer.php b/src/Fixer/Comment/NoTrailingWhitespaceInCommentFixer.php index eac9a969485..9e893ff7b02 100644 --- a/src/Fixer/Comment/NoTrailingWhitespaceInCommentFixer.php +++ b/src/Fixer/Comment/NoTrailingWhitespaceInCommentFixer.php @@ -72,7 +72,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } if ($token->isGivenKind(T_COMMENT)) { - if ('/*' === substr($token->getContent(), 0, 2)) { + if (str_starts_with($token->getContent(), '/*')) { $tokens[$index] = new Token([T_COMMENT, Preg::replace('/(*ANY)[\h]+$/m', '', $token->getContent())]); } elseif (isset($tokens[$index + 1]) && $tokens[$index + 1]->isWhitespace()) { $trimmedContent = ltrim($tokens[$index + 1]->getContent(), " \t"); diff --git a/src/Fixer/Comment/SingleLineCommentStyleFixer.php b/src/Fixer/Comment/SingleLineCommentStyleFixer.php index ff81467d12c..1991abb549f 100644 --- a/src/Fixer/Comment/SingleLineCommentStyleFixer.php +++ b/src/Fixer/Comment/SingleLineCommentStyleFixer.php @@ -135,7 +135,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ($this->hashEnabled && '#' === $content[0]) { if (isset($content[1]) && '[' === $content[1]) { - continue; // This might be attribute on PHP8, do not change + continue; // This might be an attribute on PHP8, do not change } $tokens[$index] = new Token([$token->getId(), '//'.substr($content, 1)]); @@ -145,8 +145,8 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ( !$this->asteriskEnabled - || false !== strpos($commentContent, '?>') - || '/*' !== substr($content, 0, 2) + || str_contains($commentContent, '?>') + || !str_starts_with($content, '/*') || 1 === Preg::match('/[^\s\*].*\R.*[^\s\*]/s', $commentContent) ) { continue; diff --git a/src/Fixer/ConfigurableFixerInterface.php b/src/Fixer/ConfigurableFixerInterface.php index 8b2211772f0..1cc18ad1ae6 100644 --- a/src/Fixer/ConfigurableFixerInterface.php +++ b/src/Fixer/ConfigurableFixerInterface.php @@ -19,7 +19,6 @@ /** * @author Dariusz Rumiński - * @author SpacePossum */ interface ConfigurableFixerInterface extends FixerInterface { diff --git a/src/Fixer/ConstantNotation/NativeConstantInvocationFixer.php b/src/Fixer/ConstantNotation/NativeConstantInvocationFixer.php index 11137b5553f..7793120079f 100644 --- a/src/Fixer/ConstantNotation/NativeConstantInvocationFixer.php +++ b/src/Fixer/ConstantNotation/NativeConstantInvocationFixer.php @@ -161,7 +161,7 @@ public function configure(array $configuration): void $caseInsensitiveConstantsToEscape = array_diff( array_unique($caseInsensitiveConstantsToEscape), - array_map(static function (string $function) { return strtolower($function); }, $uniqueConfiguredExclude) + array_map(static function (string $function): string { return strtolower($function); }, $uniqueConfiguredExclude) ); // Store the cache diff --git a/src/Fixer/ControlStructure/ControlStructureContinuationPositionFixer.php b/src/Fixer/ControlStructure/ControlStructureContinuationPositionFixer.php new file mode 100644 index 00000000000..dd3088b0c01 --- /dev/null +++ b/src/Fixer/ControlStructure/ControlStructureContinuationPositionFixer.php @@ -0,0 +1,144 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\Tokens; + +final class ControlStructureContinuationPositionFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @internal + */ + public const NEXT_LINE = 'next_line'; + + /** + * @internal + */ + public const SAME_LINE = 'same_line'; + + private const CONTROL_CONTINUATION_TOKENS = [ + T_CATCH, + T_ELSE, + T_ELSEIF, + T_FINALLY, + T_WHILE, + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition(): FixerDefinitionInterface + { + return new FixerDefinition( + 'Control structure continuation keyword must be on the configured line.', + [ + new CodeSample( + ' self::NEXT_LINE] + ), + ] + ); + } + + public function isCandidate(Tokens $tokens): bool + { + return $tokens->isAnyTokenKindsFound(self::CONTROL_CONTINUATION_TOKENS); + } + + /** + * Must run after ControlStructureBracesFixer. + */ + public function getPriority(): int + { + return parent::getPriority(); + } + + protected function createConfigurationDefinition(): FixerConfigurationResolverInterface + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('position', 'the position of the keyword that continues the control structure.')) + ->setAllowedValues([self::NEXT_LINE, self::SAME_LINE]) + ->setDefault(self::SAME_LINE) + ->getOption(), + ]); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens): void + { + $this->fixControlContinuationBraces($tokens); + } + + private function fixControlContinuationBraces(Tokens $tokens): void + { + for ($index = \count($tokens) - 1; 0 < $index; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(self::CONTROL_CONTINUATION_TOKENS)) { + continue; + } + + $prevIndex = $tokens->getPrevNonWhitespace($index); + $prevToken = $tokens[$prevIndex]; + + if (!$prevToken->equals('}')) { + continue; + } + + if ($token->isGivenKind(T_WHILE)) { + $prevIndex = $tokens->getPrevMeaningfulToken( + $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $prevIndex) + ); + + if (!$tokens[$prevIndex]->isGivenKind(T_DO)) { + continue; + } + } + + $tokens->ensureWhitespaceAtIndex( + $index - 1, + 1, + self::NEXT_LINE === $this->configuration['position'] ? + $this->whitespacesConfig->getLineEnding().WhitespacesAnalyzer::detectIndent($tokens, $index) + : ' ' + ); + } + } +} diff --git a/src/Fixer/ControlStructure/EmptyLoopBodyFixer.php b/src/Fixer/ControlStructure/EmptyLoopBodyFixer.php index 98476e4b6b8..f0898a6fd4a 100644 --- a/src/Fixer/ControlStructure/EmptyLoopBodyFixer.php +++ b/src/Fixer/ControlStructure/EmptyLoopBodyFixer.php @@ -26,9 +26,6 @@ use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\TokensAnalyzer; -/** - * @author SpacePossum - */ final class EmptyLoopBodyFixer extends AbstractFixer implements ConfigurableFixerInterface { private const STYLE_BRACES = 'braces'; diff --git a/src/Fixer/ControlStructure/EmptyLoopConditionFixer.php b/src/Fixer/ControlStructure/EmptyLoopConditionFixer.php new file mode 100644 index 00000000000..7f82fc4aae5 --- /dev/null +++ b/src/Fixer/ControlStructure/EmptyLoopConditionFixer.php @@ -0,0 +1,200 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class EmptyLoopConditionFixer extends AbstractFixer implements ConfigurableFixerInterface +{ + private const STYLE_FOR = 'for'; + + private const STYLE_WHILE = 'while'; + + private const TOKEN_LOOP_KINDS = [T_FOR, T_WHILE]; + + /** + * {@inheritdoc} + */ + public function getDefinition(): FixerDefinitionInterface + { + return new FixerDefinition( + 'Empty loop-condition must be in configured style.', + [ + new CodeSample(" 'for']), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoExtraBlankLinesFixer, NoTrailingWhitespaceFixer. + */ + public function getPriority(): int + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens): bool + { + return $tokens->isAnyTokenKindsFound(self::TOKEN_LOOP_KINDS); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens): void + { + if (self::STYLE_WHILE === $this->configuration['style']) { + $candidateLoopKinds = [T_FOR, T_WHILE]; + $replacement = [new Token([T_WHILE, 'while']), new Token([T_WHITESPACE, ' ']), new Token('('), new Token([T_STRING, 'true']), new Token(')')]; + + $fixLoop = static function (int $index, int $openIndex, int $endIndex) use ($tokens, $replacement): void { + if (self::isForLoopWithEmptyCondition($tokens, $index, $openIndex, $endIndex)) { + self::clearNotCommentsInRange($tokens, $index, $endIndex); + self::cloneAndInsert($tokens, $index, $replacement); + } elseif (self::isWhileLoopWithEmptyCondition($tokens, $index, $openIndex, $endIndex)) { + $doIndex = self::getDoIndex($tokens, $index); + + if (null !== $doIndex) { + self::clearNotCommentsInRange($tokens, $index, $tokens->getNextMeaningfulToken($endIndex)); // clear including `;` + $tokens->clearAt($doIndex); + self::cloneAndInsert($tokens, $doIndex, $replacement); + } + } + }; + } else { // self::STYLE_FOR + $candidateLoopKinds = [T_WHILE]; + $replacement = [new Token([T_FOR, 'for']), new Token('('), new Token(';'), new Token(';'), new Token(')')]; + + $fixLoop = static function (int $index, int $openIndex, int $endIndex) use ($tokens, $replacement): void { + if (!self::isWhileLoopWithEmptyCondition($tokens, $index, $openIndex, $endIndex)) { + return; + } + + $doIndex = self::getDoIndex($tokens, $index); + + if (null === $doIndex) { + self::clearNotCommentsInRange($tokens, $index, $endIndex); + self::cloneAndInsert($tokens, $index, $replacement); + } else { + self::clearNotCommentsInRange($tokens, $index, $tokens->getNextMeaningfulToken($endIndex)); // clear including `;` + $tokens->clearAt($doIndex); + self::cloneAndInsert($tokens, $doIndex, $replacement); + } + }; + } + + for ($index = $tokens->count() - 1; $index > 0; --$index) { + if ($tokens[$index]->isGivenKind($candidateLoopKinds)) { + $openIndex = $tokens->getNextTokenOfKind($index, ['(']); // proceed to open '(' + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); // proceed to close ')' + $fixLoop($index, $openIndex, $endIndex); // fix loop if needed + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition(): FixerConfigurationResolverInterface + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('style', 'Style of empty loop-condition.')) + ->setAllowedTypes(['string']) + ->setAllowedValues([self::STYLE_WHILE, self::STYLE_FOR]) + ->setDefault(self::STYLE_WHILE) + ->getOption(), + ]); + } + + private static function clearNotCommentsInRange(Tokens $tokens, int $indexStart, int $indexEnd): void + { + for ($i = $indexStart; $i <= $indexEnd; ++$i) { + if (!$tokens[$i]->isComment()) { + $tokens->clearTokenAndMergeSurroundingWhitespace($i); + } + } + } + + /** + * @param Token[] $replacement + */ + private static function cloneAndInsert(Tokens $tokens, int $index, array $replacement): void + { + $replacementClones = []; + + foreach ($replacement as $token) { + $replacementClones[] = clone $token; + } + + $tokens->insertAt($index, $replacementClones); + } + + private static function getDoIndex(Tokens $tokens, int $index): ?int + { + $endIndex = $tokens->getPrevMeaningfulToken($index); + + if (!$tokens[$endIndex]->equals('}')) { + return null; + } + + $startIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $endIndex); + $index = $tokens->getPrevMeaningfulToken($startIndex); + + return null === $index || !$tokens[$index]->isGivenKind(T_DO) ? null : $index; + } + + private static function isForLoopWithEmptyCondition(Tokens $tokens, int $index, int $openIndex, int $endIndex): bool + { + if (!$tokens[$index]->isGivenKind(T_FOR)) { + return false; + } + + $index = $tokens->getNextMeaningfulToken($openIndex); + + if (null === $index || !$tokens[$index]->equals(';')) { + return false; + } + + $index = $tokens->getNextMeaningfulToken($index); + + return null !== $index && $tokens[$index]->equals(';') && $endIndex === $tokens->getNextMeaningfulToken($index); + } + + private static function isWhileLoopWithEmptyCondition(Tokens $tokens, int $index, int $openIndex, int $endIndex): bool + { + if (!$tokens[$index]->isGivenKind(T_WHILE)) { + return false; + } + + $index = $tokens->getNextMeaningfulToken($openIndex); + + return null !== $index && $tokens[$index]->equals([T_STRING, 'true']) && $endIndex === $tokens->getNextMeaningfulToken($index); + } +} diff --git a/src/Fixer/ControlStructure/NoAlternativeSyntaxFixer.php b/src/Fixer/ControlStructure/NoAlternativeSyntaxFixer.php index 0c0c28ad347..e94a21bfab6 100644 --- a/src/Fixer/ControlStructure/NoAlternativeSyntaxFixer.php +++ b/src/Fixer/ControlStructure/NoAlternativeSyntaxFixer.php @@ -15,6 +15,10 @@ namespace PhpCsFixer\Fixer\ControlStructure; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; @@ -24,7 +28,7 @@ /** * @author Eddilbert Macharia */ -final class NoAlternativeSyntaxFixer extends AbstractFixer +final class NoAlternativeSyntaxFixer extends AbstractFixer implements ConfigurableFixerInterface { /** * {@inheritdoc} @@ -38,13 +42,8 @@ public function getDefinition(): FixerDefinitionInterface "\nLorem ipsum.\n\n", + ['fix_non_monolithic_code' => true] ), ] ); @@ -55,7 +54,7 @@ public function getDefinition(): FixerDefinitionInterface */ public function isCandidate(Tokens $tokens): bool { - return $tokens->hasAlternativeSyntax(); + return $tokens->hasAlternativeSyntax() && ($this->configuration['fix_non_monolithic_code'] || $tokens->isMonolithicPhp()); } /** @@ -68,6 +67,19 @@ public function getPriority(): int return 42; } + /** + * {@inheritDoc} + */ + protected function createConfigurationDefinition(): FixerConfigurationResolverInterface + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('fix_non_monolithic_code', 'Whether to also fix code with inline HTML.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) // @TODO change to "false" on next major 4.0 + ->getOption(), + ]); + } + /** * {@inheritdoc} */ @@ -86,12 +98,10 @@ private function findParenthesisEnd(Tokens $tokens, int $structureTokenIndex): i $nextIndex = $tokens->getNextMeaningfulToken($structureTokenIndex); $nextToken = $tokens[$nextIndex]; - // return if next token is not opening parenthesis - if (!$nextToken->equals('(')) { - return $structureTokenIndex; - } - - return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextIndex); + return $nextToken->equals('(') + ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextIndex) + : $structureTokenIndex // return if next token is not opening parenthesis + ; } /** diff --git a/src/Fixer/ControlStructure/NoBreakCommentFixer.php b/src/Fixer/ControlStructure/NoBreakCommentFixer.php index 8a750bfad61..55336176605 100644 --- a/src/Fixer/ControlStructure/NoBreakCommentFixer.php +++ b/src/Fixer/ControlStructure/NoBreakCommentFixer.php @@ -100,7 +100,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn (new FixerOptionBuilder('comment_text', 'The text to use in the added comment and to detect it.')) ->setAllowedTypes(['string']) ->setAllowedValues([ - static function (string $value) { + static function (string $value): bool { if (Preg::match('/\R/', $value)) { throw new InvalidOptionsException('The comment text must not contain new lines.'); } @@ -108,7 +108,7 @@ static function (string $value) { return true; }, ]) - ->setNormalizer(static function (Options $options, $value) { + ->setNormalizer(static function (Options $options, string $value): string { return rtrim($value); }) ->setDefault('no break') @@ -122,17 +122,15 @@ static function (string $value) { protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { for ($index = \count($tokens) - 1; $index >= 0; --$index) { - if (!$tokens[$index]->isGivenKind([T_CASE, T_DEFAULT])) { + if ($tokens[$index]->isGivenKind(T_DEFAULT)) { + if ($tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind(T_DOUBLE_ARROW)) { + continue; // this is "default" from "match" + } + } elseif (!$tokens[$index]->isGivenKind(T_CASE)) { continue; } - $caseColonIndex = $tokens->getNextTokenOfKind($index, [':', ';', [T_DOUBLE_ARROW]]); - - if ($tokens[$caseColonIndex]->isGivenKind(T_DOUBLE_ARROW)) { - continue; // this is "default" from "match" - } - - $this->fixCase($tokens, $caseColonIndex); + $this->fixCase($tokens, $tokens->getNextTokenOfKind($index, [':', ';'])); } } diff --git a/src/Fixer/ControlStructure/NoUnneededControlParenthesesFixer.php b/src/Fixer/ControlStructure/NoUnneededControlParenthesesFixer.php index 69085b9fb83..d6226da70a7 100644 --- a/src/Fixer/ControlStructure/NoUnneededControlParenthesesFixer.php +++ b/src/Fixer/ControlStructure/NoUnneededControlParenthesesFixer.php @@ -16,6 +16,7 @@ use PhpCsFixer\AbstractFixer; use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; @@ -44,14 +45,6 @@ final class NoUnneededControlParenthesesFixer extends AbstractFixer implements C 'yield_from' => ['lookupTokens' => T_YIELD_FROM, 'neededSuccessors' => [';', ')']], ]; - /** - * Dynamic option set on constructor. - */ - public function __construct() - { - parent::__construct(); - } - /** * {@inheritdoc} */ @@ -62,6 +55,7 @@ public function isCandidate(Tokens $tokens): bool foreach (self::$loops as $loop) { $types[] = (array) $loop['lookupTokens']; } + $types = array_merge(...$types); return $tokens->isAnyTokenKindsFound($types); @@ -140,6 +134,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $token->equals('(') ? Tokens::BLOCK_TYPE_PARENTHESIS_BRACE : Tokens::BLOCK_TYPE_BRACE_CLASS_INSTANTIATION, $blockStartIndex ); + $blockEndNextIndex = $tokens->getNextMeaningfulToken($blockEndIndex); if (!$tokens[$blockEndNextIndex]->equalsAny($loop['neededSuccessors'])) { @@ -148,6 +143,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if (\array_key_exists('forbiddenContents', $loop)) { $forbiddenTokenIndex = $tokens->getNextTokenOfKind($blockStartIndex, $loop['forbiddenContents']); + // A forbidden token is found and is inside the parenthesis. if (null !== $forbiddenTokenIndex && $forbiddenTokenIndex < $blockEndIndex) { continue; @@ -174,6 +170,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn return new FixerConfigurationResolver([ (new FixerOptionBuilder('statements', 'List of control statements to fix.')) ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(array_keys(self::$loops))]) ->setDefault([ 'break', 'clone', diff --git a/src/Fixer/ControlStructure/NoUnneededCurlyBracesFixer.php b/src/Fixer/ControlStructure/NoUnneededCurlyBracesFixer.php index c130965c089..34c80d18e04 100644 --- a/src/Fixer/ControlStructure/NoUnneededCurlyBracesFixer.php +++ b/src/Fixer/ControlStructure/NoUnneededCurlyBracesFixer.php @@ -25,9 +25,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NoUnneededCurlyBracesFixer extends AbstractFixer implements ConfigurableFixerInterface { /** diff --git a/src/Fixer/ControlStructure/NoUselessElseFixer.php b/src/Fixer/ControlStructure/NoUselessElseFixer.php index 1a3dc2d7582..58a9a3cb400 100644 --- a/src/Fixer/ControlStructure/NoUselessElseFixer.php +++ b/src/Fixer/ControlStructure/NoUselessElseFixer.php @@ -20,9 +20,6 @@ use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NoUselessElseFixer extends AbstractNoUselessElseFixer { /** diff --git a/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php b/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php index 51de357c222..355643dc18f 100644 --- a/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php +++ b/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php @@ -23,8 +23,6 @@ /** * Fixer for rules defined in PSR2 ¶5.2. - * - * @author SpacePossum */ final class SwitchCaseSemicolonToColonFixer extends AbstractFixer { diff --git a/src/Fixer/ControlStructure/SwitchContinueToBreakFixer.php b/src/Fixer/ControlStructure/SwitchContinueToBreakFixer.php index b8db6a50c1a..c929c983052 100644 --- a/src/Fixer/ControlStructure/SwitchContinueToBreakFixer.php +++ b/src/Fixer/ControlStructure/SwitchContinueToBreakFixer.php @@ -152,7 +152,7 @@ private function fixInLoop(Tokens $tokens, int $openIndex, int $depth): int { $openCount = 1; - do { + while (true) { ++$openIndex; $token = $tokens[$openIndex]; @@ -173,7 +173,7 @@ private function fixInLoop(Tokens $tokens, int $openIndex, int $depth): int } $openIndex = $this->doFix($tokens, $openIndex, $depth, false); - } while (true); + } return $openIndex; } diff --git a/src/Fixer/ControlStructure/TrailingCommaInMultilineFixer.php b/src/Fixer/ControlStructure/TrailingCommaInMultilineFixer.php index 58020fc317e..01950325fe2 100644 --- a/src/Fixer/ControlStructure/TrailingCommaInMultilineFixer.php +++ b/src/Fixer/ControlStructure/TrailingCommaInMultilineFixer.php @@ -127,6 +127,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn if (\PHP_VERSION_ID < 70300 && \in_array(self::ELEMENTS_ARGUMENTS, $value, true)) { throw new InvalidOptionsForEnvException(sprintf('"%s" option can only be enabled with PHP 7.3+.', self::ELEMENTS_ARGUMENTS)); } + if (\PHP_VERSION_ID < 80000 && \in_array(self::ELEMENTS_PARAMETERS, $value, true)) { throw new InvalidOptionsForEnvException(sprintf('"%s" option can only be enabled with PHP 8.0+.', self::ELEMENTS_PARAMETERS)); } diff --git a/src/Fixer/ControlStructure/YodaStyleFixer.php b/src/Fixer/ControlStructure/YodaStyleFixer.php index 9cfd7f45481..24049d547ef 100644 --- a/src/Fixer/ControlStructure/YodaStyleFixer.php +++ b/src/Fixer/ControlStructure/YodaStyleFixer.php @@ -30,7 +30,6 @@ /** * @author Bram Gotink * @author Dariusz Rumiński - * @author SpacePossum */ final class YodaStyleFixer extends AbstractFixer implements ConfigurableFixerInterface { @@ -179,8 +178,10 @@ private function findComparisonEnd(Tokens $tokens, int $index): int { ++$index; $count = \count($tokens); + while ($index < $count) { $token = $tokens[$index]; + if ($token->isGivenKind([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { ++$index; @@ -192,6 +193,7 @@ private function findComparisonEnd(Tokens $tokens, int $index): int } $block = Tokens::detectBlockType($token); + if (null === $block) { ++$index; @@ -230,6 +232,7 @@ private function findComparisonStart(Tokens $tokens, int $index): int while (0 <= $index) { $token = $tokens[$index]; + if ($token->isGivenKind([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { --$index; @@ -241,6 +244,7 @@ private function findComparisonStart(Tokens $tokens, int $index): int } $block = Tokens::detectBlockType($token); + if (null === $block) { --$index; $nonBlockFound = true; @@ -276,6 +280,7 @@ private function fixTokens(Tokens $tokens): Tokens } $fixableCompareInfo = $this->getCompareFixableInfo($tokens, $i, $yoda); + if (null === $fixableCompareInfo) { continue; } @@ -304,7 +309,7 @@ private function fixTokens(Tokens $tokens): Tokens * If the left-hand side and right-hand side of the given comparison are * swapped, this function runs recursively on the previous left-hand-side. * - * @return int a upper bound for all non-fixed comparisons + * @return int an upper bound for all non-fixed comparisons */ private function fixTokensCompare( Tokens $tokens, @@ -316,6 +321,7 @@ private function fixTokensCompare( ): int { $type = $tokens[$compareOperatorIndex]->getId(); $content = $tokens[$compareOperatorIndex]->getContent(); + if (\array_key_exists($type, $this->candidatesMap)) { $tokens[$compareOperatorIndex] = clone $this->candidatesMap[$type]; } elseif (\array_key_exists($content, $this->candidatesMap)) { @@ -364,7 +370,6 @@ private function getCompareFixableInfo(Tokens $tokens, int $index, bool $yoda): } $strict = $this->configuration['always_move_variable']; - $leftSideIsVariable = $this->isVariable($tokens, $left['start'], $left['end'], $strict); $rightSideIsVariable = $this->isVariable($tokens, $right['start'], $right['end'], $strict); @@ -459,7 +464,7 @@ private function isOfLowerPrecedence(Token $token): bool * Checks whether the given assignment token has a lower precedence than `T_IS_EQUAL` * or `T_IS_IDENTICAL`. */ - private function isOfLowerPrecedenceAssignment(Token $token) + private function isOfLowerPrecedenceAssignment(Token $token): bool { static $tokens; @@ -536,6 +541,7 @@ private function isVariable(Tokens $tokens, int $start, int $end, bool $strict): } $expectString = false; + while ($index <= $end) { $current = $tokens[$index]; if ($current->isComment() || $current->isWhitespace() || $tokens->isEmptyAt($index)) { diff --git a/src/Fixer/DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php b/src/Fixer/DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php index 8a5f25498b2..199e008d0da 100644 --- a/src/Fixer/DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php +++ b/src/Fixer/DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php @@ -82,7 +82,7 @@ protected function fixAnnotations(Tokens $doctrineAnnotationTokens): void $indentLevel = 0; foreach ($doctrineAnnotationTokens as $index => $token) { - if (!$token->isType(DocLexer::T_NONE) || false === strpos($token->getContent(), "\n")) { + if (!$token->isType(DocLexer::T_NONE) || !str_contains($token->getContent(), "\n")) { continue; } @@ -125,7 +125,7 @@ private function getLineBracesCount(Tokens $tokens, int $index): array while (isset($tokens[++$index])) { $token = $tokens[$index]; - if ($token->isType(DocLexer::T_NONE) && false !== strpos($token->getContent(), "\n")) { + if ($token->isType(DocLexer::T_NONE) && str_contains($token->getContent(), "\n")) { break; } @@ -154,7 +154,7 @@ private function isClosingLineWithMeaningfulContent(Tokens $tokens, int $index): while (isset($tokens[++$index])) { $token = $tokens[$index]; if ($token->isType(DocLexer::T_NONE)) { - if (false !== strpos($token->getContent(), "\n")) { + if (str_contains($token->getContent(), "\n")) { return false; } @@ -181,7 +181,7 @@ private function indentationCanBeFixed(Tokens $tokens, int $newLineTokenIndex, a for ($index = $newLineTokenIndex + 1, $max = \count($tokens); $index < $max; ++$index) { $token = $tokens[$index]; - if (false !== strpos($token->getContent(), "\n")) { + if (str_contains($token->getContent(), "\n")) { return false; } diff --git a/src/Fixer/DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php b/src/Fixer/DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php index 50ccf7f992b..49ca2a60983 100644 --- a/src/Fixer/DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php +++ b/src/Fixer/DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php @@ -170,7 +170,7 @@ private function fixSpacesAroundParentheses(Tokens $tokens): void } if ($token->isType(DocLexer::T_NONE)) { - if (false !== strpos($token->getContent(), "\n")) { + if (str_contains($token->getContent(), "\n")) { continue; } diff --git a/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php b/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php index 878d50a9b8f..35e37b0a12e 100644 --- a/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php +++ b/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php @@ -15,10 +15,9 @@ namespace PhpCsFixer\Fixer\FunctionNotation; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -36,9 +35,8 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'Replace multiple nested calls of `dirname` by only one call with second `$level` parameter. Requires PHP >= 7.0.', [ - new VersionSpecificCodeSample( - "= 70000 && $tokens->isTokenKindFound(T_STRING); + return $tokens->isTokenKindFound(T_STRING); } /** @@ -160,7 +158,7 @@ private function getDirnameInfo(Tokens $tokens, int $index, ?int $firstArgumentE while (!$tokens[$next]->equalsAny([',', ')'])) { $blockType = Tokens::detectBlockType($tokens[$next]); - if ($blockType) { + if (null !== $blockType) { $next = $tokens->findBlockEnd($blockType['type'], $next); } diff --git a/src/Fixer/FunctionNotation/FopenFlagOrderFixer.php b/src/Fixer/FunctionNotation/FopenFlagOrderFixer.php index e873ec5a22b..15b0174fab3 100644 --- a/src/Fixer/FunctionNotation/FopenFlagOrderFixer.php +++ b/src/Fixer/FunctionNotation/FopenFlagOrderFixer.php @@ -22,9 +22,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class FopenFlagOrderFixer extends AbstractFopenFlagFixer { /** @@ -99,7 +96,7 @@ private function sortFlags(array $flags): array { usort( $flags, - static function (string $flag1, string $flag2) { + static function (string $flag1, string $flag2): int { if ($flag1 === $flag2) { return 0; } diff --git a/src/Fixer/FunctionNotation/FopenFlagsFixer.php b/src/Fixer/FunctionNotation/FopenFlagsFixer.php index faf5f51e0cb..301639a2fd0 100644 --- a/src/Fixer/FunctionNotation/FopenFlagsFixer.php +++ b/src/Fixer/FunctionNotation/FopenFlagsFixer.php @@ -25,9 +25,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class FopenFlagsFixer extends AbstractFopenFlagFixer implements ConfigurableFixerInterface { /** @@ -98,7 +95,7 @@ protected function fixFopenFlagToken(Tokens $tokens, int $argumentStartIndex, in $mode = str_replace('t', '', $mode); if ($this->configuration['b_mode']) { - if (false === strpos($mode, 'b')) { + if (!str_contains($mode, 'b')) { $mode .= 'b'; } } else { diff --git a/src/Fixer/FunctionNotation/ImplodeCallFixer.php b/src/Fixer/FunctionNotation/ImplodeCallFixer.php index 6ac1e19b441..166482d6109 100644 --- a/src/Fixer/FunctionNotation/ImplodeCallFixer.php +++ b/src/Fixer/FunctionNotation/ImplodeCallFixer.php @@ -101,7 +101,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } if (2 === \count($argumentsIndices)) { - list($firstArgumentIndex, $secondArgumentIndex) = array_keys($argumentsIndices); + [$firstArgumentIndex, $secondArgumentIndex] = array_keys($argumentsIndices); // If the first argument is string we have nothing to do if ($tokens[$firstArgumentIndex]->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { diff --git a/src/Fixer/FunctionNotation/LambdaNotUsedImportFixer.php b/src/Fixer/FunctionNotation/LambdaNotUsedImportFixer.php index 926ea5bd880..d0e73f90d4c 100644 --- a/src/Fixer/FunctionNotation/LambdaNotUsedImportFixer.php +++ b/src/Fixer/FunctionNotation/LambdaNotUsedImportFixer.php @@ -24,9 +24,6 @@ use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\TokensAnalyzer; -/** - * @author SpacePossum - */ final class LambdaNotUsedImportFixer extends AbstractFixer { /** diff --git a/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php b/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php index a38de80970f..e34ad84f862 100644 --- a/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php +++ b/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php @@ -137,6 +137,7 @@ public function getPriority(): int protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { $expectedTokens = [T_LIST, T_FUNCTION, CT::T_USE_LAMBDA]; + if (\PHP_VERSION_ID >= 70400) { $expectedTokens[] = T_FN; } @@ -149,6 +150,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } $meaningfulTokenBeforeParenthesis = $tokens[$tokens->getPrevMeaningfulToken($index)]; + if ( $meaningfulTokenBeforeParenthesis->isKeyword() && !$meaningfulTokenBeforeParenthesis->isGivenKind($expectedTokens) @@ -209,10 +211,9 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn */ private function fixFunction(Tokens $tokens, int $startFunctionIndex): bool { - $endFunctionIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startFunctionIndex); - $isMultiline = false; + $endFunctionIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startFunctionIndex); $firstWhitespaceIndex = $this->findWhitespaceIndexAfterParenthesis($tokens, $startFunctionIndex, $endFunctionIndex); $lastWhitespaceIndex = $this->findWhitespaceIndexAfterParenthesis($tokens, $endFunctionIndex, $startFunctionIndex); @@ -228,6 +229,7 @@ private function fixFunction(Tokens $tokens, int $startFunctionIndex): bool } $newLinesRemoved = $this->ensureSingleLine($tokens, $index); + if (!$newLinesRemoved) { $isMultiline = true; } @@ -294,11 +296,13 @@ private function findWhitespaceIndexAfterParenthesis(Tokens $tokens, int $startP private function ensureSingleLine(Tokens $tokens, int $index): bool { $previousToken = $tokens[$index - 1]; - if ($previousToken->isComment() && 0 !== strpos($previousToken->getContent(), '/*')) { + + if ($previousToken->isComment() && !str_starts_with($previousToken->getContent(), '/*')) { return false; } $content = Preg::replace('/\R\h*/', '', $tokens[$index]->getContent()); + if ('' !== $content) { $tokens[$index] = new Token([T_WHITESPACE, $content]); } else { @@ -317,9 +321,10 @@ private function ensureFunctionFullyMultiline(Tokens $tokens, int $startFunction $searchIndex, [[T_WHITESPACE]] ); + $searchIndex = $prevWhitespaceTokenIndex; } while (null !== $prevWhitespaceTokenIndex - && false === strpos($tokens[$prevWhitespaceTokenIndex]->getContent(), "\n") + && !str_contains($tokens[$prevWhitespaceTokenIndex]->getContent(), "\n") ); if (null === $prevWhitespaceTokenIndex) { @@ -400,6 +405,7 @@ private function fixNewline(Tokens $tokens, int $index, string $indentation, boo } $nextMeaningfulTokenIndex = $tokens->getNextMeaningfulToken($index); + if ($tokens[$nextMeaningfulTokenIndex]->equals(')')) { return; } @@ -476,6 +482,6 @@ private function isCommentLastLineToken(Tokens $tokens, int $index): bool */ private function isNewline(Token $token): bool { - return $token->isWhitespace() && false !== strpos($token->getContent(), "\n"); + return $token->isWhitespace() && str_contains($token->getContent(), "\n"); } } diff --git a/src/Fixer/FunctionNotation/NativeFunctionInvocationFixer.php b/src/Fixer/FunctionNotation/NativeFunctionInvocationFixer.php index 7da5ab1c0fa..5cbffc88dea 100644 --- a/src/Fixer/FunctionNotation/NativeFunctionInvocationFixer.php +++ b/src/Fixer/FunctionNotation/NativeFunctionInvocationFixer.php @@ -31,7 +31,6 @@ /** * @author Andreas Möller - * @author SpacePossum */ final class NativeFunctionInvocationFixer extends AbstractFixer implements ConfigurableFixerInterface { @@ -168,7 +167,7 @@ function baz($options) * {@inheritdoc} * * Must run before GlobalNamespaceImportFixer. - * Must run after BacktickToShellExecFixer, StrictParamFixer. + * Must run after BacktickToShellExecFixer, RegularCallableCallFixer, StrictParamFixer. */ public function getPriority(): int { @@ -219,7 +218,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn return new FixerConfigurationResolver([ (new FixerOptionBuilder('exclude', 'List of functions to ignore.')) ->setAllowedTypes(['array']) - ->setAllowedValues([static function (array $value) { + ->setAllowedValues([static function (array $value): bool { foreach ($value as $functionName) { if (!\is_string($functionName) || '' === trim($functionName) || trim($functionName) !== $functionName) { throw new InvalidOptionsException(sprintf( @@ -235,7 +234,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ->getOption(), (new FixerOptionBuilder('include', 'List of function names or sets to fix. Defined sets are `@internal` (all native functions), `@all` (all global functions) and `@compiler_optimized` (functions that are specially optimized by Zend).')) ->setAllowedTypes(['array']) - ->setAllowedValues([static function (array $value) { + ->setAllowedValues([static function (array $value): bool { foreach ($value as $functionName) { if (!\is_string($functionName) || '' === trim($functionName) || trim($functionName) !== $functionName) { throw new InvalidOptionsException(sprintf( @@ -309,17 +308,18 @@ private function getFunctionFilter(): callable if (\in_array(self::SET_ALL, $this->configuration['include'], true)) { if (\count($exclude) > 0) { - return static function (string $functionName) use ($exclude) { + return static function (string $functionName) use ($exclude): bool { return !isset($exclude[strtolower($functionName)]); }; } - return static function () { + return static function (): bool { return true; }; } $include = []; + if (\in_array(self::SET_INTERNAL, $this->configuration['include'], true)) { $include = $this->getAllInternalFunctionsNormalized(); } elseif (\in_array(self::SET_COMPILER_OPTIMIZED, $this->configuration['include'], true)) { @@ -333,12 +333,12 @@ private function getFunctionFilter(): callable } if (\count($exclude) > 0) { - return static function (string $functionName) use ($include, $exclude) { + return static function (string $functionName) use ($include, $exclude): bool { return isset($include[strtolower($functionName)]) && !isset($exclude[strtolower($functionName)]); }; } - return static function (string $functionName) use ($include) { + return static function (string $functionName) use ($include): bool { return isset($include[strtolower($functionName)]); }; } diff --git a/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php b/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php index c4ce88a1ecf..8aca8026a82 100644 --- a/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php +++ b/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php @@ -19,10 +19,9 @@ use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Analyzer\Analysis\ArgumentAnalysis; use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; use PhpCsFixer\Tokenizer\CT; @@ -42,13 +41,11 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'Adds or removes `?` before type declarations for parameters with a default `null` value.', [ - new VersionSpecificCodeSample( - " false] ), ], @@ -61,10 +58,6 @@ public function getDefinition(): FixerDefinitionInterface */ public function isCandidate(Tokens $tokens): bool { - if (\PHP_VERSION_ID < 70100) { - return false; - } - if (!$tokens->isTokenKindFound(T_VARIABLE)) { return false; } @@ -135,7 +128,7 @@ private function fixFunctionParameters(Tokens $tokens, array $arguments): void // - doesn't have a type declaration !$argumentInfo->hasTypeAnalysis() // type is a union - || false !== strpos($argumentInfo->getTypeAnalysis()->getName(), '|') + || str_contains($argumentInfo->getTypeAnalysis()->getName(), '|') // - a default value is not null we can continue || !$argumentInfo->hasDefault() || 'null' !== strtolower($argumentInfo->getDefault()) ) { diff --git a/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php b/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php index 06e36dc8001..52a082dbacd 100644 --- a/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php +++ b/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php @@ -16,10 +16,9 @@ use PhpCsFixer\AbstractPhpdocToTypeDeclarationFixer; use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -28,8 +27,6 @@ */ final class PhpdocToParamTypeFixer extends AbstractPhpdocToTypeDeclarationFixer { - private const MINIMUM_PHP_VERSION = 70000; - /** * @var array{int, string}[] */ @@ -56,25 +53,18 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'EXPERIMENTAL: Takes `@param` annotations of non-mixed types and adjusts accordingly the function signature. Requires PHP >= 7.0.', [ - new VersionSpecificCodeSample( + new CodeSample( ' false] ), ], @@ -96,7 +85,7 @@ function bar($foo) {} */ public function isCandidate(Tokens $tokens): bool { - return \PHP_VERSION_ID >= self::MINIMUM_PHP_VERSION && $tokens->isTokenKindFound(T_FUNCTION); + return $tokens->isTokenKindFound(T_FUNCTION); } /** @@ -143,7 +132,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - list($paramType, $isNullable) = $typeInfo; + [$paramType, $isNullable] = $typeInfo; $startIndex = $tokens->getNextTokenOfKind($index, ['(']); $variableIndex = $this->findCorrectVariable($tokens, $startIndex, $paramTypeAnnotation); diff --git a/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php b/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php index d3506c2036f..bc20074570f 100644 --- a/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php +++ b/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php @@ -134,7 +134,7 @@ private function fixClass(Tokens $tokens, int $index): void continue; } - $typeInfo = $this->resolveAppliableType( + $typeInfo = $this->resolveApplicableType( $propertyIndexes, $this->getAnnotationsFromDocComment('var', $tokens, $docCommentIndex) ); @@ -143,9 +143,9 @@ private function fixClass(Tokens $tokens, int $index): void continue; } - list($propertyType, $isNullable) = $typeInfo; + [$propertyType, $isNullable] = $typeInfo; - if (\in_array($propertyType, ['void', 'callable'], true)) { + if (\in_array($propertyType, ['callable', 'never', 'void'], true)) { continue; } @@ -181,6 +181,7 @@ private function findNextUntypedPropertiesDeclaration(Tokens $tokens, int $index } $properties = []; + while (!$tokens[$index]->equals(';')) { if ($tokens[$index]->isGivenKind(T_VARIABLE)) { $properties[$tokens[$index]->getContent()] = $index; @@ -196,7 +197,7 @@ private function findNextUntypedPropertiesDeclaration(Tokens $tokens, int $index * @param array $propertyIndexes * @param Annotation[] $annotations */ - private function resolveAppliableType(array $propertyIndexes, array $annotations): ?array + private function resolveApplicableType(array $propertyIndexes, array $annotations): ?array { $propertyTypes = []; @@ -231,6 +232,7 @@ private function resolveAppliableType(array $propertyIndexes, array $annotations } $type = array_shift($propertyTypes); + foreach ($propertyTypes as $propertyType) { if ($propertyType !== $type) { return null; diff --git a/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php b/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php index 38e15cb2914..e31f247e5a9 100644 --- a/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php +++ b/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php @@ -15,6 +15,7 @@ namespace PhpCsFixer\Fixer\FunctionNotation; use PhpCsFixer\AbstractPhpdocToTypeDeclarationFixer; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\FixerDefinition\VersionSpecification; @@ -54,23 +55,17 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'EXPERIMENTAL: Takes `@return` annotation of non-mixed types and adjusts accordingly the function signature. Requires PHP >= 7.0.', [ - new VersionSpecificCodeSample( + new CodeSample( ' false] ), new VersionSpecificCodeSample( @@ -120,7 +114,7 @@ public function isCandidate(Tokens $tokens): bool return true; } - return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_FUNCTION); + return $tokens->isTokenKindFound(T_FUNCTION); } /** @@ -178,7 +172,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - list($returnType, $isNullable) = $typeInfo; + [$returnType, $isNullable] = $typeInfo; $startIndex = $tokens->getNextTokenOfKind($index, ['{', ';']); diff --git a/src/Fixer/FunctionNotation/RegularCallableCallFixer.php b/src/Fixer/FunctionNotation/RegularCallableCallFixer.php index d226737ee7b..1cd3f6ec330 100644 --- a/src/Fixer/FunctionNotation/RegularCallableCallFixer.php +++ b/src/Fixer/FunctionNotation/RegularCallableCallFixer.php @@ -18,8 +18,6 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; use PhpCsFixer\Tokenizer\Token; @@ -47,13 +45,12 @@ public function getDefinition(): FixerDefinitionInterface call_user_func_array($callback, [1, 2]); ' ), - new VersionSpecificCodeSample( + new CodeSample( 'replaceCallUserFuncWithCallback($tokens, $index, $newCallTokens, $firstArgIndex, $firstArgIndex); } elseif ($firstArgToken->isGivenKind([T_FUNCTION, T_STATIC])) { - if (\PHP_VERSION_ID >= 70000) { - $firstArgEndIndex = $tokens->findBlockEnd( - Tokens::BLOCK_TYPE_CURLY_BRACE, - $tokens->getNextTokenOfKind($firstArgIndex, ['{']) - ); + $firstArgEndIndex = $tokens->findBlockEnd( + Tokens::BLOCK_TYPE_CURLY_BRACE, + $tokens->getNextTokenOfKind($firstArgIndex, ['{']) + ); - $newCallTokens = $this->getTokensSubcollection($tokens, $firstArgIndex, $firstArgEndIndex); - $newCallTokens->insertAt($newCallTokens->count(), new Token(')')); - $newCallTokens->insertAt(0, new Token('(')); - $this->replaceCallUserFuncWithCallback($tokens, $index, $newCallTokens, $firstArgIndex, $firstArgEndIndex); - } + $newCallTokens = $this->getTokensSubcollection($tokens, $firstArgIndex, $firstArgEndIndex); + $newCallTokens->insertAt($newCallTokens->count(), new Token(')')); + $newCallTokens->insertAt(0, new Token('(')); + $this->replaceCallUserFuncWithCallback($tokens, $index, $newCallTokens, $firstArgIndex, $firstArgEndIndex); } elseif ($firstArgToken->isGivenKind(T_VARIABLE)) { $firstArgEndIndex = reset($arguments); @@ -178,10 +183,6 @@ private function processCall(Tokens $tokens, int $index, array $arguments): void } if ($complex) { - if (\PHP_VERSION_ID < 70000) { - return; - } - $newCallTokens->insertAt($newCallTokens->count(), new Token(')')); $newCallTokens->insertAt(0, new Token('(')); } diff --git a/src/Fixer/FunctionNotation/ReturnTypeDeclarationFixer.php b/src/Fixer/FunctionNotation/ReturnTypeDeclarationFixer.php index e931e9d9c33..fe3015929f0 100644 --- a/src/Fixer/FunctionNotation/ReturnTypeDeclarationFixer.php +++ b/src/Fixer/FunctionNotation/ReturnTypeDeclarationFixer.php @@ -19,10 +19,9 @@ use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -37,23 +36,18 @@ final class ReturnTypeDeclarationFixer extends AbstractFixer implements Configur */ public function getDefinition(): FixerDefinitionInterface { - $versionSpecification = new VersionSpecification(70000); - return new FixerDefinition( 'There should be one or no space before colon, and one space after it in return type declarations, according to configuration.', [ - new VersionSpecificCodeSample( - " 'none'] ), - new VersionSpecificCodeSample( + new CodeSample( " 'one'] ), ], @@ -76,7 +70,7 @@ public function getPriority(): int */ public function isCandidate(Tokens $tokens): bool { - return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(CT::T_TYPE_COLON); + return $tokens->isTokenKindFound(CT::T_TYPE_COLON); } /** diff --git a/src/Fixer/FunctionNotation/SingleLineThrowFixer.php b/src/Fixer/FunctionNotation/SingleLineThrowFixer.php index f8599dd395b..da61d6f473b 100644 --- a/src/Fixer/FunctionNotation/SingleLineThrowFixer.php +++ b/src/Fixer/FunctionNotation/SingleLineThrowFixer.php @@ -95,10 +95,10 @@ private function trimNewLines(Tokens $tokens, int $startIndex, int $endIndex): v $content = $tokens[$index]->getContent(); if ($tokens[$index]->isGivenKind(T_COMMENT)) { - if (0 === strpos($content, '//')) { + if (str_starts_with($content, '//')) { $content = '/*'.substr($content, 2).' */'; $tokens->clearAt($index + 1); - } elseif (0 === strpos($content, '#')) { + } elseif (str_starts_with($content, '#')) { $content = '/*'.substr($content, 1).' */'; $tokens->clearAt($index + 1); } elseif (false !== Preg::match('/\R/', $content)) { diff --git a/src/Fixer/FunctionNotation/StaticLambdaFixer.php b/src/Fixer/FunctionNotation/StaticLambdaFixer.php index c43b09e91e0..1220bb459a9 100644 --- a/src/Fixer/FunctionNotation/StaticLambdaFixer.php +++ b/src/Fixer/FunctionNotation/StaticLambdaFixer.php @@ -23,9 +23,6 @@ use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\TokensAnalyzer; -/** - * @author SpacePossum - */ final class StaticLambdaFixer extends AbstractFixer { /** diff --git a/src/Fixer/FunctionNotation/UseArrowFunctionsFixer.php b/src/Fixer/FunctionNotation/UseArrowFunctionsFixer.php index 6681386910e..8a5733745c5 100644 --- a/src/Fixer/FunctionNotation/UseArrowFunctionsFixer.php +++ b/src/Fixer/FunctionNotation/UseArrowFunctionsFixer.php @@ -177,7 +177,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void private function isMultilined(Tokens $tokens, int $start, int $end): bool { for ($i = $start; $i < $end; ++$i) { - if (false !== strpos($tokens[$i]->getContent(), "\n")) { + if (str_contains($tokens[$i]->getContent(), "\n")) { return true; } } @@ -188,18 +188,17 @@ private function isMultilined(Tokens $tokens, int $start, int $end): bool private function transform(Tokens $tokens, int $index, ?int $useStart, ?int $useEnd, int $braceOpen, int $return, int $semicolon, int $braceClose): void { $tokensToInsert = [new Token([T_DOUBLE_ARROW, '=>'])]; + if ($tokens->getNextMeaningfulToken($return) === $semicolon) { $tokensToInsert[] = new Token([T_WHITESPACE, ' ']); $tokensToInsert[] = new Token([T_STRING, 'null']); } $tokens->clearRange($semicolon, $braceClose); - $tokens->clearRange($braceOpen + 1, $return); - $tokens->overrideRange($braceOpen, $braceOpen, $tokensToInsert); - if ($useStart) { + if (null !== $useStart) { $tokens->clearRange($useStart, $useEnd); } diff --git a/src/Fixer/FunctionNotation/VoidReturnFixer.php b/src/Fixer/FunctionNotation/VoidReturnFixer.php index 84ccdd52f4c..47fb0118268 100644 --- a/src/Fixer/FunctionNotation/VoidReturnFixer.php +++ b/src/Fixer/FunctionNotation/VoidReturnFixer.php @@ -17,10 +17,9 @@ use PhpCsFixer\AbstractFixer; use PhpCsFixer\DocBlock\Annotation; use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -39,9 +38,8 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'Add `void` return type to functions with missing or empty return statements, but priority is given to `@return` annotations. Requires PHP >= 7.1.', [ - new VersionSpecificCodeSample( - "= 70100 && $tokens->isTokenKindFound(T_FUNCTION); + return $tokens->isTokenKindFound(T_FUNCTION); } /** diff --git a/src/Fixer/Import/FullyQualifiedStrictTypesFixer.php b/src/Fixer/Import/FullyQualifiedStrictTypesFixer.php index f03276c57cf..26027cdad2d 100644 --- a/src/Fixer/Import/FullyQualifiedStrictTypesFixer.php +++ b/src/Fixer/Import/FullyQualifiedStrictTypesFixer.php @@ -18,8 +18,6 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Analyzer\Analysis\TypeAnalysis; use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; @@ -55,7 +53,7 @@ public function doSomething(\Foo\Bar $foo) } ' ), - new VersionSpecificCodeSample( + new CodeSample( 'getFunctionReturnType($tokens, $index); if (!$returnType) { return; @@ -157,7 +150,7 @@ private function detectAndReplaceTypeWithShortType( foreach ($this->getSimpleTypes($tokens, $typeStartIndex, $type->getEndIndex()) as $simpleType) { $typeName = $tokens->generatePartialCode($simpleType['start'], $simpleType['end']); - if (0 !== strpos($typeName, '\\')) { + if (!str_starts_with($typeName, '\\')) { continue; } diff --git a/src/Fixer/Import/GlobalNamespaceImportFixer.php b/src/Fixer/Import/GlobalNamespaceImportFixer.php index bf6abc987c5..3f7e13ceffe 100644 --- a/src/Fixer/Import/GlobalNamespaceImportFixer.php +++ b/src/Fixer/Import/GlobalNamespaceImportFixer.php @@ -176,7 +176,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn */ private function importConstants(Tokens $tokens, array $useDeclarations): array { - list($global, $other) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + [$global, $other] = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration): bool { return $declaration->isConstant(); }, true); @@ -248,7 +248,7 @@ private function importConstants(Tokens $tokens, array $useDeclarations): array */ private function importFunctions(Tokens $tokens, array $useDeclarations): array { - list($global, $other) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + [$global, $other] = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration): bool { return $declaration->isFunction(); }, false); @@ -299,7 +299,7 @@ private function importFunctions(Tokens $tokens, array $useDeclarations): array */ private function importClasses(Tokens $tokens, array $useDeclarations): array { - list($global, $other) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + [$global, $other] = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration): bool { return $declaration->isClass(); }, false); @@ -315,7 +315,7 @@ private function importClasses(Tokens $tokens, array $useDeclarations): array $docBlocks[$index] = new DocBlock($token->getContent()); $this->traverseDocBlockTypes($docBlocks[$index], static function (string $type) use ($global, &$other): void { - if (false !== strpos($type, '\\')) { + if (str_contains($type, '\\')) { return; } @@ -378,7 +378,7 @@ private function importClasses(Tokens $tokens, array $useDeclarations): array $imports = []; foreach ($docBlocks as $index => $docBlock) { - $changed = $this->traverseDocBlockTypes($docBlock, static function (string $type) use ($global, $other, &$imports) { + $changed = $this->traverseDocBlockTypes($docBlock, static function (string $type) use ($global, $other, &$imports): string { if ('\\' !== $type[0]) { return $type; } @@ -386,7 +386,7 @@ private function importClasses(Tokens $tokens, array $useDeclarations): array $name = substr($type, 1); $checkName = strtolower($name); - if (false !== strpos($checkName, '\\') || isset($other[$checkName])) { + if (str_contains($checkName, '\\') || isset($other[$checkName])) { return $type; } @@ -453,7 +453,7 @@ private function insertImports(Tokens $tokens, array $imports, array $useDeclara $lineEnding = $this->whitespacesConfig->getLineEnding(); - if (!$tokens[$index]->isWhitespace() || false === strpos($tokens[$index]->getContent(), "\n")) { + if (!$tokens[$index]->isWhitespace() || !str_contains($tokens[$index]->getContent(), "\n")) { $tokens->insertAt($index, new Token([T_WHITESPACE, $lineEnding])); } @@ -490,7 +490,7 @@ private function fullyQualifyConstants(Tokens $tokens, array $useDeclarations): return; } - list($global) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + [$global] = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration): bool { return $declaration->isConstant() && !$declaration->isAliased(); }, true); @@ -532,7 +532,7 @@ private function fullyQualifyFunctions(Tokens $tokens, array $useDeclarations): return; } - list($global) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + [$global] = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration): bool { return $declaration->isFunction() && !$declaration->isAliased(); }, false); @@ -574,7 +574,7 @@ private function fullyQualifyClasses(Tokens $tokens, array $useDeclarations): vo return; } - list($global) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + [$global] = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration): bool { return $declaration->isClass() && !$declaration->isAliased(); }, false); @@ -590,7 +590,7 @@ private function fullyQualifyClasses(Tokens $tokens, array $useDeclarations): vo if ($token->isGivenKind(T_DOC_COMMENT)) { $doc = new DocBlock($token->getContent()); - $changed = $this->traverseDocBlockTypes($doc, static function (string $type) use ($global) { + $changed = $this->traverseDocBlockTypes($doc, static function (string $type) use ($global): string { if (!isset($global[strtolower($type)])) { return $type; } @@ -640,7 +640,7 @@ private function filterUseDeclarations(array $declarations, callable $callback, $fullName = ltrim($declaration->getFullName(), '\\'); - if (false !== strpos($fullName, '\\')) { + if (str_contains($fullName, '\\')) { $name = $caseSensitive ? $declaration->getShortName() : strtolower($declaration->getShortName()); $other[$name] = true; @@ -723,7 +723,7 @@ private function traverseDocBlockTypes(DocBlock $doc, callable $callback): bool Preg::matchAll('/[\\\\\w]+/', $fullType, $matches, PREG_OFFSET_CAPTURE); - foreach (array_reverse($matches[0]) as list($type, $offset)) { + foreach (array_reverse($matches[0]) as [$type, $offset]) { $newType = $callback($type); if (null !== $newType && $type !== $newType) { diff --git a/src/Fixer/Import/GroupImportFixer.php b/src/Fixer/Import/GroupImportFixer.php index 7d5e364f677..d6e4351d526 100644 --- a/src/Fixer/Import/GroupImportFixer.php +++ b/src/Fixer/Import/GroupImportFixer.php @@ -15,10 +15,9 @@ namespace PhpCsFixer\Fixer\Import; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; use PhpCsFixer\Tokenizer\CT; @@ -38,9 +37,8 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'There MUST be group use for the same namespaces.', [ - new VersionSpecificCodeSample( - "= 70000 && $tokens->isTokenKindFound(T_USE); + return $tokens->isTokenKindFound(T_USE); } /** @@ -83,24 +81,24 @@ private function getSameNamespaces(Tokens $tokens): array } $allNamespaceAndType = array_map( - function (NamespaceUseAnalysis $useDeclaration) { + function (NamespaceUseAnalysis $useDeclaration): string { return $this->getNamespaceNameWithSlash($useDeclaration).$useDeclaration->getType(); }, $useDeclarations ); - $sameNamespaces = array_filter(array_count_values($allNamespaceAndType), function (int $count) { + $sameNamespaces = array_filter(array_count_values($allNamespaceAndType), static function (int $count): bool { return $count > 1; }); $sameNamespaces = array_keys($sameNamespaces); - $sameNamespaceAnalysis = array_filter($useDeclarations, function (NamespaceUseAnalysis $useDeclaration) use ($sameNamespaces) { + $sameNamespaceAnalysis = array_filter($useDeclarations, function (NamespaceUseAnalysis $useDeclaration) use ($sameNamespaces): bool { $namespaceNameAndType = $this->getNamespaceNameWithSlash($useDeclaration).$useDeclaration->getType(); return \in_array($namespaceNameAndType, $sameNamespaces, true); }); - usort($sameNamespaceAnalysis, function (NamespaceUseAnalysis $a, NamespaceUseAnalysis $b) { + usort($sameNamespaceAnalysis, function (NamespaceUseAnalysis $a, NamespaceUseAnalysis $b): int { $namespaceA = $this->getNamespaceNameWithSlash($a); $namespaceB = $this->getNamespaceNameWithSlash($b); diff --git a/src/Fixer/Import/NoUnusedImportsFixer.php b/src/Fixer/Import/NoUnusedImportsFixer.php index 3f404710d71..2f8f5ce8c37 100644 --- a/src/Fixer/Import/NoUnusedImportsFixer.php +++ b/src/Fixer/Import/NoUnusedImportsFixer.php @@ -21,10 +21,13 @@ use PhpCsFixer\Preg; use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\GotoLabelAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; /** * @author Dariusz Rumiński @@ -73,24 +76,18 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } foreach ((new NamespacesAnalyzer())->getDeclarations($tokens) as $namespace) { - $currentNamespaceUseDeclarations = array_filter( - $useDeclarations, - static function (NamespaceUseAnalysis $useDeclaration) use ($namespace) { - return - $useDeclaration->getStartIndex() >= $namespace->getScopeStartIndex() - && $useDeclaration->getEndIndex() <= $namespace->getScopeEndIndex() - ; - } - ); - - $usagesSearchIgnoredIndexes = []; + $currentNamespaceUseDeclarations = []; + $currentNamespaceUseDeclarationIndexes = []; - foreach ($currentNamespaceUseDeclarations as $useDeclaration) { - $usagesSearchIgnoredIndexes[$useDeclaration->getStartIndex()] = $useDeclaration->getEndIndex(); + foreach ($useDeclarations as $useDeclaration) { + if ($useDeclaration->getStartIndex() >= $namespace->getScopeStartIndex() && $useDeclaration->getEndIndex() <= $namespace->getScopeEndIndex()) { + $currentNamespaceUseDeclarations[] = $useDeclaration; + $currentNamespaceUseDeclarationIndexes[$useDeclaration->getStartIndex()] = $useDeclaration->getEndIndex(); + } } foreach ($currentNamespaceUseDeclarations as $useDeclaration) { - if (!$this->isImportUsed($tokens, $namespace, $usagesSearchIgnoredIndexes, $useDeclaration->getShortName())) { + if (!$this->isImportUsed($tokens, $namespace, $useDeclaration, $currentNamespaceUseDeclarationIndexes)) { $this->removeUseDeclaration($tokens, $useDeclaration); } } @@ -100,21 +97,54 @@ static function (NamespaceUseAnalysis $useDeclaration) use ($namespace) { } /** - * @param array $ignoredIndexes + * @param array $ignoredIndexes indexes of the use statements themselves that should not be checked as being "used" */ - private function isImportUsed(Tokens $tokens, NamespaceAnalysis $namespace, array $ignoredIndexes, string $shortName): bool + private function isImportUsed(Tokens $tokens, NamespaceAnalysis $namespace, NamespaceUseAnalysis $import, array $ignoredIndexes): bool { + $analyzer = new TokensAnalyzer($tokens); + $gotoLabelAnalyzer = new GotoLabelAnalyzer(); + + $tokensNotBeforeFunctionCall = [T_NEW]; + + $attributeIsDefined = \defined('T_ATTRIBUTE'); + + if ($attributeIsDefined) { // @TODO: drop condition when PHP 8.0+ is required + $tokensNotBeforeFunctionCall[] = T_ATTRIBUTE; + } + $namespaceEndIndex = $namespace->getScopeEndIndex(); + $inAttribute = false; + for ($index = $namespace->getScopeStartIndex(); $index <= $namespaceEndIndex; ++$index) { + $token = $tokens[$index]; + + if ($attributeIsDefined && $token->isGivenKind(T_ATTRIBUTE)) { + $inAttribute = true; + + continue; + } + + if ($attributeIsDefined && $token->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { + $inAttribute = false; + + continue; + } + if (isset($ignoredIndexes[$index])) { $index = $ignoredIndexes[$index]; continue; } - $token = $tokens[$index]; - if ($token->isGivenKind(T_STRING)) { + if (0 !== strcasecmp($import->getShortName(), $token->getContent())) { + continue; + } + + if ($inAttribute) { + return true; + } + $prevMeaningfulToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; if ($prevMeaningfulToken->isGivenKind(T_NAMESPACE)) { @@ -124,10 +154,29 @@ private function isImportUsed(Tokens $tokens, NamespaceAnalysis $namespace, arra } if ( - 0 === strcasecmp($shortName, $token->getContent()) - && !$prevMeaningfulToken->isGivenKind([T_NS_SEPARATOR, T_CONST, T_DOUBLE_COLON]) - && !$prevMeaningfulToken->isObjectOperator() + $prevMeaningfulToken->isGivenKind([T_NS_SEPARATOR, T_FUNCTION, T_CONST, T_DOUBLE_COLON]) + || $prevMeaningfulToken->isObjectOperator() ) { + continue; + } + + $nextMeaningfulIndex = $tokens->getNextMeaningfulToken($index); + + if ($gotoLabelAnalyzer->belongsToGoToLabel($tokens, $nextMeaningfulIndex)) { + continue; + } + + $nextMeaningfulToken = $tokens[$nextMeaningfulIndex]; + + if ($analyzer->isConstantInvocation($index)) { + $type = NamespaceUseAnalysis::TYPE_CONSTANT; + } elseif ($nextMeaningfulToken->equals('(') && !$prevMeaningfulToken->isGivenKind($tokensNotBeforeFunctionCall)) { + $type = NamespaceUseAnalysis::TYPE_FUNCTION; + } else { + $type = NamespaceUseAnalysis::TYPE_CLASS; + } + + if ($import->getType() === $type) { return true; } @@ -136,7 +185,7 @@ private function isImportUsed(Tokens $tokens, NamespaceAnalysis $namespace, arra if ($token->isComment() && Preg::match( - '/(?getShortName().'(?![[:alnum:]])/i', $token->getContent() ) ) { @@ -154,7 +203,7 @@ private function removeUseDeclaration(Tokens $tokens, NamespaceUseAnalysis $useD continue; } - if (!$tokens[$index]->isWhitespace() || false === strpos($tokens[$index]->getContent(), "\n")) { + if (!$tokens[$index]->isWhitespace() || !str_contains($tokens[$index]->getContent(), "\n")) { $tokens->clearTokenAndMergeSurroundingWhitespace($index); continue; @@ -162,6 +211,7 @@ private function removeUseDeclaration(Tokens $tokens, NamespaceUseAnalysis $useD // when multi line white space keep the line feed if the previous token is a comment $prevIndex = $tokens->getPrevNonWhitespace($index); + if ($tokens[$prevIndex]->isComment()) { $content = $tokens[$index]->getContent(); $tokens[$index] = new Token([T_WHITESPACE, substr($content, strrpos($content, "\n"))]); // preserve indent only @@ -196,6 +246,7 @@ private function removeUseDeclaration(Tokens $tokens, NamespaceUseAnalysis $useD } $nextIndex = $tokens->getNonEmptySibling($useDeclaration->getEndIndex(), 1); + if (null === $nextIndex) { return; } @@ -244,13 +295,13 @@ private function removeUsesInSameNamespace(Tokens $tokens, array $useDeclaration $useDeclarationFullName = ltrim($useDeclaration->getFullName(), '\\'); - if (0 !== strpos($useDeclarationFullName, $namespace.'\\')) { + if (!str_starts_with($useDeclarationFullName, $namespace.'\\')) { continue; } $partName = substr($useDeclarationFullName, $nsLength); - if (false === strpos($partName, '\\')) { + if (!str_contains($partName, '\\')) { $this->removeUseDeclaration($tokens, $useDeclaration); } } diff --git a/src/Fixer/Import/OrderedImportsFixer.php b/src/Fixer/Import/OrderedImportsFixer.php index 29b68c5da61..d2434c7b4a9 100644 --- a/src/Fixer/Import/OrderedImportsFixer.php +++ b/src/Fixer/Import/OrderedImportsFixer.php @@ -23,8 +23,6 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Preg; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; @@ -35,7 +33,6 @@ /** * @author Sebastiaan Stok * @author Dariusz Rumiński - * @author SpacePossum * @author Darius Matulionis * @author Adriano Pilger */ @@ -93,7 +90,9 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'Ordering `use` statements.', [ - new CodeSample(" self::SORT_LENGTH] ), - new VersionSpecificCodeSample( - " self::SORT_LENGTH, 'imports_order' => [ @@ -129,7 +123,7 @@ public function getDefinition(): FixerDefinitionInterface ], ] ), - new VersionSpecificCodeSample( + new CodeSample( ' self::SORT_ALPHA, 'imports_order' => [ @@ -151,7 +144,7 @@ public function getDefinition(): FixerDefinitionInterface ], ] ), - new VersionSpecificCodeSample( + new CodeSample( ' self::SORT_NONE, 'imports_order' => [ @@ -264,7 +256,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ->getOption(), (new FixerOptionBuilder('imports_order', 'Defines the order of import types.')) ->setAllowedTypes(['array', 'null']) - ->setAllowedValues([static function (?array $value) use ($supportedSortTypes) { + ->setAllowedValues([static function (?array $value) use ($supportedSortTypes): bool { if (null !== $value) { $missing = array_diff($supportedSortTypes, $value); if (\count($missing)) { @@ -414,7 +406,7 @@ private function getNewOrder(array $uses, Tokens $tokens): array if ( '' === $firstIndent && $namespaceTokens[$k2]->isWhitespace() - && false !== strpos($namespaceTokens[$k2]->getContent(), $lineEnding) + && str_contains($namespaceTokens[$k2]->getContent(), $lineEnding) ) { $lastIndent = $lineEnding; $firstIndent = $lineEnding.$this->whitespacesConfig->getIndent(); diff --git a/src/Fixer/Import/SingleImportPerStatementFixer.php b/src/Fixer/Import/SingleImportPerStatementFixer.php index c941f5cf9e0..0a48baacad6 100644 --- a/src/Fixer/Import/SingleImportPerStatementFixer.php +++ b/src/Fixer/Import/SingleImportPerStatementFixer.php @@ -29,7 +29,6 @@ * Fixer for rules defined in PSR2 ¶3. * * @author Dariusz Rumiński - * @author SpacePossum */ final class SingleImportPerStatementFixer extends AbstractFixer implements WhitespacesAwareFixerInterface { @@ -156,7 +155,7 @@ private function getGroupStatements(Tokens $tokens, string $groupPrefix, int $gr $i += 2; } - if ($token->isWhitespace(" \t") || '//' !== substr($tokens[$i - 1]->getContent(), 0, 2)) { + if ($token->isWhitespace(" \t") || !str_starts_with($tokens[$i - 1]->getContent(), '//')) { continue; } } @@ -173,7 +172,7 @@ private function getGroupStatements(Tokens $tokens, string $groupPrefix, int $gr private function fixGroupUse(Tokens $tokens, int $index, int $endIndex): void { - list($groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment) = $this->getGroupDeclaration($tokens, $index); + [$groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment] = $this->getGroupDeclaration($tokens, $index); $statements = $this->getGroupStatements($tokens, $groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment); if (\count($statements) < 2) { @@ -232,7 +231,7 @@ private function fixMultipleUse(Tokens $tokens, int $index, int $endIndex): void if ($tokens[$i - 1]->isWhitespace()) { $tokens[$i - 1] = new Token([T_WHITESPACE, $ending.$indent]); - } elseif (false === strpos($tokens[$i - 1]->getContent(), "\n")) { + } elseif (!str_contains($tokens[$i - 1]->getContent(), "\n")) { $tokens->insertAt($i, new Token([T_WHITESPACE, $ending.$indent])); } } diff --git a/src/Fixer/Import/SingleLineAfterImportsFixer.php b/src/Fixer/Import/SingleLineAfterImportsFixer.php index 7ef368ce6ac..773f25bf4c9 100644 --- a/src/Fixer/Import/SingleLineAfterImportsFixer.php +++ b/src/Fixer/Import/SingleLineAfterImportsFixer.php @@ -28,7 +28,7 @@ * Fixer for rules defined in PSR2 ¶3. * * @author Ceeram - * @author Graham Campbell + * @author Graham Campbell */ final class SingleLineAfterImportsFixer extends AbstractFixer implements WhitespacesAwareFixerInterface { diff --git a/src/Fixer/LanguageConstruct/ClassKeywordRemoveFixer.php b/src/Fixer/LanguageConstruct/ClassKeywordRemoveFixer.php index 2a6b8d93b23..23b2b48142b 100644 --- a/src/Fixer/LanguageConstruct/ClassKeywordRemoveFixer.php +++ b/src/Fixer/LanguageConstruct/ClassKeywordRemoveFixer.php @@ -15,6 +15,7 @@ namespace PhpCsFixer\Fixer\LanguageConstruct; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; @@ -25,9 +26,11 @@ use PhpCsFixer\Tokenizer\TokensAnalyzer; /** + * @deprecated + * * @author Sullivan Senechal */ -final class ClassKeywordRemoveFixer extends AbstractFixer +final class ClassKeywordRemoveFixer extends AbstractFixer implements DeprecatedFixerInterface { /** * @var string[] @@ -54,6 +57,14 @@ public function getDefinition(): FixerDefinitionInterface ); } + /** + * {@inheritdoc} + */ + public function getSuccessorsNames(): array + { + return []; + } + /** * {@inheritdoc} * @@ -113,13 +124,13 @@ private function storeImports(Tokens $tokens, int $startIndex, int $endIndex): v if ($tokens[$index]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_OPEN)) { $groupEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_GROUP_IMPORT_BRACE, $index); $groupImports = array_map( - static function (string $import) { + static function (string $import): string { return trim($import); }, explode(',', $tokens->generatePartialCode($index + 1, $groupEndIndex - 1)) ); foreach ($groupImports as $groupImport) { - $groupImportParts = array_map(static function (string $import) { + $groupImportParts = array_map(static function (string $import): string { return trim($import); }, explode(' as ', $groupImport)); if (2 === \count($groupImportParts)) { @@ -205,7 +216,7 @@ private function replaceClassKeyword(Tokens $tokens, string $namespacePrefix, in } for ($i = $classBeginIndex; $i <= $classIndex; ++$i) { - if (!$tokens[$i]->isComment() && !($tokens[$i]->isWhitespace() && false !== strpos($tokens[$i]->getContent(), "\n"))) { + if (!$tokens[$i]->isComment() && !($tokens[$i]->isWhitespace() && str_contains($tokens[$i]->getContent(), "\n"))) { $tokens->clearAt($i); } } diff --git a/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php b/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php index cf7063e0a2c..cc53bfde3d7 100644 --- a/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php +++ b/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class CombineConsecutiveIssetsFixer extends AbstractFixer { /** @@ -97,7 +94,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // clone what we want to move, do not clone '(' and ')' of the 'isset' statement we're merging $clones = $this->getTokenClones($tokens, \array_slice($nextIssetInfo, 1, -1)); - // clean up no the tokens of the 'isset' statement we're merging + // clean up now the tokens of the 'isset' statement we're merging $this->clearTokens($tokens, array_merge($nextIssetInfo, [$issetIndex, $booleanAndTokenIndex])); // insert the tokens to create the new statement diff --git a/src/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixer.php b/src/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixer.php index 68055a97523..6a595b69c8c 100644 --- a/src/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixer.php +++ b/src/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class CombineConsecutiveUnsetsFixer extends AbstractFixer { /** @@ -73,7 +70,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - list($previousUnset, , $previousUnsetBraceEnd) = $previousUnsetCall; + [$previousUnset, , $previousUnsetBraceEnd] = $previousUnsetCall; // Merge the tokens inside the 'unset' call into the previous one 'unset' call. $tokensAddCount = $this->moveTokens( @@ -122,7 +119,7 @@ private function clearOffsetTokens(Tokens $tokens, int $offset, array $indices): * * closing brace index * * end semicolon index * - * Or the index to where the method looked for an call. + * Or the index to where the method looked for a call. * * @return int|int[] */ diff --git a/src/Fixer/LanguageConstruct/DeclareEqualNormalizeFixer.php b/src/Fixer/LanguageConstruct/DeclareEqualNormalizeFixer.php index 2546e7a2628..c1320344963 100644 --- a/src/Fixer/LanguageConstruct/DeclareEqualNormalizeFixer.php +++ b/src/Fixer/LanguageConstruct/DeclareEqualNormalizeFixer.php @@ -27,7 +27,6 @@ /** * @author Dariusz Rumiński - * @author SpacePossum */ final class DeclareEqualNormalizeFixer extends AbstractFixer implements ConfigurableFixerInterface { diff --git a/src/Fixer/LanguageConstruct/DeclareParenthesesFixer.php b/src/Fixer/LanguageConstruct/DeclareParenthesesFixer.php new file mode 100644 index 00000000000..e3879731018 --- /dev/null +++ b/src/Fixer/LanguageConstruct/DeclareParenthesesFixer.php @@ -0,0 +1,56 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; +use PhpCsFixer\Tokenizer\Tokens; + +final class DeclareParenthesesFixer extends AbstractFixer +{ + public function getDefinition(): FixerDefinitionInterface + { + return new FixerDefinition( + 'There must not be spaces around `declare` statement parentheses.', + [new CodeSample("isTokenKindFound(T_DECLARE); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens): void + { + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_DECLARE)) { + continue; + } + + $tokens->removeTrailingWhitespace($index); + + $startParenthesisIndex = $tokens->getNextTokenOfKind($index, ['(']); + $tokens->removeTrailingWhitespace($startParenthesisIndex); + + $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); + $tokens->removeLeadingWhitespace($endParenthesisIndex); + } + } +} diff --git a/src/Fixer/LanguageConstruct/DirConstantFixer.php b/src/Fixer/LanguageConstruct/DirConstantFixer.php index 59e67e5cd21..be692bc2663 100644 --- a/src/Fixer/LanguageConstruct/DirConstantFixer.php +++ b/src/Fixer/LanguageConstruct/DirConstantFixer.php @@ -63,13 +63,14 @@ public function getPriority(): int protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { $currIndex = 0; - while (null !== $currIndex) { + + do { $boundaries = $this->find('dirname', $tokens, $currIndex, $tokens->count() - 1); if (null === $boundaries) { return; } - list($functionNameIndex, $openParenthesis, $closeParenthesis) = $boundaries; + [$functionNameIndex, $openParenthesis, $closeParenthesis] = $boundaries; // analysing cursor shift, so nested expressions kept processed $currIndex = $openParenthesis; @@ -78,12 +79,14 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $fileCandidateRightIndex = $tokens->getPrevMeaningfulToken($closeParenthesis); $trailingCommaIndex = null; + if ($tokens[$fileCandidateRightIndex]->equals(',')) { $trailingCommaIndex = $fileCandidateRightIndex; $fileCandidateRightIndex = $tokens->getPrevMeaningfulToken($fileCandidateRightIndex); } $fileCandidateRight = $tokens[$fileCandidateRightIndex]; + if (!$fileCandidateRight->isGivenKind(T_FILE)) { continue; } @@ -98,6 +101,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // get rid of root namespace when it used $namespaceCandidateIndex = $tokens->getPrevMeaningfulToken($functionNameIndex); $namespaceCandidate = $tokens[$namespaceCandidateIndex]; + if ($namespaceCandidate->isGivenKind(T_NS_SEPARATOR)) { $tokens->removeTrailingWhitespace($namespaceCandidateIndex); $tokens->clearAt($namespaceCandidateIndex); @@ -129,6 +133,6 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // replace constant and remove function name $tokens[$fileCandidateLeftIndex] = new Token([T_DIR, '__DIR__']); $tokens->clearTokenAndMergeSurroundingWhitespace($functionNameIndex); - } + } while (null !== $currIndex); } } diff --git a/src/Fixer/LanguageConstruct/ErrorSuppressionFixer.php b/src/Fixer/LanguageConstruct/ErrorSuppressionFixer.php index df2d1f7135d..94411090e5b 100644 --- a/src/Fixer/LanguageConstruct/ErrorSuppressionFixer.php +++ b/src/Fixer/LanguageConstruct/ErrorSuppressionFixer.php @@ -78,7 +78,7 @@ public function getDefinition(): FixerDefinitionInterface */ public function isCandidate(Tokens $tokens): bool { - return $tokens->isAnyTokenKindsFound(['@', T_STRING]); + return $tokens->isTokenKindFound(T_STRING); } /** @@ -116,7 +116,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { $functionsAnalyzer = new FunctionsAnalyzer(); - $excludedFunctions = array_map(static function (string $function) { + $excludedFunctions = array_map(static function (string $function): string { return strtolower($function); }, $this->configuration[self::OPTION_NOISE_REMAINING_USAGES_EXCLUDE]); @@ -136,6 +136,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $functionIndex = $index; $startIndex = $index; $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { $startIndex = $prevIndex; $prevIndex = $tokens->getPrevMeaningfulToken($startIndex); @@ -174,8 +175,8 @@ private function isDeprecationErrorCall(Tokens $tokens, int $index): bool } $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextTokenOfKind($index, [T_STRING, '('])); - $prevIndex = $tokens->getPrevMeaningfulToken($endBraceIndex); + if ($tokens[$prevIndex]->equals(',')) { $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); } diff --git a/src/Fixer/LanguageConstruct/ExplicitIndirectVariableFixer.php b/src/Fixer/LanguageConstruct/ExplicitIndirectVariableFixer.php index d63355c64c8..25925fe1f1c 100644 --- a/src/Fixer/LanguageConstruct/ExplicitIndirectVariableFixer.php +++ b/src/Fixer/LanguageConstruct/ExplicitIndirectVariableFixer.php @@ -15,10 +15,9 @@ namespace PhpCsFixer\Fixer\LanguageConstruct; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -36,7 +35,7 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'Add curly braces to indirect variables to make them clear to understand. Requires PHP >= 7.0.', [ - new VersionSpecificCodeSample( + new CodeSample( <<<'EOT' $callback($baz); EOT -, - new VersionSpecification(70000) ), ] ); @@ -57,7 +54,7 @@ public function getDefinition(): FixerDefinitionInterface */ public function isCandidate(Tokens $tokens): bool { - return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_VARIABLE); + return $tokens->isTokenKindFound(T_VARIABLE); } /** diff --git a/src/Fixer/LanguageConstruct/FunctionToConstantFixer.php b/src/Fixer/LanguageConstruct/FunctionToConstantFixer.php index ba315bfa0f6..40ce735ef55 100644 --- a/src/Fixer/LanguageConstruct/FunctionToConstantFixer.php +++ b/src/Fixer/LanguageConstruct/FunctionToConstantFixer.php @@ -28,9 +28,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class FunctionToConstantFixer extends AbstractFixer implements ConfigurableFixerInterface { /** diff --git a/src/Fixer/LanguageConstruct/IsNullFixer.php b/src/Fixer/LanguageConstruct/IsNullFixer.php index 784a92629c2..405c6c81348 100644 --- a/src/Fixer/LanguageConstruct/IsNullFixer.php +++ b/src/Fixer/LanguageConstruct/IsNullFixer.php @@ -75,9 +75,9 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { static $sequenceNeeded = [[T_STRING, 'is_null'], '(']; $functionsAnalyzer = new FunctionsAnalyzer(); - $currIndex = 0; - while (null !== $currIndex) { + + do { $matches = $tokens->findSequence($sequenceNeeded, $currIndex, $tokens->count() - 1, false); // stop looping if didn't find any new matches @@ -89,13 +89,14 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $matches = array_keys($matches); // move the cursor just after the sequence - list($isNullIndex, $currIndex) = $matches; + [$isNullIndex, $currIndex] = $matches; if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $matches[0])) { continue; } $next = $tokens->getNextMeaningfulToken($currIndex); + if ($tokens[$next]->equals(')')) { continue; } @@ -112,6 +113,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // check if inversion being used, text comparison is due to not existing constant $isInvertedNullCheck = false; + if ($tokens[$prevTokenIndex]->equals('!')) { $isInvertedNullCheck = true; @@ -123,6 +125,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // before getting rind of `()` around a parameter, ensure it's not assignment/ternary invariant $referenceEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $matches[1]); $isContainingDangerousConstructs = false; + for ($paramTokenIndex = $matches[1]; $paramTokenIndex <= $referenceEnd; ++$paramTokenIndex) { if (\in_array($tokens[$paramTokenIndex]->getContent(), ['?', '?:', '=', '??'], true)) { $isContainingDangerousConstructs = true; @@ -139,6 +142,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // possible trailing comma removed $prevIndex = $tokens->getPrevMeaningfulToken($referenceEnd); + if ($tokens[$prevIndex]->equals(',')) { $tokens->clearTokenAndMergeSurroundingWhitespace($prevIndex); } @@ -171,6 +175,6 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // nested is_null calls support $currIndex = $isNullIndex; - } + } while (null !== $currIndex); } } diff --git a/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php b/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php index 272827449ea..af7f65d6048 100644 --- a/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php +++ b/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php @@ -83,7 +83,8 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - $isLastUnset = true; // yes, last - we reverse the array below + $isLastUnset = true; // "last" as we reverse the array below + foreach (array_reverse($unsetsInfo) as $unsetInfo) { $this->updateTokens($tokens, $unsetInfo, $isLastUnset); $isLastUnset = false; @@ -101,8 +102,8 @@ private function getUnsetsInfo(Tokens $tokens, int $index): array $unsetStart = $tokens->getNextTokenOfKind($index, ['(']); $unsetEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $unsetStart); $isFirst = true; - $unsets = []; + foreach ($argumentsAnalyzer->getArguments($tokens, $unsetStart, $unsetEnd) as $startIndex => $endIndex) { $startIndex = $tokens->getNextMeaningfulToken($startIndex - 1); $endIndex = $tokens->getPrevMeaningfulToken($endIndex + 1); @@ -122,11 +123,14 @@ private function isProperty(Tokens $tokens, int $index, int $endIndex): bool { if ($tokens[$index]->isGivenKind(T_VARIABLE)) { $nextIndex = $tokens->getNextMeaningfulToken($index); + if (null === $nextIndex || !$tokens[$nextIndex]->isGivenKind(T_OBJECT_OPERATOR)) { return false; } + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); + if (null !== $nextNextIndex && $nextNextIndex < $endIndex) { return false; } @@ -137,6 +141,7 @@ private function isProperty(Tokens $tokens, int $index, int $endIndex): bool if ($tokens[$index]->isGivenKind([T_NS_SEPARATOR, T_STRING])) { $nextIndex = $tokens->getTokenNotOfKindsSibling($index, 1, [T_DOUBLE_COLON, T_NS_SEPARATOR, T_STRING]); $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); + if (null !== $nextNextIndex && $nextNextIndex < $endIndex) { return false; } @@ -166,7 +171,7 @@ private function isAnyUnsetToTransform(array $unsetsInfo): bool */ private function updateTokens(Tokens $tokens, array $unsetInfo, bool $isLastUnset): void { - // if entry is first and to be transform we remove leading "unset(" + // if entry is first and to be transformed we remove leading "unset(" if ($unsetInfo['isFirst'] && $unsetInfo['isToTransform']) { $braceIndex = $tokens->getPrevTokenOfKind($unsetInfo['startIndex'], ['(']); $unsetIndex = $tokens->getPrevTokenOfKind($braceIndex, [[T_UNSET]]); diff --git a/src/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixer.php b/src/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixer.php index b0f0e67c757..6e25abcb4e8 100644 --- a/src/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixer.php +++ b/src/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixer.php @@ -23,8 +23,6 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Preg; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; @@ -110,11 +108,18 @@ public function configure(array $configuration): void { parent::configure($configuration); - // @TODO: drop condition when PHP 8.0+ is required - if (\defined('T_MATCH')) { + if (\defined('T_MATCH')) { // @TODO: drop condition when PHP 8.0+ is required self::$tokenMap['match'] = T_MATCH; } + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + self::$tokenMap['readonly'] = T_READONLY; + } + + if (\defined('T_ENUM')) { // @TODO: drop condition when PHP 8.1+ is required + self::$tokenMap['enum'] = T_ENUM; + } + $this->fixTokenMap = []; foreach ($this->configuration['constructs'] as $key) { @@ -159,12 +164,11 @@ public function getDefinition(): FixerDefinitionInterface ], ] ), - new VersionSpecificCodeSample( + new CodeSample( ' [ 'yield_from', @@ -179,6 +183,7 @@ public function getDefinition(): FixerDefinitionInterface * {@inheritdoc} * * Must run before BracesFixer, FunctionDeclarationFixer. + * Must run after ModernizeStrposFixer. */ public function getPriority(): int { @@ -209,7 +214,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $whitespaceTokenIndex = $index + 1; - if ($tokens[$whitespaceTokenIndex]->equalsAny([';', ')', [CT::T_ARRAY_SQUARE_BRACE_CLOSE]])) { + if ($tokens[$whitespaceTokenIndex]->equalsAny([',', ';', ')', [CT::T_ARRAY_SQUARE_BRACE_CLOSE]])) { continue; } @@ -221,7 +226,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } if ($token->isGivenKind(T_OPEN_TAG)) { - if ($tokens[$whitespaceTokenIndex]->equals([T_WHITESPACE]) && false === strpos($token->getContent(), "\n")) { + if ($tokens[$whitespaceTokenIndex]->equals([T_WHITESPACE]) && !str_contains($token->getContent(), "\n")) { $tokens->clearAt($whitespaceTokenIndex); } @@ -241,7 +246,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } if ($token->isComment() || $token->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { - if ($tokens[$whitespaceTokenIndex]->equals([T_WHITESPACE]) && false !== strpos($tokens[$whitespaceTokenIndex]->getContent(), "\n")) { + if ($tokens[$whitespaceTokenIndex]->equals([T_WHITESPACE]) && str_contains($tokens[$whitespaceTokenIndex]->getContent(), "\n")) { continue; } } @@ -253,8 +258,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } if ( - 70000 <= \PHP_VERSION_ID - && $token->isGivenKind(T_YIELD_FROM) + $token->isGivenKind(T_YIELD_FROM) && 'yield from' !== strtolower($token->getContent()) ) { $tokens[$index] = new Token([T_YIELD_FROM, Preg::replace( @@ -284,7 +288,7 @@ private function isMultiLineReturn(Tokens $tokens, int $index): bool if ( !$tokenFollowingReturn->isGivenKind(T_WHITESPACE) - || false === strpos($tokenFollowingReturn->getContent(), "\n") + || !str_contains($tokenFollowingReturn->getContent(), "\n") ) { return false; } @@ -292,7 +296,7 @@ private function isMultiLineReturn(Tokens $tokens, int $index): bool $nestedCount = 0; for ($indexEnd = \count($tokens) - 1, ++$index; $index < $indexEnd; ++$index) { - if (false !== strpos($tokens[$index]->getContent(), "\n")) { + if (str_contains($tokens[$index]->getContent(), "\n")) { return true; } @@ -325,7 +329,7 @@ private function isMultilineExtendsOrImplementsWithMoreThanOneAncestor(Tokens $t return false; } - if ($hasMoreThanOneAncestor && false !== strpos($token->getContent(), "\n")) { + if ($hasMoreThanOneAncestor && str_contains($token->getContent(), "\n")) { return true; } } diff --git a/src/Fixer/ListNotation/ListSyntaxFixer.php b/src/Fixer/ListNotation/ListSyntaxFixer.php index a7bd701b016..bdd35d7c606 100644 --- a/src/Fixer/ListNotation/ListSyntaxFixer.php +++ b/src/Fixer/ListNotation/ListSyntaxFixer.php @@ -20,17 +20,13 @@ use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class ListSyntaxFixer extends AbstractFixer implements ConfigurableFixerInterface { /** @@ -60,13 +56,11 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'List (`array` destructuring) assignment should be declared using the configured syntax. Requires PHP >= 7.1.', [ - new VersionSpecificCodeSample( - " 'long'] ), ] @@ -88,7 +82,7 @@ public function getPriority(): int */ public function isCandidate(Tokens $tokens): bool { - return \PHP_VERSION_ID >= 70100 && $tokens->isTokenKindFound($this->candidateTokenKind); + return $tokens->isTokenKindFound($this->candidateTokenKind); } /** diff --git a/src/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php b/src/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php index 9a88263dad3..96bc14b0851 100644 --- a/src/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php +++ b/src/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php @@ -21,7 +21,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class NoBlankLinesBeforeNamespaceFixer extends AbstractLinesBeforeNamespaceFixer { diff --git a/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php b/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php index f3d46ce66ca..667b1da55f0 100644 --- a/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php +++ b/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php @@ -21,7 +21,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class SingleBlankLineBeforeNamespaceFixer extends AbstractLinesBeforeNamespaceFixer { diff --git a/src/Fixer/Naming/NoHomoglyphNamesFixer.php b/src/Fixer/Naming/NoHomoglyphNamesFixer.php index 35c18e0d059..40a40aa4f12 100644 --- a/src/Fixer/Naming/NoHomoglyphNamesFixer.php +++ b/src/Fixer/Naming/NoHomoglyphNamesFixer.php @@ -232,11 +232,8 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - $replaced = Preg::replaceCallback('/[^[:ascii:]]/u', static function (array $matches) { - return isset(self::$replacements[$matches[0]]) - ? self::$replacements[$matches[0]] - : $matches[0] - ; + $replaced = Preg::replaceCallback('/[^[:ascii:]]/u', static function (array $matches): string { + return self::$replacements[$matches[0]] ?? $matches[0]; }, $token->getContent(), -1, $count); if ($count) { diff --git a/src/Fixer/Operator/BinaryOperatorSpacesFixer.php b/src/Fixer/Operator/BinaryOperatorSpacesFixer.php index 8ea85fc083a..dbcd8fab0c7 100644 --- a/src/Fixer/Operator/BinaryOperatorSpacesFixer.php +++ b/src/Fixer/Operator/BinaryOperatorSpacesFixer.php @@ -31,7 +31,6 @@ /** * @author Dariusz Rumiński - * @author SpacePossum */ final class BinaryOperatorSpacesFixer extends AbstractFixer implements ConfigurableFixerInterface { @@ -254,7 +253,7 @@ public function getDefinition(): FixerDefinitionInterface /** * {@inheritdoc} * - * Must run after ArrayIndentationFixer, ArraySyntaxFixer, ListSyntaxFixer, NoMultilineWhitespaceAroundDoubleArrowFixer, NoUnsetCastFixer, PowToExponentiationFixer, StandardizeNotEqualsFixer, StrictComparisonFixer. + * Must run after ArrayIndentationFixer, ArraySyntaxFixer, ListSyntaxFixer, ModernizeStrposFixer, NoMultilineWhitespaceAroundDoubleArrowFixer, NoUnsetCastFixer, PowToExponentiationFixer, StandardizeNotEqualsFixer, StrictComparisonFixer. */ public function getPriority(): int { @@ -297,7 +296,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void --$index; } - if (\count($this->alignOperatorTokens)) { + if (\count($this->alignOperatorTokens) > 0) { $this->fixAlignment($tokens, $this->alignOperatorTokens); } } @@ -314,7 +313,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ->getOption(), (new FixerOptionBuilder('operators', 'Dictionary of `binary operator` => `fix strategy` values that differ from the default strategy.')) ->setAllowedTypes(['array']) - ->setAllowedValues([static function (array $option) { + ->setAllowedValues([static function (array $option): bool { foreach ($option as $operator => $value) { if (!\in_array($operator, self::SUPPORTED_OPERATORS, true)) { throw new InvalidOptionsException( @@ -389,7 +388,7 @@ private function fixWhiteSpaceAroundOperatorToSingleSpace(Tokens $tokens, int $i // fix white space after operator if ($tokens[$index + 1]->isWhitespace()) { $content = $tokens[$index + 1]->getContent(); - if (' ' !== $content && false === strpos($content, "\n") && !$tokens[$tokens->getNextNonWhitespace($index + 1)]->isComment()) { + if (' ' !== $content && !str_contains($content, "\n") && !$tokens[$tokens->getNextNonWhitespace($index + 1)]->isComment()) { $tokens[$index + 1] = new Token([T_WHITESPACE, ' ']); } } else { @@ -399,7 +398,7 @@ private function fixWhiteSpaceAroundOperatorToSingleSpace(Tokens $tokens, int $i // fix white space before operator if ($tokens[$index - 1]->isWhitespace()) { $content = $tokens[$index - 1]->getContent(); - if (' ' !== $content && false === strpos($content, "\n") && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { + if (' ' !== $content && !str_contains($content, "\n") && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { $tokens[$index - 1] = new Token([T_WHITESPACE, ' ']); } } else { @@ -412,7 +411,7 @@ private function fixWhiteSpaceAroundOperatorToNoSpace(Tokens $tokens, int $index // fix white space after operator if ($tokens[$index + 1]->isWhitespace()) { $content = $tokens[$index + 1]->getContent(); - if (false === strpos($content, "\n") && !$tokens[$tokens->getNextNonWhitespace($index + 1)]->isComment()) { + if (!str_contains($content, "\n") && !$tokens[$tokens->getNextNonWhitespace($index + 1)]->isComment()) { $tokens->clearAt($index + 1); } } @@ -420,7 +419,7 @@ private function fixWhiteSpaceAroundOperatorToNoSpace(Tokens $tokens, int $index // fix white space before operator if ($tokens[$index - 1]->isWhitespace()) { $content = $tokens[$index - 1]->getContent(); - if (false === strpos($content, "\n") && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { + if (!str_contains($content, "\n") && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { $tokens->clearAt($index - 1); } } @@ -625,7 +624,7 @@ private function injectAlignmentPlaceholdersForArrow(Tokens $tokens, int $startA if ($token->equals(',')) { for ($i = $index; $i < $endAt - 1; ++$i) { - if (false !== strpos($tokens[$i - 1]->getContent(), "\n")) { + if (str_contains($tokens[$i - 1]->getContent(), "\n")) { break; } @@ -673,7 +672,7 @@ private function fixWhiteSpaceBeforeOperator(Tokens $tokens, int $index, string } $content = $tokens[$index - 1]->getContent(); - if (' ' !== $content && false === strpos($content, "\n")) { + if (' ' !== $content && !str_contains($content, "\n")) { $tokens[$index - 1] = new Token([T_WHITESPACE, ' ']); } } @@ -688,7 +687,7 @@ private function replacePlaceholders(Tokens $tokens, string $alignStrategy): str for ($j = 0; $j <= $this->deepestLevel; ++$j) { $placeholder = sprintf(self::ALIGN_PLACEHOLDER, $j); - if (false === strpos($tmpCode, $placeholder)) { + if (!str_contains($tmpCode, $placeholder)) { continue; } diff --git a/src/Fixer/Operator/ConcatSpaceFixer.php b/src/Fixer/Operator/ConcatSpaceFixer.php index afb2cb979c1..c0b87eb4366 100644 --- a/src/Fixer/Operator/ConcatSpaceFixer.php +++ b/src/Fixer/Operator/ConcatSpaceFixer.php @@ -27,7 +27,6 @@ /** * @author Dariusz Rumiński - * @author SpacePossum */ final class ConcatSpaceFixer extends AbstractFixer implements ConfigurableFixerInterface { @@ -123,7 +122,8 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn private function fixConcatenationToNoSpace(Tokens $tokens, int $index): void { $prevNonWhitespaceToken = $tokens[$tokens->getPrevNonWhitespace($index)]; - if (!$prevNonWhitespaceToken->isGivenKind([T_LNUMBER, T_COMMENT, T_DOC_COMMENT]) || '/*' === substr($prevNonWhitespaceToken->getContent(), 0, 2)) { + + if (!$prevNonWhitespaceToken->isGivenKind([T_LNUMBER, T_COMMENT, T_DOC_COMMENT]) || str_starts_with($prevNonWhitespaceToken->getContent(), '/*')) { $tokens->removeLeadingWhitespace($index, " \t"); } @@ -155,7 +155,7 @@ private function fixWhiteSpaceAroundConcatToken(Tokens $tokens, int $index, int return; } - if (false !== strpos($tokens[$offsetIndex]->getContent(), "\n")) { + if (str_contains($tokens[$offsetIndex]->getContent(), "\n")) { return; } diff --git a/src/Fixer/Operator/NewWithBracesFixer.php b/src/Fixer/Operator/NewWithBracesFixer.php index bcf5bbf6328..91421d03abe 100644 --- a/src/Fixer/Operator/NewWithBracesFixer.php +++ b/src/Fixer/Operator/NewWithBracesFixer.php @@ -115,9 +115,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } for ($index = $tokens->count() - 3; $index > 0; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind(T_NEW)) { + if (!$tokens[$index]->isGivenKind(T_NEW)) { continue; } @@ -155,7 +153,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // entrance into array index syntax - need to look for exit while ($nextToken->equals('[') || $nextToken->isGivenKind(CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN)) { - $nextIndex = $tokens->findBlockEnd($tokens->detectBlockType($nextToken)['type'], $nextIndex) + 1; + $nextIndex = $tokens->findBlockEnd(Tokens::detectBlockType($nextToken)['type'], $nextIndex) + 1; $nextToken = $tokens[$nextIndex]; } diff --git a/src/Fixer/Operator/NotOperatorWithSpaceFixer.php b/src/Fixer/Operator/NotOperatorWithSpaceFixer.php index 84313560468..83c5cf55099 100644 --- a/src/Fixer/Operator/NotOperatorWithSpaceFixer.php +++ b/src/Fixer/Operator/NotOperatorWithSpaceFixer.php @@ -47,7 +47,7 @@ public function getDefinition(): FixerDefinitionInterface /** * {@inheritdoc} * - * Must run after UnaryOperatorSpacesFixer. + * Must run after ModernizeStrposFixer, UnaryOperatorSpacesFixer. */ public function getPriority(): int { diff --git a/src/Fixer/Operator/NotOperatorWithSuccessorSpaceFixer.php b/src/Fixer/Operator/NotOperatorWithSuccessorSpaceFixer.php index ca10dc4eaf0..acdf0b3dcc8 100644 --- a/src/Fixer/Operator/NotOperatorWithSuccessorSpaceFixer.php +++ b/src/Fixer/Operator/NotOperatorWithSuccessorSpaceFixer.php @@ -47,7 +47,7 @@ public function getDefinition(): FixerDefinitionInterface /** * {@inheritdoc} * - * Must run after UnaryOperatorSpacesFixer. + * Must run after ModernizeStrposFixer, UnaryOperatorSpacesFixer. */ public function getPriority(): int { diff --git a/src/Fixer/Operator/OperatorLinebreakFixer.php b/src/Fixer/Operator/OperatorLinebreakFixer.php index 38cc50f1723..45052121712 100644 --- a/src/Fixer/Operator/OperatorLinebreakFixer.php +++ b/src/Fixer/Operator/OperatorLinebreakFixer.php @@ -84,10 +84,6 @@ public function configure(array $configuration): void $this->operators = self::BOOLEAN_OPERATORS; if (!$this->configuration['only_booleans']) { $this->operators = array_merge($this->operators, self::getNonBooleanOperators()); - if (\PHP_VERSION_ID >= 70000) { - $this->operators[] = [T_COALESCE]; - $this->operators[] = [T_SPACESHIP]; - } } $this->position = $this->configuration['position']; } @@ -184,7 +180,7 @@ private function getExcludedIndices(Tokens $tokens): array private function getCasesColonsForSwitch(Tokens $tokens, int $switchIndex): array { return array_map( - static function (CaseAnalysis $caseAnalysis) { + static function (CaseAnalysis $caseAnalysis): int { return $caseAnalysis->getColonIndex(); }, (new SwitchAnalyzer())->getSwitchAnalysis($tokens, $switchIndex)->getCases() @@ -281,11 +277,13 @@ private function fixMoveToTheEnd(Tokens $tokens, array $operatorIndices): void private function getReplacementsAndClear(Tokens $tokens, array $indices, int $direction): array { return array_map( - static function (int $index) use ($tokens, $direction) { + static function (int $index) use ($tokens, $direction): Token { $clone = $tokens[$index]; + if ($tokens[$index + $direction]->isWhitespace()) { $tokens->clearAt($index + $direction); } + $tokens->clearAt($index); return $clone; @@ -297,7 +295,7 @@ static function (int $index) use ($tokens, $direction) { private function isMultiline(Tokens $tokens, int $indexStart, int $indexEnd): bool { for ($index = $indexStart; $index <= $indexEnd; ++$index) { - if (false !== strpos($tokens[$index]->getContent(), "\n")) { + if (str_contains($tokens[$index]->getContent(), "\n")) { return true; } } @@ -314,8 +312,9 @@ private static function getNonBooleanOperators(): array [T_IS_IDENTICAL], [T_IS_NOT_EQUAL], [T_IS_NOT_IDENTICAL], [T_IS_SMALLER_OR_EQUAL], [T_MINUS_EQUAL], [T_MOD_EQUAL], [T_MUL_EQUAL], [T_OR_EQUAL], [T_PAAMAYIM_NEKUDOTAYIM], [T_PLUS_EQUAL], [T_POW], [T_POW_EQUAL], [T_SL], [T_SL_EQUAL], [T_SR], [T_SR_EQUAL], [T_XOR_EQUAL], + [T_COALESCE], [T_SPACESHIP], ], - array_map(function ($id) { return [$id]; }, Token::getObjectOperatorKinds()) + array_map(static function ($id): array { return [$id]; }, Token::getObjectOperatorKinds()) ); } } diff --git a/src/Fixer/Operator/TernaryOperatorSpacesFixer.php b/src/Fixer/Operator/TernaryOperatorSpacesFixer.php index fe49cac952e..6929d609ee5 100644 --- a/src/Fixer/Operator/TernaryOperatorSpacesFixer.php +++ b/src/Fixer/Operator/TernaryOperatorSpacesFixer.php @@ -154,7 +154,7 @@ private function belongsToAlternativeSyntax(Tokens $tokens, int $index): bool private function getColonIndicesForSwitch(Tokens $tokens, int $switchIndex): array { return array_map( - static function (CaseAnalysis $caseAnalysis) { + static function (CaseAnalysis $caseAnalysis): int { return $caseAnalysis->getColonIndex(); }, (new SwitchAnalyzer())->getSwitchAnalysis($tokens, $switchIndex)->getCases() @@ -165,7 +165,7 @@ private function ensureWhitespaceExistence(Tokens $tokens, int $index, bool $aft { if ($tokens[$index]->isWhitespace()) { if ( - false === strpos($tokens[$index]->getContent(), "\n") + !str_contains($tokens[$index]->getContent(), "\n") && !$tokens[$index - 1]->isComment() ) { $tokens[$index] = new Token([T_WHITESPACE, ' ']); diff --git a/src/Fixer/Operator/TernaryToElvisOperatorFixer.php b/src/Fixer/Operator/TernaryToElvisOperatorFixer.php index 44d8527b441..9a643f617ad 100644 --- a/src/Fixer/Operator/TernaryToElvisOperatorFixer.php +++ b/src/Fixer/Operator/TernaryToElvisOperatorFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class TernaryToElvisOperatorFixer extends AbstractFixer { /** diff --git a/src/Fixer/Operator/TernaryToNullCoalescingFixer.php b/src/Fixer/Operator/TernaryToNullCoalescingFixer.php index d0b5ce4230d..45349e5d1ea 100644 --- a/src/Fixer/Operator/TernaryToNullCoalescingFixer.php +++ b/src/Fixer/Operator/TernaryToNullCoalescingFixer.php @@ -15,10 +15,9 @@ namespace PhpCsFixer\Fixer\Operator; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -35,9 +34,8 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'Use `null` coalescing operator `??` where possible. Requires PHP >= 7.0.', [ - new VersionSpecificCodeSample( - "= 70000 && $tokens->isTokenKindFound(T_ISSET); + return $tokens->isTokenKindFound(T_ISSET); } /** diff --git a/src/Fixer/PhpTag/BlankLineAfterOpeningTagFixer.php b/src/Fixer/PhpTag/BlankLineAfterOpeningTagFixer.php index 81a381785d2..897bd1fc472 100644 --- a/src/Fixer/PhpTag/BlankLineAfterOpeningTagFixer.php +++ b/src/Fixer/PhpTag/BlankLineAfterOpeningTagFixer.php @@ -72,7 +72,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $newlineFound = false; /** @var Token $token */ foreach ($tokens as $token) { - if ($token->isWhitespace() && false !== strpos($token->getContent(), "\n")) { + if ($token->isWhitespace() && str_contains($token->getContent(), "\n")) { $newlineFound = true; break; @@ -86,11 +86,11 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $token = $tokens[0]; - if (false === strpos($token->getContent(), "\n")) { + if (!str_contains($token->getContent(), "\n")) { $tokens[0] = new Token([$token->getId(), rtrim($token->getContent()).$lineEnding]); } - if (false === strpos($tokens[1]->getContent(), "\n")) { + if (!str_contains($tokens[1]->getContent(), "\n")) { if ($tokens[1]->isWhitespace()) { $tokens[1] = new Token([T_WHITESPACE, $lineEnding.$tokens[1]->getContent()]); } else { diff --git a/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php b/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php index aaacb4f2a08..74727d10168 100644 --- a/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php +++ b/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php @@ -57,13 +57,13 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } // ignore if linebreak already present - if (false !== strpos($tokens[0]->getContent(), "\n")) { + if (str_contains($tokens[0]->getContent(), "\n")) { return; } $newlineFound = false; foreach ($tokens as $token) { - if ($token->isWhitespace() && false !== strpos($token->getContent(), "\n")) { + if ($token->isWhitespace() && str_contains($token->getContent(), "\n")) { $newlineFound = true; break; diff --git a/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php b/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php index 9d554be6e85..5c4656f3710 100644 --- a/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php @@ -27,7 +27,6 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author SpacePossum * @author Dariusz Rumiński */ final class PhpUnitDedicateAssertFixer extends AbstractPhpUnitFixer implements ConfigurableFixerInterface @@ -356,18 +355,21 @@ private function getPreviousAssertCall(Tokens $tokens, int $startIndex, int $end for ($index = $endIndex; $index > $startIndex; --$index) { $index = $tokens->getPrevTokenOfKind($index, [[T_STRING]]); + if (null === $index) { return; } // test if "assert" something call $loweredContent = strtolower($tokens[$index]->getContent()); - if ('assert' !== substr($loweredContent, 0, 6)) { + + if (!str_starts_with($loweredContent, 'assert')) { continue; } // test candidate for simple calls like: ([\]+'some fixable call'(...)) $openBraceIndex = $tokens->getNextMeaningfulToken($index); + if (!$tokens[$openBraceIndex]->equals('(')) { continue; } diff --git a/src/Fixer/PhpUnit/PhpUnitExpectationFixer.php b/src/Fixer/PhpUnit/PhpUnitExpectationFixer.php index 0f15868d7dc..4bb80013455 100644 --- a/src/Fixer/PhpUnit/PhpUnitExpectationFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitExpectationFixer.php @@ -207,7 +207,7 @@ private function applyPhpUnitClassFixWithObjectOperator(Tokens $tokens, int $sta return; } - list($thisIndex, , $index) = array_keys($match); + [$thisIndex, , $index] = array_keys($match); if (!isset($this->methodMap[$tokens[$index]->getContent()])) { continue; diff --git a/src/Fixer/PhpUnit/PhpUnitMethodCasingFixer.php b/src/Fixer/PhpUnit/PhpUnitMethodCasingFixer.php index 5dbf6f0c52f..5764d424f34 100644 --- a/src/Fixer/PhpUnit/PhpUnitMethodCasingFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitMethodCasingFixer.php @@ -162,7 +162,7 @@ private function isTestMethod(Tokens $tokens, int $index): bool return $this->isPHPDoc($tokens, $docBlockIndex) // If the function doesn't have test in its name, and no doc block, it's not a test - && false !== strpos($tokens[$docBlockIndex]->getContent(), '@test') + && str_contains($tokens[$docBlockIndex]->getContent(), '@test') ; } @@ -186,11 +186,11 @@ private function updateDocBlock(Tokens $tokens, int $docBlockIndex): void $docBlockNeedsUpdate = false; for ($inc = 0; $inc < \count($lines); ++$inc) { $lineContent = $lines[$inc]->getContent(); - if (false === strpos($lineContent, '@depends')) { + if (!str_contains($lineContent, '@depends')) { continue; } - $newLineContent = Preg::replaceCallback('/(@depends\s+)(.+)(\b)/', function (array $matches) { + $newLineContent = Preg::replaceCallback('/(@depends\s+)(.+)(\b)/', function (array $matches): string { return sprintf( '%s%s%s', $matches[1], diff --git a/src/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixer.php b/src/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixer.php index dab8655a581..4e3ea63733d 100644 --- a/src/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixer.php @@ -19,6 +19,7 @@ use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -111,6 +112,10 @@ protected function applyPhpUnitClassFix(Tokens $tokens, int $startIndex, int $en continue; } + if ($tokens[$tokens->getNextMeaningfulToken($openingBraceIndex)]->isGivenKind(CT::T_FIRST_CLASS_CALLABLE)) { + continue; + } + $closingBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openingBraceIndex); $tokens[$functionToReplaceIndex] = new Token([T_STRING, self::RETURN_METHODS_MAP[strtolower($tokens[$functionToRemoveIndex]->getContent())]]); diff --git a/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php b/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php index 3b5b11ae068..2c171a31e76 100644 --- a/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php @@ -149,7 +149,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $importedOriginalClassesMap = []; $currIndex = 0; - while (null !== $currIndex) { + while (true) { $currIndex = $tokens->getNextTokenOfKind($currIndex, [[T_STRING]]); if (null === $currIndex) { @@ -157,6 +157,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } $prevIndex = $tokens->getPrevMeaningfulToken($currIndex); + if ($tokens[$prevIndex]->isGivenKind([T_CONST, T_DOUBLE_COLON])) { continue; } diff --git a/src/Fixer/PhpUnit/PhpUnitNoExpectationAnnotationFixer.php b/src/Fixer/PhpUnit/PhpUnitNoExpectationAnnotationFixer.php index e468536025e..0ed433df41e 100644 --- a/src/Fixer/PhpUnit/PhpUnitNoExpectationAnnotationFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitNoExpectationAnnotationFixer.php @@ -247,7 +247,7 @@ private function annotationsToParamList(array $annotations): array { $params = []; $exceptionClass = ltrim($annotations['expectedException'], '\\'); - if (false !== strpos($exceptionClass, '*')) { + if (str_contains($exceptionClass, '*')) { $exceptionClass = substr($exceptionClass, 0, strpos($exceptionClass, '*')); } $exceptionClass = trim($exceptionClass); diff --git a/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php b/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php index e8d890c4245..4e059d0fc0d 100644 --- a/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php @@ -165,9 +165,6 @@ private function applyTestPrefix(Tokens $tokens, int $startIndex, int $endIndex) } } - /** - * @param int$index - */ private function isTestMethod(Tokens $tokens, int $index): bool { // Check if we are dealing with a (non abstract, non lambda) function @@ -175,7 +172,7 @@ private function isTestMethod(Tokens $tokens, int $index): bool return false; } - // if the function name starts with test its a test + // if the function name starts with test it is a test $functionNameIndex = $tokens->getNextMeaningfulToken($index); $functionName = $tokens[$functionNameIndex]->getContent(); @@ -185,10 +182,10 @@ private function isTestMethod(Tokens $tokens, int $index): bool $docBlockIndex = $this->getDocBlockIndex($tokens, $index); - // If the function doesn't have test in its name, and no doc block, its not a test + // If the function doesn't have test in its name, and no doc block, it is not a test return $this->isPHPDoc($tokens, $docBlockIndex) - && false !== strpos($tokens[$docBlockIndex]->getContent(), '@test') + && str_contains($tokens[$docBlockIndex]->getContent(), '@test') ; } @@ -201,7 +198,7 @@ private function isMethod(Tokens $tokens, int $index): bool private function hasTestPrefix(string $functionName): bool { - return 0 === strpos($functionName, 'test'); + return str_starts_with($functionName, 'test'); } private function hasProperTestAnnotation(Tokens $tokens, int $index): bool @@ -273,15 +270,15 @@ private function updateLines(array $lines, Tokens $tokens, int $docBlockIndex): } if (!$needsAnnotation - && false !== strpos($lines[$i]->getContent(), ' @test') - && false === strpos($lines[$i]->getContent(), '@testWith') - && false === strpos($lines[$i]->getContent(), '@testdox') + && str_contains($lines[$i]->getContent(), ' @test') + && !str_contains($lines[$i]->getContent(), '@testWith') + && !str_contains($lines[$i]->getContent(), '@testdox') ) { // We remove @test from the doc block $lines[$i] = new Line(str_replace(' @test', '', $lines[$i]->getContent())); } // ignore the line if it isn't @depends - if (false === strpos($lines[$i]->getContent(), '@depends')) { + if (!str_contains($lines[$i]->getContent(), '@depends')) { continue; } diff --git a/src/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php b/src/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php index 7eb05e06664..d6493e5da64 100644 --- a/src/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php @@ -23,6 +23,7 @@ use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\TokensAnalyzer; @@ -360,7 +361,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ->getOption(), (new FixerOptionBuilder('methods', 'Dictionary of `method` => `call_type` values that differ from the default strategy.')) ->setAllowedTypes(['array']) - ->setAllowedValues([static function (array $option) use ($thisFixer) { + ->setAllowedValues([static function (array $option) use ($thisFixer): bool { foreach ($option as $method => $value) { if (!isset($thisFixer->staticMethods[$method])) { throw new InvalidOptionsException( @@ -438,6 +439,10 @@ protected function applyPhpUnitClassFix(Tokens $tokens, int $startIndex, int $en continue; } + if ($tokens[$tokens->getNextMeaningfulToken($nextIndex)]->isGivenKind(CT::T_FIRST_CLASS_CALLABLE)) { + continue; + } + $methodName = $tokens[$index]->getContent(); if (isset($this->configuration['methods'][$methodName])) { diff --git a/src/Fixer/PhpUnit/PhpUnitTestClassRequiresCoversFixer.php b/src/Fixer/PhpUnit/PhpUnitTestClassRequiresCoversFixer.php index 4323a747e99..2539ccd9a34 100644 --- a/src/Fixer/PhpUnit/PhpUnitTestClassRequiresCoversFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitTestClassRequiresCoversFixer.php @@ -79,7 +79,7 @@ protected function applyPhpUnitClassFix(Tokens $tokens, int $startIndex, int $en $docContent = $tokens[$docIndex]->getContent(); // ignore one-line phpdocs like `/** foo */`, as there is no place to put new annotations - if (false === strpos($docContent, "\n")) { + if (!str_contains($docContent, "\n")) { return; } diff --git a/src/Fixer/Phpdoc/AlignMultilineCommentFixer.php b/src/Fixer/Phpdoc/AlignMultilineCommentFixer.php index e23fb5e4ce8..01f2d4b6cb4 100644 --- a/src/Fixer/Phpdoc/AlignMultilineCommentFixer.php +++ b/src/Fixer/Phpdoc/AlignMultilineCommentFixer.php @@ -122,10 +122,12 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $whitespace = ''; $previousIndex = $index - 1; + if ($tokens[$previousIndex]->isWhitespace()) { $whitespace = $tokens[$previousIndex]->getContent(); --$previousIndex; } + if ($tokens[$previousIndex]->isGivenKind(T_OPEN_TAG)) { $whitespace = Preg::replace('/\S/', '', $tokens[$previousIndex]->getContent()).$whitespace; } @@ -147,6 +149,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } $line = ltrim($line); + if ($token->isGivenKind(T_COMMENT) && (!isset($line[0]) || '*' !== $line[0])) { continue; } diff --git a/src/Fixer/Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php b/src/Fixer/Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php index a72c09c6cd2..de6939c3ad7 100644 --- a/src/Fixer/Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php +++ b/src/Fixer/Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php @@ -27,7 +27,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński */ final class GeneralPhpdocAnnotationRemoveFixer extends AbstractFixer implements ConfigurableFixerInterface diff --git a/src/Fixer/Phpdoc/GeneralPhpdocTagRenameFixer.php b/src/Fixer/Phpdoc/GeneralPhpdocTagRenameFixer.php index e7253e4d3fa..9906942957f 100644 --- a/src/Fixer/Phpdoc/GeneralPhpdocTagRenameFixer.php +++ b/src/Fixer/Phpdoc/GeneralPhpdocTagRenameFixer.php @@ -101,7 +101,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ->getOption(), (new FixerOptionBuilder('replacements', 'A map of tags to replace.')) ->setAllowedTypes(['array']) - ->setNormalizer(function (Options $options, $value) { + ->setNormalizer(static function (Options $options, $value): array { $normalizedValue = []; foreach ($value as $from => $to) { @@ -116,7 +116,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn )); } - if (1 !== Preg::match('#^\S+$#', $to) || false !== strpos($to, '*/')) { + if (1 !== Preg::match('#^\S+$#', $to) || str_contains($to, '*/')) { throw new InvalidOptionsException(sprintf( 'Tag "%s" cannot be replaced by invalid tag "%s".', $from, @@ -199,7 +199,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $tokens[$index] = new Token([T_DOC_COMMENT, Preg::replaceCallback( $regex, - function (array $matches) use ($caseInsensitive, $replacements) { + static function (array $matches) use ($caseInsensitive, $replacements) { if ($caseInsensitive) { $matches[1] = strtolower($matches[1]); } diff --git a/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php b/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php index 1d700392111..ec3dadda84b 100644 --- a/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php +++ b/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php @@ -22,7 +22,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class NoBlankLinesAfterPhpdocFixer extends AbstractFixer { diff --git a/src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php b/src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php index 64154cd962e..843bf01daa8 100644 --- a/src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php +++ b/src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Preg; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NoEmptyPhpdocFixer extends AbstractFixer { /** diff --git a/src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php b/src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php index 00ab3539fce..e5e630c37d9 100644 --- a/src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php +++ b/src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php @@ -24,8 +24,6 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Preg; use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; use PhpCsFixer\Tokenizer\CT; @@ -47,8 +45,10 @@ class Foo { /** * @param Bar $bar * @param mixed $baz + * + * @return Baz */ - public function doFoo(Bar $bar, $baz) {} + public function doFoo(Bar $bar, $baz): Baz {} } '), new CodeSample(' true]), - new VersionSpecificCodeSample('getDeclarationsFromTokens($tokens) as $namespaceUseAnalysis) { $shortNames[strtolower($namespaceUseAnalysis->getShortName())] = '\\'.strtolower($namespaceUseAnalysis->getFullName()); } @@ -130,7 +120,6 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } $content = $initialContent = $token->getContent(); - $documentedElementIndex = $this->findDocumentedElement($tokens, $index); if (null === $documentedElementIndex) { @@ -187,15 +176,19 @@ private function findDocumentedElement(Tokens $tokens, int $docCommentIndex): ?i do { $index = $tokens->getNextMeaningfulToken($index); - if (null === $index || $tokens[$index]->isGivenKind([T_FUNCTION, T_CLASS, T_INTERFACE])) { + if (null === $index || $tokens[$index]->isGivenKind([T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT])) { return $index; } } while ($tokens[$index]->isGivenKind([T_ABSTRACT, T_FINAL, T_STATIC, T_PRIVATE, T_PROTECTED, T_PUBLIC])); - $index = $tokens->getNextMeaningfulToken($docCommentIndex); - $kindsBeforeProperty = [T_STATIC, T_PRIVATE, T_PROTECTED, T_PUBLIC, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, T_STRING, T_NS_SEPARATOR]; + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $kindsBeforeProperty[] = T_READONLY; + } + + $index = $tokens->getNextMeaningfulToken($docCommentIndex); + if (!$tokens[$index]->isGivenKind($kindsBeforeProperty)) { return null; } @@ -256,11 +249,17 @@ private function fixFunctionDocComment(string $content, Tokens $tokens, int $fun */ private function fixPropertyDocComment(string $content, Tokens $tokens, int $index, array $shortNames): string { + $propertyModifierKinds = [T_STATIC, T_PRIVATE, T_PROTECTED, T_PUBLIC]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $propertyModifierKinds[] = T_READONLY; + } + $docBlock = new DocBlock($content); do { $index = $tokens->getNextMeaningfulToken($index); - } while ($tokens[$index]->isGivenKind([T_STATIC, T_PRIVATE, T_PROTECTED, T_PUBLIC])); + } while ($tokens[$index]->isGivenKind($propertyModifierKinds)); $propertyTypeInfo = $this->getPropertyTypeInfo($tokens, $index); @@ -349,15 +348,16 @@ private function getPropertyTypeInfo(Tokens $tokens, int $index): array private function parseTypeHint(Tokens $tokens, int $index): array { $allowsNull = false; + if ($tokens[$index]->isGivenKind(CT::T_NULLABLE_TYPE)) { $allowsNull = true; $index = $tokens->getNextMeaningfulToken($index); } $type = ''; + while ($tokens[$index]->isGivenKind([T_NS_SEPARATOR, T_STATIC, T_STRING, CT::T_ARRAY_TYPEHINT, T_CALLABLE])) { $type .= $tokens[$index]->getContent(); - $index = $tokens->getNextMeaningfulToken($index); } @@ -395,6 +395,7 @@ private function annotationIsSuperfluous(Annotation $annotation, array $info, ar } $actualTypes = null === $info['type'] ? [] : [$info['type']]; + if ($info['allows_null']) { $actualTypes[] = 'null'; } @@ -419,11 +420,7 @@ private function toComparableNames(array $types, array $symbolShortNames): array static function (string $type) use ($symbolShortNames) { $type = strtolower($type); - if (isset($symbolShortNames[$type])) { - return $symbolShortNames[$type]; - } - - return $type; + return $symbolShortNames[$type] ?? $type; }, $types ); diff --git a/src/Fixer/Phpdoc/PhpdocAddMissingParamAnnotationFixer.php b/src/Fixer/Phpdoc/PhpdocAddMissingParamAnnotationFixer.php index 9c99630e498..514593d4cb1 100644 --- a/src/Fixer/Phpdoc/PhpdocAddMissingParamAnnotationFixer.php +++ b/src/Fixer/Phpdoc/PhpdocAddMissingParamAnnotationFixer.php @@ -119,7 +119,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } // ignore one-line phpdocs like `/** foo */`, as there is no place to put new annotations - if (false === strpos($tokenContent, "\n")) { + if (!str_contains($tokenContent, "\n")) { continue; } diff --git a/src/Fixer/Phpdoc/PhpdocAlignFixer.php b/src/Fixer/Phpdoc/PhpdocAlignFixer.php index 822bcb9f281..986706ea292 100644 --- a/src/Fixer/Phpdoc/PhpdocAlignFixer.php +++ b/src/Fixer/Phpdoc/PhpdocAlignFixer.php @@ -16,6 +16,7 @@ use PhpCsFixer\AbstractFixer; use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\TypeExpression; use PhpCsFixer\Fixer\ConfigurableFixerInterface; use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; use PhpCsFixer\FixerConfiguration\AllowedValueSubset; @@ -33,7 +34,7 @@ * @author Fabien Potencier * @author Jordi Boggiano * @author Sebastiaan Stok - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński */ final class PhpdocAlignFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface @@ -96,26 +97,27 @@ public function configure(array $configuration): void $tagsWithoutNameToAlign = array_diff($this->configuration['tags'], $tagsWithNameToAlign, $tagsWithMethodSignatureToAlign); $types = []; - $indent = '(?P(?: {2}|\t)*)'; + $indent = '(?P(?:\ {2}|\t)*)'; + // e.g. @param <$var> - if (!empty($tagsWithNameToAlign)) { - $types[] = '(?P'.implode('|', $tagsWithNameToAlign).')\s+(?P[^$]+?)\s+(?P(?:&|\.{3})?\$[^\s]+)'; + if ([] !== $tagsWithNameToAlign) { + $types[] = '(?P'.implode('|', $tagsWithNameToAlign).')\s+(?P(?:'.TypeExpression::REGEX_TYPES.')?)\s+(?P(?:&|\.{3})?\$\S+)'; } // e.g. @return - if (!empty($tagsWithoutNameToAlign)) { - $types[] = '(?P'.implode('|', $tagsWithoutNameToAlign).')\s+(?P[^\s]+?)'; + if ([] !== $tagsWithoutNameToAlign) { + $types[] = '(?P'.implode('|', $tagsWithoutNameToAlign).')\s+(?P(?:'.TypeExpression::REGEX_TYPES.')?)'; } // e.g. @method - if (!empty($tagsWithMethodSignatureToAlign)) { + if ([] !== $tagsWithMethodSignatureToAlign) { $types[] = '(?P'.implode('|', $tagsWithMethodSignatureToAlign).')(\s+(?P[^\s(]+)|)\s+(?P.+\))'; } // optional $desc = '(?:\s+(?P\V*))'; - $this->regex = '/^'.$indent.' \* @(?:'.implode('|', $types).')'.$desc.'\s*$/u'; + $this->regex = '/^'.$indent.'\ \*\ @(?J)(?:'.implode('|', $types).')'.$desc.'\s*$/ux'; $this->regexCommentLine = '/^'.$indent.' \*(?! @)(?:\s+(?P\V+))(?align = $this->configuration['align']; } diff --git a/src/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixer.php b/src/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixer.php index eadade37bf7..3a5516adac8 100644 --- a/src/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixer.php +++ b/src/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixer.php @@ -119,7 +119,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void : ''; $content = Preg::replaceCallback( '/^(\s*\*\s*@\w+\s+'.$optionalTypeRegEx.')(\p{Lu}?(?=\p{Ll}|\p{Zs}))(.*)$/', - static function (array $matches) { + static function (array $matches): string { if (\function_exists('mb_strtolower')) { return $matches[1].mb_strtolower($matches[2]).$matches[3]; } diff --git a/src/Fixer/Phpdoc/PhpdocIndentFixer.php b/src/Fixer/Phpdoc/PhpdocIndentFixer.php index 2ccf3f42fd3..c40bc9d3ed1 100644 --- a/src/Fixer/Phpdoc/PhpdocIndentFixer.php +++ b/src/Fixer/Phpdoc/PhpdocIndentFixer.php @@ -25,7 +25,7 @@ /** * @author Ceeram - * @author Graham Campbell + * @author Graham Campbell */ final class PhpdocIndentFixer extends AbstractFixer { diff --git a/src/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixer.php b/src/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixer.php index 2da42290e51..9d7569e9876 100644 --- a/src/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixer.php +++ b/src/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixer.php @@ -26,9 +26,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class PhpdocInlineTagNormalizerFixer extends AbstractFixer implements ConfigurableFixerInterface { /** @@ -89,11 +86,11 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $content = Preg::replaceCallback( sprintf( '#(?:@{+|{+\h*@)\h*(%s)s?([^}]*)(?:}+)#i', - implode('|', array_map(function ($tag) { + implode('|', array_map(static function (string $tag): string { return preg_quote($tag, '/'); }, $this->configuration['tags'])) ), - function (array $matches) { + static function (array $matches): string { $doc = trim($matches[2]); if ('' === $doc) { diff --git a/src/Fixer/Phpdoc/PhpdocLineSpanFixer.php b/src/Fixer/Phpdoc/PhpdocLineSpanFixer.php index 3fbf0ec7405..53963ec714d 100644 --- a/src/Fixer/Phpdoc/PhpdocLineSpanFixer.php +++ b/src/Fixer/Phpdoc/PhpdocLineSpanFixer.php @@ -96,19 +96,16 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { $analyzer = new TokensAnalyzer($tokens); - $elements = $analyzer->getClassyElements(); - - foreach ($elements as $index => $element) { + foreach ($analyzer->getClassyElements() as $index => $element) { if (!$this->hasDocBlock($tokens, $index)) { continue; } - $type = $element['type']; $docIndex = $this->getDocBlockIndex($tokens, $index); $doc = new DocBlock($tokens[$docIndex]->getContent()); - if ('multi' === $this->configuration[$type]) { - $doc->makeMultiLine($originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $docIndex), $this->whitespacesConfig->getLineEnding()); + if ('multi' === $this->configuration[$element['type']]) { + $doc->makeMultiLine(WhitespacesAnalyzer::detectIndent($tokens, $docIndex), $this->whitespacesConfig->getLineEnding()); } else { $doc->makeSingleLine(); } @@ -126,9 +123,7 @@ private function hasDocBlock(Tokens $tokens, int $index): bool private function getDocBlockIndex(Tokens $tokens, int $index): int { - do { - $index = $tokens->getPrevNonWhitespace($index); - } while ($tokens[$index]->isGivenKind([ + $propertyPartKinds = [ T_PUBLIC, T_PROTECTED, T_PRIVATE, @@ -141,7 +136,15 @@ private function getDocBlockIndex(Tokens $tokens, int $index): int T_NS_SEPARATOR, CT::T_ARRAY_TYPEHINT, CT::T_NULLABLE_TYPE, - ])); + ]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $propertyPartKinds[] = T_READONLY; + } + + do { + $index = $tokens->getPrevNonWhitespace($index); + } while ($tokens[$index]->isGivenKind($propertyPartKinds)); return $index; } diff --git a/src/Fixer/Phpdoc/PhpdocNoAccessFixer.php b/src/Fixer/Phpdoc/PhpdocNoAccessFixer.php index 439f0d53d80..a168a9137fe 100644 --- a/src/Fixer/Phpdoc/PhpdocNoAccessFixer.php +++ b/src/Fixer/Phpdoc/PhpdocNoAccessFixer.php @@ -20,7 +20,7 @@ use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; /** - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński */ final class PhpdocNoAccessFixer extends AbstractProxyFixer diff --git a/src/Fixer/Phpdoc/PhpdocNoAliasTagFixer.php b/src/Fixer/Phpdoc/PhpdocNoAliasTagFixer.php index 95ade7c5992..b5af8fab66a 100644 --- a/src/Fixer/Phpdoc/PhpdocNoAliasTagFixer.php +++ b/src/Fixer/Phpdoc/PhpdocNoAliasTagFixer.php @@ -29,9 +29,8 @@ /** * Case sensitive tag replace fixer (does not process inline tags like {@inheritdoc}). * - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński - * @author SpacePossum */ final class PhpdocNoAliasTagFixer extends AbstractProxyFixer implements ConfigurableFixerInterface { diff --git a/src/Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php b/src/Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php index f2cd3f94ee9..bc5ec718c8d 100644 --- a/src/Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php +++ b/src/Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php @@ -24,7 +24,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class PhpdocNoEmptyReturnFixer extends AbstractFixer { diff --git a/src/Fixer/Phpdoc/PhpdocNoPackageFixer.php b/src/Fixer/Phpdoc/PhpdocNoPackageFixer.php index 6b009a01c90..d7da1d1aeb8 100644 --- a/src/Fixer/Phpdoc/PhpdocNoPackageFixer.php +++ b/src/Fixer/Phpdoc/PhpdocNoPackageFixer.php @@ -20,7 +20,7 @@ use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; /** - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński */ final class PhpdocNoPackageFixer extends AbstractProxyFixer diff --git a/src/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixer.php b/src/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixer.php index 17ac23b62e5..ef99675ffbe 100644 --- a/src/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixer.php +++ b/src/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixer.php @@ -25,8 +25,6 @@ /** * Remove inheritdoc tags from classy that does not inherit. - * - * @author SpacePossum */ final class PhpdocNoUselessInheritdocFixer extends AbstractFixer { @@ -126,7 +124,7 @@ private function fixToken(Tokens $tokens, int $tokenIndex): void $count = 0; $content = Preg::replaceCallback( '#(\h*(?:@{*|{*\h*@)\h*inheritdoc\h*)([^}]*)((?:}*)\h*)#i', - static function (array $matches) { + static function (array $matches): string { return ' '.$matches[2]; }, $tokens[$tokenIndex]->getContent(), diff --git a/src/Fixer/Phpdoc/PhpdocOrderByValueFixer.php b/src/Fixer/Phpdoc/PhpdocOrderByValueFixer.php index cae0f4be615..28bee070667 100644 --- a/src/Fixer/Phpdoc/PhpdocOrderByValueFixer.php +++ b/src/Fixer/Phpdoc/PhpdocOrderByValueFixer.php @@ -202,11 +202,11 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn ->setAllowedValues([ new AllowedValueSubset($allowedValues), ]) - ->setNormalizer(function (Options $options, $value) { + ->setNormalizer(static function (Options $options, $value): array { $normalized = []; - foreach ($value as $index => $annotation) { - // since we will be using strtolower on the input annotations when building the sorting + foreach ($value as $annotation) { + // since we will be using "strtolower" on the input annotations when building the sorting // map we must match the type in lower case as well $normalized[$annotation] = strtolower($annotation); } diff --git a/src/Fixer/Phpdoc/PhpdocOrderFixer.php b/src/Fixer/Phpdoc/PhpdocOrderFixer.php index 6ae218c5a61..ba12687f496 100644 --- a/src/Fixer/Phpdoc/PhpdocOrderFixer.php +++ b/src/Fixer/Phpdoc/PhpdocOrderFixer.php @@ -23,7 +23,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class PhpdocOrderFixer extends AbstractFixer { diff --git a/src/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixer.php b/src/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixer.php index 015f7bdde04..e2b6b3f7b49 100644 --- a/src/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixer.php +++ b/src/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixer.php @@ -29,9 +29,6 @@ use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\OptionsResolver\Options; -/** - * @author SpacePossum - */ final class PhpdocReturnSelfReferenceFixer extends AbstractFixer implements ConfigurableFixerInterface { /** @@ -125,6 +122,7 @@ public function getPriority(): int protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { $tokensAnalyzer = new TokensAnalyzer($tokens); + foreach ($tokensAnalyzer->getClassyElements() as $index => $element) { if ('method' === $element['type']) { $this->fixMethod($tokens, $index); @@ -149,8 +147,9 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn return new FixerConfigurationResolver([ (new FixerOptionBuilder('replacements', 'Mapping between replaced return types with new ones.')) ->setAllowedTypes(['array']) - ->setNormalizer(static function (Options $options, $value) use ($default) { + ->setNormalizer(static function (Options $options, array $value) use ($default): array { $normalizedValue = []; + foreach ($value as $from => $to) { if (\is_string($from)) { $from = strtolower($from); @@ -159,7 +158,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn if (!isset($default[$from])) { throw new InvalidOptionsException(sprintf( 'Unknown key "%s", expected any of "%s".', - \is_object($from) ? \get_class($from) : \gettype($from).(\is_resource($from) ? '' : '#'.$from), + \gettype($from).'#'.$from, implode('", "', array_keys($default)) )); } @@ -187,14 +186,14 @@ private function fixMethod(Tokens $tokens, int $index): void static $methodModifiers = [T_STATIC, T_FINAL, T_ABSTRACT, T_PRIVATE, T_PROTECTED, T_PUBLIC]; // find PHPDoc of method (if any) - do { + while (true) { $tokenIndex = $tokens->getPrevMeaningfulToken($index); if (!$tokens[$tokenIndex]->isGivenKind($methodModifiers)) { break; } $index = $tokenIndex; - } while (true); + } $docIndex = $tokens->getPrevNonWhitespace($index); if (!$tokens[$docIndex]->isGivenKind(T_DOC_COMMENT)) { @@ -217,9 +216,9 @@ private function fixMethod(Tokens $tokens, int $index): void } $newTypes = []; + foreach ($types as $type) { - $lower = strtolower($type); - $newTypes[] = isset($this->configuration['replacements'][$lower]) ? $this->configuration['replacements'][$lower] : $type; + $newTypes[] = $this->configuration['replacements'][strtolower($type)] ?? $type; } if ($types === $newTypes) { diff --git a/src/Fixer/Phpdoc/PhpdocScalarFixer.php b/src/Fixer/Phpdoc/PhpdocScalarFixer.php index 047e7743d45..cbfdfe65771 100644 --- a/src/Fixer/Phpdoc/PhpdocScalarFixer.php +++ b/src/Fixer/Phpdoc/PhpdocScalarFixer.php @@ -25,7 +25,7 @@ use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; /** - * @author Graham Campbell + * @author Graham Campbell */ final class PhpdocScalarFixer extends AbstractPhpdocTypesFixer implements ConfigurableFixerInterface { diff --git a/src/Fixer/Phpdoc/PhpdocSeparationFixer.php b/src/Fixer/Phpdoc/PhpdocSeparationFixer.php index 210c208be70..b8140f62642 100644 --- a/src/Fixer/Phpdoc/PhpdocSeparationFixer.php +++ b/src/Fixer/Phpdoc/PhpdocSeparationFixer.php @@ -25,7 +25,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class PhpdocSeparationFixer extends AbstractFixer { @@ -117,7 +117,7 @@ private function fixDescription(DocBlock $doc): void /** * Make sure the annotations are correctly separated. */ - private function fixAnnotations(DocBlock $doc): string + private function fixAnnotations(DocBlock $doc): void { foreach ($doc->getAnnotations() as $index => $annotation) { $next = $doc->getAnnotation($index + 1); @@ -134,8 +134,6 @@ private function fixAnnotations(DocBlock $doc): string } } } - - return $doc->getContent(); } /** diff --git a/src/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixer.php b/src/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixer.php index bc47903d0c3..8ccd3d74eaa 100644 --- a/src/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixer.php +++ b/src/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixer.php @@ -24,8 +24,6 @@ /** * Fixer for part of rule defined in PSR5 ¶7.22. - * - * @author SpacePossum */ final class PhpdocSingleLineVarSpacingFixer extends AbstractFixer { diff --git a/src/Fixer/Phpdoc/PhpdocSummaryFixer.php b/src/Fixer/Phpdoc/PhpdocSummaryFixer.php index abb6a7c2684..090ac88f333 100644 --- a/src/Fixer/Phpdoc/PhpdocSummaryFixer.php +++ b/src/Fixer/Phpdoc/PhpdocSummaryFixer.php @@ -25,7 +25,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class PhpdocSummaryFixer extends AbstractFixer implements WhitespacesAwareFixerInterface { diff --git a/src/Fixer/Phpdoc/PhpdocTagTypeFixer.php b/src/Fixer/Phpdoc/PhpdocTagTypeFixer.php index 03337745520..735b4e29b01 100644 --- a/src/Fixer/Phpdoc/PhpdocTagTypeFixer.php +++ b/src/Fixer/Phpdoc/PhpdocTagTypeFixer.php @@ -28,9 +28,6 @@ use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\OptionsResolver\Options; -/** - * @author SpacePossum - */ final class PhpdocTagTypeFixer extends AbstractFixer implements ConfigurableFixerInterface { private const TAG_REGEX = '/^(?: @@ -90,21 +87,23 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void return; } + $regularExpression = sprintf( + '/({?@(?:%s).*?(?:(?=\s\*\/)|(?=\n)}?))/i', + implode('|', array_map( + static function (string $tag): string { + return preg_quote($tag, '/'); + }, + array_keys($this->configuration['tags']) + )) + ); + foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_DOC_COMMENT)) { continue; } $parts = Preg::split( - sprintf( - '/({?@(?:%s)(?:}|\h.*?(?:}|(?=\R)|(?=\h+\*\/)))?)/i', - implode('|', array_map( - function (string $tag) { - return preg_quote($tag, '/'); - }, - array_keys($this->configuration['tags']) - )) - ), + $regularExpression, $token->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE @@ -151,7 +150,7 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn return new FixerConfigurationResolver([ (new FixerOptionBuilder('tags', 'The list of tags to fix')) ->setAllowedTypes(['array']) - ->setAllowedValues([function ($value) { + ->setAllowedValues([static function (array $value): bool { foreach ($value as $type) { if (!\in_array($type, ['annotation', 'inline'], true)) { throw new InvalidOptionsException("Unknown tag type \"{$type}\"."); @@ -183,8 +182,9 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn 'var' => 'annotation', 'version' => 'annotation', ]) - ->setNormalizer(function (Options $options, $value) { + ->setNormalizer(static function (Options $options, $value): array { $normalized = []; + foreach ($value as $tag => $type) { $normalized[strtolower($tag)] = $type; } diff --git a/src/Fixer/Phpdoc/PhpdocToCommentFixer.php b/src/Fixer/Phpdoc/PhpdocToCommentFixer.php index 34da0e85719..b335b4019a8 100644 --- a/src/Fixer/Phpdoc/PhpdocToCommentFixer.php +++ b/src/Fixer/Phpdoc/PhpdocToCommentFixer.php @@ -108,7 +108,7 @@ public function configure(array $configuration = null): void parent::configure($configuration); $this->ignoredTags = array_map( - static function ($tag) { + static function (string $tag): string { return strtolower($tag); }, $this->configuration['ignored_tags'] diff --git a/src/Fixer/Phpdoc/PhpdocTrimFixer.php b/src/Fixer/Phpdoc/PhpdocTrimFixer.php index 52ff0aed0fc..d835fb337ea 100644 --- a/src/Fixer/Phpdoc/PhpdocTrimFixer.php +++ b/src/Fixer/Phpdoc/PhpdocTrimFixer.php @@ -23,7 +23,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class PhpdocTrimFixer extends AbstractFixer { diff --git a/src/Fixer/Phpdoc/PhpdocTypesFixer.php b/src/Fixer/Phpdoc/PhpdocTypesFixer.php index 6a823931a86..7371b6b3fd1 100644 --- a/src/Fixer/Phpdoc/PhpdocTypesFixer.php +++ b/src/Fixer/Phpdoc/PhpdocTypesFixer.php @@ -25,7 +25,7 @@ use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; /** - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński */ final class PhpdocTypesFixer extends AbstractPhpdocTypesFixer implements ConfigurableFixerInterface @@ -80,7 +80,7 @@ public function configure(array $configuration): void { parent::configure($configuration); - $this->typesToFix = array_merge(...array_map(static function (string $group) { + $this->typesToFix = array_merge(...array_map(static function (string $group): array { return self::$possibleTypes[$group]; }, $this->configuration['groups'])); } diff --git a/src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php b/src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php index 5d5c9ca5c78..01437fa413c 100644 --- a/src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php +++ b/src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php @@ -147,7 +147,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void // fix @method parameters types $line = $doc->getLine($annotation->getStart()); $line->setContent(Preg::replaceCallback('/(@method\s+.+?\s+\w+\()(.*)\)/', function (array $matches) { - $sorted = Preg::replaceCallback('/([^\s,]+)([\s]+\$[^\s,]+)/', function (array $matches) { + $sorted = Preg::replaceCallback('/([^\s,]+)([\s]+\$[^\s,]+)/', function (array $matches): string { return $this->sortJoinedTypes($matches[1]).$matches[2]; }, $matches[2]); @@ -175,8 +175,8 @@ private function sortTypes(array $types): array if ('alpha' === $this->configuration['sort_algorithm']) { $types = Utils::stableSort( $types, - static function (string $type) { return $type; }, - static function (string $typeA, string $typeB) { + static function (string $type): string { return $type; }, + static function (string $typeA, string $typeB): int { $regexp = '/^\\??\\\?/'; return strcasecmp( @@ -212,7 +212,7 @@ private function sortJoinedTypes(string $types): string { $types = array_filter( Preg::split('/([^|<{\(]+(?:[<{].*[>}]|\(.+\)(?::.+)?)?)/', $types, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), - static function (string $value) { + static function (string $value): bool { return '|' !== $value; } ); diff --git a/src/Fixer/Phpdoc/PhpdocVarWithoutNameFixer.php b/src/Fixer/Phpdoc/PhpdocVarWithoutNameFixer.php index 9e4529a1f42..7bfca416015 100644 --- a/src/Fixer/Phpdoc/PhpdocVarWithoutNameFixer.php +++ b/src/Fixer/Phpdoc/PhpdocVarWithoutNameFixer.php @@ -25,7 +25,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell * @author Dave van der Brugge */ final class PhpdocVarWithoutNameFixer extends AbstractFixer @@ -89,13 +89,19 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - // For people writing static public $foo instead of public static $foo + // For people writing "static public $foo" instead of "public static $foo" if ($tokens[$nextIndex]->isGivenKind(T_STATIC)) { $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); } // We want only doc blocks that are for properties and thus have specified access modifiers next - if (!$tokens[$nextIndex]->isGivenKind([T_PRIVATE, T_PROTECTED, T_PUBLIC, T_VAR])) { + $propertyModifierKinds = [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_VAR]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $propertyModifierKinds[] = T_READONLY; + } + + if (!$tokens[$nextIndex]->isGivenKind($propertyModifierKinds)) { continue; } diff --git a/src/Fixer/ReturnNotation/NoUselessReturnFixer.php b/src/Fixer/ReturnNotation/NoUselessReturnFixer.php index e268eb34dcf..7656f950a03 100644 --- a/src/Fixer/ReturnNotation/NoUselessReturnFixer.php +++ b/src/Fixer/ReturnNotation/NoUselessReturnFixer.php @@ -20,9 +20,6 @@ use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class NoUselessReturnFixer extends AbstractFixer { /** diff --git a/src/Fixer/ReturnNotation/ReturnAssignmentFixer.php b/src/Fixer/ReturnNotation/ReturnAssignmentFixer.php index 6cc4bfa9984..143d6007f1c 100644 --- a/src/Fixer/ReturnNotation/ReturnAssignmentFixer.php +++ b/src/Fixer/ReturnNotation/ReturnAssignmentFixer.php @@ -23,9 +23,6 @@ use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\TokensAnalyzer; -/** - * @author SpacePossum - */ final class ReturnAssignmentFixer extends AbstractFixer { /** @@ -180,7 +177,7 @@ private function fixFunction(Tokens $tokens, int $functionIndex, int $functionOp continue; } - // test if there this is anything in the function body that might + // test if there is anything in the function body that might // change global state or indirect changes (like through references, eval, etc.) if ($tokens[$index]->isGivenKind($riskyKinds)) { @@ -231,7 +228,7 @@ private function fixFunction(Tokens $tokens, int $functionIndex, int $functionOp } // Note: here we are @ "; return $a;" (or "; return $a ? >") - do { + while (true) { $prevMeaningFul = $tokens->getPrevMeaningfulToken($assignVarEndIndex); if (!$tokens[$prevMeaningFul]->equals(')')) { @@ -239,7 +236,7 @@ private function fixFunction(Tokens $tokens, int $functionIndex, int $functionOp } $assignVarEndIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $prevMeaningFul); - } while (true); + } $assignVarOperatorIndex = $tokens->getPrevTokenOfKind( $assignVarEndIndex, diff --git a/src/Fixer/ReturnNotation/SimplifiedNullReturnFixer.php b/src/Fixer/ReturnNotation/SimplifiedNullReturnFixer.php index ccf920b7512..800c21c13a7 100644 --- a/src/Fixer/ReturnNotation/SimplifiedNullReturnFixer.php +++ b/src/Fixer/ReturnNotation/SimplifiedNullReturnFixer.php @@ -18,13 +18,11 @@ use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class SimplifiedNullReturnFixer extends AbstractFixer { @@ -37,7 +35,7 @@ public function getDefinition(): FixerDefinitionInterface 'A return statement wishing to return `void` should not return `null`.', [ new CodeSample(" + * @author Graham Campbell * @author Egidijus Girčys */ final class MultilineWhitespaceBeforeSemicolonsFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface @@ -134,12 +134,12 @@ private function applyNoMultiLineFix(Tokens $tokens): void $previousIndex = $index - 1; $previous = $tokens[$previousIndex]; - if (!$previous->isWhitespace() || false === strpos($previous->getContent(), "\n")) { + if (!$previous->isWhitespace() || !str_contains($previous->getContent(), "\n")) { continue; } $content = $previous->getContent(); - if (0 === strpos($content, $lineEnding) && $tokens[$index - 2]->isComment()) { + if (str_starts_with($content, $lineEnding) && $tokens[$index - 2]->isComment()) { $tokens->ensureWhitespaceAtIndex($previousIndex, 0, $lineEnding); } else { $tokens->clearAt($previousIndex); diff --git a/src/Fixer/Semicolon/NoEmptyStatementFixer.php b/src/Fixer/Semicolon/NoEmptyStatementFixer.php index 36ba1d3e790..bbd423e148e 100644 --- a/src/Fixer/Semicolon/NoEmptyStatementFixer.php +++ b/src/Fixer/Semicolon/NoEmptyStatementFixer.php @@ -22,7 +22,6 @@ use PhpCsFixer\Tokenizer\TokensAnalyzer; /** - * @author SpacePossum * @author Dariusz Rumiński */ final class NoEmptyStatementFixer extends AbstractFixer diff --git a/src/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php b/src/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php index 1cc51c05d03..c4030cff0f2 100644 --- a/src/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php +++ b/src/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php @@ -22,7 +22,7 @@ use PhpCsFixer\Tokenizer\Tokens; /** - * @author Graham Campbell + * @author Graham Campbell */ final class NoSinglelineWhitespaceBeforeSemicolonsFixer extends AbstractFixer { diff --git a/src/Fixer/Semicolon/SemicolonAfterInstructionFixer.php b/src/Fixer/Semicolon/SemicolonAfterInstructionFixer.php index 484a6c8decc..c9a9131f73a 100644 --- a/src/Fixer/Semicolon/SemicolonAfterInstructionFixer.php +++ b/src/Fixer/Semicolon/SemicolonAfterInstructionFixer.php @@ -21,9 +21,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class SemicolonAfterInstructionFixer extends AbstractFixer { /** diff --git a/src/Fixer/Semicolon/SpaceAfterSemicolonFixer.php b/src/Fixer/Semicolon/SpaceAfterSemicolonFixer.php index 53977efe0c7..b2d46ae06cd 100644 --- a/src/Fixer/Semicolon/SpaceAfterSemicolonFixer.php +++ b/src/Fixer/Semicolon/SpaceAfterSemicolonFixer.php @@ -26,9 +26,6 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; -/** - * @author SpacePossum - */ final class SpaceAfterSemicolonFixer extends AbstractFixer implements ConfigurableFixerInterface { /** diff --git a/src/Fixer/Strict/DeclareStrictTypesFixer.php b/src/Fixer/Strict/DeclareStrictTypesFixer.php index ef5d0be1f27..76e26b47387 100644 --- a/src/Fixer/Strict/DeclareStrictTypesFixer.php +++ b/src/Fixer/Strict/DeclareStrictTypesFixer.php @@ -16,16 +16,14 @@ use PhpCsFixer\AbstractFixer; use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; /** * @author Jordi Boggiano - * @author SpacePossum */ final class DeclareStrictTypesFixer extends AbstractFixer implements WhitespacesAwareFixerInterface { @@ -37,9 +35,8 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'Force strict types declaration in all files. Requires PHP >= 7.0.', [ - new VersionSpecificCodeSample( - "= 70000 && isset($tokens[0]) && $tokens[0]->isGivenKind(T_OPEN_TAG); + return isset($tokens[0]) && $tokens[0]->isGivenKind(T_OPEN_TAG); } /** @@ -134,12 +131,12 @@ private function insertSequence(Tokens $tokens): void // start index of the sequence is always 1 here, 0 is always open tag // transform "getContent(), "\n")) { + if (str_contains($tokens[0]->getContent(), "\n")) { $tokens[0] = new Token([$tokens[0]->getId(), trim($tokens[0]->getContent()).' ']); } if ($endIndex === \count($tokens) - 1) { - return; // no more tokens afters sequence, single_blank_line_at_eof might add a line + return; // no more tokens after sequence, single_blank_line_at_eof might add a line } $lineEnding = $this->whitespacesConfig->getLineEnding(); diff --git a/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php b/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php index bcae727af44..d05e5139f92 100644 --- a/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php +++ b/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php @@ -110,7 +110,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ($token->equalsAny(['"', 'b"', 'B"'])) { $doubleQuoteOpened = !$doubleQuoteOpened; } - if (!$token->isGivenKind([T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING]) || false === strpos($content, '\\')) { + if (!$token->isGivenKind([T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING]) || !str_contains($content, '\\')) { continue; } diff --git a/src/Fixer/StringNotation/HeredocToNowdocFixer.php b/src/Fixer/StringNotation/HeredocToNowdocFixer.php index 343fad5376d..185cc8bcaae 100644 --- a/src/Fixer/StringNotation/HeredocToNowdocFixer.php +++ b/src/Fixer/StringNotation/HeredocToNowdocFixer.php @@ -71,7 +71,7 @@ public function isCandidate(Tokens $tokens): bool protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(T_START_HEREDOC) || false !== strpos($token->getContent(), "'")) { + if (!$token->isGivenKind(T_START_HEREDOC) || str_contains($token->getContent(), "'")) { continue; } diff --git a/src/Fixer/StringNotation/SimpleToComplexStringVariableFixer.php b/src/Fixer/StringNotation/SimpleToComplexStringVariableFixer.php index 8ad39153d4a..53ccabae3bf 100644 --- a/src/Fixer/StringNotation/SimpleToComplexStringVariableFixer.php +++ b/src/Fixer/StringNotation/SimpleToComplexStringVariableFixer.php @@ -100,7 +100,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $tokenOfStringBeforeToken = $tokens[$index - 1]; $stringContent = $tokenOfStringBeforeToken->getContent(); - if ('$' === substr($stringContent, -1) && '\\$' !== substr($stringContent, -2)) { + if (str_ends_with($stringContent, '$') && !str_ends_with($stringContent, '\\$')) { $newContent = substr($stringContent, 0, -1).'\\$'; $tokenOfStringBeforeToken = new Token([T_ENCAPSED_AND_WHITESPACE, $newContent]); } diff --git a/src/Fixer/StringNotation/SingleQuoteFixer.php b/src/Fixer/StringNotation/SingleQuoteFixer.php index 959b8cc6663..b269b418cd7 100644 --- a/src/Fixer/StringNotation/SingleQuoteFixer.php +++ b/src/Fixer/StringNotation/SingleQuoteFixer.php @@ -94,7 +94,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ( '"' === $content[0] - && (true === $this->configuration['strings_containing_single_quote_chars'] || false === strpos($content, "'")) + && (true === $this->configuration['strings_containing_single_quote_chars'] || !str_contains($content, "'")) // regex: odd number of backslashes, not followed by double quote or dollar && !Preg::match('/(?getPrevMeaningfulToken($parentScopeEndIndex); + return $endIndex ?? $tokens->getPrevMeaningfulToken($parentScopeEndIndex); } private function getLineIndentation(Tokens $tokens, int $index): string diff --git a/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php b/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php index 1a8364da0f5..9e7cff6933c 100644 --- a/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php +++ b/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php @@ -31,7 +31,6 @@ /** * @author Dariusz Rumiński * @author Andreas Möller - * @author SpacePossum */ final class BlankLineBeforeStatementFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface { @@ -314,7 +313,7 @@ private function shouldAddBlankLine(Tokens $tokens, int $prevNonWhitespace): boo if ($prevNonWhitespaceToken->isComment()) { for ($j = $prevNonWhitespace - 1; $j >= 0; --$j) { - if (false !== strpos($tokens[$j]->getContent(), "\n")) { + if (str_contains($tokens[$j]->getContent(), "\n")) { return false; } diff --git a/src/Fixer/Whitespace/CompactNullableTypehintFixer.php b/src/Fixer/Whitespace/CompactNullableTypehintFixer.php index e92a69b4a0f..042d82847c4 100644 --- a/src/Fixer/Whitespace/CompactNullableTypehintFixer.php +++ b/src/Fixer/Whitespace/CompactNullableTypehintFixer.php @@ -15,10 +15,9 @@ namespace PhpCsFixer\Fixer\Whitespace; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; -use PhpCsFixer\FixerDefinition\VersionSpecification; -use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\Tokens; @@ -35,9 +34,8 @@ public function getDefinition(): FixerDefinitionInterface return new FixerDefinition( 'Remove extra spaces in a nullable typehint.', [ - new VersionSpecificCodeSample( - "= 70100 && $tokens->isTokenKindFound(CT::T_NULLABLE_TYPE); + return $tokens->isTokenKindFound(CT::T_NULLABLE_TYPE); } /** diff --git a/src/Fixer/Whitespace/IndentationTypeFixer.php b/src/Fixer/Whitespace/IndentationTypeFixer.php index a06c2b2534c..14a1d29e56b 100644 --- a/src/Fixer/Whitespace/IndentationTypeFixer.php +++ b/src/Fixer/Whitespace/IndentationTypeFixer.php @@ -101,7 +101,7 @@ private function fixIndentInComment(Tokens $tokens, int $index): Token $indent = $this->indent; // change indent to expected one - $content = Preg::replaceCallback('/^(?: )+/m', function (array $matches) use ($indent) { + $content = Preg::replaceCallback('/^(?: )+/m', function (array $matches) use ($indent): string { return $this->getExpectedIndent($matches[0], $indent); }, $content); @@ -114,7 +114,7 @@ private function fixIndentToken(Tokens $tokens, int $index): Token $previousTokenHasTrailingLinebreak = false; // @TODO this can be removed when we have a transformer for "T_OPEN_TAG" to "T_OPEN_TAG + T_WHITESPACE" - if (false !== strpos($tokens[$index - 1]->getContent(), "\n")) { + if (str_contains($tokens[$index - 1]->getContent(), "\n")) { $content = "\n".$content; $previousTokenHasTrailingLinebreak = true; } @@ -122,7 +122,7 @@ private function fixIndentToken(Tokens $tokens, int $index): Token $indent = $this->indent; $newContent = Preg::replaceCallback( '/(\R)(\h+)/', // find indent - function (array $matches) use ($indent) { + function (array $matches) use ($indent): string { // normalize mixed indent $content = Preg::replace('/(?:(? - * @author SpacePossum * @author Dariusz Rumiński */ final class LineEndingFixer extends AbstractFixer implements WhitespacesAwareFixerInterface diff --git a/src/Fixer/Whitespace/NoExtraBlankLinesFixer.php b/src/Fixer/Whitespace/NoExtraBlankLinesFixer.php index e7d71c0f703..fb183f6514a 100644 --- a/src/Fixer/Whitespace/NoExtraBlankLinesFixer.php +++ b/src/Fixer/Whitespace/NoExtraBlankLinesFixer.php @@ -29,10 +29,10 @@ use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\TokensAnalyzer; +use PhpCsFixer\Utils; /** * @author Dariusz Rumiński - * @author SpacePossum */ final class NoExtraBlankLinesFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface { @@ -80,6 +80,10 @@ final class NoExtraBlankLinesFixer extends AbstractFixer implements Configurable */ public function configure(array $configuration): void { + if (isset($configuration['tokens']) && \in_array('use_trait', $configuration['tokens'], true)) { + Utils::triggerDeprecation(new \RuntimeException('Option "use_trait" is deprecated, use the rule `class_attributes_separation` with `elements: trait_import` instead.')); + } + parent::configure($configuration); static $reprToTokenMap = [ @@ -248,18 +252,6 @@ class Bar ), new CodeSample( ' ['use_trait']] - ), - new CodeSample( - 'tokens[$i]->isWhitespace() && false !== strpos($this->tokens[$i]->getContent(), "\n")) { + if ($this->tokens[$i]->isWhitespace() && str_contains($this->tokens[$i]->getContent(), "\n")) { break; } } @@ -408,7 +400,7 @@ private function fixStructureOpenCloseIfMultiLine(int $index): void $bodyEnd = $this->tokens->findBlockEnd($blockTypeInfo['type'], $index); for ($i = $bodyEnd - 1; $i >= $index; --$i) { - if (false !== strpos($this->tokens[$i]->getContent(), "\n")) { + if (str_contains($this->tokens[$i]->getContent(), "\n")) { $this->removeEmptyLinesAfterLineWithTokenAt($i); $this->removeEmptyLinesAfterLineWithTokenAt($index); @@ -424,7 +416,7 @@ private function removeEmptyLinesAfterLineWithTokenAt(int $index): void for ($end = $index; $end < $tokenCount; ++$end) { if ( $this->tokens[$end]->equals('}') - || false !== strpos($this->tokens[$end]->getContent(), "\n") + || str_contains($this->tokens[$end]->getContent(), "\n") ) { break; } diff --git a/src/Fixer/Whitespace/NoSpacesInsideParenthesisFixer.php b/src/Fixer/Whitespace/NoSpacesInsideParenthesisFixer.php index 3511d3aad1a..998171e0a25 100644 --- a/src/Fixer/Whitespace/NoSpacesInsideParenthesisFixer.php +++ b/src/Fixer/Whitespace/NoSpacesInsideParenthesisFixer.php @@ -51,7 +51,7 @@ function foo( \$bar, \$baz ) * {@inheritdoc} * * Must run before FunctionToConstantFixer. - * Must run after CombineConsecutiveIssetsFixer, CombineNestedDirnameFixer, LambdaNotUsedImportFixer, NoUselessSprintfFixer, PowToExponentiationFixer. + * Must run after CombineConsecutiveIssetsFixer, CombineNestedDirnameFixer, LambdaNotUsedImportFixer, ModernizeStrposFixer, NoUselessSprintfFixer, PowToExponentiationFixer. */ public function getPriority(): int { @@ -104,7 +104,7 @@ private function removeSpaceAroundToken(Tokens $tokens, int $index): void { $token = $tokens[$index]; - if ($token->isWhitespace() && false === strpos($token->getContent(), "\n")) { + if ($token->isWhitespace() && !str_contains($token->getContent(), "\n")) { $tokens->clearAt($index); } } diff --git a/src/Fixer/Whitespace/NoTrailingWhitespaceFixer.php b/src/Fixer/Whitespace/NoTrailingWhitespaceFixer.php index ff132cf4a2d..05a4f429690 100644 --- a/src/Fixer/Whitespace/NoTrailingWhitespaceFixer.php +++ b/src/Fixer/Whitespace/NoTrailingWhitespaceFixer.php @@ -46,7 +46,7 @@ public function getDefinition(): FixerDefinitionInterface /** * {@inheritdoc} * - * Must run after CombineConsecutiveIssetsFixer, CombineConsecutiveUnsetsFixer, EmptyLoopBodyFixer, FunctionToConstantFixer, NoEmptyCommentFixer, NoEmptyPhpdocFixer, NoEmptyStatementFixer, NoUnneededControlParenthesesFixer, NoUselessElseFixer, TernaryToElvisOperatorFixer. + * Must run after CombineConsecutiveIssetsFixer, CombineConsecutiveUnsetsFixer, EmptyLoopBodyFixer, EmptyLoopConditionFixer, FunctionToConstantFixer, ModernizeStrposFixer, NoEmptyCommentFixer, NoEmptyPhpdocFixer, NoEmptyStatementFixer, NoUnneededControlParenthesesFixer, NoUselessElseFixer, TernaryToElvisOperatorFixer. */ public function getPriority(): int { diff --git a/src/Fixer/Whitespace/TypesSpacesFixer.php b/src/Fixer/Whitespace/TypesSpacesFixer.php new file mode 100644 index 00000000000..b2b18775fd6 --- /dev/null +++ b/src/Fixer/Whitespace/TypesSpacesFixer.php @@ -0,0 +1,126 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class TypesSpacesFixer extends AbstractFixer implements ConfigurableFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition(): FixerDefinitionInterface + { + return new FixerDefinition( + 'A single space or none should be around union type operator.', + [ + new CodeSample( + " 'single'] + ), + new VersionSpecificCodeSample( + "isTokenKindFound(CT::T_TYPE_ALTERNATION); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition(): FixerConfigurationResolverInterface + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('space', 'spacing to apply around union type operator.')) + ->setAllowedValues(['none', 'single']) + ->setDefault('none') + ->getOption(), + ]); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens): void + { + for ($index = $tokens->count() - 1; $index > 0; --$index) { + if (!$tokens[$index]->isGivenKind(CT::T_TYPE_ALTERNATION)) { + continue; + } + + if ('single' === $this->configuration['space']) { + $this->ensureSingleSpace($tokens, $index + 1, 0); + $this->ensureSingleSpace($tokens, $index - 1, 1); + } else { + $this->ensureNoSpace($tokens, $index + 1); + $this->ensureNoSpace($tokens, $index - 1); + } + } + } + + private function ensureSingleSpace(Tokens $tokens, int $index, int $offset): void + { + if (!$tokens[$index]->isWhitespace()) { + $tokens->insertSlices([$index + $offset => new Token([T_WHITESPACE, ' '])]); + + return; + } + + if (' ' === $tokens[$index]->getContent()) { + return; + } + + if (1 === Preg::match('/\R/', $tokens[$index]->getContent())) { + return; + } + + $tokens[$index] = new Token([T_WHITESPACE, ' ']); + } + + private function ensureNoSpace(Tokens $tokens, int $index): void + { + if (!$tokens[$index]->isWhitespace()) { + return; + } + + if (1 === Preg::match('/\R/', $tokens[$index]->getContent())) { + return; + } + + $tokens->clearAt($index); + } +} diff --git a/src/FixerConfiguration/FixerConfigurationResolver.php b/src/FixerConfiguration/FixerConfigurationResolver.php index ca862772ae1..6c79e4495dc 100644 --- a/src/FixerConfiguration/FixerConfigurationResolver.php +++ b/src/FixerConfiguration/FixerConfigurationResolver.php @@ -116,10 +116,8 @@ public function resolve(array $options): array /** * @throws \LogicException when the option is already defined - * - * @return $this */ - private function addOption(FixerOptionInterface $option): self + private function addOption(FixerOptionInterface $option): void { $name = $option->getName(); @@ -129,7 +127,5 @@ private function addOption(FixerOptionInterface $option): self $this->options[] = $option; $this->registeredNames[] = $name; - - return $this; } } diff --git a/src/FixerFactory.php b/src/FixerFactory.php index c683052fc03..2ad10fdcd99 100644 --- a/src/FixerFactory.php +++ b/src/FixerFactory.php @@ -89,12 +89,10 @@ public function registerBuiltInFixers(): self $builtInFixers = []; /** @var SplFileInfo $file */ - foreach (SymfonyFinder::create()->files()->in(__DIR__.'/Fixer')->depth(1) as $file) { + foreach (SymfonyFinder::create()->files()->in(__DIR__.'/Fixer')->name('*Fixer.php')->depth(1) as $file) { $relativeNamespace = $file->getRelativePath(); $fixerClass = 'PhpCsFixer\\Fixer\\'.($relativeNamespace ? $relativeNamespace.'\\' : '').$file->getBasename('.php'); - if ('Fixer' === substr($fixerClass, -5)) { - $builtInFixers[] = $fixerClass; - } + $builtInFixers[] = $fixerClass; } } @@ -158,11 +156,11 @@ public function useRuleSet(RuleSetInterface $ruleSet): self } $fixer = $this->fixersByName[$name]; - $config = $ruleSet->getRuleConfiguration($name); + if (null !== $config) { if ($fixer instanceof ConfigurableFixerInterface) { - if (!\is_array($config) || !\count($config)) { + if (\count($config) < 1) { throw new InvalidFixerConfigurationException($fixer->getName(), 'Configuration must be an array and may not be empty.'); } @@ -225,7 +223,7 @@ private function generateConflictMessage(array $fixerConflicts): string // filter mutual conflicts $report[$fixer] = array_filter( $fixers, - static function (string $candidate) use ($report, $fixer) { + static function (string $candidate) use ($report, $fixer): bool { return !\array_key_exists($candidate, $report) || !\in_array($fixer, $report[$candidate], true); } ); diff --git a/src/Linter/ProcessLinter.php b/src/Linter/ProcessLinter.php index da418ce6f5f..d19b69e2ae7 100644 --- a/src/Linter/ProcessLinter.php +++ b/src/Linter/ProcessLinter.php @@ -60,7 +60,7 @@ public function __construct(?string $executable = null) } if ('phpdbg' === \PHP_SAPI) { - if (false === strpos($executable, 'phpdbg')) { + if (!str_contains($executable, 'phpdbg')) { throw new UnavailableLinterException('Automatically found PHP executable is non-standard phpdbg. Could not find proper PHP executable.'); } diff --git a/src/RuleSet/AbstractMigrationSetDescription.php b/src/RuleSet/AbstractMigrationSetDescription.php new file mode 100644 index 00000000000..9c36c3c79b1 --- /dev/null +++ b/src/RuleSet/AbstractMigrationSetDescription.php @@ -0,0 +1,38 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet; + +use PhpCsFixer\Preg; + +/** + * @internal + */ +abstract class AbstractMigrationSetDescription extends AbstractRuleSetDescription +{ + public function getDescription(): string + { + $name = $this->getName(); + + if (0 !== Preg::match('#^@PHPUnit([\d]{2})Migration.*$#', $name, $matches)) { + return sprintf('Rules to improve tests code for PHPUnit %d.%d compatibility.', $matches[1][0], $matches[1][1]); + } + + if (0 !== Preg::match('#^@PHP([\d]{2})Migration.*$#', $name, $matches)) { + return sprintf('Rules to improve code for PHP %d.%d compatibility.', $matches[1][0], $matches[1][1]); + } + + throw new \RuntimeException(sprintf('Cannot generate description for "%s" "%s".', static::class, $name)); + } +} diff --git a/src/RuleSet/AbstractRuleSetDescription.php b/src/RuleSet/AbstractRuleSetDescription.php index 4556d0f19bd..d822ffccaf2 100644 --- a/src/RuleSet/AbstractRuleSetDescription.php +++ b/src/RuleSet/AbstractRuleSetDescription.php @@ -32,6 +32,6 @@ public function getName(): string public function isRisky(): bool { - return false !== strpos(static::class, 'Risky'); + return str_contains(static::class, 'Risky'); } } diff --git a/src/RuleSet/RuleSet.php b/src/RuleSet/RuleSet.php index b7c61974d7c..be66ba43529 100644 --- a/src/RuleSet/RuleSet.php +++ b/src/RuleSet/RuleSet.php @@ -20,7 +20,6 @@ * Set of rules to be used by fixer. * * @author Dariusz Rumiński - * @author SpacePossum * * @internal */ @@ -95,10 +94,8 @@ public function getRules(): array /** * Resolve input set into group of rules. - * - * @return $this */ - private function resolveSet(array $rules): self + private function resolveSet(array $rules): void { $resolvedRules = []; @@ -120,8 +117,6 @@ private function resolveSet(array $rules): self $resolvedRules = array_filter($resolvedRules); $this->rules = $resolvedRules; - - return $this; } /** diff --git a/src/RuleSet/RuleSetDescriptionInterface.php b/src/RuleSet/RuleSetDescriptionInterface.php index 9fa6e91e8f1..1d4555c8617 100644 --- a/src/RuleSet/RuleSetDescriptionInterface.php +++ b/src/RuleSet/RuleSetDescriptionInterface.php @@ -15,8 +15,6 @@ namespace PhpCsFixer\RuleSet; /** - * @author SpacePossum - * * @internal */ interface RuleSetDescriptionInterface diff --git a/src/RuleSet/RuleSets.php b/src/RuleSet/RuleSets.php index 0d07716fe13..833a386189f 100644 --- a/src/RuleSet/RuleSets.php +++ b/src/RuleSet/RuleSets.php @@ -19,8 +19,6 @@ /** * Set of rule sets to be used by fixer. * - * @author SpacePossum - * * @internal */ final class RuleSets diff --git a/src/RuleSet/Sets/PHP54MigrationSet.php b/src/RuleSet/Sets/PHP54MigrationSet.php index 7986c7471b4..bb877922220 100644 --- a/src/RuleSet/Sets/PHP54MigrationSet.php +++ b/src/RuleSet/Sets/PHP54MigrationSet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP54MigrationSet extends AbstractRuleSetDescription +final class PHP54MigrationSet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -27,9 +27,4 @@ public function getRules(): array 'array_syntax' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 5.4 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP56MigrationRiskySet.php b/src/RuleSet/Sets/PHP56MigrationRiskySet.php index 0b8127b6d9b..848b3501ebd 100644 --- a/src/RuleSet/Sets/PHP56MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHP56MigrationRiskySet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP56MigrationRiskySet extends AbstractRuleSetDescription +final class PHP56MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -27,9 +27,4 @@ public function getRules(): array 'pow_to_exponentiation' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 5.6 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP70MigrationRiskySet.php b/src/RuleSet/Sets/PHP70MigrationRiskySet.php index 9a1f88ec332..a7fcb21160c 100644 --- a/src/RuleSet/Sets/PHP70MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHP70MigrationRiskySet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP70MigrationRiskySet extends AbstractRuleSetDescription +final class PHP70MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -36,9 +36,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 7.0 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP70MigrationSet.php b/src/RuleSet/Sets/PHP70MigrationSet.php index 0775376700d..62b0ad99176 100644 --- a/src/RuleSet/Sets/PHP70MigrationSet.php +++ b/src/RuleSet/Sets/PHP70MigrationSet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP70MigrationSet extends AbstractRuleSetDescription +final class PHP70MigrationSet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -28,9 +28,4 @@ public function getRules(): array 'ternary_to_null_coalescing' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 7.0 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP71MigrationRiskySet.php b/src/RuleSet/Sets/PHP71MigrationRiskySet.php index 632b203a4d9..5a57f26246b 100644 --- a/src/RuleSet/Sets/PHP71MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHP71MigrationRiskySet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP71MigrationRiskySet extends AbstractRuleSetDescription +final class PHP71MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -28,9 +28,4 @@ public function getRules(): array 'void_return' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 7.1 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP71MigrationSet.php b/src/RuleSet/Sets/PHP71MigrationSet.php index 6f06df387ac..9379628dc65 100644 --- a/src/RuleSet/Sets/PHP71MigrationSet.php +++ b/src/RuleSet/Sets/PHP71MigrationSet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP71MigrationSet extends AbstractRuleSetDescription +final class PHP71MigrationSet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -29,9 +29,4 @@ public function getRules(): array 'visibility_required' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 7.1 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP73MigrationSet.php b/src/RuleSet/Sets/PHP73MigrationSet.php index 3b4ca5e99bb..aa0ed8fb255 100644 --- a/src/RuleSet/Sets/PHP73MigrationSet.php +++ b/src/RuleSet/Sets/PHP73MigrationSet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP73MigrationSet extends AbstractRuleSetDescription +final class PHP73MigrationSet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array 'trailing_comma_in_multiline' => ['after_heredoc' => true], ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 7.3 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP74MigrationRiskySet.php b/src/RuleSet/Sets/PHP74MigrationRiskySet.php index 078d577b57e..0a1bc17dd3a 100644 --- a/src/RuleSet/Sets/PHP74MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHP74MigrationRiskySet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP74MigrationRiskySet extends AbstractRuleSetDescription +final class PHP74MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -30,9 +30,4 @@ public function getRules(): array 'use_arrow_functions' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 7.4 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP74MigrationSet.php b/src/RuleSet/Sets/PHP74MigrationSet.php index e0d8af27b1e..09d372f4f3d 100644 --- a/src/RuleSet/Sets/PHP74MigrationSet.php +++ b/src/RuleSet/Sets/PHP74MigrationSet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP74MigrationSet extends AbstractRuleSetDescription +final class PHP74MigrationSet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -29,9 +29,4 @@ public function getRules(): array 'short_scalar_cast' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 7.4 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP80MigrationRiskySet.php b/src/RuleSet/Sets/PHP80MigrationRiskySet.php index ab244cd1047..e3daabf5284 100644 --- a/src/RuleSet/Sets/PHP80MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHP80MigrationRiskySet.php @@ -14,17 +14,18 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP80MigrationRiskySet extends AbstractRuleSetDescription +final class PHP80MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { return [ '@PHP74Migration:risky' => true, + 'modernize_strpos' => true, 'no_alias_functions' => [ 'sets' => [ '@all', @@ -35,9 +36,4 @@ public function getRules(): array 'no_unreachable_default_argument_value' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 8.0 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP80MigrationSet.php b/src/RuleSet/Sets/PHP80MigrationSet.php index 43f3a9fb79c..8b49a55c6b6 100644 --- a/src/RuleSet/Sets/PHP80MigrationSet.php +++ b/src/RuleSet/Sets/PHP80MigrationSet.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\RuleSet\Sets; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHP80MigrationSet extends AbstractRuleSetDescription +final class PHP80MigrationSet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -29,9 +29,4 @@ public function getRules(): array 'no_unset_cast' => true, ]; } - - public function getDescription(): string - { - return 'Rules to improve code for PHP 8.0 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHP81MigrationSet.php b/src/RuleSet/Sets/PHP81MigrationSet.php new file mode 100644 index 00000000000..eaa27e9d26e --- /dev/null +++ b/src/RuleSet/Sets/PHP81MigrationSet.php @@ -0,0 +1,31 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; + +/** + * @internal + */ +final class PHP81MigrationSet extends AbstractMigrationSetDescription +{ + public function getRules(): array + { + return [ + '@PHP80Migration' => true, + 'octal_notation' => true, + ]; + } +} diff --git a/src/RuleSet/Sets/PHPUnit30MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit30MigrationRiskySet.php index 753b3db166a..1cabfc04b92 100644 --- a/src/RuleSet/Sets/PHPUnit30MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit30MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit30MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit30MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -30,9 +30,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 3.0 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit32MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit32MigrationRiskySet.php index 265c5be9bb5..fb4cbfb5797 100644 --- a/src/RuleSet/Sets/PHPUnit32MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit32MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit32MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit32MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 3.2 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit35MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit35MigrationRiskySet.php index 3e5e45a52e4..6a52afac5af 100644 --- a/src/RuleSet/Sets/PHPUnit35MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit35MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit35MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit35MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 3.5 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit43MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit43MigrationRiskySet.php index 4945ef1cf95..13927970c9e 100644 --- a/src/RuleSet/Sets/PHPUnit43MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit43MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit43MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit43MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 4.3 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit48MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit48MigrationRiskySet.php index 6c84b021965..fcb1b57e6c5 100644 --- a/src/RuleSet/Sets/PHPUnit48MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit48MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit48MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit48MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 4.8 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit50MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit50MigrationRiskySet.php index 93de1083f54..38474584b17 100644 --- a/src/RuleSet/Sets/PHPUnit50MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit50MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit50MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit50MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 5.0 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit52MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit52MigrationRiskySet.php index a170c28ed39..d0f71ee3bf5 100644 --- a/src/RuleSet/Sets/PHPUnit52MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit52MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit52MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit52MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 5.2 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit54MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit54MigrationRiskySet.php index fa1ee5b0e20..b7c87922dcc 100644 --- a/src/RuleSet/Sets/PHPUnit54MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit54MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit54MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit54MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 5.4 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit55MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit55MigrationRiskySet.php index b895d2e49a0..e3c1647de4a 100644 --- a/src/RuleSet/Sets/PHPUnit55MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit55MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit55MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit55MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 5.5 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit56MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit56MigrationRiskySet.php index f58cff53cfb..a1038bf809c 100644 --- a/src/RuleSet/Sets/PHPUnit56MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit56MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit56MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit56MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -34,9 +34,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 5.6 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit57MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit57MigrationRiskySet.php index 5fcd183a79c..84076e119dd 100644 --- a/src/RuleSet/Sets/PHPUnit57MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit57MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit57MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit57MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 5.7 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php index 8894febd331..6bc7f711059 100644 --- a/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit60MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit60MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 6.0 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php index 43ff35a4c7e..a7efa2347aa 100644 --- a/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit75MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit75MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -31,9 +31,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 7.5 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php b/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php index cab174a070c..aaf5fc312ac 100644 --- a/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php +++ b/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php @@ -15,12 +15,12 @@ namespace PhpCsFixer\RuleSet\Sets; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; -use PhpCsFixer\RuleSet\AbstractRuleSetDescription; +use PhpCsFixer\RuleSet\AbstractMigrationSetDescription; /** * @internal */ -final class PHPUnit84MigrationRiskySet extends AbstractRuleSetDescription +final class PHPUnit84MigrationRiskySet extends AbstractMigrationSetDescription { public function getRules(): array { @@ -32,9 +32,4 @@ public function getRules(): array ], ]; } - - public function getDescription(): string - { - return 'Rules to improve tests code for PHPUnit 8.4 compatibility.'; - } } diff --git a/src/RuleSet/Sets/PSR12Set.php b/src/RuleSet/Sets/PSR12Set.php index bc6a8ea6e2b..9a8e4c1bf1e 100644 --- a/src/RuleSet/Sets/PSR12Set.php +++ b/src/RuleSet/Sets/PSR12Set.php @@ -29,6 +29,7 @@ public function getRules(): array 'braces' => [ 'allow_single_line_anonymous_class_with_empty_body' => true, ], + 'class_definition' => ['space_before_parenthesis' => true], // defined in PSR12 ¶8. Anonymous Classes 'compact_nullable_typehint' => true, 'declare_equal_normalize' => true, 'lowercase_cast' => true, diff --git a/src/RuleSet/Sets/PhpCsFixerSet.php b/src/RuleSet/Sets/PhpCsFixerSet.php index 51a38f4e9aa..6bd37f60bb0 100644 --- a/src/RuleSet/Sets/PhpCsFixerSet.php +++ b/src/RuleSet/Sets/PhpCsFixerSet.php @@ -75,7 +75,6 @@ public function getRules(): array 'switch', 'throw', 'use', - 'use_trait', ], ], 'no_null_property_initialization' => true, diff --git a/src/RuleSet/Sets/SymfonySet.php b/src/RuleSet/Sets/SymfonySet.php index 5a58b6fc6ec..ad7a652c09e 100644 --- a/src/RuleSet/Sets/SymfonySet.php +++ b/src/RuleSet/Sets/SymfonySet.php @@ -49,6 +49,8 @@ public function getRules(): array 'clean_namespace' => true, 'concat_space' => true, 'echo_tag_syntax' => true, + 'empty_loop_body' => ['style' => 'braces'], + 'empty_loop_condition' => true, 'fully_qualified_strict_types' => true, 'function_typehint_space' => true, 'general_phpdoc_tag_rename' => [ @@ -58,6 +60,7 @@ public function getRules(): array ], 'include' => true, 'increment_style' => true, + 'integer_literal_case' => true, 'lambda_not_used_import' => true, 'linebreak_after_opening_tag' => true, 'magic_constant_casing' => true, @@ -86,7 +89,6 @@ public function getRules(): array 'switch', 'throw', 'use', - 'use_trait', ], ], 'no_leading_namespace_whitespace' => true, @@ -170,6 +172,7 @@ public function getRules(): array 'switch_continue_to_break' => true, 'trailing_comma_in_multiline' => true, 'trim_array_spaces' => true, + 'types_spaces' => true, 'unary_operator_spaces' => true, 'whitespace_after_comma_in_array' => true, 'yoda_style' => true, diff --git a/src/Runner/Runner.php b/src/Runner/Runner.php index 337ee107b62..971a8a9fd50 100644 --- a/src/Runner/Runner.php +++ b/src/Runner/Runner.php @@ -193,10 +193,6 @@ private function fixFile(\SplFileInfo $file, LintingResultInterface $lintingResu $appliedFixers[] = $fixer->getName(); } } - } catch (\Exception $e) { - $this->processException($name, $e); - - return null; } catch (\ParseError $e) { $this->dispatchEvent( FixerFileProcessedEvent::NAME, @@ -220,7 +216,7 @@ private function fixFile(\SplFileInfo $file, LintingResultInterface $lintingResu } // We need to check if content was changed and then applied changes. - // But we can't simple check $appliedFixers, because one fixer may revert + // But we can't simply check $appliedFixers, because one fixer may revert // work of other and both of them will mark collection as changed. // Therefore we need to check if code hashes changed. if ($oldHash !== $newHash) { diff --git a/src/Tokenizer/Analyzer/Analysis/NamespaceUseAnalysis.php b/src/Tokenizer/Analyzer/Analysis/NamespaceUseAnalysis.php index adf57870a08..beb29d70edd 100644 --- a/src/Tokenizer/Analyzer/Analysis/NamespaceUseAnalysis.php +++ b/src/Tokenizer/Analyzer/Analysis/NamespaceUseAnalysis.php @@ -19,7 +19,7 @@ */ final class NamespaceUseAnalysis implements StartEndTokenAwareAnalysis { - public const TYPE_CLASS = 1; + public const TYPE_CLASS = 1; // "classy" could be class, interface or trait public const TYPE_FUNCTION = 2; public const TYPE_CONSTANT = 3; diff --git a/src/Tokenizer/Analyzer/Analysis/TypeAnalysis.php b/src/Tokenizer/Analyzer/Analysis/TypeAnalysis.php index 51b520ea35e..9c55d60b423 100644 --- a/src/Tokenizer/Analyzer/Analysis/TypeAnalysis.php +++ b/src/Tokenizer/Analyzer/Analysis/TypeAnalysis.php @@ -34,10 +34,11 @@ final class TypeAnalysis implements StartEndTokenAwareAnalysis 'array', 'bool', 'callable', + 'float', 'int', 'iterable', - 'float', 'mixed', + 'never', 'numeric', 'object', 'resource', @@ -71,7 +72,7 @@ public function __construct(string $name, int $startIndex, int $endIndex) $this->name = $name; $this->nullable = false; - if (0 === strpos($name, '?')) { + if (str_starts_with($name, '?')) { $this->name = substr($name, 1); $this->nullable = true; } diff --git a/src/Tokenizer/Analyzer/AttributeAnalyzer.php b/src/Tokenizer/Analyzer/AttributeAnalyzer.php new file mode 100644 index 00000000000..c67b76bc525 --- /dev/null +++ b/src/Tokenizer/Analyzer/AttributeAnalyzer.php @@ -0,0 +1,70 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class AttributeAnalyzer +{ + private const TOKEN_KINDS_NOT_ALLOWED_IN_ATTRIBUTE = [ + ';', + '{', + [T_ATTRIBUTE], + [T_FUNCTION], + [T_OPEN_TAG], + [T_OPEN_TAG_WITH_ECHO], + [T_PRIVATE], + [T_PROTECTED], + [T_PUBLIC], + [T_RETURN], + [T_VARIABLE], + [CT::T_ATTRIBUTE_CLOSE], + ]; + + /** + * Check if given index is an attribute declaration. + */ + public static function isAttribute(Tokens $tokens, int $index): bool + { + if ( + !\defined('T_ATTRIBUTE') // attributes not available, PHP version lower than 8.0 + || !$tokens[$index]->isGivenKind(T_STRING) // checked token is not a string + || !$tokens->isAnyTokenKindsFound([T_ATTRIBUTE]) // no attributes in the tokens collection + ) { + return false; + } + + $attributeStartIndex = $tokens->getPrevTokenOfKind($index, self::TOKEN_KINDS_NOT_ALLOWED_IN_ATTRIBUTE); + if (!$tokens[$attributeStartIndex]->isGivenKind(T_ATTRIBUTE)) { + return false; + } + + // now, between attribute start and the attribute candidate index cannot be more "(" than ")" + $count = 0; + for ($i = $attributeStartIndex + 1; $i < $index; ++$i) { + if ($tokens[$i]->equals('(')) { + ++$count; + } elseif ($tokens[$i]->equals(')')) { + --$count; + } + } + + return 0 === $count; + } +} diff --git a/src/Tokenizer/Analyzer/ClassyAnalyzer.php b/src/Tokenizer/Analyzer/ClassyAnalyzer.php index 49d6e3a7d3d..1edb2c70a4a 100644 --- a/src/Tokenizer/Analyzer/ClassyAnalyzer.php +++ b/src/Tokenizer/Analyzer/ClassyAnalyzer.php @@ -30,7 +30,7 @@ public function isClassyInvocation(Tokens $tokens, int $index): bool throw new \LogicException(sprintf('No T_STRING at given index %d, got "%s".', $index, $tokens[$index]->getName())); } - if (\in_array(strtolower($token->getContent()), ['bool', 'float', 'int', 'iterable', 'object', 'parent', 'self', 'string', 'void', 'null', 'false'], true)) { + if (\in_array(strtolower($token->getContent()), ['bool', 'float', 'int', 'iterable', 'object', 'parent', 'self', 'string', 'void', 'null', 'false', 'never'], true)) { return false; } @@ -57,6 +57,10 @@ public function isClassyInvocation(Tokens $tokens, int $index): bool return true; } + if (AttributeAnalyzer::isAttribute($tokens, $index)) { + return true; + } + // `Foo & $bar` could be: // - function reference parameter: function baz(Foo & $bar) {} // - bit operator: $x = Foo & $bar; diff --git a/src/Tokenizer/Analyzer/CommentsAnalyzer.php b/src/Tokenizer/Analyzer/CommentsAnalyzer.php index 9ca60e972a5..2726086f72b 100644 --- a/src/Tokenizer/Analyzer/CommentsAnalyzer.php +++ b/src/Tokenizer/Analyzer/CommentsAnalyzer.php @@ -21,7 +21,6 @@ /** * @author Kuba Werłos - * @author SpacePossum * * @internal */ @@ -157,22 +156,30 @@ public function getCommentBlockIndices(Tokens $tokens, int $index): ?array */ private function isStructuralElement(Token $token): bool { - static $skip = [ - T_PRIVATE, - T_PROTECTED, - T_PUBLIC, - T_VAR, - T_FUNCTION, - T_ABSTRACT, - T_CONST, - T_NAMESPACE, - T_REQUIRE, - T_REQUIRE_ONCE, - T_INCLUDE, - T_INCLUDE_ONCE, - T_FINAL, - T_STATIC, - ]; + static $skip; + + if (null === $skip) { + $skip = [ + T_PRIVATE, + T_PROTECTED, + T_PUBLIC, + T_VAR, + T_FUNCTION, + T_ABSTRACT, + T_CONST, + T_NAMESPACE, + T_REQUIRE, + T_REQUIRE_ONCE, + T_INCLUDE, + T_INCLUDE_ONCE, + T_FINAL, + T_STATIC, + ]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $skip[] = T_READONLY; + } + } return $token->isClassy() || $token->isGivenKind($skip); } @@ -206,7 +213,7 @@ private function isValidControl(Tokens $tokens, Token $docsToken, int $controlIn if ( $token->isGivenKind(T_VARIABLE) - && false !== strpos($docsContent, $token->getContent()) + && str_contains($docsContent, $token->getContent()) ) { return true; } @@ -245,7 +252,7 @@ private function isValidLanguageConstruct(Tokens $tokens, Token $docsToken, int for ($index = $languageConstructIndex + 1; $index < $endIndex; ++$index) { $token = $tokens[$index]; - if ($token->isGivenKind(T_VARIABLE) && false !== strpos($docsContent, $token->getContent())) { + if ($token->isGivenKind(T_VARIABLE) && str_contains($docsContent, $token->getContent())) { return true; } } diff --git a/src/Tokenizer/Analyzer/FunctionsAnalyzer.php b/src/Tokenizer/Analyzer/FunctionsAnalyzer.php index d10b02d0076..5edfab27cd4 100644 --- a/src/Tokenizer/Analyzer/FunctionsAnalyzer.php +++ b/src/Tokenizer/Analyzer/FunctionsAnalyzer.php @@ -69,6 +69,10 @@ public function isGlobalFunctionCall(Tokens $tokens, int $index): bool return true; } + if ($tokens[$tokens->getNextMeaningfulToken($nextIndex)]->isGivenKind(CT::T_FIRST_CLASS_CALLABLE)) { + return false; + } + if ($tokens->isChanged() || $tokens->getCodeHash() !== $this->functionsAnalysis['tokens']) { $this->buildFunctionsAnalysis($tokens); } @@ -125,15 +129,19 @@ public function isGlobalFunctionCall(Tokens $tokens, int $index): bool return $functionUse->getShortName() === ltrim($functionUse->getFullName(), '\\'); } + if (AttributeAnalyzer::isAttribute($tokens, $index)) { + return false; + } + return true; } /** * @return ArgumentAnalysis[] */ - public function getFunctionArguments(Tokens $tokens, int $methodIndex): array + public function getFunctionArguments(Tokens $tokens, int $functionIndex): array { - $argumentsStart = $tokens->getNextTokenOfKind($methodIndex, ['(']); + $argumentsStart = $tokens->getNextTokenOfKind($functionIndex, ['(']); $argumentsEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $argumentsStart); $argumentAnalyzer = new ArgumentsAnalyzer(); $arguments = []; diff --git a/src/Tokenizer/Analyzer/GotoLabelAnalyzer.php b/src/Tokenizer/Analyzer/GotoLabelAnalyzer.php index fb851f8dcb5..15d5b0660f8 100644 --- a/src/Tokenizer/Analyzer/GotoLabelAnalyzer.php +++ b/src/Tokenizer/Analyzer/GotoLabelAnalyzer.php @@ -35,6 +35,6 @@ public function belongsToGoToLabel(Tokens $tokens, int $index): bool $prevMeaningfulTokenIndex = $tokens->getPrevMeaningfulToken($prevMeaningfulTokenIndex); - return $tokens[$prevMeaningfulTokenIndex]->equalsAny([';', '{', '}', [T_OPEN_TAG]]); + return $tokens[$prevMeaningfulTokenIndex]->equalsAny([':', ';', '{', '}', [T_OPEN_TAG]]); } } diff --git a/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php b/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php index fde4c34d31a..e31985668fa 100644 --- a/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php +++ b/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php @@ -62,7 +62,8 @@ private function getDeclarations(Tokens $tokens, array $useIndexes): array foreach ($useIndexes as $index) { $endIndex = $tokens->getNextTokenOfKind($index, [';', [T_CLOSE_TAG]]); $analysis = $this->parseDeclaration($tokens, $index, $endIndex); - if ($analysis) { + + if (null !== $analysis) { $uses[] = $analysis; } } diff --git a/src/Tokenizer/Analyzer/NamespacesAnalyzer.php b/src/Tokenizer/Analyzer/NamespacesAnalyzer.php index c8bd2fe2ed8..e5e3f572ace 100644 --- a/src/Tokenizer/Analyzer/NamespacesAnalyzer.php +++ b/src/Tokenizer/Analyzer/NamespacesAnalyzer.php @@ -74,7 +74,7 @@ public function getDeclarations(Tokens $tokens): array public function getNamespaceAt(Tokens $tokens, int $index): NamespaceAnalysis { if (!$tokens->offsetExists($index)) { - throw new \InvalidArgumentException("Token index {$index} does not exist."); + throw new \InvalidArgumentException(sprintf('Token index %d does not exist.', $index)); } foreach ($this->getDeclarations($tokens) as $namespace) { @@ -83,6 +83,6 @@ public function getNamespaceAt(Tokens $tokens, int $index): NamespaceAnalysis } } - throw new \LogicException("Unable to get the namespace at index {$index}."); + throw new \LogicException(sprintf('Unable to get the namespace at index %d.', $index)); } } diff --git a/src/Tokenizer/Analyzer/WhitespacesAnalyzer.php b/src/Tokenizer/Analyzer/WhitespacesAnalyzer.php index 7b1d596368d..0845ce40336 100644 --- a/src/Tokenizer/Analyzer/WhitespacesAnalyzer.php +++ b/src/Tokenizer/Analyzer/WhitespacesAnalyzer.php @@ -32,7 +32,7 @@ public static function detectIndent(Tokens $tokens, int $index): string $whitespaceToken = $tokens[$whitespaceIndex]; - if (false !== strpos($whitespaceToken->getContent(), "\n")) { + if (str_contains($whitespaceToken->getContent(), "\n")) { break; } diff --git a/src/Tokenizer/CT.php b/src/Tokenizer/CT.php index 59fea01f542..c2879569322 100644 --- a/src/Tokenizer/CT.php +++ b/src/Tokenizer/CT.php @@ -52,6 +52,7 @@ final class CT public const T_ATTRIBUTE_CLOSE = 10031; public const T_NAMED_ARGUMENT_NAME = 10032; public const T_NAMED_ARGUMENT_COLON = 10033; + public const T_FIRST_CLASS_CALLABLE = 10034; private function __construct() { diff --git a/src/Tokenizer/Resolver/TypeShortNameResolver.php b/src/Tokenizer/Resolver/TypeShortNameResolver.php index 0e6cc86f14b..d07a0d5503c 100644 --- a/src/Tokenizer/Resolver/TypeShortNameResolver.php +++ b/src/Tokenizer/Resolver/TypeShortNameResolver.php @@ -71,7 +71,7 @@ public function resolve(Tokens $tokens, string $typeName): string */ private function getNamespacesFromTokens(Tokens $tokens): array { - return array_map(static function (NamespaceAnalysis $info) { + return array_map(static function (NamespaceAnalysis $info): string { return $info->getFullName(); }, (new NamespacesAnalyzer())->getDeclarations($tokens)); } diff --git a/src/Tokenizer/Token.php b/src/Tokenizer/Token.php index c178d7d2255..e1099825a9e 100644 --- a/src/Tokenizer/Token.php +++ b/src/Tokenizer/Token.php @@ -202,7 +202,7 @@ public function equalsAny(array $others, bool $caseSensitive = true): bool } /** - * A helper method used to find out whether or not a certain input token has to be case-sensitively matched. + * A helper method used to find out whether a certain input token has to be case-sensitively matched. * * @param array|bool $caseSensitive global case sensitiveness or an array of booleans, whose keys should match * the ones used in $others. If any is missing, the default case-sensitive @@ -212,7 +212,7 @@ public function equalsAny(array $others, bool $caseSensitive = true): bool public static function isKeyCaseSensitive($caseSensitive, int $key): bool { if (\is_array($caseSensitive)) { - return isset($caseSensitive[$key]) ? $caseSensitive[$key] : true; + return $caseSensitive[$key] ?? true; } return $caseSensitive; @@ -306,7 +306,7 @@ public static function getKeywords(): array 'T_INTERFACE', 'T_ISSET', 'T_LIST', 'T_LOGICAL_AND', 'T_LOGICAL_OR', 'T_LOGICAL_XOR', 'T_NAMESPACE', 'T_MATCH', 'T_NEW', 'T_PRINT', 'T_PRIVATE', 'T_PROTECTED', 'T_PUBLIC', 'T_REQUIRE', 'T_REQUIRE_ONCE', 'T_RETURN', 'T_STATIC', 'T_SWITCH', 'T_THROW', 'T_TRAIT', 'T_TRY', - 'T_UNSET', 'T_USE', 'T_VAR', 'T_WHILE', 'T_YIELD', 'T_YIELD_FROM', + 'T_UNSET', 'T_USE', 'T_VAR', 'T_WHILE', 'T_YIELD', 'T_YIELD_FROM', 'T_READONLY', 'T_ENUM', ]) + [ CT::T_ARRAY_TYPEHINT => CT::T_ARRAY_TYPEHINT, CT::T_CLASS_CONSTANT => CT::T_CLASS_CONSTANT, diff --git a/src/Tokenizer/Tokens.php b/src/Tokenizer/Tokens.php index 2873ded078e..5c56efe33ed 100644 --- a/src/Tokenizer/Tokens.php +++ b/src/Tokenizer/Tokens.php @@ -365,7 +365,7 @@ public function ensureWhitespaceAtIndex(int $index, int $indexOffset, string $wh $token = $tokens[$index]; if (1 === $indexOffset && $token->isGivenKind(T_OPEN_TAG)) { - if (0 === strpos($whitespace, "\r\n")) { + if (str_starts_with($whitespace, "\r\n")) { $tokens[$index] = new Token([T_OPEN_TAG, rtrim($token->getContent())."\r\n"]); return \strlen($whitespace) > 2 // can be removed on PHP 7; https://php.net/manual/en/function.substr.php @@ -453,7 +453,7 @@ public function findGivenKind($possibleKind, int $start = 0, ?int $end = null): $elements[$kind] = []; } - $possibleKinds = array_filter($possibleKinds, function ($kind) { + $possibleKinds = array_filter($possibleKinds, function ($kind): bool { return $this->isTokenKindFound($kind); }); @@ -587,7 +587,7 @@ public function getPrevTokenOfKind(int $index, array $tokens = [], bool $caseSen */ public function getTokenOfKindSibling(int $index, int $direction, array $tokens = [], bool $caseSensitive = true): ?int { - $tokens = array_filter($tokens, function ($token) { + $tokens = array_filter($tokens, function ($token): bool { return $this->isTokenKindFound($this->extractTokenKind($token)); }); @@ -620,7 +620,7 @@ public function getTokenNotOfKindSibling(int $index, int $direction, array $toke return $this->getTokenNotOfKind( $index, $direction, - function (int $a) use ($tokens) { + function (int $a) use ($tokens): bool { return $this[$a]->equalsAny($tokens); } ); @@ -638,7 +638,7 @@ public function getTokenNotOfKindsSibling(int $index, int $direction, array $kin return $this->getTokenNotOfKind( $index, $direction, - function (int $index) use ($kinds) { + function (int $index) use ($kinds): bool { return $this[$index]->isGivenKind($kinds); } ); @@ -705,7 +705,7 @@ public function getPrevMeaningfulToken(int $index): ?int * * @param array $sequence an array of tokens (kinds) (same format used by getNextTokenOfKind) * @param int $start start index, defaulting to the start of the file - * @param int $end end index, defaulting to the end of the file + * @param null|int $end end index, defaulting to the end of the file * @param array|bool $caseSensitive global case sensitiveness or an array of booleans, whose keys should match * the ones used in $others. If any is missing, the default case-sensitive * comparison is used @@ -827,7 +827,7 @@ public function insertAt(int $index, $items): void * like edge case example of 3.7h vs 4s (https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues/3996#issuecomment-455617637), * yet at same time changing a logic of fixers in not-always easy way. * - * To be discuss: + * To be discussed: * - should we always aim to use this method? * - should we deprecate `insertAt` method ? * @@ -941,7 +941,7 @@ public function overrideRange(int $indexStart, int $indexEnd, iterable $items): $this[$indexStart + $itemIndex] = $item; } - // If we want to add less tokens than passed range contains then clear + // If we want to add fewer tokens than passed range contains then clear // not needed tokens. if ($itemsCount < $indexToChange) { $this->clearRange($indexStart + $itemsCount, $indexEnd); @@ -1062,7 +1062,7 @@ public function isTokenKindFound($tokenKind): bool */ public function countTokenKind($tokenKind): int { - return isset($this->foundTokenKinds[$tokenKind]) ? $this->foundTokenKinds[$tokenKind] : 0; + return $this->foundTokenKinds[$tokenKind] ?? 0; } /** @@ -1103,7 +1103,7 @@ public function isMonolithicPhp(): bool public function isPartialCodeMultiline(int $start, int $end): bool { for ($i = $start; $i <= $end; ++$i) { - if (false !== strpos($this[$i]->getContent(), "\n")) { + if (str_contains($this[$i]->getContent(), "\n")) { return true; } } @@ -1167,7 +1167,7 @@ private function removeWhitespaceSafely(int $index, int $direction, ?string $whi // if the token candidate to remove is preceded by single line comment we do not consider the new line after this comment as part of T_WHITESPACE if (isset($this[$whitespaceIndex - 1]) && $this[$whitespaceIndex - 1]->isComment() && '/*' !== substr($this[$whitespaceIndex - 1]->getContent(), 0, 2)) { - list($emptyString, $newContent, $whitespacesToCheck) = Preg::split('/^(\R)/', $this[$whitespaceIndex]->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + [$emptyString, $newContent, $whitespacesToCheck] = Preg::split('/^(\R)/', $this[$whitespaceIndex]->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); if ('' === $whitespacesToCheck) { return; @@ -1217,7 +1217,7 @@ private function findOppositeBlockEdge(int $type, int $searchIndex, bool $findEn $indexOffset = 1; if (!$findEnd) { - list($startEdge, $endEdge) = [$endEdge, $startEdge]; + [$startEdge, $endEdge] = [$endEdge, $startEdge]; $indexOffset = -1; $endIndex = 0; } @@ -1243,8 +1243,6 @@ private function findOppositeBlockEdge(int $type, int $searchIndex, bool $findEn if (0 === $blockLevel) { break; } - - continue; } } diff --git a/src/Tokenizer/TokensAnalyzer.php b/src/Tokenizer/TokensAnalyzer.php index 9ab225a65a0..8a58f7d8881 100644 --- a/src/Tokenizer/TokensAnalyzer.php +++ b/src/Tokenizer/TokensAnalyzer.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tokenizer; +use PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\GotoLabelAnalyzer; /** @@ -23,7 +24,6 @@ * * @author Dariusz Rumiński * @author Gregor Harlan - * @author SpacePossum * * @internal */ @@ -57,7 +57,7 @@ public function getClassyElements(): array for ($index = 1, $count = \count($this->tokens) - 2; $index < $count; ++$index) { if ($this->tokens[$index]->isClassy()) { - list($index, $newElements) = $this->findClassyElements($index, $index); + [$index, $newElements] = $this->findClassyElements($index, $index); $elements += $newElements; } } @@ -132,7 +132,7 @@ public function isArrayMultiLine(int $index): bool $tokens = $this->tokens; - // Skip only when its an array, for short arrays we need the brace for correct + // Skip only when it's an array, for short arrays we need the brace for correct // level counting if ($tokens[$index]->isGivenKind(T_ARRAY)) { $index = $tokens->getNextMeaningfulToken($index); @@ -164,7 +164,7 @@ public function isBlockMultiline(Tokens $tokens, int $index): bool if ( $token->isWhitespace() && !$tokens[$index - 1]->isGivenKind(T_END_HEREDOC) - && false !== strpos($token->getContent(), "\n") + && str_contains($token->getContent(), "\n") ) { return true; } @@ -265,7 +265,14 @@ public function isAnonymousClass(int $index): bool return false; } - return $this->tokens[$this->tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NEW); + $index = $this->tokens->getPrevMeaningfulToken($index); + + while ($this->tokens[$index]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { + $index = $this->tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $index); + $index = $this->tokens->getPrevMeaningfulToken($index); + } + + return $this->tokens[$index]->isGivenKind(T_NEW); } /** @@ -312,7 +319,7 @@ public function isConstantInvocation(int $index): bool $prevIndex = $this->tokens->getPrevMeaningfulToken($index); - if ($this->tokens[$prevIndex]->isGivenKind([T_AS, T_CLASS, T_CONST, T_DOUBLE_COLON, T_FUNCTION, T_GOTO, CT::T_GROUP_IMPORT_BRACE_OPEN, T_INTERFACE, T_TRAIT, CT::T_TYPE_COLON]) || $this->tokens[$prevIndex]->isObjectOperator()) { + if ($this->tokens[$prevIndex]->isGivenKind([T_AS, T_CLASS, T_CONST, T_DOUBLE_COLON, T_FUNCTION, T_GOTO, CT::T_GROUP_IMPORT_BRACE_OPEN, T_INTERFACE, T_TRAIT, CT::T_TYPE_COLON, CT::T_TYPE_ALTERNATION]) || $this->tokens[$prevIndex]->isObjectOperator()) { return false; } @@ -357,10 +364,7 @@ public function isConstantInvocation(int $index): bool } // check for attribute: `#[Foo]` - if ( - \defined('T_ATTRIBUTE') // @TODO: drop condition when PHP 8.0+ is required - && $this->tokens[$prevIndex]->isGivenKind(T_ATTRIBUTE) - ) { + if (AttributeAnalyzer::isAttribute($this->tokens, $index)) { return false; } @@ -391,7 +395,7 @@ public function isConstantInvocation(int $index): bool } /** - * Checks if there is an unary successor operator under given index. + * Checks if there is a unary successor operator under given index. */ public function isUnarySuccessorOperator(int $index): bool { @@ -417,7 +421,7 @@ public function isUnarySuccessorOperator(int $index): bool } /** - * Checks if there is an unary predecessor operator under given index. + * Checks if there is a unary predecessor operator under given index. */ public function isUnaryPredecessorOperator(int $index): bool { @@ -672,7 +676,7 @@ private function findClassyElements(int $classIndex, int $index): array --$nestedBracesLevel; if (0 === $nestedBracesLevel) { - list($index, $newElements) = $this->findClassyElements($nestedClassIndex, $index); + [$index, $newElements] = $this->findClassyElements($nestedClassIndex, $index); $elements += $newElements; break; @@ -682,12 +686,12 @@ private function findClassyElements(int $classIndex, int $index): array } if ($token->isClassy()) { // anonymous class in class - list($index, $newElements) = $this->findClassyElements($index, $index); + [$index, $newElements] = $this->findClassyElements($index, $index); $elements += $newElements; } } } else { - list($index, $newElements) = $this->findClassyElements($nestedClassIndex, $nestedClassIndex); + [$index, $newElements] = $this->findClassyElements($nestedClassIndex, $nestedClassIndex); $elements += $newElements; } @@ -728,9 +732,9 @@ private function findClassyElements(int $classIndex, int $index): array if (0 === $bracesLevel && $token->isGivenKind(T_VARIABLE)) { $elements[$index] = [ + 'classIndex' => $classIndex, 'token' => $token, 'type' => 'property', - 'classIndex' => $classIndex, ]; continue; @@ -738,21 +742,21 @@ private function findClassyElements(int $classIndex, int $index): array if ($token->isGivenKind(T_FUNCTION)) { $elements[$index] = [ + 'classIndex' => $classIndex, 'token' => $token, 'type' => 'method', - 'classIndex' => $classIndex, ]; } elseif ($token->isGivenKind(T_CONST)) { $elements[$index] = [ + 'classIndex' => $classIndex, 'token' => $token, 'type' => 'const', - 'classIndex' => $classIndex, ]; } elseif ($token->isGivenKind(CT::T_USE_TRAIT)) { $elements[$index] = [ + 'classIndex' => $classIndex, 'token' => $token, 'type' => 'trait_import', - 'classIndex' => $classIndex, ]; } } diff --git a/src/Tokenizer/Transformer/CurlyBraceTransformer.php b/src/Tokenizer/Transformer/CurlyBraceTransformer.php index e8122f39692..14333dc0af0 100644 --- a/src/Tokenizer/Transformer/CurlyBraceTransformer.php +++ b/src/Tokenizer/Transformer/CurlyBraceTransformer.php @@ -54,10 +54,7 @@ public function process(Tokens $tokens, Token $token, int $index): void $this->transformIntoDynamicPropBraces($tokens, $token, $index); $this->transformIntoDynamicVarBraces($tokens, $token, $index); $this->transformIntoCurlyIndexBraces($tokens, $token, $index); - - if (\PHP_VERSION_ID >= 70000) { - $this->transformIntoGroupUseBraces($tokens, $token, $index); - } + $this->transformIntoGroupUseBraces($tokens, $token, $index); } /** @@ -91,25 +88,18 @@ private function transformIntoCurlyCloseBrace(Tokens $tokens, Token $token, int } $level = 1; - $nestIndex = $index; - while (0 < $level) { - ++$nestIndex; + do { + ++$index; - // we count all kind of { - if ($tokens[$nestIndex]->equals('{')) { + if ($tokens[$index]->equals('{') || $tokens[$index]->isGivenKind(T_CURLY_OPEN)) { // we count all kind of { ++$level; - - continue; - } - - // we count all kind of } - if ($tokens[$nestIndex]->equals('}')) { + } elseif ($tokens[$index]->equals('}')) { // we count all kind of } --$level; } - } + } while (0 < $level); - $tokens[$nestIndex] = new Token([CT::T_CURLY_CLOSE, '}']); + $tokens[$index] = new Token([CT::T_CURLY_CLOSE, '}']); } private function transformIntoDollarCloseBrace(Tokens $tokens, Token $token, int $index): void @@ -131,7 +121,7 @@ private function transformIntoDynamicPropBraces(Tokens $tokens, Token $token, in } $openIndex = $index + 1; - $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openIndex); + $closeIndex = $this->naivelyFindCurlyBlockEnd($tokens, $openIndex); $tokens[$openIndex] = new Token([CT::T_DYNAMIC_PROP_BRACE_OPEN, '{']); $tokens[$closeIndex] = new Token([CT::T_DYNAMIC_PROP_BRACE_CLOSE, '}']); @@ -155,7 +145,7 @@ private function transformIntoDynamicVarBraces(Tokens $tokens, Token $token, int return; } - $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openIndex); + $closeIndex = $this->naivelyFindCurlyBlockEnd($tokens, $openIndex); $tokens[$openIndex] = new Token([CT::T_DYNAMIC_VAR_BRACE_OPEN, '{']); $tokens[$closeIndex] = new Token([CT::T_DYNAMIC_VAR_BRACE_CLOSE, '}']); @@ -195,7 +185,7 @@ private function transformIntoCurlyIndexBraces(Tokens $tokens, Token $token, int return; } - $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + $closeIndex = $this->naivelyFindCurlyBlockEnd($tokens, $index); $tokens[$index] = new Token([CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN, '{']); $tokens[$closeIndex] = new Token([CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE, '}']); @@ -213,9 +203,51 @@ private function transformIntoGroupUseBraces(Tokens $tokens, Token $token, int $ return; } - $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + $closeIndex = $this->naivelyFindCurlyBlockEnd($tokens, $index); $tokens[$index] = new Token([CT::T_GROUP_IMPORT_BRACE_OPEN, '{']); $tokens[$closeIndex] = new Token([CT::T_GROUP_IMPORT_BRACE_CLOSE, '}']); } + + /** + * We do not want to rely on `$tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index)` here, + * as it relies on block types that are assuming that `}` tokens are already transformed to Custom Tokens that are allowing to distinguish different block types. + * As we are just about to transform `{` and `}` into Custom Tokens by this transformer, thus we need to compare those tokens manually by content without using `Tokens::findBlockEnd`. + */ + private function naivelyFindCurlyBlockEnd(Tokens $tokens, int $startIndex): int + { + if (!$tokens->offsetExists($startIndex)) { + throw new \OutOfBoundsException(sprintf('Unavailable index: "%s".', $startIndex)); + } + + if ('{' !== $tokens[$startIndex]->getContent()) { + throw new \InvalidArgumentException(sprintf('Wrong start index: "%s".', $startIndex)); + } + + $blockLevel = 1; + $endIndex = $tokens->count() - 1; + for ($index = $startIndex + 1; $index !== $endIndex; ++$index) { + $token = $tokens[$index]; + + if ('{' === $token->getContent()) { + ++$blockLevel; + + continue; + } + + if ('}' === $token->getContent()) { + --$blockLevel; + + if (0 === $blockLevel) { + if (!$token->equals('}')) { + throw new \UnexpectedValueException(sprintf('Detected block end for index: "%s" was already transformed into other token type: "%s".', $startIndex, $token->getName())); + } + + return $index; + } + } + } + + throw new \UnexpectedValueException(sprintf('Missing block end for index: "%s".', $startIndex)); + } } diff --git a/src/Tokenizer/Transformer/FirstClassCallableTransformer.php b/src/Tokenizer/Transformer/FirstClassCallableTransformer.php new file mode 100644 index 00000000000..f96a3e6111d --- /dev/null +++ b/src/Tokenizer/Transformer/FirstClassCallableTransformer.php @@ -0,0 +1,58 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class FirstClassCallableTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId(): int + { + return 80100; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, int $index): void + { + if ( + $token->isGivenKind(T_ELLIPSIS) + && $tokens[$tokens->getPrevMeaningfulToken($index)]->equals('(') + && $tokens[$tokens->getNextMeaningfulToken($index)]->equals(')') + ) { + $tokens[$index] = new Token([CT::T_FIRST_CLASS_CALLABLE, '...']); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens(): array + { + return [ + CT::T_FIRST_CLASS_CALLABLE, + ]; + } +} diff --git a/src/Tokenizer/Transformer/NameQualifiedTransformer.php b/src/Tokenizer/Transformer/NameQualifiedTransformer.php index fc8e1dc0764..d84037730ec 100644 --- a/src/Tokenizer/Transformer/NameQualifiedTransformer.php +++ b/src/Tokenizer/Transformer/NameQualifiedTransformer.php @@ -21,8 +21,6 @@ /** * Transform NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED and T_NAME_RELATIVE into T_NAMESPACE T_NS_SEPARATOR T_STRING. * - * @author SpacePossum - * * @internal */ final class NameQualifiedTransformer extends AbstractTransformer diff --git a/src/Tokenizer/Transformer/NamedArgumentTransformer.php b/src/Tokenizer/Transformer/NamedArgumentTransformer.php index cddb29cf334..e72993f50ad 100644 --- a/src/Tokenizer/Transformer/NamedArgumentTransformer.php +++ b/src/Tokenizer/Transformer/NamedArgumentTransformer.php @@ -22,8 +22,6 @@ /** * Transform named argument tokens. * - * @author SpacePossum - * * @internal */ final class NamedArgumentTransformer extends AbstractTransformer diff --git a/src/Tokenizer/Transformer/NullableTypeTransformer.php b/src/Tokenizer/Transformer/NullableTypeTransformer.php index 0a7cc7ff90f..c8f17ecf72e 100644 --- a/src/Tokenizer/Transformer/NullableTypeTransformer.php +++ b/src/Tokenizer/Transformer/NullableTypeTransformer.php @@ -54,23 +54,32 @@ public function process(Tokens $tokens, Token $token, int $index): void return; } + static $types; + + if (null === $types) { + $types = [ + '(', + ',', + [CT::T_TYPE_COLON], + [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC], + [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED], + [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE], + [CT::T_ATTRIBUTE_CLOSE], + [T_PRIVATE], + [T_PROTECTED], + [T_PUBLIC], + [T_VAR], + [T_STATIC], + ]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $types[] = [T_READONLY]; + } + } + $prevIndex = $tokens->getPrevMeaningfulToken($index); - $prevToken = $tokens[$prevIndex]; - if ($prevToken->equalsAny([ - '(', - ',', - [CT::T_TYPE_COLON], - [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC], - [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED], - [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE], - [CT::T_ATTRIBUTE_CLOSE], - [T_PRIVATE], - [T_PROTECTED], - [T_PUBLIC], - [T_VAR], - [T_STATIC], - ])) { + if ($tokens[$prevIndex]->equalsAny($types)) { $tokens[$index] = new Token([CT::T_NULLABLE_TYPE, '?']); } } diff --git a/src/Tokenizer/Transformer/SquareBraceTransformer.php b/src/Tokenizer/Transformer/SquareBraceTransformer.php index 26982aee1ef..dfce9310a05 100644 --- a/src/Tokenizer/Transformer/SquareBraceTransformer.php +++ b/src/Tokenizer/Transformer/SquareBraceTransformer.php @@ -27,7 +27,6 @@ * - in `[$a, &$b, [$c]] = array(1, 2, array(3))` into CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN and CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE. * * @author Dariusz Rumiński - * @author SpacePossum * * @internal */ @@ -150,7 +149,7 @@ private function isShortArray(Tokens $tokens, int $index): bool private function isArrayDestructing(Tokens $tokens, int $index): bool { - if (\PHP_VERSION_ID < 70100 || !$tokens[$index]->equals('[')) { + if (!$tokens[$index]->equals('[')) { return false; } diff --git a/src/Tokenizer/Transformer/TypeAlternationTransformer.php b/src/Tokenizer/Transformer/TypeAlternationTransformer.php index a407c63178e..384960b70f1 100644 --- a/src/Tokenizer/Transformer/TypeAlternationTransformer.php +++ b/src/Tokenizer/Transformer/TypeAlternationTransformer.php @@ -55,7 +55,7 @@ public function process(Tokens $tokens, Token $token, int $index): void return; } - $prevIndex = $tokens->getTokenNotOfKindsSibling($index, -1, [T_NS_SEPARATOR, T_STRING, CT::T_ARRAY_TYPEHINT, T_WHITESPACE, T_COMMENT, T_DOC_COMMENT]); + $prevIndex = $tokens->getTokenNotOfKindsSibling($index, -1, [T_CALLABLE, T_NS_SEPARATOR, T_STRING, CT::T_ARRAY_TYPEHINT, T_WHITESPACE, T_COMMENT, T_DOC_COMMENT]); /** @var Token $prevToken */ $prevToken = $tokens[$prevIndex]; @@ -64,12 +64,19 @@ public function process(Tokens $tokens, Token $token, int $index): void CT::T_TYPE_COLON, // `:` is part of a function return type `foo(): X|Y` CT::T_TYPE_ALTERNATION, // `|` is part of a union (chain) `X|Y` T_STATIC, T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, // `var X|Y $a;`, `private X|Y $a` or `public static X|Y $a` + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, // promoted properties ])) { $this->replaceToken($tokens, $index); return; } + if (\defined('T_READONLY') && $prevToken->isGivenKind(T_READONLY)) { // @TODO: drop condition when PHP 8.1+ is required + $this->replaceToken($tokens, $index); + + return; + } + if (!$prevToken->equalsAny(['(', ','])) { return; } diff --git a/src/Tokenizer/Transformers.php b/src/Tokenizer/Transformers.php index f7cbc95d11e..ac6334783d2 100644 --- a/src/Tokenizer/Transformers.php +++ b/src/Tokenizer/Transformers.php @@ -40,7 +40,7 @@ private function __construct() { $this->registerBuiltInTransformers(); - usort($this->items, static function (TransformerInterface $a, TransformerInterface $b) { + usort($this->items, static function (TransformerInterface $a, TransformerInterface $b): int { return $b->getPriority() <=> $a->getPriority(); }); } diff --git a/src/ToolInfo.php b/src/ToolInfo.php index 3a675a71b90..f8e2aba388e 100644 --- a/src/ToolInfo.php +++ b/src/ToolInfo.php @@ -48,7 +48,7 @@ public function getComposerInstallationDetails(): array if (null === $this->composerInstallationDetails) { $composerInstalled = json_decode(file_get_contents($this->getComposerInstalledFile()), true); - $packages = isset($composerInstalled['packages']) ? $composerInstalled['packages'] : $composerInstalled; + $packages = $composerInstalled['packages'] ?? $composerInstalled; foreach ($packages as $package) { if (\in_array($package['name'], [self::COMPOSER_PACKAGE_NAME, self::COMPOSER_LEGACY_PACKAGE_NAME], true)) { @@ -86,7 +86,7 @@ public function getVersion(): string public function isInstalledAsPhar(): bool { - return 'phar://' === substr(__DIR__, 0, 7); + return str_starts_with(__DIR__, 'phar://'); } public function isInstalledByComposer(): bool diff --git a/src/Utils.php b/src/Utils.php index d601c6d61b8..805babc3f43 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -19,7 +19,7 @@ /** * @author Dariusz Rumiński - * @author Graham Campbell + * @author Graham Campbell * @author Odín del Río * * @internal @@ -79,7 +79,7 @@ public static function stableSort(array $elements, callable $getComparedValue, c $element = [$element, $index, $getComparedValue($element)]; }); - usort($elements, static function ($a, $b) use ($compareValues) { + usort($elements, static function ($a, $b) use ($compareValues): int { $comparison = $compareValues($a[2], $b[2]); if (0 !== $comparison) { @@ -107,10 +107,10 @@ public static function sortFixers(array $fixers): array // `usort(): Array was modified by the user comparison function` warning for mocked objects. return self::stableSort( $fixers, - static function (FixerInterface $fixer) { + static function (FixerInterface $fixer): int { return $fixer->getPriority(); }, - static function (int $a, int $b) { + static function (int $a, int $b): int { return $b <=> $a; } ); @@ -129,7 +129,7 @@ public static function naturalLanguageJoinWithBackticks(array $names): string throw new \InvalidArgumentException('Array of names cannot be empty.'); } - $names = array_map(static function (string $name) { + $names = array_map(static function (string $name): string { return sprintf('`%s`', $name); }, $names); diff --git a/src/WordMatcher.php b/src/WordMatcher.php index 61cb0a11407..5314b1e1c72 100644 --- a/src/WordMatcher.php +++ b/src/WordMatcher.php @@ -16,7 +16,6 @@ /** * @author Dariusz Rumiński - * @author SpacePossum * * @internal */ diff --git a/tests/AbstractDoctrineAnnotationFixerTestCase.php b/tests/AbstractDoctrineAnnotationFixerTestCase.php index 878a44546c3..197de2ad38a 100644 --- a/tests/AbstractDoctrineAnnotationFixerTestCase.php +++ b/tests/AbstractDoctrineAnnotationFixerTestCase.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** @@ -26,7 +27,7 @@ abstract class AbstractDoctrineAnnotationFixerTestCase extends AbstractFixerTest */ public function testConfigureWithInvalidConfiguration(array $configuration): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->fixer->configure($configuration); } diff --git a/tests/AbstractFunctionReferenceFixerTest.php b/tests/AbstractFunctionReferenceFixerTest.php index 2c84a2396a4..e7841336ad3 100644 --- a/tests/AbstractFunctionReferenceFixerTest.php +++ b/tests/AbstractFunctionReferenceFixerTest.php @@ -69,7 +69,7 @@ public function testAbstractFunctionReferenceFixer( static::assertFalse($tokens->isChanged()); } - public function provideAbstractFunctionReferenceFixerCases() + public function provideAbstractFunctionReferenceFixerCases(): array { return [ 'simple case I' => [ diff --git a/tests/AutoReview/CiConfigurationTest.php b/tests/AutoReview/CiConfigurationTest.php index ad01b08e3d9..9132228e7f9 100644 --- a/tests/AutoReview/CiConfigurationTest.php +++ b/tests/AutoReview/CiConfigurationTest.php @@ -81,7 +81,7 @@ public function testDeploymentJobsRunOnLatestStablePhpThatIsSupportedByTool(): v } } - private static function generateMinorVersionsRange(float $from, float $to) + private static function generateMinorVersionsRange(float $from, float $to): array { $range = []; @@ -135,13 +135,13 @@ private static function assertSupportedPhpVersionsAreCoveredByCiJobs(array $supp )); } - private function getAllPhpVersionsUsedByCiForDeployments() + private function getAllPhpVersionsUsedByCiForDeployments(): array { - $jobs = array_filter($this->getGitHubJobs(), function (array $job) { + $jobs = array_filter($this->getGitHubJobs(), static function (array $job): bool { return isset($job['execute-deployment']) && 'yes' === $job['execute-deployment']; }); - return array_map(function ($job) { + return array_map(static function ($job): string { return \is_string($job['php-version']) ? $job['php-version'] : sprintf('%.1f', $job['php-version']); }, $jobs); } @@ -151,7 +151,7 @@ private function getAllPhpVersionsUsedByCiForTests() return $this->getPhpVersionsUsedByGitHub(); } - private function convertPhpVerIdToNiceVer(string $verId) + private function convertPhpVerIdToNiceVer(string $verId): string { $matchResult = Preg::match('/^(?\d{1,2})(?\d{2})(?\d{2})$/', $verId, $capture); if (1 !== $matchResult) { @@ -161,7 +161,7 @@ private function convertPhpVerIdToNiceVer(string $verId) return sprintf('%d.%d', $capture['major'], $capture['minor']); } - private function getMaxPhpVersionFromEntryFile() + private function getMaxPhpVersionFromEntryFile(): string { $tokens = Tokens::fromCode(file_get_contents(__DIR__.'/../../php-cs-fixer')); $sequence = $tokens->findSequence([ @@ -179,7 +179,7 @@ private function getMaxPhpVersionFromEntryFile() return $this->convertPhpVerIdToNiceVer((string) ($phpVerId - 100)); } - private function getMinPhpVersionFromEntryFile() + private function getMinPhpVersionFromEntryFile(): string { $tokens = Tokens::fromCode(file_get_contents(__DIR__.'/../../php-cs-fixer')); $sequence = $tokens->findSequence([ @@ -208,7 +208,7 @@ private function getPhpVersionsUsedByGitHub() { $yaml = Yaml::parse(file_get_contents(__DIR__.'/../../.github/workflows/ci.yml')); - $phpVersions = isset($yaml['jobs']['tests']['strategy']['matrix']['php-version']) ? $yaml['jobs']['tests']['strategy']['matrix']['php-version'] : []; + $phpVersions = $yaml['jobs']['tests']['strategy']['matrix']['php-version'] ?? []; foreach ($yaml['jobs']['tests']['strategy']['matrix']['include'] as $job) { $phpVersions[] = $job['php-version']; diff --git a/tests/AutoReview/CommandTest.php b/tests/AutoReview/CommandTest.php index 8d0a5209bb5..d419bf3420f 100644 --- a/tests/AutoReview/CommandTest.php +++ b/tests/AutoReview/CommandTest.php @@ -34,20 +34,20 @@ final class CommandTest extends TestCase */ public function testCommandHasNameConst(Command $command): void { - static::assertNotNull($command->getDefaultName()); + static::assertNotNull($command::getDefaultName()); } - public function provideCommandHasNameConstCases() + public function provideCommandHasNameConstCases(): array { $application = new Application(); $commands = $application->all(); - $names = array_filter(array_keys($commands), static function (string $name) use ($commands) { + $names = array_filter(array_keys($commands), static function (string $name) use ($commands): bool { return // is not an alias !\in_array($name, $commands[$name]->getAliases(), true) // and is our command - && 0 === strpos(\get_class($commands[$name]), 'PhpCsFixer\\') + && str_starts_with(\get_class($commands[$name]), 'PhpCsFixer\\') ; }); diff --git a/tests/AutoReview/DescribeCommandTest.php b/tests/AutoReview/DescribeCommandTest.php index a520bbf5456..ebe700e58a2 100644 --- a/tests/AutoReview/DescribeCommandTest.php +++ b/tests/AutoReview/DescribeCommandTest.php @@ -48,17 +48,13 @@ public function testDescribeCommand(FixerFactory $factory, string $fixerName): v static::assertSame(0, $commandTester->getStatusCode()); } - public function provideDescribeCommandCases() + public function provideDescribeCommandCases(): \Generator { $factory = new FixerFactory(); $factory->registerBuiltInFixers(); - $cases = []; - foreach ($factory->getFixers() as $fixer) { - $cases[] = [$factory, $fixer->getName()]; + yield [$factory, $fixer->getName()]; } - - return $cases; } } diff --git a/tests/AutoReview/DocumentationTest.php b/tests/AutoReview/DocumentationTest.php index 7c86470cd90..ee4d071554a 100644 --- a/tests/AutoReview/DocumentationTest.php +++ b/tests/AutoReview/DocumentationTest.php @@ -67,7 +67,7 @@ public function testFixerDocumentationFileIsUpToDate(FixerInterface $fixer): voi |$ ) /x', - function (array $matches) use ($actual) { + static function (array $matches) use ($actual): string { $before = preg_quote($matches['before'], '/'); $after = preg_quote($matches['after'], '/'); @@ -85,15 +85,11 @@ function (array $matches) use ($actual) { static::assertSame($expected, $actual); } - public function provideFixerCases() + public function provideFixerCases(): \Generator { - $cases = []; - foreach ($this->getFixers() as $fixer) { - $cases[$fixer->getName()] = [$fixer]; + yield $fixer->getName() => [$fixer]; } - - return $cases; } public function testFixersDocumentationIndexFileIsUpToDate(): void @@ -183,7 +179,7 @@ private static function assertFileEqualsString(string $expectedString, string $a static::assertSame($expectedString, file_get_contents($actualFilePath), $message); } - private function getFixers() + private function getFixers(): array { $factory = new FixerFactory(); $factory->registerBuiltInFixers(); diff --git a/tests/AutoReview/FixerFactoryTest.php b/tests/AutoReview/FixerFactoryTest.php index 4bb400da649..21084181940 100644 --- a/tests/AutoReview/FixerFactoryTest.php +++ b/tests/AutoReview/FixerFactoryTest.php @@ -51,7 +51,7 @@ public function testFixersPriority(FixerInterface $first, FixerInterface $second static::assertLessThan($first->getPriority(), $second->getPriority(), sprintf('"%s" should have less priority than "%s"', \get_class($second), \get_class($first))); } - public function provideFixersPriorityCases() + public function provideFixersPriorityCases(): array { $factory = new FixerFactory(); $factory->registerBuiltInFixers(); @@ -78,6 +78,7 @@ public function provideFixersPriorityCases() [$fixers['braces'], $fixers['method_chaining_indentation']], [$fixers['class_attributes_separation'], $fixers['braces']], [$fixers['class_attributes_separation'], $fixers['indentation_type']], + [$fixers['class_attributes_separation'], $fixers['no_extra_blank_lines']], [$fixers['class_definition'], $fixers['braces']], [$fixers['class_keyword_remove'], $fixers['no_unused_imports']], [$fixers['combine_consecutive_issets'], $fixers['multiline_whitespace_before_semicolons']], @@ -101,6 +102,8 @@ public function provideFixersPriorityCases() [$fixers['empty_loop_body'], $fixers['braces']], [$fixers['empty_loop_body'], $fixers['no_extra_blank_lines']], [$fixers['empty_loop_body'], $fixers['no_trailing_whitespace']], + [$fixers['empty_loop_condition'], $fixers['no_extra_blank_lines']], + [$fixers['empty_loop_condition'], $fixers['no_trailing_whitespace']], [$fixers['escape_implicit_backslashes'], $fixers['heredoc_to_nowdoc']], [$fixers['escape_implicit_backslashes'], $fixers['single_quote']], [$fixers['explicit_string_variable'], $fixers['simple_to_complex_string_variable']], @@ -132,6 +135,13 @@ public function provideFixersPriorityCases() [$fixers['method_argument_space'], $fixers['array_indentation']], [$fixers['method_chaining_indentation'], $fixers['array_indentation']], [$fixers['method_chaining_indentation'], $fixers['method_argument_space']], + [$fixers['modernize_strpos'], $fixers['binary_operator_spaces']], + [$fixers['modernize_strpos'], $fixers['no_extra_blank_lines']], + [$fixers['modernize_strpos'], $fixers['no_spaces_inside_parenthesis']], + [$fixers['modernize_strpos'], $fixers['no_trailing_whitespace']], + [$fixers['modernize_strpos'], $fixers['not_operator_with_space']], + [$fixers['modernize_strpos'], $fixers['not_operator_with_successor_space']], + [$fixers['modernize_strpos'], $fixers['single_space_after_construct']], [$fixers['multiline_whitespace_before_semicolons'], $fixers['space_after_semicolon']], [$fixers['native_constant_invocation'], $fixers['global_namespace_import']], [$fixers['native_function_invocation'], $fixers['global_namespace_import']], @@ -254,6 +264,7 @@ public function provideFixersPriorityCases() [$fixers['pow_to_exponentiation'], $fixers['no_spaces_after_function_name']], [$fixers['pow_to_exponentiation'], $fixers['no_spaces_inside_parenthesis']], [$fixers['protected_to_private'], $fixers['ordered_class_elements']], + [$fixers['regular_callable_call'], $fixers['native_function_invocation']], [$fixers['return_assignment'], $fixers['blank_line_before_statement']], [$fixers['semicolon_after_instruction'], $fixers['simplified_if_return']], [$fixers['simplified_if_return'], $fixers['multiline_whitespace_before_semicolons']], @@ -285,7 +296,7 @@ public function provideFixersPriorityCases() ]; } - public function provideFixersPrioritySpecialPhpdocCases() + public function provideFixersPrioritySpecialPhpdocCases(): array { $factory = new FixerFactory(); $factory->registerBuiltInFixers(); @@ -315,8 +326,8 @@ public function provideFixersPrioritySpecialPhpdocCases() $docFixerNames = array_filter( array_keys($fixers), - static function (string $name) { - return false !== strpos($name, 'phpdoc'); + static function (string $name): bool { + return str_contains($name, 'phpdoc'); } ); @@ -381,12 +392,12 @@ public function testFixersPriorityPairsHaveIntegrationTest(FixerInterface $first static::assertSame($expected, $actual, sprintf('The ruleset of "%s" must contain the rules for the priority test.', $file)); } - public function provideFixersPriorityPairsHaveIntegrationTestCases() + public function provideFixersPriorityPairsHaveIntegrationTestCases(): array { return array_filter( $this->provideFixersPriorityCases(), // ignore speed-up only priorities set up - function (array $case) { + function (array $case): bool { return !\in_array( $this->generateIntegrationTestName($case[0], $case[1]), [ @@ -454,9 +465,10 @@ public function testPriorityIntegrationTestFilesAreListedPriorityCases(string $f ); } - public function provideIntegrationTestFilesCases() + public function provideIntegrationTestFilesCases(): array { $fileNames = []; + foreach (new \DirectoryIterator($this->getIntegrationPriorityDirectory()) as $candidate) { if ($candidate->isDot()) { continue; @@ -481,7 +493,7 @@ public function testProvideFixersPriorityCasesAreSorted(): void * @param array $priorityPair1 * @param array $priorityPair2 */ - static function (array $priorityPair1, array $priorityPair2) { + static function (array $priorityPair1, array $priorityPair2): int { $fixer1 = $priorityPair1[0]; $fixer2 = $priorityPair2[0]; @@ -523,7 +535,7 @@ public function testFixerPriorityComment(): void $map = []; foreach ($cases as $beforeAfter) { - list($before, $after) = $beforeAfter; + [$before, $after] = $beforeAfter; $beforeClass = \get_class($before); $afterClass = \get_class($after); diff --git a/tests/AutoReview/ProjectCodeTest.php b/tests/AutoReview/ProjectCodeTest.php index a4a7010dfad..768bc9c5e4e 100644 --- a/tests/AutoReview/ProjectCodeTest.php +++ b/tests/AutoReview/ProjectCodeTest.php @@ -54,7 +54,7 @@ public function testThatClassesWithoutTestsVarIsProper(): void { $unknownClasses = array_filter( self::$classesWithoutTests, - static function (string $class) { return !class_exists($class) && !trait_exists($class); } + static function (string $class): bool { return !class_exists($class) && !trait_exists($class); } ); static::assertSame([], $unknownClasses); @@ -84,13 +84,13 @@ public function testThatSrcClassesNotAbuseInterfaces(string $className): void $rc = new \ReflectionClass($className); $allowedMethods = array_map( - function (\ReflectionClass $interface) { + function (\ReflectionClass $interface): array { return $this->getPublicMethodNames($interface); }, $rc->getInterfaces() ); - if (\count($allowedMethods)) { + if (\count($allowedMethods) > 0) { $allowedMethods = array_unique(array_merge(...array_values($allowedMethods))); } @@ -120,7 +120,7 @@ function (\ReflectionClass $interface) { sprintf( "Class '%s' should not have public methods that are not part of implemented interfaces.\nViolations:\n%s", $className, - implode("\n", array_map(static function (string $item) { + implode("\n", array_map(static function (string $item): string { return " * {$item}"; }, $extraMethods)) ) @@ -150,11 +150,11 @@ public function testThatSrcClassesNotExposeProperties(string $className): void $allowedProps = $rc->getParentClass()->getProperties(\ReflectionProperty::IS_PROTECTED); } - $allowedProps = array_map(static function (\ReflectionProperty $item) { + $allowedProps = array_map(static function (\ReflectionProperty $item): string { return $item->getName(); }, $allowedProps); - $definedProps = array_map(static function (\ReflectionProperty $item) { + $definedProps = array_map(static function (\ReflectionProperty $item): string { return $item->getName(); }, $definedProps); @@ -167,7 +167,7 @@ public function testThatSrcClassesNotExposeProperties(string $className): void $extraProps = array_diff( $definedProps, $allowedProps, - isset($exceptionPropsPerClass[$className]) ? $exceptionPropsPerClass[$className] : [] + $exceptionPropsPerClass[$className] ?? [] ); sort($extraProps); @@ -177,7 +177,7 @@ public function testThatSrcClassesNotExposeProperties(string $className): void sprintf( "Class '%s' should not have protected properties.\nViolations:\n%s", $className, - implode("\n", array_map(static function (string $item) { + implode("\n", array_map(static function (string $item): string { return " * {$item}"; }, $extraProps)) ) @@ -214,19 +214,21 @@ public function testThatTestClassesAreInternal(string $testClassName): void /** * @dataProvider provideTestClassCases */ - public function testThatPublicMethodsAreCorrectlyNamed(string $testClassName): void + public function testThatTestClassesPublicMethodsAreCorrectlyNamed(string $testClassName): void { $reflectionClass = new \ReflectionClass($testClassName); $publicMethods = array_filter( $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC), - static function (\ReflectionMethod $reflectionMethod) use ($reflectionClass) { + static function (\ReflectionMethod $reflectionMethod) use ($reflectionClass): bool { return $reflectionMethod->getDeclaringClass()->getName() === $reflectionClass->getName(); } ); if ([] === $publicMethods) { $this->addToAssertionCount(1); // no methods to test, all good! + + return; } foreach ($publicMethods as $method) { @@ -241,45 +243,51 @@ static function (\ReflectionMethod $reflectionMethod) use ($reflectionClass) { /** * @dataProvider provideTestClassCases */ - public function testThatDataProvidersAreCorrectlyNamed(string $testClassName): void + public function testThatTestDataProvidersAreCorrectlyNamed(string $testClassName): void { - $usedDataProviderMethodNames = $this->getUsedDataProviderMethodNames($testClassName); - - if (empty($usedDataProviderMethodNames)) { - $this->addToAssertionCount(1); // no data providers to test, all good! - - return; - } + $asserts = 0; - foreach ($usedDataProviderMethodNames as $dataProviderMethodName) { + foreach ($this->getUsedDataProviderMethodNames($testClassName) as $dataProviderMethodName) { static::assertMatchesRegularExpression('/^provide[A-Z]\S+Cases$/', $dataProviderMethodName, sprintf( 'Data provider in "%s" with name "%s" is not correctly named.', $testClassName, $dataProviderMethodName )); + + ++$asserts; + } + + if (0 === $asserts) { + $this->addToAssertionCount(1); // no data providers to test, all good! } } /** * @dataProvider provideTestClassCases */ - public function testThatDataProvidersAreUsed(string $testClassName): void + public function testThatTestDataProvidersAreUsed(string $testClassName): void { $reflectionClass = new \ReflectionClass($testClassName); $definedDataProviders = array_filter( $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC), - static function (\ReflectionMethod $reflectionMethod) use ($reflectionClass) { + static function (\ReflectionMethod $reflectionMethod) use ($reflectionClass): bool { return $reflectionMethod->getDeclaringClass()->getName() === $reflectionClass->getName() - && 'provide' === substr($reflectionMethod->getName(), 0, 7); + && str_starts_with($reflectionMethod->getName(), 'provide'); } ); if ([] === $definedDataProviders) { $this->addToAssertionCount(1); // no methods to test, all good! + + return; } - $usedDataProviderMethodNames = $this->getUsedDataProviderMethodNames($testClassName); + $usedDataProviderMethodNames = []; + + foreach ($this->getUsedDataProviderMethodNames($testClassName) as $providerName) { + $usedDataProviderMethodNames[] = $providerName; + } foreach ($definedDataProviders as $definedDataProvider) { static::assertContains( @@ -340,13 +348,13 @@ public function testThereIsNoPregFunctionUsedDirectly(string $className): void $tokens = Tokens::fromCode(file_get_contents($rc->getFileName())); $stringTokens = array_filter( $tokens->toArray(), - static function (Token $token) { + static function (Token $token): bool { return $token->isGivenKind(T_STRING); } ); $strings = array_map( - static function (Token $token) { + static function (Token $token): string { return $token->getContent(); }, $stringTokens @@ -372,7 +380,7 @@ public function testExpectedInputOrder(string $testClassName): void $publicMethods = array_filter( $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC), - static function (\ReflectionMethod $reflectionMethod) use ($reflectionClass) { + static function (\ReflectionMethod $reflectionMethod) use ($reflectionClass): bool { return $reflectionMethod->getDeclaringClass()->getName() === $reflectionClass->getName(); } ); @@ -406,7 +414,7 @@ static function (\ReflectionMethod $reflectionMethod) use ($reflectionClass) { } } - $expected = array_filter($expected); + $expected = array_filter($expected, static function ($item): bool { return false !== $item; }); if (\count($expected) < 2) { $this->addToAssertionCount(1); // not enough parameters to test, all good! @@ -492,7 +500,7 @@ public function testThereIsNoTriggerErrorUsedDirectly(string $className): void $triggerErrors = array_filter( $tokens->toArray(), - static function (Token $token) { + static function (Token $token): bool { return $token->equals([T_STRING, 'trigger_error'], false); } ); @@ -512,13 +520,13 @@ public function testInheritdocIsNotAbused(string $className): void $rc = new \ReflectionClass($className); $allowedMethods = array_map( - function (\ReflectionClass $interface) { + function (\ReflectionClass $interface): array { return $this->getPublicMethodNames($interface); }, $rc->getInterfaces() ); - if (\count($allowedMethods)) { + if (\count($allowedMethods) > 0) { $allowedMethods = array_merge(...array_values($allowedMethods)); } @@ -533,13 +541,13 @@ function (\ReflectionClass $interface) { $methodsWithInheritdoc = array_filter( $rc->getMethods(), - static function (\ReflectionMethod $rm) { + static function (\ReflectionMethod $rm): bool { return false !== $rm->getDocComment() && stripos($rm->getDocComment(), '@inheritdoc'); } ); $methodsWithInheritdoc = array_map( - static function (\ReflectionMethod $rm) { + static function (\ReflectionMethod $rm): string { return $rm->getName(); }, $methodsWithInheritdoc @@ -552,30 +560,30 @@ static function (\ReflectionMethod $rm) { sprintf( "Class '%s' should not have methods with '@inheritdoc' in PHPDoc that are not inheriting PHPDoc.\nViolations:\n%s", $className, - implode("\n", array_map(static function ($item) { + implode("\n", array_map(static function ($item): string { return " * {$item}"; }, $extraMethods)) ) ); } - public function provideSrcClassCases() + public function provideSrcClassCases(): array { return array_map( - static function (string $item) { + static function (string $item): array { return [$item]; }, $this->getSrcClasses() ); } - public function provideSrcClassesNotAbuseInterfacesCases() + public function provideSrcClassesNotAbuseInterfacesCases(): array { return array_map( - static function (string $item) { + static function (string $item): array { return [$item]; }, - array_filter($this->getSrcClasses(), static function (string $className) { + array_filter($this->getSrcClasses(), static function (string $className): bool { $rc = new \ReflectionClass($className); $doc = false !== $rc->getDocComment() @@ -615,13 +623,13 @@ static function (string $item) { ); } - public function provideSrcConcreteClassCases() + public function provideSrcConcreteClassCases(): array { return array_map( - static function (string $item) { return [$item]; }, + static function (string $item): array { return [$item]; }, array_filter( $this->getSrcClasses(), - static function (string $className) { + static function (string $className): bool { $rc = new \ReflectionClass($className); return !$rc->isAbstract() && !$rc->isInterface(); @@ -630,25 +638,25 @@ static function (string $className) { ); } - public function provideTestClassCases() + public function provideTestClassCases(): array { return array_map( - static function (string $item) { + static function (string $item): array { return [$item]; }, $this->getTestClasses() ); } - public function provideClassesWherePregFunctionsAreForbiddenCases() + public function provideClassesWherePregFunctionsAreForbiddenCases(): array { return array_map( - static function (string $item) { + static function (string $item): array { return [$item]; }, array_filter( $this->getSrcClasses(), - static function (string $className) { + static function (string $className): bool { return Preg::class !== $className; } ) @@ -665,13 +673,13 @@ public function testPhpUnitFixerExtendsAbstractPhpUnitFixer(string $className): static::assertTrue($reflection->isSubclassOf(\PhpCsFixer\Fixer\AbstractPhpUnitFixer::class)); } - public function providePhpUnitFixerExtendsAbstractPhpUnitFixerCases() + public function providePhpUnitFixerExtendsAbstractPhpUnitFixerCases(): \Generator { $factory = new FixerFactory(); $factory->registerBuiltInFixers(); foreach ($factory->getFixers() as $fixer) { - if (0 !== strpos($fixer->getName(), 'php_unit_')) { + if (!str_starts_with($fixer->getName(), 'php_unit_')) { continue; } @@ -710,27 +718,35 @@ public function testConstantsAreInUpperCase(string $className): void } } - private function getUsedDataProviderMethodNames(string $testClassName) + private function getUsedDataProviderMethodNames(string $testClassName): \Generator + { + foreach ($this->getAnnotationsOfTestClass($testClassName, 'dataProvider') as $methodName => $dataProviderAnnotation) { + if (1 === preg_match('/@dataProvider\s+(?P\w+)/', $dataProviderAnnotation->getContent(), $matches)) { + yield $methodName => $matches['methodName']; + } + } + } + + private function getAnnotationsOfTestClass(string $testClassName, string $annotation): \Generator { - $dataProviderMethodNames = []; $tokens = Tokens::fromCode(file_get_contents( str_replace('\\', \DIRECTORY_SEPARATOR, preg_replace('#^PhpCsFixer\\\Tests#', 'tests', $testClassName)).'.php' )); - foreach ($tokens as $token) { - if ($token->isGivenKind(T_DOC_COMMENT)) { - $docBlock = new DocBlock($token->getContent()); - $dataProviderAnnotations = $docBlock->getAnnotationsOfType('dataProvider'); + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $methodName = $tokens[$tokens->getNextTokenOfKind($index, [[T_STRING]])]->getContent(); - foreach ($dataProviderAnnotations as $dataProviderAnnotation) { - if (1 === preg_match('/@dataProvider\s+(?P\w+)/', $dataProviderAnnotation->getContent(), $matches)) { - $dataProviderMethodNames[] = $matches['methodName']; - } - } + $docBlock = new DocBlock($token->getContent()); + $dataProviderAnnotations = $docBlock->getAnnotationsOfType($annotation); + + foreach ($dataProviderAnnotations as $dataProviderAnnotation) { + yield $methodName => $dataProviderAnnotation; } } - - return array_unique($dataProviderMethodNames); } private function getSrcClasses() @@ -751,7 +767,7 @@ private function getSrcClasses() ; $classes = array_map( - static function (SplFileInfo $file) { + static function (SplFileInfo $file): string { return sprintf( '%s\\%s%s%s', 'PhpCsFixer', @@ -786,7 +802,7 @@ private function getTestClasses() ; $classes = array_map( - static function (SplFileInfo $file) { + static function (SplFileInfo $file): string { return sprintf( 'PhpCsFixer\\Tests\\%s%s%s', strtr($file->getRelativePath(), \DIRECTORY_SEPARATOR, '\\'), @@ -798,6 +814,7 @@ static function (SplFileInfo $file) { ); $classes = array_filter($classes, static function (string $class): bool { + // @phpstan-ignore-next-line due to false positive reported in https://github.com/phpstan/phpstan/issues/5369 return is_subclass_of($class, TestCase::class); }); @@ -812,7 +829,7 @@ static function (SplFileInfo $file) { private function getPublicMethodNames(\ReflectionClass $rc): array { return array_map( - static function (\ReflectionMethod $rm) { + static function (\ReflectionMethod $rm): string { return $rm->getName(); }, $rc->getMethods(\ReflectionMethod::IS_PUBLIC) diff --git a/tests/AutoReview/ProjectFixerConfigurationTest.php b/tests/AutoReview/ProjectFixerConfigurationTest.php index 35b531ac27c..6cd18d40553 100644 --- a/tests/AutoReview/ProjectFixerConfigurationTest.php +++ b/tests/AutoReview/ProjectFixerConfigurationTest.php @@ -20,8 +20,6 @@ use PhpCsFixer\ToolInfo; /** - * @author SpacePossum - * * @internal * * @coversNothing @@ -34,7 +32,6 @@ public function testCreate(): void { $config = $this->loadConfig(); - static::assertInstanceOf(\PhpCsFixer\Config::class, $config); static::assertEmpty($config->getCustomFixers()); static::assertNotEmpty($config->getRules()); diff --git a/tests/AutoReview/TransformerTest.php b/tests/AutoReview/TransformerTest.php index a7dcd11fd3d..efe455254c3 100644 --- a/tests/AutoReview/TransformerTest.php +++ b/tests/AutoReview/TransformerTest.php @@ -19,7 +19,6 @@ use PhpCsFixer\Tokenizer\Transformers; /** - * @author SpacePossum * @author Dave van der Brugge * * @internal @@ -58,7 +57,7 @@ public function testTransformerPriorityIsListed(TransformerInterface $transforme $name = $transformer->getName(); foreach ($this->provideTransformerPriorityCases() as $pair) { - list($first, $second) = $pair; + [$first, $second] = $pair; if ($name === $first->getName() || $name === $second->getName()) { $this->addToAssertionCount(1); @@ -70,11 +69,11 @@ public function testTransformerPriorityIsListed(TransformerInterface $transforme static::fail(sprintf('Transformer "%s" has priority %d but is not in priority test list.', $name, $priority)); } - public function provideTransformerPriorityCases() + public function provideTransformerPriorityCases(): array { $transformers = []; - foreach ($this->provideTransformerCases() as list($transformer)) { + foreach ($this->provideTransformerCases() as [$transformer]) { $transformers[$transformer->getName()] = $transformer; } diff --git a/tests/Cache/CacheTest.php b/tests/Cache/CacheTest.php index 0e12441a91a..a7af5e04f79 100644 --- a/tests/Cache/CacheTest.php +++ b/tests/Cache/CacheTest.php @@ -128,7 +128,7 @@ public function provideMissingDataCases(): array 'hashes' => [], ]; - return array_map(static function (string $missingKey) use ($data) { + return array_map(static function (string $missingKey) use ($data): array { unset($data[$missingKey]); return [ @@ -155,7 +155,7 @@ public function testCanConvertToAndFromJson(SignatureInterface $signature): void static::assertSame($hash, $cached->get($file)); } - public function provideCanConvertToAndFromJsonCases() + public function provideCanConvertToAndFromJsonCases(): array { $toolInfo = new ToolInfo(); $config = new Config(); @@ -202,6 +202,7 @@ public function testToJsonThrowsExceptionOnInvalid(): void $this->expectException( \UnexpectedValueException::class ); + $this->expectExceptionMessage( 'Can not encode cache signature to JSON, error: "Malformed UTF-8 characters, possibly incorrectly encoded". If you have non-UTF8 chars in your signature, like in license for `header_comment`, consider enabling `ext-mbstring` or install `symfony/polyfill-mbstring`.' ); diff --git a/tests/Cache/FileCacheManagerTest.php b/tests/Cache/FileCacheManagerTest.php index c64b6f0b451..ac35961765e 100644 --- a/tests/Cache/FileCacheManagerTest.php +++ b/tests/Cache/FileCacheManagerTest.php @@ -48,7 +48,7 @@ public function testCreatesCacheIfHandlerReturnedNoCache(): void $handlerProphecy = $this->prophesize(\PhpCsFixer\Cache\FileHandlerInterface::class); $handlerProphecy->read()->shouldBeCalled()->willReturn(null); - $handlerProphecy->write(Argument::that(static function (CacheInterface $cache) use ($signature) { + $handlerProphecy->write(Argument::that(static function (CacheInterface $cache) use ($signature): bool { return $cache->getSignature() === $signature; }))->shouldBeCalled(); $handler = $handlerProphecy->reveal(); @@ -75,7 +75,7 @@ public function testCreatesCacheIfCachedSignatureIsDifferent(): void $handlerProphecy = $this->prophesize(\PhpCsFixer\Cache\FileHandlerInterface::class); $handlerProphecy->read()->shouldBeCalled()->willReturn($cache); - $handlerProphecy->write(Argument::that(static function (CacheInterface $cache) use ($signature) { + $handlerProphecy->write(Argument::that(static function (CacheInterface $cache) use ($signature): bool { return $cache->getSignature() === $signature; }))->shouldBeCalled(); $handler = $handlerProphecy->reveal(); diff --git a/tests/Cache/FileHandlerTest.php b/tests/Cache/FileHandlerTest.php index a4219556ce3..bafd73c4b95 100644 --- a/tests/Cache/FileHandlerTest.php +++ b/tests/Cache/FileHandlerTest.php @@ -19,6 +19,7 @@ use PhpCsFixer\Cache\Signature; use PhpCsFixer\Cache\SignatureInterface; use PhpCsFixer\Tests\TestCase; +use Symfony\Component\Filesystem\Exception\IOException; /** * @author Andreas Möller @@ -100,7 +101,7 @@ public function testWriteThrowsIOExceptionIfFileCanNotBeWritten(): void { $file = __DIR__.'/non-existent-directory/.php-cs-fixer.cache'; - $this->expectException(\Symfony\Component\Filesystem\Exception\IOException::class); + $this->expectException(IOException::class); $this->expectExceptionMessageMatches(sprintf( '#^Directory of cache file "%s" does not exists.#', preg_quote($file, '#') @@ -136,7 +137,7 @@ public function testWriteCacheToDirectory(): void $handler = new FileHandler($dir); - $this->expectException(\Symfony\Component\Filesystem\Exception\IOException::class); + $this->expectException(IOException::class); $this->expectExceptionMessageMatches(sprintf( '#^%s$#', preg_quote('Cannot write cache file "'.realpath($dir).'" as the location exists as directory.', '#') @@ -154,7 +155,7 @@ public function testWriteCacheToNonWriteableFile(): void $handler = new FileHandler($file); - $this->expectException(\Symfony\Component\Filesystem\Exception\IOException::class); + $this->expectException(IOException::class); $this->expectExceptionMessageMatches(sprintf( '#^%s$#', preg_quote('Cannot write to file "'.realpath($file).'" as it is not writable.', '#') diff --git a/tests/Cache/SignatureTest.php b/tests/Cache/SignatureTest.php index 3b49ff2844e..a6d7e72adfc 100644 --- a/tests/Cache/SignatureTest.php +++ b/tests/Cache/SignatureTest.php @@ -74,7 +74,7 @@ public function testEqualsReturnsFalseIfValuesAreNotIdentical(Signature $signatu static::assertFalse($signature->equals($anotherSignature)); } - public function provideEqualsReturnsFalseIfValuesAreNotIdenticalCases() + public function provideEqualsReturnsFalseIfValuesAreNotIdenticalCases(): \Generator { $php = PHP_VERSION; $version = '2.0'; diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index 7e578a1267a..db597921458 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -15,6 +15,7 @@ namespace PhpCsFixer\Tests; use PhpCsFixer\Config; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; use PhpCsFixer\Console\Application; use PhpCsFixer\Console\Command\FixCommand; use PhpCsFixer\Console\ConfigurationResolver; @@ -80,7 +81,7 @@ public function testConfigRulesUsingJsonMethod(): void public function testConfigRulesUsingInvalidJson(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $config = new Config(); $configResolver = new ConfigurationResolver( diff --git a/tests/ConfigurationException/InvalidFixerConfigurationExceptionTest.php b/tests/ConfigurationException/InvalidFixerConfigurationExceptionTest.php index bfa39a7b8aa..13b99c218e9 100644 --- a/tests/ConfigurationException/InvalidFixerConfigurationExceptionTest.php +++ b/tests/ConfigurationException/InvalidFixerConfigurationExceptionTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\ConfigurationException; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Console\Command\FixCommandExitStatusCalculator; use PhpCsFixer\Tests\TestCase; @@ -31,7 +32,7 @@ public function testIsInvalidArgumentException(): void { $exception = new InvalidFixerConfigurationException('foo', 'I cannot do that, Dave.'); - static::assertInstanceOf(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class, $exception); + static::assertInstanceOf(InvalidConfigurationException::class, $exception); } public function testDefaults(): void diff --git a/tests/ConfigurationException/InvalidForEnvFixerConfigurationExceptionTest.php b/tests/ConfigurationException/InvalidForEnvFixerConfigurationExceptionTest.php index 8bea0ca34e9..14116ad8acd 100644 --- a/tests/ConfigurationException/InvalidForEnvFixerConfigurationExceptionTest.php +++ b/tests/ConfigurationException/InvalidForEnvFixerConfigurationExceptionTest.php @@ -14,13 +14,12 @@ namespace PhpCsFixer\Tests\ConfigurationException; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\ConfigurationException\InvalidForEnvFixerConfigurationException; use PhpCsFixer\Console\Command\FixCommandExitStatusCalculator; use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\ConfigurationException\InvalidForEnvFixerConfigurationException @@ -37,7 +36,7 @@ public function testDefaults(): void $message ); - static::assertInstanceOf(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class, $exception); + static::assertInstanceOf(InvalidFixerConfigurationException::class, $exception); static::assertSame(sprintf('[%s] %s', $fixerName, $message), $exception->getMessage()); static::assertSame(FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_FIXER_CONFIG, $exception->getCode()); static::assertSame($fixerName, $exception->getFixerName()); diff --git a/tests/ConfigurationException/RequiredFixerConfigurationExceptionTest.php b/tests/ConfigurationException/RequiredFixerConfigurationExceptionTest.php index 6d38b367e05..b68bc7575d5 100644 --- a/tests/ConfigurationException/RequiredFixerConfigurationExceptionTest.php +++ b/tests/ConfigurationException/RequiredFixerConfigurationExceptionTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\ConfigurationException; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\ConfigurationException\RequiredFixerConfigurationException; use PhpCsFixer\Console\Command\FixCommandExitStatusCalculator; use PhpCsFixer\Tests\TestCase; @@ -34,7 +35,7 @@ public function testIsInvalidFixerConfigurationException(): void 'I cannot do that, Dave.' ); - static::assertInstanceOf(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class, $exception); + static::assertInstanceOf(InvalidFixerConfigurationException::class, $exception); } public function testDefaults(): void diff --git a/tests/Console/ApplicationTest.php b/tests/Console/ApplicationTest.php index 3559008595c..5939b348e7c 100644 --- a/tests/Console/ApplicationTest.php +++ b/tests/Console/ApplicationTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Console\Application diff --git a/tests/Console/Command/FixCommandExitStatusCalculatorTest.php b/tests/Console/Command/FixCommandExitStatusCalculatorTest.php index 732dcb41440..9cd824ef389 100644 --- a/tests/Console/Command/FixCommandExitStatusCalculatorTest.php +++ b/tests/Console/Command/FixCommandExitStatusCalculatorTest.php @@ -40,7 +40,7 @@ public function testCalculate(int $expected, bool $isDryRun, bool $hasChangedFil ); } - public function provideCalculateCases() + public function provideCalculateCases(): array { return [ [0, true, false, false, false, false], diff --git a/tests/Console/Command/FixCommandTest.php b/tests/Console/Command/FixCommandTest.php index 30eea9f7837..76a7e01f55e 100644 --- a/tests/Console/Command/FixCommandTest.php +++ b/tests/Console/Command/FixCommandTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Console\Command; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; use PhpCsFixer\Console\Application; use PhpCsFixer\Console\Command\FixCommand; use PhpCsFixer\Tests\TestCase; @@ -31,7 +32,7 @@ final class FixCommandTest extends TestCase public function testEmptyRulesValue(): void { $this->expectException( - \PhpCsFixer\ConfigurationException\InvalidConfigurationException::class + InvalidConfigurationException::class ); $this->expectExceptionMessageMatches( '#^Empty rules value is not allowed\.$#' @@ -44,7 +45,7 @@ public function testEmptyRulesValue(): void public function testEmptyFormatValue(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage('Expected "yes" or "no" for option "using-cache", got "not today".'); $cmdTester = $this->doTestExecute( @@ -81,7 +82,7 @@ private function doTestExecute(array $arguments): CommandTester return $commandTester; } - private function getDefaultArguments() + private function getDefaultArguments(): array { return [ 'path' => [__FILE__], diff --git a/tests/Console/Command/HelpCommandTest.php b/tests/Console/Command/HelpCommandTest.php index 84314f09d9e..ac2c01649da 100644 --- a/tests/Console/Command/HelpCommandTest.php +++ b/tests/Console/Command/HelpCommandTest.php @@ -36,7 +36,7 @@ public function testToString(string $expected, $input): void static::assertSame($expected, HelpCommand::toString($input)); } - public function provideToStringCases() + public function provideToStringCases(): \Generator { yield ["['a' => 3, 'b' => 'c']", ['a' => 3, 'b' => 'c']]; yield ['[[1], [2]]', [[1], [2]]]; @@ -61,7 +61,7 @@ public function testGetDisplayableAllowedValues($expected, FixerOptionInterface static::assertSame($expected, HelpCommand::getDisplayableAllowedValues($input)); } - public function provideGetDisplayableAllowedValuesCases() + public function provideGetDisplayableAllowedValuesCases(): \Generator { yield [null, new FixerOption('foo', 'bar', false, null, ['int'], [])]; yield [['A', 'B', 'x', 'z'], new FixerOption('foo', 'bar', false, null, ['string'], ['z', 'x', 'B', 'A'])]; diff --git a/tests/Console/Command/SelfUpdateCommandTest.php b/tests/Console/Command/SelfUpdateCommandTest.php index 52c6476ca15..fd47b4c5ba1 100644 --- a/tests/Console/Command/SelfUpdateCommandTest.php +++ b/tests/Console/Command/SelfUpdateCommandTest.php @@ -80,7 +80,7 @@ public function testCommandName(string $name): void static::assertSame($command, $application->find($name)); } - public function provideCommandNameCases() + public function provideCommandNameCases(): array { return [ ['self-update'], @@ -116,7 +116,7 @@ public function testExecute( $versionChecker ->compareVersions(Argument::type('string'), Argument::type('string')) - ->will(function (array $arguments) use ($actualVersionCheck) { + ->will(function (array $arguments) use ($actualVersionCheck): int { return $actualVersionCheck->compareVersions($arguments[0], $arguments[1]); }) ; @@ -134,7 +134,7 @@ public function testExecute( static::assertSame(0, $commandTester->getStatusCode()); } - public function provideExecuteCases() + public function provideExecuteCases(): array { $currentVersion = Application::VERSION; $minorRelease = $this->getNewMinorReleaseVersion(); @@ -238,7 +238,7 @@ public function testExecuteWhenNotAbleToGetLatestVersions( $versionChecker = $this->prophesize(\PhpCsFixer\Console\SelfUpdate\NewVersionCheckerInterface::class); $newMajorVersion = $this->getNewMajorReleaseVersion(); - $versionChecker->getLatestVersion()->will(function () use ($latestVersionSuccess, $newMajorVersion) { + $versionChecker->getLatestVersion()->will(function () use ($latestVersionSuccess, $newMajorVersion): string { if ($latestVersionSuccess) { return $newMajorVersion; } @@ -249,7 +249,7 @@ public function testExecuteWhenNotAbleToGetLatestVersions( $newMinorVersion = $this->getNewMinorReleaseVersion(); $versionChecker ->getLatestVersionOfMajor($this->getCurrentMajorVersion()) - ->will(function () use ($latestMinorVersionSuccess, $newMinorVersion) { + ->will(function () use ($latestMinorVersionSuccess, $newMinorVersion): string { if ($latestMinorVersionSuccess) { return $newMinorVersion; } @@ -273,7 +273,7 @@ public function testExecuteWhenNotAbleToGetLatestVersions( static::assertSame(1, $commandTester->getStatusCode()); } - public function provideExecuteWhenNotAbleToGetLatestVersionsCases() + public function provideExecuteWhenNotAbleToGetLatestVersionsCases(): array { return [ [false, false, [], true], @@ -317,7 +317,7 @@ public function testExecuteWhenNotInstalledAsPhar(array $input, bool $decorated) static::assertSame(1, $commandTester->getStatusCode()); } - public function provideExecuteWhenNotInstalledAsPharCases() + public function provideExecuteWhenNotInstalledAsPharCases(): array { return [ [[], true], @@ -329,7 +329,7 @@ public function provideExecuteWhenNotInstalledAsPharCases() ]; } - private function execute(Command $command, array $input, $decorated) + private function execute(Command $command, array $input, $decorated): CommandTester { $application = new Application(); $application->add($command); @@ -348,14 +348,14 @@ private function execute(Command $command, array $input, $decorated) return $commandTester; } - private function assertDisplay(string $expectedDisplay, CommandTester $commandTester): void + private static function assertDisplay(string $expectedDisplay, CommandTester $commandTester): void { if (!$commandTester->getOutput()->isDecorated()) { $expectedDisplay = preg_replace("/\033\\[(\\d+;)*\\d+m/", '', $expectedDisplay); } // TODO drop preg_replace() usage when symfony/console is bumped - $cleanDisplay = function (string $display) { + $cleanDisplay = static function (string $display) { return preg_replace("/\033\\[39(;49)?m/", "\033[0m", $display); }; @@ -373,7 +373,7 @@ private function createToolInfo(bool $isInstalledAsPhar = true) $toolInfo->isInstalledAsPhar()->willReturn($isInstalledAsPhar); $toolInfo ->getPharDownloadUri(Argument::type('string')) - ->will(function (array $arguments) use ($root) { + ->will(function (array $arguments) use ($root): string { return "{$root->url()}/{$arguments[0]}.phar"; }) ; @@ -381,27 +381,27 @@ private function createToolInfo(bool $isInstalledAsPhar = true) return $toolInfo->reveal(); } - private function getToolPath() + private function getToolPath(): string { return "{$this->root->url()}/php-cs-fixer"; } - private function getCurrentMajorVersion() + private function getCurrentMajorVersion(): int { return (int) preg_replace('/^v?(\d+).*$/', '$1', Application::VERSION); } - private function getNewMinorReleaseVersion() + private function getNewMinorReleaseVersion(): string { return "{$this->getCurrentMajorVersion()}.999.0"; } - private function getNewMajorVersion() + private function getNewMajorVersion(): int { return $this->getCurrentMajorVersion() + 1; } - private function getNewMajorReleaseVersion() + private function getNewMajorReleaseVersion(): string { return $this->getNewMajorVersion().'.0.0'; } diff --git a/tests/Console/ConfigurationResolverTest.php b/tests/Console/ConfigurationResolverTest.php index ff17a476980..7eb666d1f1c 100644 --- a/tests/Console/ConfigurationResolverTest.php +++ b/tests/Console/ConfigurationResolverTest.php @@ -130,7 +130,7 @@ public function testResolveProgressWithNegativeConfigAndExplicitProgress(string static::assertSame($progressType, $resolver->getProgress()); } - public function provideProgressTypeCases() + public function provideProgressTypeCases(): array { return [ ['none'], @@ -195,7 +195,7 @@ public function testResolveConfigFileChooseFile(string $expectedFile, string $ex static::assertInstanceOf($expectedClass, $resolver->getConfig()); } - public function provideResolveConfigFileDefaultCases() + public function provideResolveConfigFileDefaultCases(): array { $dirBase = $this->getFixtureDir(); @@ -297,7 +297,7 @@ public function testResolvePath(array $paths, string $cwd, array $expectedPaths) static::assertSame($expectedPaths, $resolver->getPath()); } - public function providePathCases() + public function providePathCases(): \Generator { yield [ ['Command'], @@ -343,7 +343,7 @@ public function testRejectInvalidPath(array $paths, string $expectedMessage): vo $resolver->getPath(); } - public function provideEmptyPathCases() + public function provideEmptyPathCases(): \Generator { yield [ [''], @@ -484,7 +484,7 @@ public function testResolveIntersectionOfPaths($expected, ?Finder $configFinder, ], $config); $intersectionItems = array_map( - static function (\SplFileInfo $file) { + static function (\SplFileInfo $file): string { return $file->getRealPath(); }, iterator_to_array($resolver->getFinder(), false) @@ -496,12 +496,12 @@ static function (\SplFileInfo $file) { static::assertSame($expected, $intersectionItems); } - public function provideResolveIntersectionOfPathsCases() + public function provideResolveIntersectionOfPathsCases(): array { $dir = __DIR__.'/../Fixtures/ConfigurationResolverPathsIntersection'; - $cb = static function (array $items) use ($dir) { + $cb = static function (array $items) use ($dir): array { return array_map( - static function (string $item) use ($dir) { + static function (string $item) use ($dir): string { return realpath($dir.'/'.$item); }, $items @@ -662,7 +662,7 @@ public function testConfigFinderIsOverridden(array $options, bool $expectedResul static::assertSame($expectedResult, $resolver->configFinderIsOverridden()); } - public function provideConfigFinderIsOverriddenCases() + public function provideConfigFinderIsOverriddenCases(): array { $root = __DIR__.'/../..'; @@ -954,17 +954,53 @@ public function testResolveRulesWithOption(): void ); } + /** + * @param string[] $rules + * + * @dataProvider provideRenamedRulesCases + */ + public function testResolveRenamedRulesWithUnknownRules(string $expectedMessage, array $rules): void + { + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage($expectedMessage); + + $resolver = $this->createConfigurationResolver(['rules' => implode(',', $rules)]); + $resolver->getRules(); + } + + public function provideRenamedRulesCases(): \Generator + { + yield 'with config' => [ + 'The rules contain unknown fixers: "blank_line_before_return" is renamed (did you mean "blank_line_before_statement"? (note: use configuration "[\'statements\' => [\'return\']]")). +For more info about updating see: https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v3.0.0/UPGRADE-v3.md#renamed-ruless.', + ['blank_line_before_return'], + ]; + + yield 'without config' => [ + 'The rules contain unknown fixers: "final_static_access" is renamed (did you mean "self_static_accessor"?). +For more info about updating see: https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v3.0.0/UPGRADE-v3.md#renamed-ruless.', + ['final_static_access'], + ]; + + yield [ + 'The rules contain unknown fixers: "hash_to_slash_comment" is renamed (did you mean "single_line_comment_style"? (note: use configuration "[\'comment_types\' => [\'hash\']]")). +For more info about updating see: https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v3.0.0/UPGRADE-v3.md#renamed-ruless.', + ['hash_to_slash_comment'], + ]; + + yield 'both renamed and unknown' => [ + 'The rules contain unknown fixers: "final_static_access" is renamed (did you mean "self_static_accessor"?), "binary_operator_space" (did you mean "binary_operator_spaces"?). +For more info about updating see: https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v3.0.0/UPGRADE-v3.md#renamed-ruless.', + ['final_static_access', 'binary_operator_space'], + ]; + } + public function testResolveRulesWithUnknownRules(): void { - $this->expectException( - \PhpCsFixer\ConfigurationException\InvalidConfigurationException::class - ); - $this->expectExceptionMessage( - 'The rules contain unknown fixers: "bar", "binary_operator_space" (did you mean "binary_operator_spaces"?).' - ); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The rules contain unknown fixers: "bar", "binary_operator_space" (did you mean "binary_operator_spaces"?).'); $resolver = $this->createConfigurationResolver(['rules' => 'braces,-bar,binary_operator_space']); - $resolver->getRules(); } @@ -1040,7 +1076,7 @@ public function testResolveDiffer(string $expected, $diffConfig): void static::assertInstanceOf($expected, $resolver->getDiffer()); } - public function provideDifferCases() + public function provideDifferCases(): array { return [ [ @@ -1073,7 +1109,7 @@ public function testResolveConfigFileOverridesDefault(): void public function testDeprecationOfPassingOtherThanNoOrYes(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage('Expected "yes" or "no" for option "allow-risky", got "yes please".'); $resolver = $this->createConfigurationResolver(['allow-risky' => 'yes please']); @@ -1081,7 +1117,7 @@ public function testDeprecationOfPassingOtherThanNoOrYes(): void $resolver->getRiskyAllowed(); } - public function provideResolveBooleanOptionCases() + public function provideResolveBooleanOptionCases(): array { return [ [true, true, 'yes'], @@ -1122,7 +1158,7 @@ public function testDeprecatedFixerConfigured($ruleConfig): void $resolver->getFixers(); } - public function provideDeprecatedFixerConfiguredCases() + public function provideDeprecatedFixerConfiguredCases(): array { return [ [true], @@ -1131,7 +1167,7 @@ public function provideDeprecatedFixerConfiguredCases() ]; } - public function provideGetDirectoryCases() + public function provideGetDirectoryCases(): array { return [ [null, '/my/path/my/file', 'path/my/file'], @@ -1171,20 +1207,20 @@ private function normalizePath(string $path): string return str_replace('/', \DIRECTORY_SEPARATOR, $path); } - private static function assertSameRules(array $expected, array $actual, string $message = ''): void + private static function assertSameRules(array $expected, array $actual): void { ksort($expected); ksort($actual); - static::assertSame($expected, $actual, $message); + static::assertSame($expected, $actual); } - private function getFixtureDir() + private function getFixtureDir(): string { return realpath(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR.'ConfigurationResolverConfigFile'.\DIRECTORY_SEPARATOR).'/'; } - private function createConfigurationResolver(array $options, Config $config = null, string $cwdPath = '') + private function createConfigurationResolver(array $options, Config $config = null, string $cwdPath = ''): ConfigurationResolver { if (null === $config) { $config = new Config(); diff --git a/tests/Console/Output/ErrorOutputTest.php b/tests/Console/Output/ErrorOutputTest.php index e082583302f..e739030c7da 100644 --- a/tests/Console/Output/ErrorOutputTest.php +++ b/tests/Console/Output/ErrorOutputTest.php @@ -22,8 +22,6 @@ use Symfony\Component\Console\Output\StreamOutput; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Console\Output\ErrorOutput @@ -83,10 +81,10 @@ public function testErrorOutput(Error $error, int $verbosityLevel, int $lineNumb static::assertStringStartsWith($startWith, $displayed); } - public function provideTestCases() + public function provideTestCases(): array { $lineNumber = __LINE__; - list($exceptionLineNumber, $error) = $this->getErrorAndLineNumber(); // note: keep call and __LINE__ separated with one line break + [$exceptionLineNumber, $error] = $this->getErrorAndLineNumber(); // note: keep call and __LINE__ separated with one line break ++$lineNumber; return [ @@ -159,7 +157,7 @@ private function readFullStreamOutput(StreamOutput $output): string return str_replace(PHP_EOL, "\n", $displayed); } - private function getErrorAndLineNumber() + private function getErrorAndLineNumber(): array { $lineNumber = __LINE__; $exception = new \RuntimeException(// note: keep exception constructor and __LINE__ separated with one line break diff --git a/tests/Console/Output/NullOutputTest.php b/tests/Console/Output/NullOutputTest.php index a48e3e6b6c4..dbab3104d03 100644 --- a/tests/Console/Output/NullOutputTest.php +++ b/tests/Console/Output/NullOutputTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Console\Output\NullOutput diff --git a/tests/Console/Output/ProcessOutputTest.php b/tests/Console/Output/ProcessOutputTest.php index aad482a9577..c76774e0280 100644 --- a/tests/Console/Output/ProcessOutputTest.php +++ b/tests/Console/Output/ProcessOutputTest.php @@ -50,7 +50,7 @@ public function testProcessProgressOutput(array $statuses, string $expectedOutpu static::assertSame($expectedOutput, $output->fetch()); } - public function provideProcessProgressOutputCases() + public function provideProcessProgressOutputCases(): array { return [ [ @@ -179,7 +179,7 @@ public function provideProcessProgressOutputCases() private function foreachStatus(array $statuses, \Closure $action): void { foreach ($statuses as $status) { - $multiplier = isset($status[1]) ? $status[1] : 1; + $multiplier = $status[1] ?? 1; $status = $status[0]; for ($i = 0; $i < $multiplier; ++$i) { diff --git a/tests/Console/Report/FixReport/JsonReporterTest.php b/tests/Console/Report/FixReport/JsonReporterTest.php index f5d379e1a7c..c0f31e97856 100644 --- a/tests/Console/Report/FixReport/JsonReporterTest.php +++ b/tests/Console/Report/FixReport/JsonReporterTest.php @@ -168,7 +168,7 @@ private static function assertJsonSchema(string $json): void implode( "\n", array_map( - static function (array $item) { return sprintf('Property `%s`: %s.', $item['property'], $item['message']); }, + static function (array $item): string { return sprintf('Property `%s`: %s.', $item['property'], $item['message']); }, $validator->getErrors() ) ) diff --git a/tests/Console/Report/FixReport/ReportSummaryTest.php b/tests/Console/Report/FixReport/ReportSummaryTest.php index 77847632a00..4280e09c0ce 100644 --- a/tests/Console/Report/FixReport/ReportSummaryTest.php +++ b/tests/Console/Report/FixReport/ReportSummaryTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Console\Report\FixReport\ReportSummary diff --git a/tests/Console/Report/ListSetsReport/JsonReporterTest.php b/tests/Console/Report/ListSetsReport/JsonReporterTest.php index 70bc7d6cde9..98ce5245708 100644 --- a/tests/Console/Report/ListSetsReport/JsonReporterTest.php +++ b/tests/Console/Report/ListSetsReport/JsonReporterTest.php @@ -77,7 +77,7 @@ private static function assertJsonSchema(string $json): void implode( "\n", array_map( - static function (array $item) { return sprintf('Property `%s`: %s.', $item['property'], $item['message']); }, + static function (array $item): string { return sprintf('Property `%s`: %s.', $item['property'], $item['message']); }, $validator->getErrors() ) ) diff --git a/tests/Console/SelfUpdate/NewVersionCheckerTest.php b/tests/Console/SelfUpdate/NewVersionCheckerTest.php index 682a81eb31d..668169088bd 100644 --- a/tests/Console/SelfUpdate/NewVersionCheckerTest.php +++ b/tests/Console/SelfUpdate/NewVersionCheckerTest.php @@ -42,7 +42,7 @@ public function testGetLatestVersionOfMajor(int $majorVersion, ?string $expected static::assertSame($expectedVersion, $checker->getLatestVersionOfMajor($majorVersion)); } - public function provideLatestVersionOfMajorCases() + public function provideLatestVersionOfMajorCases(): array { return [ [1, 'v1.13.2'], @@ -68,7 +68,7 @@ public function testCompareVersions(string $versionA, string $versionB, int $exp ); } - public function provideCompareVersionsCases() + public function provideCompareVersionsCases(): array { $cases = []; diff --git a/tests/Differ/AbstractDifferTestCase.php b/tests/Differ/AbstractDifferTestCase.php index 17f8de29bf5..7a0b303c605 100644 --- a/tests/Differ/AbstractDifferTestCase.php +++ b/tests/Differ/AbstractDifferTestCase.php @@ -40,7 +40,7 @@ final public function testIsDiffer(): void static::assertInstanceOf(\PhpCsFixer\Differ\DifferInterface::class, $differ); } - final protected function oldCode() + final protected function oldCode(): string { return <<<'PHP' + * @author Graham Campbell * @author Dariusz Rumiński * * @internal @@ -100,15 +100,11 @@ public function testGetContent(int $index, string $content): void static::assertSame($content, (string) $annotation); } - public function provideGetContentCases() + public function provideGetContentCases(): \Generator { - $cases = []; - foreach (self::$content as $index => $content) { - $cases[] = [$index, $content]; + yield [$index, $content]; } - - return $cases; } /** @@ -122,15 +118,11 @@ public function testStart(int $index, int $start): void static::assertSame($start, $annotation->getStart()); } - public function provideStartCases() + public function provideStartCases(): \Generator { - $cases = []; - foreach (self::$start as $index => $start) { - $cases[] = [$index, $start]; + yield [$index, $start]; } - - return $cases; } /** @@ -144,15 +136,11 @@ public function testEnd(int $index, int $end): void static::assertSame($end, $annotation->getEnd()); } - public function provideEndCases() + public function provideEndCases(): \Generator { - $cases = []; - foreach (self::$end as $index => $end) { - $cases[] = [$index, $end]; + yield [$index, $end]; } - - return $cases; } /** @@ -166,15 +154,11 @@ public function testGetTag(int $index, string $tag): void static::assertSame($tag, $annotation->getTag()->getName()); } - public function provideGetTagCases() + public function provideGetTagCases(): \Generator { - $cases = []; - foreach (self::$tags as $index => $tag) { - $cases[] = [$index, $tag]; + yield [$index, $tag]; } - - return $cases; } /** @@ -191,15 +175,11 @@ public function testRemove(int $index, int $start, int $end): void static::assertSame('', $doc->getLine($end)->getContent()); } - public function provideRemoveCases() + public function provideRemoveCases(): \Generator { - $cases = []; - foreach (self::$start as $index => $start) { - $cases[] = [$index, $start, self::$end[$index]]; + yield [$index, $start, self::$end[$index]]; } - - return $cases; } /** @@ -214,7 +194,7 @@ public function testRemoveEdgeCases(string $expected, string $input): void static::assertSame($expected, $doc->getContent()); } - public function provideRemoveEdgeCasesCases() + public function provideRemoveEdgeCasesCases(): array { return [ // Single line @@ -256,211 +236,211 @@ public function provideRemoveEdgeCasesCases() * * @dataProvider provideTypeParsingCases */ - public function testTypeParsing(string $input, array $expected): void + public function testTypeParsing(array $expected, string $input): void { $tag = new Annotation([new Line($input)]); static::assertSame($expected, $tag->getTypes()); } - public function provideTypeParsingCases() + public function provideTypeParsingCases(): array { return [ [ - ' * @method int method()', ['int'], + ' * @method int method()', ], [ - " * @return int[]\r", ['int[]'], + " * @return int[]\r", ], [ - " * @return int[]\r\n", ['int[]'], + " * @return int[]\r\n", ], [ - ' * @method Foo[][] method()', ['Foo[][]'], + ' * @method Foo[][] method()', ], [ - ' * @method int[] method()', ['int[]'], + ' * @method int[] method()', ], [ - ' * @method int[]|null method()', ['int[]', 'null'], + ' * @method int[]|null method()', ], [ - ' * @method int[]|null|?int|array method()', ['int[]', 'null', '?int', 'array'], + ' * @method int[]|null|?int|array method()', ], [ - ' * @method null|Foo\Bar|\Baz\Bax|int[] method()', ['null', 'Foo\Bar', '\Baz\Bax', 'int[]'], + ' * @method null|Foo\Bar|\Baz\Bax|int[] method()', ], [ - ' * @method gen method()', ['gen'], + ' * @method gen method()', ], [ - ' * @method int|gen method()', ['int', 'gen'], + ' * @method int|gen method()', ], [ - ' * @method \int|\gen<\int, \bool> method()', ['\int', '\gen<\int, \bool>'], + ' * @method \int|\gen<\int, \bool> method()', ], [ - ' * @method gen method()', ['gen'], + ' * @method gen method()', ], [ - ' * @method gen method()', ['gen'], + ' * @method gen method()', ], [ - ' * @method gen method() <> a', ['gen'], + ' * @method gen method() <> a', ], [ - ' * @method gen> method() foo ', ['gen>'], + ' * @method gen> method() foo ', ], [ - ' * @method gen> method()', ['gen>'], + ' * @method gen> method()', ], [ - ' * @method null|gen>|int|string[] method() foo ', ['null', 'gen>', 'int', 'string[]'], + ' * @method null|gen>|int|string[] method() foo ', ], [ - ' * @method null|gen>|int|array|string[] method() foo ', ['null', 'gen>', 'int', 'array', 'string[]'], + ' * @method null|gen>|int|array|string[] method() foo ', ], [ - '/** @return this */', ['this'], + '/** @return this */', ], [ - '/** @return @this */', ['@this'], + '/** @return @this */', ], [ - '/** @return $SELF|int */', ['$SELF', 'int'], + '/** @return $SELF|int */', ], [ - '/** @var array', ['array'], + '/** @var array', ], [ - " * @return int\n", ['int'], + " * @return int\n", ], [ - " * @return int\r\n", ['int'], + " * @return int\r\n", ], [ - '/** @var Collection, Foo>', ['Collection, Foo>'], + '/** @var Collection, Foo>', ], [ - '/** @var int | string', ['int', 'string'], + '/** @var int | string', ], [ - '/** @var Foo::*', ['Foo::*'], + '/** @var Foo::*', ], [ - '/** @var Foo::A', ['Foo::A'], + '/** @var Foo::A', ], [ - '/** @var Foo::A|Foo::B', ['Foo::A', 'Foo::B'], + '/** @var Foo::A|Foo::B', ], [ - '/** @var Foo::A*', ['Foo::A*'], + '/** @var Foo::A*', ], [ - '/** @var array|null', ['array', 'null'], + '/** @var array|null', ], [ - '/** @var null|true|false|1|1.5|\'a\'|"b"', ['null', 'true', 'false', '1', '1.5', "'a'", '"b"'], + '/** @var null|true|false|1|1.5|\'a\'|"b"', ], [ - '/** @param int | "a" | A, E> $foo */', ['int', '"a"', 'A, E>'], + '/** @param int | "a" | A, E> $foo */', ], [ - '/** @var class-string */', ['class-string'], + '/** @var class-string */', ], [ - '/** @var A&B */', ['A&B'], + '/** @var A&B */', ], [ - '/** @var A & B */', ['A & B'], + '/** @var A & B */', ], [ - '/** @var array{1: bool, 2: bool} */', ['array{1: bool, 2: bool}'], + '/** @var array{1: bool, 2: bool} */', ], [ - '/** @var array{a: int|string, b?: bool} */', ['array{a: int|string, b?: bool}'], + '/** @var array{a: int|string, b?: bool} */', ], [ - '/** @var array{\'a\': "a", "b"?: \'b\'} */', ['array{\'a\': "a", "b"?: \'b\'}'], + '/** @var array{\'a\': "a", "b"?: \'b\'} */', ], [ - '/** @var array { a : int | string , b ? : A } */', ['array { a : int | string , b ? : A }'], + '/** @var array { a : int | string , b ? : A } */', ], [ - '/** @param callable(string) $function', ['callable(string)'], + '/** @param callable(string) $function', ], [ - '/** @param callable(string): bool $function', ['callable(string): bool'], + '/** @param callable(string): bool $function', ], [ - '/** @param callable(array, array): bool $function', ['callable(array, array): bool'], + '/** @param callable(array, array): bool $function', ], [ - '/** @param array $function', ['array'], + '/** @param array $function', ], [ - '/** @param callable(string): callable(int) $function', ['callable(string): callable(int)'], + '/** @param callable(string): callable(int) $function', ], [ - '/** @param callable(string) : callable(int) : bool $function', ['callable(string) : callable(int) : bool'], + '/** @param callable(string) : callable(int) : bool $function', ], [ - '* @param TheCollection|string[]|null $x', ['TheCollection', 'string[]', 'null'], + '* @param TheCollection|string[]|null $x', ], [ - '/** @param Closure(string) $function', ['Closure(string)'], + '/** @param Closure(string) $function', ], [ - '/** @param array < int , callable ( string ) : bool > $function', ['array < int , callable ( string ) : bool >'], + '/** @param array < int , callable ( string ) : bool > $function', ], ]; } @@ -485,7 +465,7 @@ public function testTypes(array $expected, array $new, string $input, string $ou static::assertSame($output, $line->getContent()); } - public function provideTypesCases() + public function provideTypesCases(): array { return [ [['Foo', 'null'], ['Bar[]'], ' * @param Foo|null $foo', ' * @param Bar[] $foo'], @@ -510,7 +490,7 @@ public function testNormalizedTypes(array $expected, string $input): void static::assertSame($expected, $tag->getNormalizedTypes()); } - public function provideNormalizedTypesCases() + public function provideNormalizedTypesCases(): array { return [ [['null', 'string'], '* @param StRiNg|NuLl $foo'], @@ -564,7 +544,7 @@ public function testGetTypeExpression(array $lines, ?NamespaceAnalysis $namespac static::assertSame($expectedCommonType, $result->getCommonType()); } - public function provideTypeExpressionCases() + public function provideTypeExpressionCases(): \Generator { $appNamespace = new NamespaceAnalysis('App', 'App', 0, 999, 0, 999); $useTraversable = new NamespaceUseAnalysis('Traversable', 'Traversable', false, 0, 999, NamespaceUseAnalysis::TYPE_CLASS); @@ -585,7 +565,7 @@ public function testGetVariableName(array $lines, ?string $expectedVariableName) static::assertSame($expectedVariableName, $annotation->getVariableName()); } - public function provideGetVariableCases() + public function provideGetVariableCases(): \Generator { yield [[new Line('* @param int $foo')], '$foo']; yield [[new Line('* @param int $foo some description')], '$foo']; diff --git a/tests/DocBlock/DocBlockTest.php b/tests/DocBlock/DocBlockTest.php index e7e702abf14..6f217b9ffda 100644 --- a/tests/DocBlock/DocBlockTest.php +++ b/tests/DocBlock/DocBlockTest.php @@ -18,7 +18,7 @@ use PhpCsFixer\Tests\TestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * @@ -178,7 +178,7 @@ public function testMakeMultiLIne(string $inputDocBlock, string $outputDocBlock static::assertSame($outputDocBlock, $doc->getContent()); } - public function provideDocBlocksToConvertToMultiLineCases() + public function provideDocBlocksToConvertToMultiLineCases(): array { return [ 'It keeps a multi line doc block as is' => [ @@ -225,7 +225,7 @@ public function testMakeSingleLine(string $inputDocBlock, string $outputDocBlock static::assertSame($outputDocBlock, $doc->getContent()); } - public function provideDocBlocksToConvertToSingleLineCases() + public function provideDocBlocksToConvertToSingleLineCases(): array { return [ 'It keeps a single line doc block as is' => [ diff --git a/tests/DocBlock/LineTest.php b/tests/DocBlock/LineTest.php index 70e3b2aa023..53c22a3eb60 100644 --- a/tests/DocBlock/LineTest.php +++ b/tests/DocBlock/LineTest.php @@ -19,7 +19,7 @@ use PhpCsFixer\Tests\TestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * @@ -141,15 +141,11 @@ public function testStartOrEndPos(int $pos): void static::assertSame(14 === $pos, $line->isTheEnd()); } - public function provideLinesCases() + public function provideLinesCases(): \Generator { - $cases = []; - foreach (self::$content as $index => $content) { - $cases[] = [$index, $content]; + yield [$index, $content]; } - - return $cases; } /** @@ -163,15 +159,11 @@ public function testUseful(int $pos, bool $useful): void static::assertSame($useful, $line->containsUsefulContent()); } - public function provideLinesWithUsefulCases() + public function provideLinesWithUsefulCases(): \Generator { - $cases = []; - foreach (self::$useful as $index => $useful) { - $cases[] = [$index, $useful]; + yield [$index, $useful]; } - - return $cases; } /** @@ -185,15 +177,11 @@ public function testTag(int $pos, bool $tag): void static::assertSame($tag, $line->containsATag()); } - public function provideLinesWithTagCases() + public function provideLinesWithTagCases(): \Generator { - $cases = []; - foreach (self::$tag as $index => $tag) { - $cases[] = [$index, $tag]; + yield [$index, $tag]; } - - return $cases; } public function testSetContent(): void diff --git a/tests/DocBlock/ShortDescriptionTest.php b/tests/DocBlock/ShortDescriptionTest.php index 524c0307d0a..60265ba290b 100644 --- a/tests/DocBlock/ShortDescriptionTest.php +++ b/tests/DocBlock/ShortDescriptionTest.php @@ -36,7 +36,7 @@ public function testGetEnd(?int $expected, string $input): void static::assertSame($expected, $shortDescription->getEnd()); } - public function provideGetEndCases() + public function provideGetEndCases(): array { return [ [1, '/** diff --git a/tests/DocBlock/TagComparatorTest.php b/tests/DocBlock/TagComparatorTest.php index d0123145af5..54ed60fdda4 100644 --- a/tests/DocBlock/TagComparatorTest.php +++ b/tests/DocBlock/TagComparatorTest.php @@ -20,7 +20,7 @@ use PhpCsFixer\Tests\TestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * @@ -39,7 +39,7 @@ public function testComparatorTogether(string $first, string $second, bool $expe static::assertSame($expected, TagComparator::shouldBeTogether($tag1, $tag2)); } - public function provideComparatorCases() + public function provideComparatorCases(): array { return [ ['return', 'return', true], diff --git a/tests/DocBlock/TagTest.php b/tests/DocBlock/TagTest.php index 715821f7df5..342b03b96fa 100644 --- a/tests/DocBlock/TagTest.php +++ b/tests/DocBlock/TagTest.php @@ -19,7 +19,7 @@ use PhpCsFixer\Tests\TestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * @@ -46,7 +46,7 @@ public function testName(string $expected, string $new, string $input): void static::assertSame($new, $tag->getName()); } - public function provideNameCases() + public function provideNameCases(): array { return [ ['param', 'var', ' * @param Foo $foo'], @@ -72,7 +72,7 @@ public function testValid(bool $expected, string $input): void static::assertSame($expected, $tag->valid()); } - public function provideValidCases() + public function provideValidCases(): array { return [ [true, ' * @param Foo $foo'], diff --git a/tests/DocBlock/TypeExpressionTest.php b/tests/DocBlock/TypeExpressionTest.php index 534ecf26a3d..f947c128f6f 100644 --- a/tests/DocBlock/TypeExpressionTest.php +++ b/tests/DocBlock/TypeExpressionTest.php @@ -37,7 +37,7 @@ public function testGetTypes(string $typesExpression, array $expectedTypes): voi static::assertSame($expectedTypes, $expression->getTypes()); } - public function provideGetTypesCases() + public function provideGetTypesCases(): \Generator { yield ['int', ['int']]; yield ['Foo[][]', ['Foo[][]']]; @@ -97,7 +97,7 @@ public function testGetCommonType(string $typesExpression, ?string $expectedComm static::assertSame($expectedCommonType, $expression->getCommonType()); } - public function provideCommonTypeCases() + public function provideCommonTypeCases(): \Generator { $globalNamespace = new NamespaceAnalysis('', '', 0, 999, 0, 999); $appNamespace = new NamespaceAnalysis('App', 'App', 0, 999, 0, 999); @@ -144,6 +144,7 @@ public function provideCommonTypeCases() yield ['int|null', 'int']; yield ['null|int', 'int']; yield ['void', 'void']; + yield ['never', 'never']; yield ['array|Traversable', 'iterable', null, [$useTraversable]]; yield ['array|Traversable', 'iterable', $globalNamespace, [$useTraversable]]; yield ['array|Traversable', 'iterable', $appNamespace, [$useTraversable]]; @@ -166,7 +167,7 @@ public function testAllowsNull(string $typesExpression, bool $expectNullAllowed) static::assertSame($expectNullAllowed, $expression->allowsNull()); } - public function provideAllowsNullCases() + public function provideAllowsNullCases(): \Generator { yield ['null', true]; yield ['mixed', true]; diff --git a/tests/FileReaderTest.php b/tests/FileReaderTest.php index 1024f485acb..b099fa89e76 100644 --- a/tests/FileReaderTest.php +++ b/tests/FileReaderTest.php @@ -41,7 +41,6 @@ public function testCreateSingleton(): void { $instance = FileReader::createSingleton(); - static::assertInstanceOf(\PhpCsFixer\FileReader::class, $instance); static::assertSame($instance, FileReader::createSingleton()); } diff --git a/tests/Fixer/Alias/ArrayPushFixerTest.php b/tests/Fixer/Alias/ArrayPushFixerTest.php index e88533e3f13..979da5a36fe 100644 --- a/tests/Fixer/Alias/ArrayPushFixerTest.php +++ b/tests/Fixer/Alias/ArrayPushFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Alias\ArrayPushFixer @@ -27,14 +25,13 @@ final class ArrayPushFixerTest extends AbstractFixerTestCase { /** * @dataProvider provideFixCases - * @requires PHP 7.0 */ public function testFix(string $expected, ?string $input = null): void { $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield 'minimal' => [ 'doTest($expected, $input); + } - yield [ - '= 80000) { - yield [ - 'c[2], $b19);', - ]; - } + yield [ + 'doTest($expected, $input); + } + + public function provideFix80Cases(): \Generator + { + yield [ + 'c[2], $b19);', + ]; + } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, string $input): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'simple 8.1' => [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'plain' => [ diff --git a/tests/Fixer/Alias/EregToPregFixerTest.php b/tests/Fixer/Alias/EregToPregFixerTest.php index 86c8b01348f..d4834bdd840 100644 --- a/tests/Fixer/Alias/EregToPregFixerTest.php +++ b/tests/Fixer/Alias/EregToPregFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $cases = [ ['= 70400) { - $cases[] = [ - 'doTest($expected, $input); + } + + public function provideFixPhp74Cases(): \Generator + { + yield [ + ' + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Fixer\Alias; + +use PhpCsFixer\Tests\Test\AbstractFixerTestCase; + +/** + * @author Alexander M. Turek + * + * @internal + * + * @covers \PhpCsFixer\Fixer\Alias\ModernizeStrposFixer + */ +final class ModernizeStrposFixerTest extends AbstractFixerTestCase +{ + /** + * @dataProvider provideFixCases + */ + public function testFix(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFixCases(): \Generator + { + yield 'yoda ===' => [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + '', + '', + ]; + + yield [ + ' [ + ' [ + ' [ + '', + ]; + + yield 'none zero int' => [ + ' [ + ' 0) {}', + ]; + + yield 'lesser condition' => [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' $b;', + ]; + } +} diff --git a/tests/Fixer/Alias/NoAliasFunctionsFixerTest.php b/tests/Fixer/Alias/NoAliasFunctionsFixerTest.php index cd55c34f72d..a22023da46a 100644 --- a/tests/Fixer/Alias/NoAliasFunctionsFixerTest.php +++ b/tests/Fixer/Alias/NoAliasFunctionsFixerTest.php @@ -34,36 +34,46 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $finalCases = []; $defaultSets = [ '@internal', '@IMAP', '@pg', ]; + foreach ($this->provideAllCases() as $set => $cases) { if (\in_array($set, $defaultSets, true)) { - $finalCases = array_merge($finalCases, $cases); + yield from $cases; } else { foreach ($cases as $case) { - $finalCases[] = [$case[0]]; + yield [$case[0]]; } } } // static case to fix - in case previous generation is broken - $finalCases[] = [ + yield [ ' mxrr' => [ + 'doTest($expected, $input); } - public function provideFixWithConfigurationCases() + public function provideFixWithConfigurationCases(): \Generator { - $finalCases = [ - '@internal' => [ - ' ['@internal']], - ], - '@IMAP' => [ - ' ['@IMAP']], - ], - '@mbreg' => [ - ' ['@mbreg']], - ], - '@all' => [ - ' ['@all']], - ], - '@IMAP, @mbreg' => [ - ' ['@IMAP', '@mbreg']], - ], - '@time' => [ - ' ['@time']], - ], - '@exif' => [ - ' ['@exif']], - ], + yield '@internal' => [ + ' ['@internal']], + ]; + + yield '@IMAP' => [ + ' ['@IMAP']], + ]; + + yield '@mbreg' => [ + ' ['@mbreg']], + ]; + + yield '@all' => [ + ' ['@all']], + ]; + + yield '@IMAP, @mbreg' => [ + ' ['@IMAP', '@mbreg']], + ]; + + yield '@time' => [ + ' ['@time']], + ]; + + yield '@exif' => [ + ' ['@exif']], ]; foreach ($this->provideAllCases() as $set => $cases) { foreach ($cases as $case) { - $finalCases[] = [ + yield [ $case[0], $case[1] ?? null, ['sets' => [$set]], ]; } } + } - return $finalCases; + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); } - private function provideAllCases(): array + public function provideFix81Cases(): \Generator + { + yield 'simple 8.1' => [ + ' $allAliases */ $allAliases = $reflectionConstant->getValue(); - $finalCases = []; $sets = $allAliases; unset($sets['@time']); // Tested manually $sets = array_keys($sets); + foreach ($sets as $set) { $aliases = $allAliases[$set]; - $cases = []; + foreach ($aliases as $alias => $master) { // valid cases $cases[] = ["{$alias}(\$a);"]; @@ -282,33 +308,36 @@ class '.$alias.' extends '.ucfirst($alias).'ing{ " $cases; } - - return $finalCases; } } diff --git a/tests/Fixer/Alias/NoAliasLanguageConstructCallFixerTest.php b/tests/Fixer/Alias/NoAliasLanguageConstructCallFixerTest.php index 410ca8526e8..be0ccbe4e24 100644 --- a/tests/Fixer/Alias/NoAliasLanguageConstructCallFixerTest.php +++ b/tests/Fixer/Alias/NoAliasLanguageConstructCallFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Alias\NoAliasLanguageConstructCallFixer @@ -33,7 +31,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Alias/NoMixedEchoPrintFixerTest.php b/tests/Fixer/Alias/NoMixedEchoPrintFixerTest.php index be848a24693..c1e1203d2b4 100644 --- a/tests/Fixer/Alias/NoMixedEchoPrintFixerTest.php +++ b/tests/Fixer/Alias/NoMixedEchoPrintFixerTest.php @@ -15,11 +15,11 @@ namespace PhpCsFixer\Tests\Fixer\Alias; use PhpCsFixer\AbstractFixer; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** * @author Sullivan Senechal - * @author SpacePossum * * @internal * @@ -38,7 +38,7 @@ public function testFixEchoToPrint(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideEchoToPrintFixCases() + public function provideEchoToPrintFixCases(): array { return [ [ @@ -135,9 +135,9 @@ public function provideEchoToPrintFixCases() ]; } - public static function provideEchoToPrintFixNewCases() + public static function provideEchoToPrintFixNewCases(): \Generator { - foreach (self::getCodeSnippetsToConvertBothWays() as $name => $codeSnippet) { + foreach (self::getCodeSnippetsToConvertBothWays() as $codeSnippet) { yield [ sprintf($codeSnippet, 'print'), sprintf($codeSnippet, 'echo'), @@ -156,7 +156,7 @@ public function testFixPrintToEcho(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function providePrintToEchoFixCases() + public function providePrintToEchoFixCases(): array { return [ [ @@ -274,9 +274,9 @@ function testFunction() { ]; } - public static function providePrintToEchoFixNewCases() + public static function providePrintToEchoFixNewCases(): \Generator { - foreach (self::getCodeSnippetsToConvertBothWays() as $name => $codeSnippet) { + foreach (self::getCodeSnippetsToConvertBothWays() as $codeSnippet) { yield [ sprintf($codeSnippet, 'echo'), sprintf($codeSnippet, 'print'), @@ -296,13 +296,13 @@ public function testDefaultConfig(): void */ public function testWrongConfig(array $wrongConfig, string $expectedMessage): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches($expectedMessage); $this->fixer->configure($wrongConfig); } - public function provideWrongConfigCases() + public function provideWrongConfigCases(): array { return [ [ @@ -324,7 +324,7 @@ public function provideWrongConfigCases() ]; } - private static function assertCandidateTokenType($expected, AbstractFixer $fixer): void + private static function assertCandidateTokenType(int $expected, AbstractFixer $fixer): void { $reflectionProperty = new \ReflectionProperty($fixer, 'candidateTokenType'); $reflectionProperty->setAccessible(true); @@ -332,7 +332,7 @@ private static function assertCandidateTokenType($expected, AbstractFixer $fixer static::assertSame($expected, $reflectionProperty->getValue($fixer)); } - private static function getCodeSnippetsToConvertBothWays() + private static function getCodeSnippetsToConvertBothWays(): \Generator { yield 'inside of HTML' => '
'; diff --git a/tests/Fixer/Alias/PowToExponentiationFixerTest.php b/tests/Fixer/Alias/PowToExponentiationFixerTest.php index 3ad1da2ef06..3b4a23ce641 100644 --- a/tests/Fixer/Alias/PowToExponentiationFixerTest.php +++ b/tests/Fixer/Alias/PowToExponentiationFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\AbstractFunctionReferenceFixer @@ -34,9 +32,9 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } + /** + * @dataProvider provideFixPre80Cases + * @requires PHP <8.0 + */ + public function testFixPre80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield [ - 'doTest($expected); } - public function provideNotFixCases() + public function provideNotFixCases(): array { return [ [ @@ -273,7 +277,7 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ @@ -296,7 +300,7 @@ public function testFix74(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ [ @@ -315,7 +319,7 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): array { return [ [ diff --git a/tests/Fixer/Alias/RandomApiMigrationFixerTest.php b/tests/Fixer/Alias/RandomApiMigrationFixerTest.php index fc1ffc0ec72..be485fa8780 100644 --- a/tests/Fixer/Alias/RandomApiMigrationFixerTest.php +++ b/tests/Fixer/Alias/RandomApiMigrationFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\Alias; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** @@ -28,7 +29,7 @@ final class RandomApiMigrationFixerTest extends AbstractFixerTestCase { public function testConfigureCheckSearchFunction(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[random_api_migration\] Invalid configuration: Function "is_null" is not handled by the fixer\.$#'); $this->fixer->configure(['replacements' => ['is_null' => 'random_int']]); @@ -36,7 +37,7 @@ public function testConfigureCheckSearchFunction(): void public function testConfigureCheckReplacementType(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[random_api_migration\] Invalid configuration: Replacement for function "rand" must be a string, "NULL" given\.$#'); $this->fixer->configure(['replacements' => ['rand' => null]]); @@ -184,18 +185,33 @@ public function testFix73(string $expected, string $input, array $config = []): $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): \Generator { - return [ - [ - ' ['rand' => 'random_int', 'mt_rand' => 'random_int']], - ], - [ - ' ['rand' => 'random_int', 'mt_rand' => 'random_int']], + ]; + + yield [ + 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'simple 8.1' => [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'null cast' => [ @@ -232,7 +230,7 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ 'null cast' => [ diff --git a/tests/Fixer/ArrayNotation/ArraySyntaxFixerTest.php b/tests/Fixer/ArrayNotation/ArraySyntaxFixerTest.php index bd118749cd6..26f0b4750e0 100644 --- a/tests/Fixer/ArrayNotation/ArraySyntaxFixerTest.php +++ b/tests/Fixer/ArrayNotation/ArraySyntaxFixerTest.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\Tests\Fixer\ArrayNotation; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** * @author Sebastiaan Stok * @author Gregor Harlan - * @author SpacePossum * * @internal * @@ -29,7 +29,7 @@ final class ArraySyntaxFixerTest extends AbstractFixerTestCase { public function testInvalidConfiguration(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[array_syntax\] Invalid configuration: The option "a" does not exist\. Defined options are: "syntax"\.$#'); $this->fixer->configure(['a' => 1]); @@ -53,7 +53,7 @@ public function testFixLongSyntax(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideLongSyntaxCases() + public function provideLongSyntaxCases(): array { return [ ['doTest($expected, $input); } - public function provideShortSyntaxCases() + public function provideShortSyntaxCases(): array { return [ [' * @author Dariusz Rumiński - * @author Graham Campbell + * @author Graham Campbell * * @internal * @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -104,7 +104,7 @@ public function testFixPhp74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ diff --git a/tests/Fixer/ArrayNotation/NoTrailingCommaInSinglelineArrayFixerTest.php b/tests/Fixer/ArrayNotation/NoTrailingCommaInSinglelineArrayFixerTest.php index 25de8e3d624..d3c76c0efea 100644 --- a/tests/Fixer/ArrayNotation/NoTrailingCommaInSinglelineArrayFixerTest.php +++ b/tests/Fixer/ArrayNotation/NoTrailingCommaInSinglelineArrayFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ diff --git a/tests/Fixer/ArrayNotation/NoWhitespaceBeforeCommaInArrayFixerTest.php b/tests/Fixer/ArrayNotation/NoWhitespaceBeforeCommaInArrayFixerTest.php index cf55971a9ae..f0743615364 100644 --- a/tests/Fixer/ArrayNotation/NoWhitespaceBeforeCommaInArrayFixerTest.php +++ b/tests/Fixer/ArrayNotation/NoWhitespaceBeforeCommaInArrayFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ //old style array @@ -150,7 +150,7 @@ public function testFix73(string $expected, ?string $input = null, array $config $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ @@ -181,7 +181,7 @@ public function testFixPhp74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ diff --git a/tests/Fixer/ArrayNotation/NormalizeIndexBraceFixerTest.php b/tests/Fixer/ArrayNotation/NormalizeIndexBraceFixerTest.php index fd59510599d..28440e2fdd8 100644 --- a/tests/Fixer/ArrayNotation/NormalizeIndexBraceFixerTest.php +++ b/tests/Fixer/ArrayNotation/NormalizeIndexBraceFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/ArrayNotation/TrimArraySpacesFixerTest.php b/tests/Fixer/ArrayNotation/TrimArraySpacesFixerTest.php index a7e5ba0ea8a..4250fe3323d 100644 --- a/tests/Fixer/ArrayNotation/TrimArraySpacesFixerTest.php +++ b/tests/Fixer/ArrayNotation/TrimArraySpacesFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/ArrayNotation/WhitespaceAfterCommaInArrayFixerTest.php b/tests/Fixer/ArrayNotation/WhitespaceAfterCommaInArrayFixerTest.php index 6f4d18b6603..3fb8116697b 100644 --- a/tests/Fixer/ArrayNotation/WhitespaceAfterCommaInArrayFixerTest.php +++ b/tests/Fixer/ArrayNotation/WhitespaceAfterCommaInArrayFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ //old style array @@ -124,7 +124,7 @@ public function testFixPhp74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ diff --git a/tests/Fixer/Basic/BracesFixerTest.php b/tests/Fixer/Basic/BracesFixerTest.php index fe0ef98e16c..110e7265e68 100644 --- a/tests/Fixer/Basic/BracesFixerTest.php +++ b/tests/Fixer/Basic/BracesFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\Basic; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Fixer\Basic\BracesFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\WhitespacesFixerConfig; @@ -33,7 +34,7 @@ final class BracesFixerTest extends AbstractFixerTestCase public function testInvalidConfigurationClassyConstructs(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[braces\] Invalid configuration: The option "position_after_functions_and_oop_constructs" with value "neither" is invalid\. Accepted values are: "next", "same"\.$#'); $this->fixer->configure(['position_after_functions_and_oop_constructs' => 'neither']); @@ -789,6 +790,12 @@ public function bar() { ', ], + [ + ' + $item) if ($item): ?> + +', + ], ]; } @@ -2960,23 +2967,6 @@ public function provideFixCommentBeforeBraceCases() ?>', ], - ]; - } - - /** - * @dataProvider provideFixCommentBeforeBrace70Cases - * @requires PHP 7.0 - */ - public function testFixCommentBeforeBrace70(string $expected, ?string $input = null, array $configuration = []): void - { - $this->fixer->configure($configuration); - - $this->doTest($expected, $input); - } - - public function provideFixCommentBeforeBrace70Cases() - { - return [ [ 'doTest($expected, $input, $file); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield $this->prepareTestCase('test-utf8.case1.php', 'test-utf8.case1-bom.php'); @@ -42,7 +42,7 @@ public function provideFixCases() yield ['getTestFile(__DIR__.'/../../Fixtures/FixerTest/encoding/'.$expectedFilename); $inputFile = $inputFilename ? $this->getTestFile(__DIR__.'/../../Fixtures/FixerTest/encoding/'.$inputFilename) : null; diff --git a/tests/Fixer/Basic/NonPrintableCharacterFixerTest.php b/tests/Fixer/Basic/NonPrintableCharacterFixerTest.php index 5df360ce28e..5cdc794bfcf 100644 --- a/tests/Fixer/Basic/NonPrintableCharacterFixerTest.php +++ b/tests/Fixer/Basic/NonPrintableCharacterFixerTest.php @@ -50,7 +50,7 @@ public function testFixWithoutEscapeSequences(string $expected, ?string $input = $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -109,7 +109,6 @@ function f(string $p) /** * @dataProvider provideFixWithEscapeSequencesInStringsCases - * @requires PHP 7.0 */ public function testFixWithEscapeSequencesInStrings(string $expected, ?string $input = null): void { @@ -120,7 +119,7 @@ public function testFixWithEscapeSequencesInStrings(string $expected, ?string $i $this->doTest($expected, $input); } - public function provideFixWithEscapeSequencesInStringsCases() + public function provideFixWithEscapeSequencesInStringsCases(): array { return [ [ diff --git a/tests/Fixer/Basic/OctalNotationFixerTest.php b/tests/Fixer/Basic/OctalNotationFixerTest.php new file mode 100644 index 00000000000..2fb865cbf37 --- /dev/null +++ b/tests/Fixer/Basic/OctalNotationFixerTest.php @@ -0,0 +1,72 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Fixer\Basic; + +use PhpCsFixer\Tests\Test\AbstractFixerTestCase; + +/** + * @author SpacePossum + * + * @internal + * + * @covers \PhpCsFixer\Fixer\Basic\OctalNotationFixer + */ +final class OctalNotationFixerTest extends AbstractFixerTestCase +{ + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public static function provideFix81Cases(): \Generator + { + yield [ + ' + * @author Graham Campbell * @author Kuba Werłos * * @internal @@ -40,7 +40,7 @@ public function testFixNew(string $expected, ?string $input = null, ?string $dir $this->doTest($expected, $input, $this->getTestFile(__FILE__)); } - public static function provideFixNewCases() + public static function provideFixNewCases(): \Generator { foreach (['class', 'interface', 'trait'] as $element) { yield sprintf('%s with originally short name', $element) => [ @@ -160,6 +160,7 @@ public static function provideFixNewCases() /** * @dataProvider provideFixCases * @dataProvider provideIgnoredCases + * @dataProvider provideAnonymousClassCases */ public function testFix(string $expected, ?string $input = null, ?\SplFileInfo $file = null, ?string $dir = null): void { @@ -173,7 +174,7 @@ public function testFix(string $expected, ?string $input = null, ?\SplFileInfo $ $this->doTest($expected, $input, $file); } - public function provideFixCases() + public function provideFixCases(): \Generator { $fileProphecy = $this->prophesize(); $fileProphecy->willExtend(\SplFileInfo::class); @@ -362,7 +363,7 @@ class PsrAutoloadingFixer {} ]; } - public function provideIgnoredCases() + public function provideIgnoredCases(): array { $cases = ['.php', 'Foo.class.php', '4Foo.php', '$#.php']; @@ -388,7 +389,7 @@ public function provideIgnoredCases() } } - return array_map(function ($case) { + return array_map(function ($case): array { return [ 'doTest($expected, $input, $this->getTestFile(__FILE__)); - } - - public function provideFix70Cases() + public function provideAnonymousClassCases(): iterable { yield 'class with anonymous class' => [ 'doTest($expected, $input); + } + + public function providePhp80Cases(): \Generator + { + yield 'anonymous + annotation' => [ + ' - * @author SpacePossum * * @internal * @@ -44,50 +43,44 @@ public function testFixUpperGeneratedCases(string $expected, ?string $input = nu $this->doTest($expected, $input); } - public function provideLowerGeneratedCases() + public function provideLowerGeneratedCases(): \Generator { - $cases = []; foreach (['true', 'false', 'null'] as $case) { - $cases[] = [ + yield [ sprintf('doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -144,8 +137,15 @@ public function provideFixCases() class Foo { const TRUE = 1; - const FALSE = 2; + const FALSE = true; const NULL = null; + }', + ''], @@ -166,7 +166,7 @@ public function testFix56(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix56Cases() + public function provideFix56Cases(): array { return [ ['doTest($expected, $input); } - public static function provideFix80Cases() + public static function provideFix80Cases(): array { return [ ['False; } }'], ]; } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public static function provideFix81Cases(): \Generator + { + yield [ + ' + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Fixer\Casing; + +use PhpCsFixer\Tests\Test\AbstractFixerTestCase; + +/** + * @internal + * + * @covers \PhpCsFixer\Fixer\Casing\IntegerLiteralCaseFixer + */ +final class IntegerLiteralCaseFixerTest extends AbstractFixerTestCase +{ + /** + * @dataProvider provideFixCases + */ + public function testFix(string $expected, string $input): void + { + $this->doTest($expected, $input); + } + + public function provideFixCases(): \Generator + { + yield [ + 'doTest($expected, $input); + } + + public static function provideFix74Cases(): \Generator + { + yield [ + 'doTest($expected, $input); + } + + public static function provideFix80Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ @@ -76,7 +76,7 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + ' [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -142,21 +142,6 @@ public function provideFixCases() [ 'doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ [ @@ -212,10 +197,94 @@ public function provideFix71Cases() } /** + * @dataProvider provideFix74Cases + * @requires PHP 7.4 + */ + public function testFix74(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix74Cases(): \Generator + { + yield [ + 'doTest('Self();'); + $this->doTest($expected, $input); + } + + public function provideFix80Cases(): \Generator + { + yield ['Self();']; + + yield [ + 'doTest($expected, $input); + } + + public static function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -96,7 +96,7 @@ public function testFix74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ [ diff --git a/tests/Fixer/Casing/MagicMethodCasingFixerTest.php b/tests/Fixer/Casing/MagicMethodCasingFixerTest.php index 9b3e75ecd22..a8c1cdca84a 100644 --- a/tests/Fixer/Casing/MagicMethodCasingFixerTest.php +++ b/tests/Fixer/Casing/MagicMethodCasingFixerTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Casing\MagicMethodCasingFixer @@ -34,7 +32,7 @@ public function testFix(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { $fixerReflection = new \ReflectionClass(MagicMethodCasingFixer::class); $property = $fixerReflection->getProperty('magicNames'); @@ -165,87 +163,8 @@ public function __unSERIALIZE($payload) { } ', ]; - } - /** - * @dataProvider provideDoNotFixCases - */ - public function testDoNotFix(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideDoNotFixCases() - { - return [ - [ - '__sleep() - /** ->__sleep() */ - echo $a->__sleep; - ', - ], - [ - '__not_magic(); - ', - ], - [ - 'a(); - ', - ], - [ - 'b;', - ], - ]; - } - - /** - * @requires PHP 7.0 - */ - public function testFixPHP7(): void - { - $this->doTest( + yield 'PHP 7 syntax' => [ '__UnSet($foo); // fix - ' - ); + ', + ]; + } + + /** + * @dataProvider provideDoNotFixCases + */ + public function testDoNotFix(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideDoNotFixCases(): array + { + return [ + [ + '__sleep() + /** ->__sleep() */ + echo $a->__sleep; + ', + ], + [ + '__not_magic(); + ', + ], + [ + 'a(); + ', + ], + [ + 'b;', + ], + ]; } /** @@ -362,4 +354,26 @@ public function testFix80(): void '__INVOKE(1, );' ); } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'static call to "__set_state".' => [ + ' [ + '__isset(...);', + '__ISSET(...);', + ]; + } } diff --git a/tests/Fixer/Casing/NativeFunctionCasingFixerTest.php b/tests/Fixer/Casing/NativeFunctionCasingFixerTest.php index 56f276d1894..93888ad7e2a 100644 --- a/tests/Fixer/Casing/NativeFunctionCasingFixerTest.php +++ b/tests/Fixer/Casing/NativeFunctionCasingFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Casing\NativeFunctionCasingFixer @@ -33,7 +31,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -154,6 +152,16 @@ function &Next() { $next2 = & \Next($array2); ', ], + [ + 'name); + } + }', + ], ]; } @@ -166,7 +174,7 @@ public function testFix73(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ @@ -186,10 +194,26 @@ public function provideFix73Cases() } /** + * @dataProvider provideFix80Cases * @requires PHP 8.0 */ - public function testFix80(): void + public function testFix80(string $expected): void { - $this->doTest('STRTOLOWER(1,);'); + $this->doTest($expected); + } + + public function provideFix80Cases(): iterable + { + yield ['STRTOLOWER(1,);']; + + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -99,39 +97,6 @@ function Foo(INTEGER $a) {} B\String\C $y ) {}', ], - ]; - } - - /** - * @requires PHP <7.0 - * - * @dataProvider provideFixPre70Cases - */ - public function testFixPre70(string $expected): void - { - $this->doTest($expected); - } - - public function provideFixPre70Cases() - { - return [ - ['doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ [ @@ -186,7 +151,7 @@ public function testFix72(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix72Cases() + public function provideFix72Cases(): array { return [ [ @@ -205,7 +170,7 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[cast_spaces\] Invalid configuration: The option "a" does not exist\. Defined options are: "space"\.$#'); $this->fixer->configure(['a' => 1]); @@ -33,7 +34,7 @@ public function testInvalidConfigMissingKey(): void public function testInvalidConfigValue(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[cast_spaces\] Invalid configuration: The option "space" with value "double" is invalid\. Accepted values are: "none", "single"\.$#'); $this->fixer->configure(['space' => 'double']); @@ -56,7 +57,7 @@ public function testFixCastsSingleSpace(string $expected, ?string $input = null) $this->doTest($expected, $input); } - public function provideFixCastsCases() + public function provideFixCastsCases(): array { return [ [ @@ -120,7 +121,7 @@ public function testFixCastsNoneSpace(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideNoneSpaceFixCases() + public function provideNoneSpaceFixCases(): array { return [ [ diff --git a/tests/Fixer/CastNotation/LowercaseCastFixerTest.php b/tests/Fixer/CastNotation/LowercaseCastFixerTest.php index f3c8cbd4b9b..195cf2609bc 100644 --- a/tests/Fixer/CastNotation/LowercaseCastFixerTest.php +++ b/tests/Fixer/CastNotation/LowercaseCastFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\CastNotation\LowercaseCastFixer @@ -60,7 +58,7 @@ public function testFix74Deprecated(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { $types = ['boolean', 'bool', 'integer', 'int', 'double', 'float', 'float', 'string', 'array', 'object', 'binary']; @@ -75,12 +73,12 @@ public function provideFixCases() } } - public function provideFixDeprecatedCases() + public function provideFixDeprecatedCases(): \Generator { return $this->createCasesFor('real'); } - private function createCasesFor(string $type) + private function createCasesFor(string $type): \Generator { yield [ sprintf('doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { $multiLinePatternToFix = <<<'FIX' doTest($expected, $input); - } - - public function provideFix70Cases() - { - $tests = [ [ ' $test) { - yield $index => $test; - } + /** + * @dataProvider provideFixPre80Cases + * @requires PHP <8.0 + */ + public function testFixPre80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield [ - 'doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ @@ -252,4 +243,20 @@ public function testFixPrePHP80(): void ;#' ); } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/CastNotation/NoUnsetCastFixerTest.php b/tests/Fixer/CastNotation/NoUnsetCastFixerTest.php index 654c1fc8691..5a73ff98e03 100644 --- a/tests/Fixer/CastNotation/NoUnsetCastFixerTest.php +++ b/tests/Fixer/CastNotation/NoUnsetCastFixerTest.php @@ -32,7 +32,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'simple form I' => [ diff --git a/tests/Fixer/CastNotation/ShortScalarCastFixerTest.php b/tests/Fixer/CastNotation/ShortScalarCastFixerTest.php index 1bff2d470c0..70d33ee92f9 100644 --- a/tests/Fixer/CastNotation/ShortScalarCastFixerTest.php +++ b/tests/Fixer/CastNotation/ShortScalarCastFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\CastNotation\ShortScalarCastFixer @@ -60,7 +58,7 @@ public function testFix74Deprecated(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { foreach (['boolean' => 'bool', 'integer' => 'int', 'double' => 'float', 'binary' => 'string'] as $from => $to) { foreach ($this->createCasesFor($from, $to) as $case) { @@ -69,7 +67,7 @@ public function provideFixCases() } } - public function provideFixDeprecatedCases() + public function provideFixDeprecatedCases(): \Generator { return $this->createCasesFor('real', 'float'); } @@ -82,7 +80,7 @@ public function testNoFix(string $expected): void $this->doTest($expected); } - public function provideNoFixCases() + public function provideNoFixCases(): array { $cases = []; $types = ['string', 'array', 'object']; @@ -101,7 +99,7 @@ public function provideNoFixCases() return $cases; } - private function createCasesFor(string $from, string $to) + private function createCasesFor(string $from, string $to): \Generator { yield [ sprintf('doTest($expected, $input); + } + + public function provideFixCases(): \Generator + { + yield [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + 'fixer, 'findCommentBlockStart'); $method->setAccessible(true); - $result = $method->invoke($this->fixer, $tokens, $index); + $result = $method->invoke($this->fixer, $tokens, $index, 0); static::assertSame( $expected, $result, @@ -60,7 +282,7 @@ public function testCommentBlockStartDetection(int $expected, string $code, int ); } - public function provideCommentBlockStartDetectionCases() + public function provideCommentBlockStartDetectionCases(): array { return [ [ @@ -145,7 +367,7 @@ public function testFixClasses(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixClassesCases() + public function provideFixClassesCases(): array { $cases = []; @@ -392,7 +614,6 @@ public static function method145() } abstract protected function method245(); - // comment final private function method345() @@ -744,7 +965,7 @@ public function testFixTraits(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixTraitsCases() + public function provideFixTraitsCases(): array { $cases = []; @@ -838,7 +1059,7 @@ public function testFixInterface(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixInterfaceCases() + public function provideFixInterfaceCases(): array { $cases = []; $cases[] = [ @@ -923,7 +1144,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ @@ -940,15 +1161,268 @@ public function provideMessyWhitespacesCases() /** * @dataProvider provideConfigCases */ - public function testWithConfig(string $expected, string $input, array $config): void + public function testWithConfig(string $expected, ?string $input, array $config): void { $this->fixer->configure($config); $this->doTest($expected, $input); } - public function provideConfigCases() + public function provideConfigCases(): array { return [ + 'multi line property' => [ + ' true, + 2 => false, + ]; + + // comment2 + private $bar = 1; +}', + ' true, + 2 => false, + ]; // comment2 + private $bar = 1; +}', + ['elements' => ['property' => 'one']], + ], + 'trait group import none' => [ + ' ['trait_import' => 'none']], + ], + [ + ' ['property' => 'none']], + ], + [ + ' ['const' => 'none']], + ], + 'multiple trait import 5954' => [ + ' ['method' => 'one']], + ], + 'multiple trait import with method 5954' => [ + ' ['method' => 'one']], + ], + 'trait group import 5843' => [ + ' ['method' => 'one', 'trait_import' => 'one']], + ], + [ + ' ['method' => 'one', 'trait_import' => 'one']], + ], + 'trait group import 5852' => [ + ' ['const' => 'one', 'method' => 'one', 'property' => 'one', 'trait_import' => 'none']], + ], + [ + ' ['const' => 'one', 'method' => 'one', 'property' => 'one']], + ], [ ' ['const' => 'only_if_meta']], @@ -1271,74 +1754,30 @@ public function __destruct() {} ', ['elements' => ['const' => 'only_if_meta', 'property' => 'only_if_meta', 'method' => 'only_if_meta']], ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - $to = $from = ' ['property' => 'none', 'trait_import' => 'none']], ], ]; } @@ -1355,7 +1794,7 @@ public function testFix71(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ [ @@ -1392,13 +1831,16 @@ public function H1(){} * @dataProvider provideFix74Cases * @requires PHP 7.4 */ - public function testFix74(string $expected, ?string $input, array $config): void + public function testFix74(string $expected, ?string $input = null, array $config = null): void { - $this->fixer->configure($config); + if (null !== $config) { + $this->fixer->configure($config); + } + $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): \Generator { yield [ ' ['property' => 'one']], ]; yield [ @@ -1433,7 +1874,6 @@ class Foo { private array $foo; private array $bar; }', - ['elements' => ['property' => 'one']], ]; yield [ @@ -1479,13 +1919,16 @@ class Entity * @dataProvider provideFixPhp80Cases * @requires PHP 8.0 */ - public function testFixPhp80(string $expected, ?string $input, array $config): void + public function testFixPhp80(string $expected, ?string $input, array $config = null): void { - $this->fixer->configure($config); + if (null !== $config) { + $this->fixer->configure($config); + } + $this->doTest($expected, $input); } - public function provideFixPhp80Cases() + public function provideFixPhp80Cases(): \Generator { yield 'attributes' => [ ' ['property' => 'one']], ]; yield 'attributes minimal' => [ @@ -1535,17 +1977,15 @@ class User2{ }', ' ['property' => 'one']], ]; - yield 'attributes not blocks' => [ + yield 'attribute block' => [ ' "Foo"])] private $email; }', @@ -1555,10 +1995,8 @@ class User3 { private $id; #[ORM\Column("string")] - #[Assert\Email(["message" => "Foo"])] private $email; }', - ['elements' => ['property' => 'one']], ]; yield 'constructor property promotion' => [ @@ -1584,7 +2022,6 @@ public function __construct( private float $z = 0.0, ) {} }', - ['elements' => ['property' => 'one', 'method' => 'one']], ]; yield 'typed properties' => [ @@ -1605,7 +2042,6 @@ class Foo { private int | float | null $c; private int | float | null $d; }', - ['elements' => ['property' => 'one']], ]; yield 'attributes with conditional spacing' => [ @@ -1681,6 +2117,30 @@ class User ', ['elements' => ['property' => 'only_if_meta']], ]; + + yield [ + ' "Foo"])] + private $email; + + private $foo1; #1 + private $foo2; /* @2 */ +}', + ' "Foo"])] + + private $email; + + private $foo1; #1 + + private $foo2; /* @2 */ +}', + ['elements' => ['property' => 'none']], + ]; } /** @@ -1698,7 +2158,6 @@ public function provideFixClassesWithTraitsCases(): iterable class Foo { use SomeTrait1; - use SomeTrait2; public function Bar(){} @@ -1708,8 +2167,67 @@ public function Bar(){} class Foo { use SomeTrait1; + use SomeTrait2; public function Bar(){} +} +', + ]; + } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + ' false, 'single_item_single_line' => false, 'single_line' => false, + 'space_before_parenthesis' => false, ]; $fixer = new ClassDefinitionFixer(); @@ -50,8 +50,6 @@ public function testConfigureDefaultToNull(): void * @param array $config * * @dataProvider provideAnonymousClassesCases - * - * @requires PHP 7.0 */ public function testFixingAnonymousClasses(string $expected, string $input, array $config = []): void { @@ -61,9 +59,6 @@ public function testFixingAnonymousClasses(string $expected, string $input, arra } /** - * @param string $expected PHP source code - * @param string $input PHP source code - * * @dataProvider provideClassesCases */ public function testFixingClasses(string $expected, string $input): void @@ -74,10 +69,6 @@ public function testFixingClasses(string $expected, string $input): void } /** - * @param string $expected PHP source code - * @param string $input PHP source code - * @param array $config - * * @dataProvider provideClassesWithConfigCases */ public function testFixingClassesWithConfig(string $expected, string $input, array $config): void @@ -88,9 +79,6 @@ public function testFixingClassesWithConfig(string $expected, string $input, arr } /** - * @param string $expected PHP source code - * @param string $input PHP source code - * * @dataProvider provideInterfacesCases */ public function testFixingInterfaces(string $expected, string $input): void @@ -101,9 +89,6 @@ public function testFixingInterfaces(string $expected, string $input): void } /** - * @param string $expected PHP source code - * @param string $input PHP source code - * * @dataProvider provideTraitsCases */ public function testFixingTraits(string $expected, string $input): void @@ -115,9 +100,9 @@ public function testFixingTraits(string $expected, string $input): void public function testInvalidConfigurationKey(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( - '/^\[class_definition\] Invalid configuration: The option "a" does not exist\. Defined options are: "multi_line_extends_each_single_line", "single_item_single_line", "single_line"\.$/' + '/^\[class_definition\] Invalid configuration: The option "a" does not exist\. Defined options are: "multi_line_extends_each_single_line", "single_item_single_line", "single_line", "space_before_parenthesis"\.$/' ); $fixer = new ClassDefinitionFixer(); @@ -126,7 +111,7 @@ public function testInvalidConfigurationKey(): void public function testInvalidConfigurationValueType(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( '/^\[class_definition\] Invalid configuration: The option "single_line" with value "z" is expected to be of type "bool", but is of type "string"\.$/' ); @@ -135,7 +120,7 @@ public function testInvalidConfigurationValueType(): void $fixer->configure(['single_line' => 'z']); } - public function provideAnonymousClassesCases() + public function provideAnonymousClassesCases(): array { return [ [ @@ -279,10 +264,20 @@ class# ' [ + ' true], + ], + 'space_before_parenthesis 2' => [ + ' true], + ], ]; } - public function provideClassesCases() + public function provideClassesCases(): array { return array_merge( $this->provideClassyCases('class'), @@ -291,7 +286,7 @@ public function provideClassesCases() ); } - public function provideClassesWithConfigCases() + public function provideClassesWithConfigCases(): array { return [ [ @@ -341,7 +336,7 @@ public function provideClassesWithConfigCases() ]; } - public function provideInterfacesCases() + public function provideInterfacesCases(): array { $cases = array_merge( $this->provideClassyCases('interface'), @@ -378,7 +373,7 @@ interface Test return $cases; } - public function provideTraitsCases() + public function provideTraitsCases(): array { return $this->provideClassyCases('trait'); } @@ -401,7 +396,7 @@ public function testClassyDefinitionInfo(string $source, array $expected): void static::assertSame($expected, $result); } - public function provideClassyDefinitionInfoCases() + public function provideClassyDefinitionInfoCases(): array { return [ [ @@ -480,20 +475,9 @@ public function testClassyInheritanceInfo(string $source, string $label, array $ $this->doTestClassyInheritanceInfo($source, $label, $expected); } - /** - * @param string $source PHP source code - * - * @requires PHP 7.0 - * @dataProvider provideClassyInheritanceInfo7Cases - */ - public function testClassyInheritanceInfo7(string $source, string $label, array $expected): void + public function provideClassyImplementsInfoCases(): \Generator { - $this->doTestClassyInheritanceInfo($source, $label, $expected); - } - - public function provideClassyImplementsInfoCases() - { - $tests = [ + yield from [ '1' => [ ' $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { $multiLine = true; $code = ' 36, 'numberOfImplements' => 2, 'multiLine' => $multiLine], ]; - } - public function provideClassyInheritanceInfo7Cases() - { - return [ + yield from [ [ "fixer->configure([]); $this->doTest($expected, $input); } - public function providePHP70Cases() + public function provideFixCases(): array { return [ [ @@ -661,7 +637,7 @@ public function testFixPHP73(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function providePHP73Cases() + public function providePHP73Cases(): array { return [ [ @@ -690,7 +666,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ @@ -721,7 +697,7 @@ private function doTestClassyInheritanceInfo(string $source, string $label, arra static::assertSame($expected, $result); } - private function provideClassyCases(string $classy) + private function provideClassyCases(string $classy): array { return [ [ @@ -789,7 +765,7 @@ private function provideClassyCases(string $classy) ]; } - private function provideClassyExtendingCases(string $classy) + private function provideClassyExtendingCases(string $classy): array { return [ [ @@ -819,9 +795,14 @@ private function provideClassyExtendingCases(string $classy) ]; } - private function provideClassyImplementsCases() + private function provideClassyImplementsCases(): array { return [ + [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ ['doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $input = $expected = 'doTest($expected, $input); } - public function provideFixWithConfigCases() + public function provideFixWithConfigCases(): array { return [ [ @@ -276,7 +272,6 @@ class B{} * @param string $expected PHP source code * @param null|string $input PHP source code * - * @requires PHP 7.0 * @dataProvider provideAnonymousClassesCases */ public function testAnonymousClassesCases(string $expected, ?string $input = null): void @@ -284,20 +279,24 @@ public function testAnonymousClassesCases(string $expected, ?string $input = nul $this->doTest($expected, $input); } - public function provideAnonymousClassesCases() + public function provideAnonymousClassesCases(): \Generator { - return [ - [ - 'expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( sprintf('#^%s$#', preg_quote('[final_internal_class] Annotation cannot be used in both the include and exclude list, got duplicates: "internal123".', '#')) ); @@ -307,4 +306,22 @@ public function testConfigureSameAnnotationInBothLists(): void 'annotation_exclude' => ['@internal123', 'b'], ]); } + + /** + * @dataProvider provideFix80Cases + * @requires PHP 8.0 + */ + public function testFix80(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix80Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $original = $fixed = $this->getClassElementStubs(); $fixed = str_replace('public function f1', 'final public function f1', $fixed); @@ -100,24 +100,6 @@ abstract public function foo(); abstract public static function bar(); }', ], - ]; - } - - /** - * @param string $expected PHP source code - * @param null|string $input PHP source code - * - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ 'anonymous-class' => [ sprintf( 'doTest($expected, $input); } - public function provideFix72Cases() + public function provideFix72Cases(): array { return [ 'constant visibility' => [ diff --git a/tests/Fixer/ClassNotation/NoBlankLinesAfterClassOpeningFixerTest.php b/tests/Fixer/ClassNotation/NoBlankLinesAfterClassOpeningFixerTest.php index b8b44e80d74..3f5f92e51aa 100644 --- a/tests/Fixer/ClassNotation/NoBlankLinesAfterClassOpeningFixerTest.php +++ b/tests/Fixer/ClassNotation/NoBlankLinesAfterClassOpeningFixerTest.php @@ -42,7 +42,7 @@ public function testFixTraits(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $cases = []; @@ -65,6 +65,7 @@ public function firstMethod() } }', ]; + $cases[] = [ 'doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/ClassNotation/NoNullPropertyInitializationFixerTest.php b/tests/Fixer/ClassNotation/NoNullPropertyInitializationFixerTest.php index 371f920222a..902d9ad6b37 100644 --- a/tests/Fixer/ClassNotation/NoNullPropertyInitializationFixerTest.php +++ b/tests/Fixer/ClassNotation/NoNullPropertyInitializationFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -243,21 +243,6 @@ public function provideFixCases() [ 'doTest($expected, $input); - } - - public function providePhp70Cases() - { - return [ [ 'doTest($expected, $input); } - public function providePhp71Cases() + public function providePhp71Cases(): array { return [ [ @@ -318,7 +303,7 @@ public function testFix74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixPrePHP80Cases() + public function provideFixPrePHP80Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'readonly - cannot have default value, fixer should not crash' => [ + 'doTest($expected, $input); } - public function provideFix70Cases() + public function provideFixCases(): array { return [ [ @@ -72,7 +71,7 @@ public function testSimpleClass(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideSimpleCases() + public function provideSimpleCases(): array { return [ [ @@ -1140,7 +1139,7 @@ public function testFixPhp80(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp80Cases() + public function provideFixPhp80Cases(): \Generator { yield [ <<<'EOF' diff --git a/tests/Fixer/ClassNotation/NoUnneededFinalMethodFixerTest.php b/tests/Fixer/ClassNotation/NoUnneededFinalMethodFixerTest.php index a1ad597ba1e..494a69dfb9c 100644 --- a/tests/Fixer/ClassNotation/NoUnneededFinalMethodFixerTest.php +++ b/tests/Fixer/ClassNotation/NoUnneededFinalMethodFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'default' => [ @@ -179,11 +179,25 @@ static final function baz() {} 'private-method' => [ ' [ @@ -225,21 +239,6 @@ final private function __construct() } }', ], - ]; - } - - /** - * @requires PHP 7.0 - * @dataProvider providePhp70Cases - */ - public function testFixPhp70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function providePhp70Cases() - { - return [ 'anonymous-class-inside' => [ ' [ + 'bar3(); } + private function bar2(){ echo 1; } + + private function bar3(){ echo 2; } +}', + 'bar3(); } + private function bar2(){ echo 1; } + + private final function bar3(){ echo 2; } +}', + ], ]; } @@ -316,7 +357,7 @@ public function testFixConfig(string $expected, string $input, array $config): v $this->doTest($expected, $input); } - public function provideFixConfigCases() + public function provideFixConfigCases(): \Generator { yield [ ' false], ]; } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public static function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -374,7 +375,7 @@ public function testFix71(array $configuration, string $expected, ?string $input $this->doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ [ @@ -443,7 +444,7 @@ public function testFixWithConfiguration(array $configuration, string $expected, $this->doTest($expected, $input); } - public function provideConfigurationCases() + public function provideConfigurationCases(): array { return [ [ @@ -974,7 +975,7 @@ public function testFixWithSortingAlgorithm(array $configuration, string $expect $this->doTest($expected, $input); } - public function provideSortingConfigurationCases() + public function provideSortingConfigurationCases(): array { return [ [ @@ -1259,7 +1260,7 @@ public function testFix74(string $expected, ?string $input = null, ?array $confi $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): \Generator { yield [ 'expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[ordered_class_elements\] Invalid configuration: The option "order" .*\.$/'); $this->fixer->configure(['order' => ['foo']]); @@ -1325,7 +1326,7 @@ public function %s(){} ); } - public function provideWithConfigWithNoCandidateCases() + public function provideWithConfigWithNoCandidateCases(): \Generator { yield ['z', '__construct']; yield ['z', '__destruct']; @@ -1342,7 +1343,7 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixAlphaCases() + public function provideFixAlphaCases(): array { return [ 'single' => [ @@ -84,21 +84,6 @@ class E5 implements Z\X\V, Y\V, X\B, U\B {} 'doTest($expected, $input); - } - - public function provideFixAlpha70Cases() - { - return [ 'nested anonymous classes' => [ 'doTest($expected, $input); } - public function provideFixAlphaDescendCases() + public function provideFixAlphaDescendCases(): array { return [ 'single' => [ @@ -169,7 +154,7 @@ public function testFixLength(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixLengthCases() + public function provideFixLengthCases(): array { return [ 'single' => [ @@ -212,7 +197,7 @@ public function testFixLengthDescend(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideFixLengthDescendCases() + public function provideFixLengthDescendCases(): array { return [ 'single' => [ diff --git a/tests/Fixer/ClassNotation/ProtectedToPrivateFixerTest.php b/tests/Fixer/ClassNotation/ProtectedToPrivateFixerTest.php index b238d3a7ddd..7b59da96d99 100644 --- a/tests/Fixer/ClassNotation/ProtectedToPrivateFixerTest.php +++ b/tests/Fixer/ClassNotation/ProtectedToPrivateFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $attributesAndMethodsOriginal = $this->getAttributesAndMethods(true); $attributesAndMethodsFixed = $this->getAttributesAndMethods(false); @@ -64,8 +64,8 @@ public function provideFixCases() " [ - " [ "doTest($expected, $input); - } - - public function provideFix70Cases() - { - $attributesAndMethodsOriginal = $this->getAttributesAndMethods(true); - $attributesAndMethodsFixed = $this->getAttributesAndMethods(false); - - return [ 'anonymous-class-inside' => [ "doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public static function provideFix80Cases(): \Generator + { + yield [ + 'doTest($expected, $input); + } + + public static function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -142,21 +142,6 @@ public function baz30(Test\Foo\Foo2\Bar $bar); public function baz31(\Test\Foo\Foo2\Bar $bar); }', ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ [ @@ -208,7 +193,7 @@ public function testFixPhp80(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp80Cases() + public function provideFixPhp80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'simple' => [ @@ -178,22 +178,7 @@ public function isBar($foo) 'doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ - 'simple' => [ + 'simple anonymous class' => [ ' [ + 'nested anonymous class' => [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -635,7 +636,7 @@ class Foo $this->doTest($expected, $input); } - public function provideConfigurationCases() + public function provideConfigurationCases(): array { return [ [ @@ -683,7 +684,7 @@ class Foo public function testWrongConfig(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[single_class_element_per_statement\] Invalid configuration: The option "elements" .*\.$/'); $this->fixer->configure(['elements' => ['foo']]); @@ -698,7 +699,7 @@ public function testPHP71(string $expected, string $input): void $this->doTest($expected, $input); } - public function providePHP71Cases() + public function providePHP71Cases(): array { return [ [ @@ -733,19 +734,14 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): \Generator { - return [ - [ - "doTest( @@ -801,7 +797,7 @@ public function testFix74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTestFix74Cases() + public function provideTestFix74Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public function provideFix80Cases(): \Generator + { + yield [ + 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'simple' => [ @@ -250,9 +248,6 @@ class Talker { ]; } - /** - * @requires PHP 7.0 - */ public function testAnonymousClassFixing(): void { $this->doTest( diff --git a/tests/Fixer/ClassNotation/VisibilityRequiredFixerTest.php b/tests/Fixer/ClassNotation/VisibilityRequiredFixerTest.php index fe619e3ea52..03790f63a41 100644 --- a/tests/Fixer/ClassNotation/VisibilityRequiredFixerTest.php +++ b/tests/Fixer/ClassNotation/VisibilityRequiredFixerTest.php @@ -14,11 +14,11 @@ namespace PhpCsFixer\Tests\Fixer\ClassNotation; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** * @author Dariusz Rumiński - * @author SpacePossum * * @internal * @@ -87,8 +87,6 @@ public function aaa() {} } /** - * @param string $input - * * @dataProvider provideFixMethodsCases */ public function testFixMethods(string $expected, string $input = null): void @@ -96,18 +94,7 @@ public function testFixMethods(string $expected, string $input = null): void $this->doTest($expected, $input); } - /** - * @param string $input - * - * @requires PHP 7.0 - * @dataProvider provideFixMethods70Cases - */ - public function testFixMethods70(string $expected, string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFixMethods70Cases(): array + public function provideFixMethodsCases(): iterable { return [ [ @@ -144,12 +131,6 @@ public function testSomethingWithMoney( EOF , ], - ]; - } - - public function provideFixMethodsCases(): array - { - return [ [ <<<'EOF' expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[visibility_required\] Invalid configuration: The option "elements" .*\.$/'); $this->fixer->configure(['elements' => [null]]); @@ -539,16 +520,13 @@ public function testInvalidConfigurationType(): void public function testInvalidConfigurationValue(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[visibility_required\] Invalid configuration: The option "elements" .*\.$/'); $this->fixer->configure(['elements' => ['_unknown_']]); } /** - * @param string $expected expected PHP source after fixing - * @param string $input PHP source to fix - * * @requires PHP 7.1 * @dataProvider provideFixClassConstCases */ @@ -558,7 +536,7 @@ public function testFixClassConst(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixClassConstCases() + public function provideFixClassConstCases(): array { return [ [ @@ -633,9 +611,6 @@ function# <- this is the function $this->doTest($expected, $input); } - /** - * @requires PHP 7.0 - */ public function testAnonymousClassFixing(): void { $this->doTest( @@ -766,7 +741,7 @@ public function testFix74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield ['DateTime();']; yield ['date_create();']; diff --git a/tests/Fixer/Comment/CommentToPhpdocFixerTest.php b/tests/Fixer/Comment/CommentToPhpdocFixerTest.php index b835be48be5..6ad3eb1906f 100644 --- a/tests/Fixer/Comment/CommentToPhpdocFixerTest.php +++ b/tests/Fixer/Comment/CommentToPhpdocFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideTestCases() + public function provideTestCases(): array { return [ [ diff --git a/tests/Fixer/Comment/HeaderCommentFixerTest.php b/tests/Fixer/Comment/HeaderCommentFixerTest.php index 885e64d36ae..69e1c22b306 100644 --- a/tests/Fixer/Comment/HeaderCommentFixerTest.php +++ b/tests/Fixer/Comment/HeaderCommentFixerTest.php @@ -15,6 +15,7 @@ namespace PhpCsFixer\Tests\Fixer\Comment; use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\ConfigurationException\RequiredFixerConfigurationException; use PhpCsFixer\Fixer\Comment\HeaderCommentFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\WhitespacesFixerConfig; @@ -36,7 +37,7 @@ public function testFix(array $configuration, string $expected, string $input): $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -571,13 +572,13 @@ public function testDefaultConfiguration(): void */ public function testMisconfiguration(?array $configuration, string $exceptionMessage): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches("#^\\[header_comment\\] {$exceptionMessage}$#"); $this->fixer->configure($configuration); } - public function provideMisconfigurationCases() + public function provideMisconfigurationCases(): array { return [ [[], 'Missing required configuration: The required option "header" is missing.'], @@ -636,7 +637,7 @@ public function testHeaderGeneration(string $expected, string $header, string $t ); } - public function provideHeaderGenerationCases() + public function provideHeaderGenerationCases(): array { return [ [ @@ -668,7 +669,7 @@ public function testDoNotTouch(string $expected): void $this->doTest($expected); } - public function provideDoNotTouchCases() + public function provideDoNotTouchCases(): array { return [ ["\nexpectException(\PhpCsFixer\ConfigurationException\RequiredFixerConfigurationException::class); + $this->expectException(RequiredFixerConfigurationException::class); $this->doTest('doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/Comment/MultilineCommentOpeningClosingFixerTest.php b/tests/Fixer/Comment/MultilineCommentOpeningClosingFixerTest.php index e6e9023d240..dccc45dedad 100644 --- a/tests/Fixer/Comment/MultilineCommentOpeningClosingFixerTest.php +++ b/tests/Fixer/Comment/MultilineCommentOpeningClosingFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ // fix cases @@ -267,14 +265,14 @@ public function testGetCommentBlock(string $source, int $startIndex, int $endInd $method = new \ReflectionMethod($this->fixer, 'getCommentBlock'); $method->setAccessible(true); - list($foundStart, $foundEnd, $foundIsEmpty) = $method->invoke($this->fixer, $tokens, $startIndex); + [$foundStart, $foundEnd, $foundIsEmpty] = $method->invoke($this->fixer, $tokens, $startIndex); static::assertSame($startIndex, $foundStart, 'Find start index of block failed.'); static::assertSame($endIndex, $foundEnd, 'Find end index of block failed.'); static::assertSame($isEmpty, $foundIsEmpty, 'Is empty comment block detection failed.'); } - public function provideCommentBlockCases() + public function provideCommentBlockCases(): array { $cases = [ [ diff --git a/tests/Fixer/Comment/NoTrailingWhitespaceInCommentFixerTest.php b/tests/Fixer/Comment/NoTrailingWhitespaceInCommentFixerTest.php index cb5877890ec..25a34852b1a 100644 --- a/tests/Fixer/Comment/NoTrailingWhitespaceInCommentFixerTest.php +++ b/tests/Fixer/Comment/NoTrailingWhitespaceInCommentFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Comment/SingleLineCommentStyleFixerTest.php b/tests/Fixer/Comment/SingleLineCommentStyleFixerTest.php index 7cd244193cf..2b6b1c5c6d3 100644 --- a/tests/Fixer/Comment/SingleLineCommentStyleFixerTest.php +++ b/tests/Fixer/Comment/SingleLineCommentStyleFixerTest.php @@ -42,7 +42,7 @@ public function testAsterisk(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideAsteriskCases() + public function provideAsteriskCases(): array { return [ [ @@ -225,7 +225,7 @@ public function testHashCases(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideHashCases() + public function provideHashCases(): array { return [ [ @@ -294,7 +294,7 @@ public function testAllCases(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideAllCases() + public function provideAllCases(): array { return [ [ diff --git a/tests/Fixer/ConstantNotation/NativeConstantInvocationFixerTest.php b/tests/Fixer/ConstantNotation/NativeConstantInvocationFixerTest.php index 98560b80beb..2f8cbed2a33 100644 --- a/tests/Fixer/ConstantNotation/NativeConstantInvocationFixerTest.php +++ b/tests/Fixer/ConstantNotation/NativeConstantInvocationFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\ConstantNotation; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** @@ -29,7 +30,7 @@ public function testConfigureRejectsUnknownConfigurationKey(): void { $key = 'foo'; - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage(sprintf('[native_constant_invocation] Invalid configuration: The option "%s" does not exist.', $key)); $this->fixer->configure([ @@ -44,7 +45,7 @@ public function testConfigureRejectsUnknownConfigurationKey(): void */ public function testConfigureRejectsInvalidExcludeConfigurationElement($element): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage(sprintf( 'Each element must be a non-empty, trimmed string, got "%s" instead.', \is_object($element) ? \get_class($element) : \gettype($element) @@ -64,7 +65,7 @@ public function testConfigureRejectsInvalidExcludeConfigurationElement($element) */ public function testConfigureRejectsInvalidIncludeConfigurationElement($element): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage(sprintf( 'Each element must be a non-empty, trimmed string, got "%s" instead.', \is_object($element) ? \get_class($element) : \gettype($element) @@ -163,22 +164,6 @@ public function provideFixWithDefaultConfigurationCases(): array 'doTest($expected, $input); - } - - public function provideFix70WithDefaultConfigurationCases(): array - { - return [ [' + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Fixer\ControlStructure; + +use PhpCsFixer\Preg; +use PhpCsFixer\Tests\Test\AbstractFixerTestCase; +use PhpCsFixer\WhitespacesFixerConfig; + +/** + * @internal + * + * @covers \PhpCsFixer\Fixer\ControlStructure\ControlStructureContinuationPositionFixer + */ +final class ControlStructureContinuationPositionFixerTest extends AbstractFixerTestCase +{ + /** + * @dataProvider provideFixCases + */ + public function testFix(string $expected, ?string $input = null, array $configuration = null): void + { + if (null !== $configuration) { + $this->fixer->configure($configuration); + } + + $this->doTest($expected, $input); + } + + public function provideFixCases(): iterable + { + yield 'else (same line, default)' => [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' 'next_line'], + ]; + + yield 'elseif (next line)' => [ + ' 'next_line'], + ]; + + yield 'else if (next line)' => [ + ' 'next_line'], + ]; + + yield 'do while (next line)' => [ + ' 'next_line'], + ]; + + yield 'try catch finally (next line)' => [ + ' 'next_line'], + ]; + + yield 'else with comment after closing brace' => [ + ' [ + ' [ + ' [ + ' [ + ' [ + 'fixer->configure($configuration); + } + + $this->fixer->setWhitespacesConfig( + new WhitespacesFixerConfig(' ', "\r\n") + ); + + $this->doTest($expected, $input); + } + + public function provideFixWithWindowsLineEndingsCases(): iterable + { + foreach ($this->provideFixCases() as $label => $case) { + yield $label => [ + Preg::replace('/\n/', "\r\n", $case[0]), + isset($case[1]) ? Preg::replace('/\n/', "\r\n", $case[1]) : null, + $case[2] ?? null, + ]; + } + } +} diff --git a/tests/Fixer/ControlStructure/ElseifFixerTest.php b/tests/Fixer/ControlStructure/ElseifFixerTest.php index 47f81fa139c..c7b6aaebf26 100644 --- a/tests/Fixer/ControlStructure/ElseifFixerTest.php +++ b/tests/Fixer/ControlStructure/ElseifFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ ['doTest($expected, $input); @@ -46,7 +44,7 @@ public function testFixConfig(string $expected, ?string $input = null, ?array $c } } - public function provideFixCases() + public function provideFixCases(): \Generator { yield 'simple "while"' => [ ' + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Fixer\ControlStructure; + +use PhpCsFixer\Tests\Test\AbstractFixerTestCase; + +/** + * @internal + * + * @covers \PhpCsFixer\Fixer\ControlStructure\EmptyLoopConditionFixer + */ +final class EmptyLoopConditionFixerTest extends AbstractFixerTestCase +{ + /** + * @dataProvider provideFixCases + */ + public function testFixConfig(string $expected, ?string $input = null, array $config = null): void + { + if (null !== $config) { + $this->fixer->configure($config); + } + + $this->doTest($expected, $input); + } + + public function provideFixCases(): \Generator + { + yield 'from `for` to `while`' => [ + ' [ + ' [ + ' 'for'], + ]; + + yield 'from `do while` to `for`' => [ + ' 'for'], + ]; + + yield 'multiple `do while` to `while`' => [ + ' [ + ' [ + ' [ + ' 'for'], + ]; + + // space cases + yield 'lot of space' => [ + ' [ + ' 'for'], + ]; + + yield 'not empty `for` condition' => [ + ' [ + ' [ + ' 'for'], + ]; + } +} diff --git a/tests/Fixer/ControlStructure/IncludeFixerTest.php b/tests/Fixer/ControlStructure/IncludeFixerTest.php index dd468a66f8d..c1700a60e14 100644 --- a/tests/Fixer/ControlStructure/IncludeFixerTest.php +++ b/tests/Fixer/ControlStructure/IncludeFixerTest.php @@ -18,7 +18,6 @@ /** * @author Саша Стаменковић - * @author SpacePossum * * @internal * @@ -34,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $template = 'fixer->configure($configuration); + } + $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - return [ - [ - '', - '', - ], - [ - '', + '', + ]; + + yield [ + '

This is visible.

', + '

This is visible.

', + ]; + + yield [ + '

This is visible.

', + null, + ['fix_non_monolithic_code' => false], + ]; + + yield [ + 'Text display.', + 'Text display.', + ['fix_non_monolithic_code' => true], + ]; + + yield [ + 'Text display.', + null, + ['fix_non_monolithic_code' => false], + ]; + + yield [ + '', + '', + ['fix_non_monolithic_code' => true], + ]; + + yield [ + '', + null, + ['fix_non_monolithic_code' => false], ]; } } diff --git a/tests/Fixer/ControlStructure/NoBreakCommentFixerTest.php b/tests/Fixer/ControlStructure/NoBreakCommentFixerTest.php index 1bceea3d05e..0c5d1337f5f 100644 --- a/tests/Fixer/ControlStructure/NoBreakCommentFixerTest.php +++ b/tests/Fixer/ControlStructure/NoBreakCommentFixerTest.php @@ -26,7 +26,7 @@ final class NoBreakCommentFixerTest extends AbstractFixerTestCase { /** - * @dataProvider provideTestFixCases + * @dataProvider provideFixCases */ public function testFix(string $expected, ?string $input = null): void { @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void } /** - * @dataProvider provideTestFixCases + * @dataProvider provideFixCases */ public function testFixWithExplicitDefaultConfiguration(string $expected, ?string $input = null): void { @@ -45,7 +45,7 @@ public function testFixWithExplicitDefaultConfiguration(string $expected, ?strin $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideFixCases(): array { return [ [ @@ -886,21 +886,6 @@ public function provideTestFixCases() break; }', ], - ]; - } - - /** - * @dataProvider provideTestFixPhp70Cases - * @requires PHP 7.0 - */ - public function testFixPhp70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideTestFixPhp70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideTestFixWithDifferentCommentTextCases() + public function provideTestFixWithDifferentCommentTextCases(): array { - $cases = $this->provideTestFixCases(); + $cases = $this->provideFixCases(); - $replaceCommentText = static function (string $php) { + $replaceCommentText = static function (string $php): string { return strtr($php, [ 'No break' => 'Fall-through case!', 'no break' => 'fall-through case!', @@ -1023,12 +1008,13 @@ public function provideTestFixWithDifferentCommentTextCases() foreach ($cases as &$case) { $case[0] = $replaceCommentText($case[0]); + if (isset($case[1])) { $case[1] = $replaceCommentText($case[1]); } } - $cases = array_merge($cases, [ + return array_merge($cases, [ [ 'doTest($expected, $input); } - public function provideTestFixWithDifferentLineEndingCases() + public function provideTestFixWithDifferentLineEndingCases(): \Generator { - $cases = []; - foreach ($this->provideTestFixCases() as $case) { + foreach ($this->provideFixCases() as $case) { $case[0] = str_replace("\n", "\r\n", $case[0]); + if (isset($case[1])) { $case[1] = str_replace("\n", "\r\n", $case[1]); } - $cases[] = $case; + yield $case; } - - return $cases; } public function testFixWithCommentTextWithSpecialRegexpCharacters(): void @@ -1153,7 +1135,7 @@ public function testFixWithCommentTextContainingNewLines(string $text): void ]); } - public function provideFixWithCommentTextContainingNewLinesCases() + public function provideFixWithCommentTextContainingNewLinesCases(): array { return [ ["No\nbreak"], @@ -1179,7 +1161,7 @@ public function testFix80(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'enums' => [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -233,21 +233,6 @@ public function provideFixCases() echo 2; }', ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, string $input): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ 'doTest($expected); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/ControlStructure/NoUnneededControlParenthesesFixerTest.php b/tests/Fixer/ControlStructure/NoUnneededControlParenthesesFixerTest.php index 9d44b9412f9..b4c824c0857 100644 --- a/tests/Fixer/ControlStructure/NoUnneededControlParenthesesFixerTest.php +++ b/tests/Fixer/ControlStructure/NoUnneededControlParenthesesFixerTest.php @@ -51,16 +51,7 @@ public function testFix(string $expected, ?string $input = null, ?string $fixSta $this->fixerTest($expected, $input, $fixStatement); } - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null, ?string $fixStatement = null): void - { - $this->fixerTest($expected, $input, $fixStatement); - } - - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -429,12 +420,6 @@ function foo() { $a = (yield $x); } function foo() { $a = (yield($x)); } ', ], - ]; - } - - public function provideFix70Cases() - { - return [ [ 'getSubject() ?? $obj2); @@ -445,7 +430,6 @@ public function provideFix70Cases() /** * @dataProvider provideFixYieldFromCases - * @requires PHP 7.0 */ public function testFixYieldFrom(string $expected, ?string $input = null): void { @@ -453,7 +437,7 @@ public function testFixYieldFrom(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixYieldFromCases() + public function provideFixYieldFromCases(): array { return [ [ @@ -505,6 +489,37 @@ function foo8() { $a = (yield from($x)); } ]; } + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->fixer->configure(['statements' => ['switch_case']]); + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'enums' => [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ 'simple sample, last token candidate' => [ ' $test) { - yield $index => $test; - } + /** + * @dataProvider provideFixPre80Cases + * @requires PHP <8.0 + */ + public function testFixPre80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield 'no fixes, offset access syntax with curly braces' => [ - ' [ + 'doTest($expected); } - public function provideNoFix7Cases() + public function provideNoFix7Cases(): array { return [ [ @@ -166,7 +170,7 @@ public function testFixNamespace(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixNamespaceCases() + public function provideFixNamespaceCases(): \Generator { yield [ 'doTest($expected, $input); } - public function providePHPCloseTagCases() + public function providePHPCloseTagCases(): array { return [ [ @@ -135,7 +133,7 @@ public function testFixIfElseIfElse(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixIfElseIfElseCases() + public function provideFixIfElseIfElseCases(): array { $expected = 'doTest($expected, $input); } - public function provideFixIfElseCases() + public function provideFixIfElseCases(): \Generator { $expected = 'generateCases($expected, $input); - - foreach ($tests as $index => $test) { - yield $index => $test; - } + yield from $this->generateCases($expected, $input); yield [ 'doTest($expected, $input); } - public function provideFixNestedIfCases() + public function provideFixNestedIfCases(): array { return [ [ @@ -359,7 +353,7 @@ public function testFixEmptyElse(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixEmptyElseCases() + public function provideFixEmptyElseCases(): array { return [ [ @@ -451,9 +445,9 @@ public function testNegativeCases(string $expected): void $this->doTest($expected); } - public function provideNegativeCases() + public function provideNegativeCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } + /** + * @dataProvider provideNegativePhp80Cases + * @requires PHP 8.0 + */ + public function testNegativePhp80Cases(string $expected): void + { + $this->doTest($expected); + } - if (\PHP_VERSION_ID >= 80000) { - $cases = [ - '$bar = $foo1 ?? throw new \Exception($e);', - '$callable = fn() => throw new Exception();', - '$value = $falsableValue ?: throw new InvalidArgumentException();', - '$value = !empty($array) + public function provideNegativePhp80Cases(): \Generator + { + $cases = [ + '$bar = $foo1 ?? throw new \Exception($e);', + '$callable = fn() => throw new Exception();', + '$value = $falsableValue ?: throw new InvalidArgumentException();', + '$value = !empty($array) ? reset($array) : throw new InvalidArgumentException();', - '$a = $condition && throw new Exception();', - '$a = $condition || throw new Exception();', - '$a = $condition and throw new Exception();', - '$a = $condition or throw new Exception();', - ]; + '$a = $condition && throw new Exception();', + '$a = $condition || throw new Exception();', + '$a = $condition and throw new Exception();', + '$a = $condition or throw new Exception();', + ]; - $template = ' $case) { - yield [sprintf('PHP8 Negative case %d', $index) => sprintf($template, $case)]; - } + foreach ($cases as $index => $case) { + yield [sprintf('PHP8 Negative case %d', $index) => sprintf($template, $case)]; } } @@ -660,7 +660,7 @@ public function testBlockDetection(array $expected, string $source, int $index): static::assertSame($expected, $result); } - public function provideBlockDetectionCases() + public function provideBlockDetectionCases(): array { $cases = []; @@ -708,9 +708,8 @@ public function testConditionsWithoutBraces(string $expected, ?string $input = n $this->doTest($expected, $input); } - public function provideConditionsWithoutBracesCases() + public function provideConditionsWithoutBracesCases(): \Generator { - $cases = []; $statements = [ 'die;', 'throw new Exception($i);', @@ -721,59 +720,11 @@ public function provideConditionsWithoutBracesCases() 'foreach($a as $b){throw new Exception($i);}', ]; - if (\PHP_VERSION_ID >= 70000) { - $statements[] = 'throw new class extends Exception{};'; - $statements[] = 'throw new class ($a, 9) extends Exception{ public function z($a, $b){ echo 7;} };'; - } - - if (\PHP_VERSION_ID >= 80000) { - $statements[] = '$b = $a ?? throw new Exception($i);'; - } - - $ifTemplate = 'generateConditionsWithoutBracesCase($statement); } - $cases[] = [ + yield [ 'doTest($expected); + } + + public function provideConditionsWithoutBraces70Cases(): \Generator + { + yield from $this->generateConditionsWithoutBracesCase('throw new class extends Exception{};'); + yield from $this->generateConditionsWithoutBracesCase('throw new class ($a, 9) extends Exception{ public function z($a, $b){ echo 7;} };'); + } + + /** + * @dataProvider provideConditionsWithoutBraces80Cases + * @requires PHP 8.0 + */ + public function testConditionsWithoutBraces80(string $expected): void + { + $this->doTest($expected); + } + + public function provideConditionsWithoutBraces80Cases(): \Generator + { + yield from $this->generateConditionsWithoutBracesCase('$b = $a ?? throw new Exception($i);'); } /** @@ -807,8 +785,8 @@ public function testIsInConditionWithoutBraces(array $indexes, string $input): v $reflection = new \ReflectionObject($this->fixer); $method = $reflection->getMethod('isInConditionWithoutBraces'); $method->setAccessible(true); - $tokens = Tokens::fromCode($input); + foreach ($indexes as $index => $expected) { static::assertSame( $expected, @@ -818,7 +796,7 @@ public function testIsInConditionWithoutBraces(array $indexes, string $input): v } } - public function provideIsInConditionWithoutBracesCases() + public function provideIsInConditionWithoutBracesCases(): array { return [ [ @@ -971,6 +949,50 @@ public function provideIsInConditionWithoutBracesCases() ]; } + private function generateConditionsWithoutBracesCase(string $statement): \Generator + { + $ifTemplate = '> */ diff --git a/tests/Fixer/ControlStructure/SimplifiedIfReturnFixerTest.php b/tests/Fixer/ControlStructure/SimplifiedIfReturnFixerTest.php index 0ad16ba04a7..5c76576b0e4 100644 --- a/tests/Fixer/ControlStructure/SimplifiedIfReturnFixerTest.php +++ b/tests/Fixer/ControlStructure/SimplifiedIfReturnFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'simple' => [ diff --git a/tests/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixerTest.php b/tests/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixerTest.php index 4bcdd875f9a..428760795eb 100644 --- a/tests/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixerTest.php +++ b/tests/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\ControlStructure\SwitchCaseSemicolonToColonFixer @@ -33,9 +31,9 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } - - if (\PHP_VERSION_ID < 80000) { - yield [ - 'doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ + yield from [ 'nested switch in switch case' => [ 'doTest($expected, $input); + } + + public function provideFixPre80Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): array { return [ 'Simple match' => [ diff --git a/tests/Fixer/ControlStructure/SwitchCaseSpaceFixerTest.php b/tests/Fixer/ControlStructure/SwitchCaseSpaceFixerTest.php index 45061485811..dd740b46bca 100644 --- a/tests/Fixer/ControlStructure/SwitchCaseSpaceFixerTest.php +++ b/tests/Fixer/ControlStructure/SwitchCaseSpaceFixerTest.php @@ -33,9 +33,9 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } + /** + * @dataProvider provideFixPre80Cases + * @requires PHP <8.0 + */ + public function testFixPre80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield [ - 'doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): \Generator { - $tests = [ + yield from [ 'alternative syntax |' => [ ' $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 70000) { yield 'simple case' => [ 'doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ 'numeric literal separator' => [ diff --git a/tests/Fixer/ControlStructure/TrailingCommaInMultilineFixerTest.php b/tests/Fixer/ControlStructure/TrailingCommaInMultilineFixerTest.php index b14f284073b..4a20f8394e2 100644 --- a/tests/Fixer/ControlStructure/TrailingCommaInMultilineFixerTest.php +++ b/tests/Fixer/ControlStructure/TrailingCommaInMultilineFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\ControlStructure; +use PhpCsFixer\ConfigurationException\InvalidForEnvFixerConfigurationException; use PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; @@ -37,13 +38,13 @@ final class TrailingCommaInMultilineFixerTest extends AbstractFixerTestCase */ public function testInvalidConfiguration($exceptionMessega, $configuration): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidForEnvFixerConfigurationException::class); + $this->expectException(InvalidForEnvFixerConfigurationException::class); $this->expectExceptionMessage($exceptionMessega); $this->fixer->configure($configuration); } - public static function provideInvalidConfigurationCases() + public static function provideInvalidConfigurationCases(): \Generator { if (\PHP_VERSION_ID < 70300) { yield [ @@ -71,7 +72,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public static function provideFixCases() + public static function provideFixCases(): array { return [ // long syntax tests @@ -410,7 +411,7 @@ public function testFix73(string $expected, ?string $input = null, array $config $this->doTest($expected, $input); } - public static function provideFix73Cases() + public static function provideFix73Cases(): array { return [ [ @@ -573,7 +574,7 @@ public function testFix80(string $expected, ?string $input = null, array $config $this->doTest($expected, $input); } - public static function provideFix80Cases() + public static function provideFix80Cases(): array { return [ [ diff --git a/tests/Fixer/ControlStructure/YodaStyleFixerTest.php b/tests/Fixer/ControlStructure/YodaStyleFixerTest.php index d18f5f3cf7b..ed0ddd82e25 100644 --- a/tests/Fixer/ControlStructure/YodaStyleFixerTest.php +++ b/tests/Fixer/ControlStructure/YodaStyleFixerTest.php @@ -14,11 +14,11 @@ namespace PhpCsFixer\Tests\Fixer\ControlStructure; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** * @author Dariusz Rumiński - * @author SpacePossum * * @internal * @@ -51,9 +51,9 @@ public function testFixInverse(string $expected, ?string $input = null, array $e } } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } - $template = '>=', '&=', '.=', '/=', '%=']; + if (\PHP_VERSION_ID >= 70400) { $assignmentOperators[] = '??='; } $logicalOperators = ['xor', 'or', 'and', '||', '&&']; + if (\PHP_VERSION_ID >= 70400) { $logicalOperators[] = '??'; } @@ -675,6 +673,45 @@ function foo() { sprintf(' $d;'], + [ + 'doTest($input, $expected); } - public function provideLessGreaterCases() + public function provideLessGreaterCases(): array { return [ [ @@ -742,7 +779,7 @@ public function testComplexConfiguration(): void */ public function testInvalidConfig(array $config, string $expectedMessage): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches("#^\\[{$this->fixer->getName()}\\] {$expectedMessage}$#"); $this->fixer->configure($config); @@ -761,75 +798,6 @@ public function testDefinition(): void static::assertInstanceOf(\PhpCsFixer\FixerDefinition\FixerDefinitionInterface::class, $this->fixer->getDefinition()); } - /** - * @dataProvider providePHP70Cases - * @requires PHP 7.0 - */ - public function testPHP70Cases(string $expected, ?string $input = null): void - { - $this->fixer->configure(['equal' => true, 'identical' => true]); - $this->doTest($expected, $input); - } - - /** - * Test with the inverse config. - * - * @dataProvider providePHP70Cases - * @requires PHP 7.0 - */ - public function testPHP70CasesInverse(string $expected, ?string $input = null): void - { - $this->fixer->configure(['equal' => false, 'identical' => false]); - - if (null === $input) { - $this->doTest($expected); - } else { - $this->doTest($input, $expected); - } - } - - public function providePHP70Cases() - { - return [ - [' $d;'], - [ - 'doTest($expected); } - public function provideFixWithConfigCases() + public function provideFixWithConfigCases(): \Generator { - return [ + yield [ [ - [ - 'identical' => false, - ], - ' false, + ], + ' false, - 'identical' => false, - ], - ' false, + 'identical' => false, + ], + 'event == \'created\') { foreach ($revision->getModified() as $col => $data) { $model->$col = $data[\'new\']; @@ -937,7 +905,6 @@ public function provideFixWithConfigCases() $model->$col = $data[\'old\']; } }', - ], ]; } @@ -950,7 +917,7 @@ public function testFixPhp74(string $expected, ?string $input): void $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function providePHP74Cases() + public function providePHP74Cases(): \Generator { - return [ - [ - ' $c === array(1) ? $b : $d;', - null, - [ - 'less_and_greater' => false, - ], - ], + yield [ + ' $c === array(1) ? $b : $d;', + null, [ - ' false, ], ]; + + yield [ + 'doTest($expected, $input); } - public function provideFixPrePHP80Cases() + public function provideFixPrePHP80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ ' true, 'identical' => true], ]; } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'does not make a lot of sense but is valid syntax, do not break 1' => [ + ' [ + 'doTest($expected, $input); } - public function provideFixCases(): array + public function provideFixCases(): \Generator { - $cases = $this->createTestCases([ + yield from $this->createTestCases([ [' /** * @Foo @@ -98,7 +98,7 @@ public function provideFixCases(): array */'], ]); - $cases[] = [ + yield [ 'doTest($expected, $input); } - public function provideFixWithColonCases(): array + public function provideFixWithColonCases(): \Generator { - return $this->createTestCases([ + yield from $this->createTestCases([ [' /** * @Foo @@ -176,4 +174,61 @@ public function provideFixWithColonCases(): array */'], ]); } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'testFixWithSpaceBeforeArgumentAssignmentOnly($expected, $input); } - public function provideFixWithSpaceBeforeArgumentAssignmentOnlyCases() + public function provideFixWithSpaceBeforeArgumentAssignmentOnlyCases(): array { return $this->createTestCases([ [' @@ -940,7 +940,7 @@ public function testFixWithoutSpaceBeforeArgumentAssignmentOnlyWithDifferentLine $this->testFixWithoutSpaceBeforeArgumentAssignmentOnly($expected, $input); } - public function provideFixWithoutSpaceBeforeArgumentAssignmentOnlyCases() + public function provideFixWithoutSpaceBeforeArgumentAssignmentOnlyCases(): array { return $this->createTestCases([ [' @@ -988,7 +988,7 @@ public function testFixWithSpaceAfterArgumentAssignmentOnlyWithDifferentLineEndi $this->testFixWithSpaceAfterArgumentAssignmentOnly($expected, $input); } - public function provideFixWithSpaceAfterArgumentAssignmentOnlyCases() + public function provideFixWithSpaceAfterArgumentAssignmentOnlyCases(): array { return $this->createTestCases([ [' @@ -1036,7 +1036,7 @@ public function testFixWithoutSpaceAfterArgumentAssignmentOnlyWithDifferentLineE $this->testFixWithoutSpaceAfterArgumentAssignmentOnly($expected, $input); } - public function provideFixWithoutSpaceAfterArgumentAssignmentOnlyCases() + public function provideFixWithoutSpaceAfterArgumentAssignmentOnlyCases(): array { return $this->createTestCases([ [' @@ -1084,7 +1084,7 @@ public function testFixWithSpaceBeforeArrayAssignmentEqualOnlyWithDifferentLineE $this->testFixWithSpaceBeforeArrayAssignmentEqualOnly($expected, $input); } - public function provideFixWithSpaceBeforeArrayAssignmentEqualOnlyCases() + public function provideFixWithSpaceBeforeArrayAssignmentEqualOnlyCases(): array { return $this->createTestCases([ [' @@ -1132,7 +1132,7 @@ public function testFixWithoutSpaceBeforeArrayAssignmentEqualOnlyWithDifferentLi $this->testFixWithoutSpaceBeforeArrayAssignmentEqualOnly($expected, $input); } - public function provideFixWithoutSpaceBeforeArrayAssignmentEqualOnlyCases() + public function provideFixWithoutSpaceBeforeArrayAssignmentEqualOnlyCases(): array { return $this->createTestCases([ [' @@ -1180,7 +1180,7 @@ public function testFixWithSpaceAfterArrayAssignmentEqualOnlyWithDifferentLineEn $this->testFixWithSpaceAfterArrayAssignmentEqualOnly($expected, $input); } - public function provideFixWithSpaceAfterArrayAssignmentEqualOnlyCases() + public function provideFixWithSpaceAfterArrayAssignmentEqualOnlyCases(): array { return $this->createTestCases([ [' @@ -1228,7 +1228,7 @@ public function testFixWithoutSpaceAfterArrayAssignmentEqualOnlyWithDifferentLin $this->testFixWithoutSpaceAfterArrayAssignmentEqualOnly($expected, $input); } - public function provideFixWithoutSpaceAfterArrayAssignmentEqualOnlyCases() + public function provideFixWithoutSpaceAfterArrayAssignmentEqualOnlyCases(): array { return $this->createTestCases([ [' @@ -1276,7 +1276,7 @@ public function testFixWithSpaceBeforeArrayAssignmentColonOnlyWithDifferentLineE $this->testFixWithSpaceBeforeArrayAssignmentColonOnly($expected, $input); } - public function provideFixWithSpaceBeforeArrayAssignmentColonOnlyCases() + public function provideFixWithSpaceBeforeArrayAssignmentColonOnlyCases(): array { return $this->createTestCases([ [' @@ -1324,7 +1324,7 @@ public function testFixWithoutSpaceBeforeArrayAssignmentColonOnlyWithDifferentLi $this->testFixWithoutSpaceBeforeArrayAssignmentColonOnly($expected, $input); } - public function provideFixWithoutSpaceBeforeArrayAssignmentColonOnlyCases() + public function provideFixWithoutSpaceBeforeArrayAssignmentColonOnlyCases(): array { return $this->createTestCases([ [' @@ -1372,7 +1372,7 @@ public function testFixWithSpaceAfterArrayAssignmentColonOnlyWithDifferentLineEn $this->testFixWithSpaceAfterArrayAssignmentColonOnly($expected, $input); } - public function provideFixWithSpaceAfterArrayAssignmentColonOnlyCases() + public function provideFixWithSpaceAfterArrayAssignmentColonOnlyCases(): array { return $this->createTestCases([ [' @@ -1420,7 +1420,7 @@ public function testFixWithoutSpaceAfterArrayAssignmentColonOnlyWithDifferentLin $this->testFixWithoutSpaceAfterArrayAssignmentColonOnly($expected, $input); } - public function provideFixWithoutSpaceAfterArrayAssignmentColonOnlyCases() + public function provideFixWithoutSpaceAfterArrayAssignmentColonOnlyCases(): array { return $this->createTestCases([ [' @@ -1465,7 +1465,7 @@ class Foo ); } - public static function provideElementDiscoveringCases() + public static function provideElementDiscoveringCases(): \Generator { yield ['private $foo;']; yield ['private string $foo;']; diff --git a/tests/Fixer/FunctionNotation/CombineNestedDirnameFixerTest.php b/tests/Fixer/FunctionNotation/CombineNestedDirnameFixerTest.php index 1e34c93f28c..7255a5a3725 100644 --- a/tests/Fixer/FunctionNotation/CombineNestedDirnameFixerTest.php +++ b/tests/Fixer/FunctionNotation/CombineNestedDirnameFixerTest.php @@ -27,14 +27,13 @@ final class CombineNestedDirnameFixerTest extends AbstractFixerTestCase { /** * @dataProvider provideFixCases - * @requires PHP 7.0 */ public function testFix(string $expected, ?string $input = null): void { $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -114,7 +113,7 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ @@ -127,4 +126,18 @@ public function provideFix73Cases() ], ]; } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield ['doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'most simple fix case' => [ diff --git a/tests/Fixer/FunctionNotation/FopenFlagsFixerTest.php b/tests/Fixer/FunctionNotation/FopenFlagsFixerTest.php index b980ed4e46f..6da37924db1 100644 --- a/tests/Fixer/FunctionNotation/FopenFlagsFixerTest.php +++ b/tests/Fixer/FunctionNotation/FopenFlagsFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\AbstractFopenFlagFixer @@ -35,7 +33,7 @@ public function testFix(string $expected, string $input, array $config = []): vo $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'missing "b"' => [ @@ -111,7 +109,7 @@ public function testDoNotFix(string $expected): void $this->doTest($expected); } - public function provideDoNotFixCases() + public function provideDoNotFixCases(): array { return [ 'not simple flags' => [ diff --git a/tests/Fixer/FunctionNotation/FunctionDeclarationFixerTest.php b/tests/Fixer/FunctionNotation/FunctionDeclarationFixerTest.php index f5b09d7acae..ebcfe46668a 100644 --- a/tests/Fixer/FunctionNotation/FunctionDeclarationFixerTest.php +++ b/tests/Fixer/FunctionNotation/FunctionDeclarationFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\FunctionNotation; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; @@ -31,7 +32,7 @@ final class FunctionDeclarationFixerTest extends AbstractFixerTestCase public function testInvalidConfigurationClosureFunctionSpacing(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( '#^\[function_declaration\] Invalid configuration: The option "closure_function_spacing" with value "neither" is invalid\. Accepted values are: "none", "one"\.$#' ); @@ -49,7 +50,7 @@ public function testFix(string $expected, ?string $input = null, array $configur $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -354,23 +355,6 @@ function foo() /* bar */ ', self::$configurationClosureSpacingNone, ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function test70(string $expected, ?string $input = null, array $configuration = []): void - { - $this->fixer->configure($configuration); - - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [''], @@ -391,7 +375,7 @@ public function test74(string $expected, ?string $input = null, array $configura $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ [ @@ -463,7 +447,7 @@ public function testFixPhp80(string $expected, ?string $input = null, array $con $this->doTest($expected, $input); } - public function provideFixPhp80Cases() + public function provideFixPhp80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -183,21 +183,6 @@ public function provideFixCases() 'doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [''], ]; @@ -212,7 +197,7 @@ public function testFix74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ [ @@ -270,7 +255,7 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield ["doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'simple' => [ @@ -103,21 +101,6 @@ public function provideFixCases() $f = function() use ($a) { return function() use ($a) { return function() use ($a) { return function() use ($a) { }; }; }; }; ', ], - ]; - } - - /** - * @requires PHP 7.0 - * @dataProvider providePhp70Cases - */ - public function testFixPhp70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function providePhp70Cases() - { - return [ 'anonymous class' => [ 'doTest($expected); } - public function provideDoNotFixCases() + public function provideDoNotFixCases(): \Generator { - $tests = [ + yield from [ 'reference' => [ '', ], @@ -196,10 +179,6 @@ public function provideDoNotFixCases() ], ]; - foreach ($tests as $index => $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 70100) { yield 'super global, invalid from PHP7.1' => [ '', @@ -220,7 +199,7 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield 'simple' => [ 'fixer->configure($configuration); @@ -77,7 +75,7 @@ public function testFixWithDifferentLineEndings(string $expected, ?string $input ); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -851,7 +849,7 @@ public function testFix56(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix56Cases() + public function provideFix56Cases(): array { return [ [ @@ -871,7 +869,7 @@ public function testFix73(string $expected, ?string $input = null, array $config $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ @@ -943,7 +941,7 @@ public function testFix74(string $expected, ?string $input = null, array $config $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ [ @@ -962,4 +960,26 @@ public function provideFix74Cases() ], ]; } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + '', + '', + ]; + } } diff --git a/tests/Fixer/FunctionNotation/NativeFunctionInvocationFixerTest.php b/tests/Fixer/FunctionNotation/NativeFunctionInvocationFixerTest.php index 517c9d9d071..cb0117a1055 100644 --- a/tests/Fixer/FunctionNotation/NativeFunctionInvocationFixerTest.php +++ b/tests/Fixer/FunctionNotation/NativeFunctionInvocationFixerTest.php @@ -14,13 +14,13 @@ namespace PhpCsFixer\Tests\Fixer\FunctionNotation; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Fixer\FunctionNotation\NativeFunctionInvocationFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** * @author Andreas Möller - * @author SpacePossum * * @internal * @@ -32,7 +32,7 @@ public function testConfigureRejectsUnknownConfigurationKey(): void { $key = 'foo'; - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage(sprintf( '[native_function_invocation] Invalid configuration: The option "%s" does not exist.', $key @@ -50,7 +50,7 @@ public function testConfigureRejectsUnknownConfigurationKey(): void */ public function testConfigureRejectsInvalidConfigurationElement($element): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage(sprintf( 'Each element must be a non-empty, trimmed string, got "%s" instead.', \is_object($element) ? \get_class($element) : \gettype($element) @@ -99,7 +99,7 @@ public function testConfigureIncludeSets( } } - public function provideConfigureIncludeSetsCases() + public function provideConfigureIncludeSetsCases(): array { return [ [['foo', 'bar']], @@ -302,7 +302,7 @@ public function testFixWithNamespaceConfiguration(string $expected, ?string $inp $this->doTest($expected, $input); } - public function provideFixWithNamespaceConfigurationCases() + public function provideFixWithNamespaceConfigurationCases(): array { return [ [ @@ -471,9 +471,9 @@ public function testFixWithConfiguredInclude(string $expected, ?string $input = $this->doTest($expected, $input); } - public function provideFixWithConfiguredIncludeCases() + public function provideFixWithConfiguredIncludeCases(): \Generator { - $tests = [ + yield from [ 'include set + 1, exclude 1' => [ ' $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { yield 'include @compiler_optimized with strict enabled' => [ 'testFixWithConfiguredInclude( - ' true] - ); + $this->fixer->configure($config); + $this->doTest($expected, $input); } - /** - * @requires PHP 8.0 - */ - public function testFixWithNullSafeObjectOperator(): void + public function provideFix80Cases(): \Generator { - $this->doTest('count();'); + yield 'attribute and strict' => [ + ' true], + ]; + + yield 'null safe operator' => ['count();']; + + yield 'multiple function-calls-like in attribute' => [ + ' ['@all']], + ]; } } diff --git a/tests/Fixer/FunctionNotation/NoSpacesAfterFunctionNameFixerTest.php b/tests/Fixer/FunctionNotation/NoSpacesAfterFunctionNameFixerTest.php index f736b92d461..96ae4796b3c 100644 --- a/tests/Fixer/FunctionNotation/NoSpacesAfterFunctionNameFixerTest.php +++ b/tests/Fixer/FunctionNotation/NoSpacesAfterFunctionNameFixerTest.php @@ -33,9 +33,9 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ 'test function call' => [ ' $test) { - yield $index => $test; - } - - if (\PHP_VERSION_ID < 80000) { - yield 'test dynamic by array, curly mix' => [ - 'getOutput();', + 'getOutput ();', + ]; - yield 'test dynamic by array, curly only' => [ - 'doTest($expected, $input); } - public function provideFix54Cases() + public function provideFixPre80Cases(): \Generator { - return [ - [ - 'getOutput();', - 'getOutput ();', - ], + yield 'test dynamic by array, curly mix' => [ + ' [ + 'doTest($expected, $input); } - public function provideFix70Cases() + public function provideFix81Cases(): \Generator { - return [ - [ - 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'do not crash' => [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield 'simple' => [ '= 70000) { - yield [ - ' 70300) { - yield 'trailing comma' => [ - 'doTest($expected, $input); + } + + public function provideFix70Cases(): \Generator + { + yield [ + 'doTest($expected, $input); + } + + public function provideFix73Cases(): \Generator + { + yield 'trailing comma' => [ + 'doTest($expected, $input); + } + + public function provideFixPre80Cases(): \Generator + { + yield [ + 'doTest($expected); } - public function provideDoNotFixCases() + public function provideDoNotFixCases(): \Generator { yield ['doTest($input); + $this->doTest($expected); } else { $this->doTest($expected, $input); } @@ -108,7 +109,7 @@ public function testFix(string $input, string $expected): void /** * @requires PHP 7.1 * - * @dataProvider provideFixCases + * @dataProvider provideInvertedFixCases * @dataProvider provideInverseOnlyFixCases */ public function testFixInverse(string $expected, string $input): void @@ -118,207 +119,212 @@ public function testFixInverse(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield [ - 'provideFixCases()); + } + + public function provideNonInverseOnlyFixCases(): \Generator { yield [ - 'doTest($expected, $input); } /** - * @dataProvider provideFixPhp74Cases + * @dataProvider provideInvertedFixPhp74Cases * @requires PHP 7.4 */ public function testFixInversePhp74(string $expected, string $input): void @@ -356,58 +362,63 @@ public function testFixInversePhp74(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): \Generator { yield [ - ' null;', ' null;', + ' null;', ]; yield [ - ' null;', ' null;', + ' null;', ]; yield [ - ' null;', ' null;', + ' null;', ]; yield [ - ' null;', ' null;', + ' null;', ]; yield [ - ' null;', ' null;', + ' null;', ]; yield [ - ' null;', ' null;', + ' null;', ]; } + public function provideInvertedFixPhp74Cases(): iterable + { + return TestCaseUtils::swapExpectedInputTestCases($this->provideFixPhp74Cases()); + } + /** * @dataProvider provideFix80Cases * @requires PHP 8.0 */ - public function testFix80(string $input, ?string $expected = null): void + public function testFix80(string $expected, ?string $input = null): void { - if (null === $expected) { - $this->doTest($input); + if (null === $input) { + $this->doTest($expected); } else { $this->doTest($expected, $input); } } /** - * @dataProvider provideFix80Cases + * @dataProvider provideInvertedFix80Cases * @requires PHP 8.0 */ public function testFixInverse80(string $expected, ?string $input = null): void @@ -417,11 +428,11 @@ public function testFixInverse80(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield 'trailing comma' => [ - ' [ @@ -430,7 +441,7 @@ public function __construct( public ?string $paramA = null, protected ?string $paramB = null, private ?string $paramC = null, - string $paramD = null, + ?string $paramD = null, $a = [] ) {} }', @@ -439,7 +450,7 @@ public function __construct( public ?string $paramA = null, protected ?string $paramB = null, private ?string $paramC = null, - ?string $paramD = null, + string $paramD = null, $a = [] ) {} }', @@ -454,21 +465,26 @@ public function bbb(int | null $bar = null, $baz = 1) {} ]; yield 'attribute' => [ - ' [ - 'provideFix80Cases()); + } } diff --git a/tests/Fixer/FunctionNotation/PhpdocToParamTypeFixerTest.php b/tests/Fixer/FunctionNotation/PhpdocToParamTypeFixerTest.php index dad5ae4475e..8327f60db4b 100644 --- a/tests/Fixer/FunctionNotation/PhpdocToParamTypeFixerTest.php +++ b/tests/Fixer/FunctionNotation/PhpdocToParamTypeFixerTest.php @@ -28,7 +28,7 @@ final class PhpdocToParamTypeFixerTest extends AbstractFixerTestCase /** * @dataProvider provideFixCases */ - public function testFix(string $expected, ?string $input = null, ?int $versionSpecificFix = null, ?array $config = null): void + public function testFix(string $expected, ?string $input = null, ?int $versionSpecificFix = null, array $config = null): void { if ( null !== $input @@ -40,6 +40,7 @@ public function testFix(string $expected, ?string $input = null, ?int $versionSp $expected = $input; $input = null; } + if (null !== $config) { $this->fixer->configure($config); } @@ -47,7 +48,7 @@ public function testFix(string $expected, ?string $input = null, ?int $versionSp $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'typehint already defined' => [ @@ -248,6 +249,9 @@ class Foo { 'skip mixed types including array' => [ ' [ + ' [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'no phpdoc return' => [ @@ -79,6 +79,9 @@ class Foo { 'void' => [ ' [ + ' [ ' [ + 'fixer->configure($config); - - $this->doTest($expected, $input); + $this->doTest($expected); } - public function provideFixPhp70Cases() + public function provideFix81Cases(): \Generator { - return [ - 'anonymous class' => [ - ' [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ 'no phpdoc return' => [ ' [ + ' [ ' $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { yield 'report static as self' => [ 'doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ 'arrow function' => [ @@ -385,7 +383,7 @@ public function testFixPhp80(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp80Cases() + public function provideFixPhp80Cases(): \Generator { yield 'static' => [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield 'call by name - list' => [ 'doTest($expected, $input); - } - public function provideFix70Cases() - { - yield 'call by variable' => [ + yield 'call by property' => [ 'c)(1, 2); ($f->{c})(1, 2); @@ -222,11 +210,27 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + '', + ]; + } } diff --git a/tests/Fixer/FunctionNotation/ReturnTypeDeclarationFixerTest.php b/tests/Fixer/FunctionNotation/ReturnTypeDeclarationFixerTest.php index 45706fddca6..e625300422d 100644 --- a/tests/Fixer/FunctionNotation/ReturnTypeDeclarationFixerTest.php +++ b/tests/Fixer/FunctionNotation/ReturnTypeDeclarationFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\FunctionNotation; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** @@ -21,14 +22,13 @@ * * @internal * - * @requires PHP 7.0 * @covers \PhpCsFixer\Fixer\FunctionNotation\ReturnTypeDeclarationFixer */ final class ReturnTypeDeclarationFixerTest extends AbstractFixerTestCase { public function testInvalidConfiguration(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( '#^\[return_type_declaration\] Invalid configuration: The option "s" does not exist\. (Known|Defined) options are: "space_before"\.$#' ); @@ -58,7 +58,7 @@ public function testFixWithSpaceBeforeNone(string $expected, ?string $input = nu $this->doTest($expected, $input); } - public function provideFixWithSpaceBeforeNoneCases() + public function provideFixWithSpaceBeforeNoneCases(): array { return [ [ @@ -124,7 +124,7 @@ public function testFixWithSpaceBeforeOne(string $expected, ?string $input = nul $this->doTest($expected, $input); } - public function provideFixWithSpaceBeforeOneCases() + public function provideFixWithSpaceBeforeOneCases(): array { return [ [ @@ -157,7 +157,7 @@ public function testFixWithDefaultConfigurationPhp74(string $expected, ?string $ $this->doTest($expected, $input); } - public function provideFixWithSpaceBeforeNonePhp74Cases() + public function provideFixWithSpaceBeforeNonePhp74Cases(): array { return [ [ @@ -176,7 +176,7 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield ['= 80000) { - yield [ - 'getExceptionFactory()?->createAnException("Foo");', - 'doTest($expected, $input); + } + + public static function provideFix80Cases(): \Generator + { + yield [ + 'getExceptionFactory()?->createAnException("Foo");', + 'getExceptionFactory() ?->createAnException( "Foo" );', - ]; + ]; - yield [' $function->one(), 2 => $function->two(), default => throw new \NotOneOrTwo() }; - ']; + ', + ]; - yield [' $function->one(), 2 => throw new Exception("Number 2 is not allowed."), 1 => $function->three(), default => throw new \NotOneOrTwo() }; - ']; + ', + ]; - yield [ - ' "a", 3 => "b" });', - ' "a", - 3 => "b" - });', - ]; - } + yield [ + ' "a", 3 => "b" });', + ' "a", + 3 => "b" + });', + ]; } } diff --git a/tests/Fixer/FunctionNotation/StaticLambdaFixerTest.php b/tests/Fixer/FunctionNotation/StaticLambdaFixerTest.php index 9a8130e7339..05f56749785 100644 --- a/tests/Fixer/FunctionNotation/StaticLambdaFixerTest.php +++ b/tests/Fixer/FunctionNotation/StaticLambdaFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\FunctionNotation\StaticLambdaFixer @@ -33,7 +31,7 @@ public function testFix(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'sample' => [ @@ -67,7 +65,7 @@ public function testDoNotFix(string $expected): void $this->doTest($expected); } - public function provideDoNotFixCases() + public function provideDoNotFixCases(): array { return [ [ @@ -249,7 +247,7 @@ public function testFixPhp74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ diff --git a/tests/Fixer/FunctionNotation/UseArrowFunctionsFixerTest.php b/tests/Fixer/FunctionNotation/UseArrowFunctionsFixerTest.php index d1e3d6c1603..197158497fe 100644 --- a/tests/Fixer/FunctionNotation/UseArrowFunctionsFixerTest.php +++ b/tests/Fixer/FunctionNotation/UseArrowFunctionsFixerTest.php @@ -42,7 +42,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/FunctionNotation/VoidReturnFixerTest.php b/tests/Fixer/FunctionNotation/VoidReturnFixerTest.php index 95acfc7c267..72afc3aef72 100644 --- a/tests/Fixer/FunctionNotation/VoidReturnFixerTest.php +++ b/tests/Fixer/FunctionNotation/VoidReturnFixerTest.php @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ @@ -252,7 +252,7 @@ public function testMethodWillNotCauseSyntaxError(string $method, int $arguments $static ? ' static' : '', $method, implode(',', array_map( - function ($n) { return sprintf('$x%d', $n); }, + static function (int $n): string { return sprintf('$x%d', $n); }, array_keys(array_fill(0, $arguments, true)) )) )); diff --git a/tests/Fixer/Import/FullyQualifiedStrictTypesFixerTest.php b/tests/Fixer/Import/FullyQualifiedStrictTypesFixerTest.php index 60850a2b18a..942d5ed611d 100644 --- a/tests/Fixer/Import/FullyQualifiedStrictTypesFixerTest.php +++ b/tests/Fixer/Import/FullyQualifiedStrictTypesFixerTest.php @@ -26,8 +26,6 @@ final class FullyQualifiedStrictTypesFixerTest extends AbstractFixerTestCase { /** - * @requires PHP 7.0 - * * @dataProvider provideCodeWithReturnTypesCases */ public function testCodeWithReturnTypes(string $expected, ?string $input = null): void @@ -53,7 +51,7 @@ public function testCodeWithoutReturnTypes(string $expected, ?string $input = nu $this->doTest($expected, $input); } - public function provideCodeWithReturnTypesCases() + public function provideCodeWithReturnTypesCases(): array { return [ 'Import common strict types' => [ @@ -238,7 +236,7 @@ public function doSomething(\Foo\Bar $foo, array $bar): \Foo\Bar\Baz ]; } - public function provideCodeWithoutReturnTypesCases() + public function provideCodeWithoutReturnTypesCases(): array { return [ 'Import common strict types' => [ @@ -440,7 +438,7 @@ function withReference(\Exception &$e) {}', ]; } - public function provideCodeWithReturnTypesCasesWithNullableCases() + public function provideCodeWithReturnTypesCasesWithNullableCases(): array { return [ 'Test namespace fixes with nullable types' => [ diff --git a/tests/Fixer/Import/GlobalNamespaceImportFixerTest.php b/tests/Fixer/Import/GlobalNamespaceImportFixerTest.php index d5a7e30584b..df2a49f3f85 100644 --- a/tests/Fixer/Import/GlobalNamespaceImportFixerTest.php +++ b/tests/Fixer/Import/GlobalNamespaceImportFixerTest.php @@ -34,7 +34,7 @@ public function testFixImportConstants(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideFixImportConstantsCases() + public function provideFixImportConstantsCases(): array { return [ 'non-global names' => [ @@ -235,7 +235,7 @@ public function testFixImportFunctions(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideFixImportFunctionsCases() + public function provideFixImportFunctionsCases(): array { return [ 'non-global names' => [ @@ -411,22 +411,6 @@ function foo() {} \foo(); INPUT ], - ]; - } - - /** - * @dataProvider provideFixImportFunctions70Cases - * @requires PHP 7.0 - */ - public function testFixImportFunctions70(string $expected, ?string $input = null): void - { - $this->fixer->configure(['import_functions' => true]); - $this->doTest($expected, $input); - } - - public function provideFixImportFunctions70Cases() - { - return [ 'name already used' => [ <<<'EXPECTED' doTest($expected, $input); } - public function provideFixImportClassesCases() + public function provideFixImportClassesCases(): array { return [ 'non-global names' => [ @@ -724,7 +708,7 @@ public function testFixImportClasses71(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideFixImportClasses71Cases() + public function provideFixImportClasses71Cases(): array { return [ 'handle typehints' => [ @@ -758,7 +742,7 @@ public function testFixFullyQualifyConstants(string $expected, ?string $input = $this->doTest($expected, $input); } - public function provideFixFullyQualifyConstantsCases() + public function provideFixFullyQualifyConstantsCases(): array { return [ 'already fqn or sub namespace' => [ @@ -817,7 +801,7 @@ public function testFixFullyQualifyFunctions(string $expected, ?string $input = $this->doTest($expected, $input); } - public function provideFixFullyQualifyFunctionsCases() + public function provideFixFullyQualifyFunctionsCases(): array { return [ 'already fqn or sub namespace' => [ @@ -883,7 +867,7 @@ public function testFixFullyQualifyClasses(string $expected, ?string $input = nu $this->doTest($expected, $input); } - public function provideFixFullyQualifyClassesCases() + public function provideFixFullyQualifyClassesCases(): array { return [ 'already fqn or sub namespace' => [ @@ -972,7 +956,7 @@ public function testMultipleNamespaces(string $expected): void $this->doTest($expected); } - public function provideMultipleNamespacesCases() + public function provideMultipleNamespacesCases(): \Generator { yield [ <<<'INPUT' @@ -1027,4 +1011,39 @@ public function provideMultipleNamespacesCases() INPUT ]; } + + /** + * @requires PHP 8.0 + */ + public function testAttributes(): void + { + $this->fixer->configure([ + 'import_classes' => true, + 'import_constants' => true, + 'import_functions' => true, + ]); + $this->doTest( + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield [ 'doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield [ - 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -184,8 +184,6 @@ class Bar { } /** - * @param string $input - * * @dataProvider provideFix72Cases * @requires PHP 7.2 */ @@ -194,7 +192,7 @@ public function testFix72(string $expected, string $input = null): void $this->doTest($expected, $input); } - public function provideFix72Cases() + public function provideFix72Cases(): array { return [ [ @@ -230,7 +228,7 @@ public function testFixPrePHP80(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPrePHP80Cases() + public function provideFixPrePHP80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'simple' => [ @@ -408,6 +408,7 @@ public function doSomething($foo) [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + 'doTest($expected); +EOF + ], + ]; } /** @@ -1115,7 +1297,7 @@ public function testFix72(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix72Cases() + public function provideFix72Cases(): array { return [ [ // TODO test shows lot of cases where imports are not removed while could be @@ -1181,10 +1363,16 @@ public function testFixPrePHP80(): void /** * @requires PHP 8.0 + * @dataProvider providePhp80Cases */ - public function testFix80(): void + public function testFix80(string $expected, ?string $input = null): void { - $this->doTest( + $this->doTest($expected, $input); + } + + public function providePhp80Cases(): \Generator + { + yield [ 'bar; $y = foo?->bar(); -' - ); +', + ]; + + yield 'with union type in non-capturing catch' => [ + ' [ + ' [ + " '%regex.uuid%'], methods: ['POST']), + IsGranted('ROLE_USER'), + JsonSchema('Public/Basket/addItem.json'), +] +class Foo {} +", + ]; + } + + /** + * @requires PHP 8.1 + * @dataProvider providePhp81Cases + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function providePhp81Cases(): \Generator + { + yield 'final const' => [ + ' [ + ' [ + 'toArray(); - /** @var ArrayInterface $bar */ - - return function () use ($bar, $foo) {}; - } -} -EOF; - - $input = <<<'EOF' -The normal -use of this fixer -should not change this sentence nor those statements below -use Zoo\Bar as ZooBar; -use Foo\Bar; -use Foo\Zar\Baz; - -toArray(); - /** @var ArrayInterface $bar */ - - return function () use ($bar, $foo) {}; - } -} -EOF; - - $this->doTest($expected, $input); - } - public function testFixWithMultipleNamespace(): void { $expected = <<<'EOF' @@ -636,19 +552,101 @@ public function testCodeWithCommentsAndMultiLine(): void } /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 + * @dataProvider provideFixCases */ - public function testFix70(string $expected, ?string $input = null, array $config = []): void + public function testFix(string $expected, ?string $input = null, array $config = []): void { $this->fixer->configure($config); $this->doTest($expected, $input); } - public function provideFix70Cases() + public function provideFixCases(): iterable { return [ + [ + <<<'EOF' +The normal +use of this fixer +should not change this sentence nor those statements below +use Zoo\Bar as ZooBar; +use Foo\Bar; +use Foo\Zar\Baz; + +toArray(); + /** @var ArrayInterface $bar */ + + return function () use ($bar, $foo) {}; + } +} +EOF + , + + <<<'EOF' +The normal +use of this fixer +should not change this sentence nor those statements below +use Zoo\Bar as ZooBar; +use Foo\Bar; +use Foo\Zar\Baz; + +toArray(); + /** @var ArrayInterface $bar */ + + return function () use ($bar, $foo) {}; + } +} +EOF + , + ], [ 'expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessage('[ordered_imports] Invalid configuration: Unknown sort types "foo", "bar".'); $this->fixer->configure([ @@ -991,7 +989,7 @@ public function testUnknownOrderTypes(): void public function testInvalidOrderTypesSize(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessage('[ordered_imports] Invalid configuration: Missing sort type "function".'); $this->fixer->configure([ @@ -1002,7 +1000,7 @@ public function testInvalidOrderTypesSize(): void public function testInvalidOrderType(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessage('[ordered_imports] Invalid configuration: Missing sort type "class".'); $this->fixer->configure([ @@ -1016,7 +1014,7 @@ public function testInvalidOrderType(): void */ public function testInvalidSortAlgorithm(array $configuration, string $expectedValue): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessage(sprintf( '[ordered_imports] Invalid configuration: The option "sort_algorithm" with value %s is invalid. Accepted values are: "alpha", "length", "none".', $expectedValue @@ -1025,7 +1023,7 @@ public function testInvalidSortAlgorithm(array $configuration, string $expectedV $this->fixer->configure($configuration); } - public function provideInvalidSortAlgorithmCases() + public function provideInvalidSortAlgorithmCases(): array { return [ [ @@ -1052,96 +1050,6 @@ public function provideInvalidSortAlgorithmCases() ]; } - public function testFixByLength(): void - { - $this->fixer->configure([ - 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH, - 'imports_order' => null, - ]); - - $expected = <<<'EOF' -The normal -use of this fixer -should not change this sentence nor those statements below -use Zoo\Bar as ZooBar; -use Foo\Bar; -use Foo\Zar\Baz; - -toArray(); - /** @var ArrayInterface $bar */ - - return function () use ($bar, $foo) {}; - } -} -EOF; - - $input = <<<'EOF' -The normal -use of this fixer -should not change this sentence nor those statements below -use Zoo\Bar as ZooBar; -use Foo\Bar; -use Foo\Zar\Baz; - -toArray(); - /** @var ArrayInterface $bar */ - - return function () use ($bar, $foo) {}; - } -} -EOF; - - $this->doTest($expected, $input); - } - public function testByLengthFixWithSameLength(): void { $this->fixer->configure([ @@ -1720,10 +1628,9 @@ public function testByLengthWithoutUses(): void } /** - * @dataProvider provideFix70ByLengthCases - * @requires PHP 7.0 + * @dataProvider provideFixByLengthCases */ - public function testFix70ByLength(string $expected, ?string $input = null): void + public function testFixByLength(string $expected, ?string $input = null): void { $this->fixer->configure([ 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH, @@ -1733,9 +1640,92 @@ public function testFix70ByLength(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix70ByLengthCases() + public function provideFixByLengthCases(): array { return [ + [ + <<<'EOF' +The normal +use of this fixer +should not change this sentence nor those statements below +use Zoo\Bar as ZooBar; +use Foo\Bar; +use Foo\Zar\Baz; + +toArray(); + /** @var ArrayInterface $bar */ + + return function () use ($bar, $foo) {}; + } +} +EOF + , + + <<<'EOF' +The normal +use of this fixer +should not change this sentence nor those statements below +use Zoo\Bar as ZooBar; +use Foo\Bar; +use Foo\Zar\Baz; + +toArray(); + /** @var ArrayInterface $bar */ + + return function () use ($bar, $foo) {}; + } +} +EOF + , + ], [ 'fixer->configure([ 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH, @@ -1797,7 +1786,7 @@ public function testFix70TypesOrderAndLength(string $expected, ?string $input = $this->doTest($expected, $input); } - public function provideFix70TypesOrderAndLengthCases() + public function provideFixTypesOrderAndLengthCases(): array { return [ [ @@ -1840,12 +1829,11 @@ public function provideFix70TypesOrderAndLengthCases() } /** - * @dataProvider provideFix70TypesOrderAndAlphabetCases - * @requires PHP 7.0 + * @dataProvider provideFixTypesOrderAndAlphabetCases * * @param string[] $importOrder */ - public function testFix70TypesOrderAndAlphabet(string $expected, ?string $input = null, array $importOrder = null): void + public function testFixTypesOrderAndAlphabet(string $expected, ?string $input = null, array $importOrder = null): void { $this->fixer->configure([ 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA, @@ -1855,7 +1843,7 @@ public function testFix70TypesOrderAndAlphabet(string $expected, ?string $input $this->doTest($expected, $input); } - public function provideFix70TypesOrderAndAlphabetCases() + public function provideFixTypesOrderAndAlphabetCases(): iterable { return [ [ @@ -1909,12 +1897,11 @@ public function provideFix70TypesOrderAndAlphabetCases() } /** - * @dataProvider provideFix70TypesOrderAndNoneCases - * @requires PHP 7.0 + * @dataProvider provideFixTypesOrderAndNoneCases * * @param null|string[] $importOrder */ - public function testFix70TypesOrderAndNone(string $expected, ?string $input = null, array $importOrder = null): void + public function testFixTypesOrderAndNone(string $expected, ?string $input = null, array $importOrder = null): void { $this->fixer->configure([ 'sort_algorithm' => OrderedImportsFixer::SORT_NONE, @@ -1924,7 +1911,7 @@ public function testFix70TypesOrderAndNone(string $expected, ?string $input = nu $this->doTest($expected, $input); } - public function provideFix70TypesOrderAndNoneCases() + public function provideFixTypesOrderAndNoneCases(): array { return [ [ @@ -1988,7 +1975,7 @@ public function testFix72(string $expected, ?string $input = null, array $config $this->doTest($expected, $input); } - public function provideFix72Cases() + public function provideFix72Cases(): array { $input = ' - * @author SpacePossum * * @internal * @@ -35,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -206,21 +205,6 @@ public function provideFixCases() use X ?>doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ '= 80000) { @@ -309,7 +290,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ @@ -328,7 +309,7 @@ public function testFix72(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix72Cases() + public function provideFix72Cases(): array { return [ [ diff --git a/tests/Fixer/Import/SingleLineAfterImportsFixerTest.php b/tests/Fixer/Import/SingleLineAfterImportsFixerTest.php index 784a05a670b..84f54e40ce7 100644 --- a/tests/Fixer/Import/SingleLineAfterImportsFixerTest.php +++ b/tests/Fixer/Import/SingleLineAfterImportsFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -360,21 +360,6 @@ class Baz class Baz {} '), ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ @@ -476,7 +461,7 @@ public function testFix72(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix72Cases() + public function provideFix72Cases(): array { $imports = [ 'some\a\{ClassA, ClassB, ClassC as C,};', diff --git a/tests/Fixer/LanguageConstruct/ClassKeywordRemoveFixerTest.php b/tests/Fixer/LanguageConstruct/ClassKeywordRemoveFixerTest.php index ab44b2d3bbd..acdac03e663 100644 --- a/tests/Fixer/LanguageConstruct/ClassKeywordRemoveFixerTest.php +++ b/tests/Fixer/LanguageConstruct/ClassKeywordRemoveFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -236,21 +236,6 @@ public function c() { var_dump(Baz::class); ', ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ "doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -179,9 +177,6 @@ public function provideFixCases() ]; } - /** - * @requires PHP 7.0 - */ public function testAnonymousClass(): void { $this->doTest( diff --git a/tests/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixerTest.php b/tests/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixerTest.php index 82123059520..57278ffc6bf 100644 --- a/tests/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixerTest.php +++ b/tests/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\LanguageConstruct\CombineConsecutiveUnsetsFixer @@ -33,9 +31,9 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } + /** + * @dataProvider provideFixPre80Cases + * @requires PHP <8.0 + */ + public function testFixPre80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield [ - ' - * @author SpacePossum * * @internal * @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input, array $config): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'minimal case remove whitespace (default config)' => [ @@ -95,13 +95,13 @@ public function provideFixCases() */ public function testInvalidConfig(array $config, string $expectedMessage): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessage(sprintf('[declare_equal_normalize] Invalid configuration: %s', $expectedMessage)); $this->fixer->configure($config); } - public function provideInvalidConfigCases() + public function provideInvalidConfigCases(): array { return [ [ diff --git a/tests/Fixer/LanguageConstruct/DeclareParenthesesFixerTest.php b/tests/Fixer/LanguageConstruct/DeclareParenthesesFixerTest.php new file mode 100644 index 00000000000..a6194a6ae11 --- /dev/null +++ b/tests/Fixer/LanguageConstruct/DeclareParenthesesFixerTest.php @@ -0,0 +1,57 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Fixer\LanguageConstruct; + +use PhpCsFixer\Tests\Test\AbstractFixerTestCase; + +/** + * @internal + * + * @covers \PhpCsFixer\Fixer\LanguageConstruct\DeclareParenthesesFixer + */ +final class DeclareParenthesesFixerTest extends AbstractFixerTestCase +{ + /** + * @dataProvider provideFixCases + */ + public function testFix(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFixCases(): \Generator + { + yield 'spaces around parentheses' => [ + ' [ + ' [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $multiLinePatternToFix = <<<'FIX' doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ diff --git a/tests/Fixer/LanguageConstruct/ErrorSuppressionFixerTest.php b/tests/Fixer/LanguageConstruct/ErrorSuppressionFixerTest.php index 8869c76b3c9..7da08f31599 100644 --- a/tests/Fixer/LanguageConstruct/ErrorSuppressionFixerTest.php +++ b/tests/Fixer/LanguageConstruct/ErrorSuppressionFixerTest.php @@ -37,11 +37,11 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ [ - '', + '', ], [ '', @@ -115,16 +115,22 @@ public function provideFixCases() [ErrorSuppressionFixer::OPTION_MUTE_DEPRECATION_ERROR => true, ErrorSuppressionFixer::OPTION_NOISE_REMAINING_USAGES => true, ErrorSuppressionFixer::OPTION_NOISE_REMAINING_USAGES_EXCLUDE => ['trigger_error']], ], ]; + } - foreach ($tests as $index => $test) { - yield $index => $test; - } + /** + * @dataProvider provideFixPre80Cases + * @requires PHP <8.0 + */ + public function testFixPre80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield [ - '', - ]; - } + public function provideFixPre80Cases(): \Generator + { + yield [ + '', + ]; } /** @@ -137,4 +143,20 @@ public function testFix73(): void 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ [ @@ -82,7 +81,7 @@ public function testFix80($expected, $input): void $this->doTest($expected, $input); } - public function provideTestFix80Cases() + public function provideTestFix80Cases(): array { return [ [ diff --git a/tests/Fixer/LanguageConstruct/FunctionToConstantFixerTest.php b/tests/Fixer/LanguageConstruct/FunctionToConstantFixerTest.php index 2d64b320a01..c28e5d56336 100644 --- a/tests/Fixer/LanguageConstruct/FunctionToConstantFixerTest.php +++ b/tests/Fixer/LanguageConstruct/FunctionToConstantFixerTest.php @@ -14,11 +14,10 @@ namespace PhpCsFixer\Tests\Fixer\LanguageConstruct; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\LanguageConstruct\FunctionToConstantFixer @@ -35,7 +34,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideTestCases() + public function provideTestCases(): array { return [ 'Minimal case, alternative casing, alternative statement end.' => [ @@ -248,13 +247,13 @@ class Foo{ public function Bar(){ echo $reflection = new \ReflectionClass(get_cl */ public function testInvalidConfigurationKeys(array $config): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[function_to_constant\] Invalid configuration: The option "functions" with value array is invalid\.$#'); $this->fixer->configure($config); } - public function provideInvalidConfigurationKeysCases() + public function provideInvalidConfigurationKeysCases(): array { return [ [['functions' => ['a']]], @@ -265,9 +264,25 @@ public function provideInvalidConfigurationKeysCases() public function testInvalidConfigurationValue(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[function_to_constant\] Invalid configuration: The option "0" does not exist\. Defined options are: "functions"\.$#'); $this->fixer->configure(['pi123']); } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'first callable class' => [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $multiLinePatternToFix = <<<'FIX' doTest( - 'doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ diff --git a/tests/Fixer/LanguageConstruct/NoUnsetOnPropertyFixerTest.php b/tests/Fixer/LanguageConstruct/NoUnsetOnPropertyFixerTest.php index a6c995fd3e8..39de88139d5 100644 --- a/tests/Fixer/LanguageConstruct/NoUnsetOnPropertyFixerTest.php +++ b/tests/Fixer/LanguageConstruct/NoUnsetOnPropertyFixerTest.php @@ -33,9 +33,9 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ 'It replaces an unset on a property with = null' => [ 'bar = null;', 'bar);', @@ -108,28 +108,12 @@ public function provideFixCases() ], ]; - foreach ($tests as $index => $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { yield 'It does not replace unsets on arrays with special notation' => [ 'foo{0});', ]; } - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - public function provideFix70Cases() - { yield 'It does not break complex expressions' => [ 'a); ', ]; + } - if (\PHP_VERSION_ID < 80000) { - yield 'It does not break curly access expressions' => [ - 'doTest($expected, $input); + } + + public function provideFixPre80Cases(): \Generator + { + yield 'It does not break curly access expressions' => [ + 'doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): \Generator { - $tests = [ + yield from [ 'It replaces an unset on a property with = null' => [ 'bar = null;', 'bar,);', @@ -238,10 +232,6 @@ public function provideFix73Cases() ], ]; - foreach ($tests as $index => $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { yield 'It does not replace unsets on arrays with special notation' => [ 'foo{0},);', diff --git a/tests/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixerTest.php b/tests/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixerTest.php index 0b56b5f89ab..25475d53043 100644 --- a/tests/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixerTest.php +++ b/tests/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixerTest.php @@ -70,7 +70,7 @@ public function testFixWithAbstract(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixWithAbstractCases() + public function provideFixWithAbstractCases(): array { return [ [ @@ -166,7 +166,7 @@ public function testFixWithBreak(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithBreakCases() + public function provideFixWithBreakCases(): array { return [ [ @@ -215,7 +215,7 @@ public function testFixWithAs(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithAsCases() + public function provideFixWithAsCases(): array { return [ [ @@ -331,7 +331,7 @@ public function testFixWithCase(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithCaseCases() + public function provideFixWithCaseCases(): array { return [ [ @@ -401,7 +401,7 @@ public function testFixWithCatch(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithCatchCases() + public function provideFixWithCatchCases(): array { return [ [ @@ -443,7 +443,7 @@ public function testFixWithClass(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithClassCases() + public function provideFixWithClassCases(): array { return [ [ @@ -467,24 +467,6 @@ public function provideFixWithClassCases() [ 'fixer->configure($config); - - $this->doTest($expected, $input); - } - - public function provideFixWithClassPhp70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideFixWithContinueCases() + public function provideFixWithContinueCases(): array { return [ [ @@ -580,7 +562,7 @@ public function testFixWithConst(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithConstCases() + public function provideFixWithConstCases(): array { return [ [ @@ -618,7 +600,7 @@ public function testFixWithConstImport(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideFixWithConstImportCases() + public function provideFixWithConstImportCases(): array { return [ [ @@ -656,7 +638,7 @@ public function testFixWithClone(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithCloneCases() + public function provideFixWithCloneCases(): array { return [ [ @@ -694,13 +676,17 @@ public function testFixWithDo(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithDoCases() + public function provideFixWithDoCases(): array { return [ [ 'doTest($expected, $input); } - public function provideFixWithEchoCases() + public function provideFixWithEchoCases(): array { return [ [ @@ -754,8 +740,8 @@ public function provideFixWithEchoCases() 9000;', ], [ - 'doTest($expected, $input); } - public function provideFixWithElseCases() + public function provideFixWithElseCases(): array { return [ [ @@ -812,7 +798,7 @@ public function testFixWithElseIf(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithElseIfCases() + public function provideFixWithElseIfCases(): array { return [ [ @@ -850,7 +836,7 @@ public function testFixWithExtends(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideFixWithExtendsCases() + public function provideFixWithExtendsCases(): array { return [ [ @@ -914,28 +900,6 @@ public function provideFixWithExtendsCases() Qux {}', ], - ]; - } - - /** - * @requires PHP 7.0 - * - * @dataProvider provideFixWithExtendsPhp70Cases - */ - public function testFixWithExtendsPhp70(string $expected, ?string $input = null): void - { - $this->fixer->configure([ - 'constructs' => [ - 'extends', - ], - ]); - - $this->doTest($expected, $input); - } - - public function provideFixWithExtendsPhp70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideFixWithFinalCases() + public function provideFixWithFinalCases(): array { return [ [ @@ -1067,7 +1031,7 @@ public function testFixWithFinally(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideFixWithFinallyCases() + public function provideFixWithFinallyCases(): array { return [ [ @@ -1109,7 +1073,7 @@ public function testFixWithFor(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithForCases() + public function provideFixWithForCases(): array { return [ [ @@ -1151,7 +1115,7 @@ public function testFixWithForeach(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideFixWithForeachCases() + public function provideFixWithForeachCases(): array { return [ [ @@ -1193,7 +1157,7 @@ public function testFixWithFunction(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixWithFunctionCases() + public function provideFixWithFunctionCases(): array { return [ [ @@ -1289,7 +1253,7 @@ public function testFixWithFunctionImport(string $expected, ?string $input = nul $this->doTest($expected, $input); } - public function provideFixWithFunctionImportCases() + public function provideFixWithFunctionImportCases(): array { return [ [ @@ -1327,7 +1291,7 @@ public function testFixWithGlobal(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithGlobalCases() + public function provideFixWithGlobalCases(): array { return [ [ @@ -1369,7 +1333,7 @@ public function testFixWithGoto(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithGotoCases() + public function provideFixWithGotoCases(): array { return [ [ @@ -1403,7 +1367,7 @@ public function testFixWithIf(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithIfCases() + public function provideFixWithIfCases(): array { return [ [ @@ -1441,7 +1405,7 @@ public function testFixWithImplements(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideFixWithImplementsCases() + public function provideFixWithImplementsCases(): array { return [ [ @@ -1469,28 +1433,6 @@ public function provideFixWithImplementsCases() Baz {}', ], - ]; - } - - /** - * @requires PHP 7.0 - * - * @dataProvider provideFixWithImplementsPhp70Cases - */ - public function testFixWithImplementsPhp70(string $expected, ?string $input = null): void - { - $this->fixer->configure([ - 'constructs' => [ - 'implements', - ], - ]); - - $this->doTest($expected, $input); - } - - public function provideFixWithImplementsPhp70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideFixWithIncludeCases() + public function provideFixWithIncludeCases(): array { return [ [ @@ -1564,7 +1506,7 @@ public function testFixWithIncludeOnce(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideFixWithIncludeOnceCases() + public function provideFixWithIncludeOnceCases(): array { return [ [ @@ -1602,7 +1544,7 @@ public function testFixWithInstanceof(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideFixWithInstanceofCases() + public function provideFixWithInstanceofCases(): array { return [ [ @@ -1644,7 +1586,7 @@ public function testFixWithInsteadof(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideFixWithInsteadofCases() + public function provideFixWithInsteadofCases(): array { return [ [ @@ -1738,7 +1680,7 @@ public function testFixWithInterface(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideFixWithInterfaceCases() + public function provideFixWithInterfaceCases(): array { return [ [ @@ -1776,7 +1718,7 @@ public function testFixWithNew(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithNewCases() + public function provideFixWithNewCases(): array { return [ [ @@ -1814,7 +1756,7 @@ public function testFixWithOpenTagWithEcho(string $expected, ?string $input = nu $this->doTest($expected, $input); } - public function provideFixWithOpenTagWithEchoCases() + public function provideFixWithOpenTagWithEchoCases(): array { return [ [ @@ -1856,7 +1798,7 @@ public function testFixWithPrint(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithPrintCases() + public function provideFixWithPrintCases(): array { return [ [ @@ -1894,7 +1836,7 @@ public function testFixWithPrivate(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideFixWithPrivateCases() + public function provideFixWithPrivateCases(): array { return [ [ @@ -1956,7 +1898,7 @@ public function testFixWithPrivatePhp71(string $expected, ?string $input = null) $this->doTest($expected, $input); } - public function provideFixWithPrivatePhp71Cases() + public function provideFixWithPrivatePhp71Cases(): array { return [ [ @@ -1994,7 +1936,7 @@ public function testFixWithProtected(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideFixWithProtectedCases() + public function provideFixWithProtectedCases(): array { return [ [ @@ -2056,7 +1998,7 @@ public function testFixWithProtectedPhp71(string $expected, ?string $input = nul $this->doTest($expected, $input); } - public function provideFixWithProtectedPhp71Cases() + public function provideFixWithProtectedPhp71Cases(): array { return [ [ @@ -2094,7 +2036,7 @@ public function testFixWithPublic(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithPublicCases() + public function provideFixWithPublicCases(): array { return [ [ @@ -2102,8 +2044,8 @@ public function provideFixWithPublicCases() 'doTest($expected, $input); } - public function provideFixWithPublicPhp71Cases() + public function provideFixWithPublicPhp71Cases(): array { return [ [ @@ -2194,7 +2136,7 @@ public function testFixWithRequire(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideFixWithRequireCases() + public function provideFixWithRequireCases(): array { return [ [ @@ -2232,7 +2174,7 @@ public function testFixWithRequireOnce(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideFixWithRequireOnceCases() + public function provideFixWithRequireOnceCases(): array { return [ [ @@ -2270,7 +2212,7 @@ public function testFixWithReturn(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithReturnCases() + public function provideFixWithReturnCases(): array { return [ [ @@ -2404,7 +2346,7 @@ public function testFixWithStatic(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithStaticCases() + public function provideFixWithStaticCases(): array { return [ [ @@ -2470,7 +2412,7 @@ public function testFixWithThrow(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithThrowCases() + public function provideFixWithThrowCases(): array { return [ [ @@ -2508,7 +2450,7 @@ public function testFixWithTrait(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithTraitCases() + public function provideFixWithTraitCases(): array { return [ [ @@ -2546,7 +2488,7 @@ public function testFixWithTry(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithTryCases() + public function provideFixWithTryCases(): array { return [ [ @@ -2588,7 +2530,7 @@ public function testFixWithUse(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithUseCases() + public function provideFixWithUseCases(): array { return [ [ @@ -2662,7 +2604,7 @@ public function testFixWithUseLambda(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideFixWithUseLambdaCases() + public function provideFixWithUseLambdaCases(): array { return [ [ @@ -2704,7 +2646,7 @@ public function testFixWithUseTrait(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixWithUseTraitCases() + public function provideFixWithUseTraitCases(): array { return [ [ @@ -2742,7 +2684,7 @@ public function testFixWithVar(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithVarCases() + public function provideFixWithVarCases(): array { return [ [ @@ -2784,7 +2726,7 @@ public function testFixWithWhile(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithWhileCases() + public function provideFixWithWhileCases(): array { return [ [ @@ -2826,7 +2768,7 @@ public function testFixWithYield(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithYieldCases() + public function provideFixWithYieldCases(): array { return [ [ @@ -2851,8 +2793,6 @@ public function provideFixWithYieldCases() } /** - * @requires PHP 7.0 - * * @dataProvider provideFixWithYieldFromCases */ public function testFixWithYieldFrom(string $expected, ?string $input = null): void @@ -2866,7 +2806,7 @@ public function testFixWithYieldFrom(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideFixWithYieldFromCases() + public function provideFixWithYieldFromCases(): array { return [ [ @@ -2940,7 +2880,7 @@ public function testFixWithPhpOpen(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideFixWithPhpOpenCases() + public function provideFixWithPhpOpenCases(): array { return [ [ @@ -2977,7 +2917,7 @@ public function testComments(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideCommentsCases() + public function provideCommentsCases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield 'match 1' => [ 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'readonly' => [ + ' [ + ' [ + 'doTest($expected, $input); } - public function provideToLongCases() + public function provideFixToLongSyntaxCases(): array { // reverse testing - $shortCases = $this->provideToShortCases(); + $shortCases = $this->provideFixToShortSyntaxCases(); $cases = []; foreach ($shortCases as $label => $shortCase) { $cases[$label] = [$shortCase[1], $shortCase[0]]; } // the reverse of this is different because of all the comments and white space, - // therefore we override with a similar case case here + // therefore we override with a similar case here $cases['comment case'] = [ 'fixer->configure(['syntax' => 'long']); $this->doTest($expected, $input); } - public function providePhp72Cases() + public function provideFixToShortSyntaxPhp72Cases(): \Generator { - return [ - [ - 'provideFixToShortSyntaxPhp72Cases()); + } + /** * @requires PHP 7.3 - * @dataProvider providePhp73Cases + * @dataProvider provideFixToShortSyntaxPhp73Cases */ public function testFixToShortSyntaxPhp73(string $expected, string $input): void { @@ -216,29 +218,50 @@ public function testFixToShortSyntaxPhp73(string $expected, string $input): void /** * @requires PHP 7.3 - * @dataProvider providePhp73Cases + * @dataProvider provideFixToLongSyntaxPhp73Cases */ - public function testFixToLongSyntaxPhp73(string $input, string $expected): void + public function testFixToLongSyntaxPhp73(string $expected, string $input): void { $this->fixer->configure(['syntax' => 'long']); $this->doTest($expected, $input); } - public function providePhp73Cases() + public function provideFixToShortSyntaxPhp73Cases(): \Generator { - return [ - [ - 'provideFixToShortSyntaxPhp73Cases()); + } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'simple 8.1' => [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -226,7 +226,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/NamespaceNotation/CleanNamespaceFixerTest.php b/tests/Fixer/NamespaceNotation/CleanNamespaceFixerTest.php index 900196e051b..f69e241aca7 100644 --- a/tests/Fixer/NamespaceNotation/CleanNamespaceFixerTest.php +++ b/tests/Fixer/NamespaceNotation/CleanNamespaceFixerTest.php @@ -32,7 +32,7 @@ public function testFix(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield [ '', diff --git a/tests/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixerTest.php b/tests/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixerTest.php index a522e6d2468..c252098596f 100644 --- a/tests/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixerTest.php +++ b/tests/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixerTest.php @@ -18,7 +18,7 @@ use PhpCsFixer\WhitespacesFixerConfig; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * diff --git a/tests/Fixer/NamespaceNotation/NoLeadingNamespaceWhitespaceFixerTest.php b/tests/Fixer/NamespaceNotation/NoLeadingNamespaceWhitespaceFixerTest.php index 108f19cda43..8faae3110dd 100644 --- a/tests/Fixer/NamespaceNotation/NoLeadingNamespaceWhitespaceFixerTest.php +++ b/tests/Fixer/NamespaceNotation/NoLeadingNamespaceWhitespaceFixerTest.php @@ -35,9 +35,10 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $manySpaces = []; + for ($i = 1; $i <= 100; ++$i) { $manySpaces[] = 'namespace Test'.$i.';'; } @@ -149,7 +150,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixerTest.php b/tests/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixerTest.php index ded89cb643a..27b9f2a86c8 100644 --- a/tests/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixerTest.php +++ b/tests/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixerTest.php @@ -18,7 +18,7 @@ use PhpCsFixer\WhitespacesFixerConfig; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * diff --git a/tests/Fixer/Naming/NoHomoglyphNamesFixerTest.php b/tests/Fixer/Naming/NoHomoglyphNamesFixerTest.php index 8ec846aa8c6..d1b0793d36c 100644 --- a/tests/Fixer/Naming/NoHomoglyphNamesFixerTest.php +++ b/tests/Fixer/Naming/NoHomoglyphNamesFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ [ diff --git a/tests/Fixer/Operator/BinaryOperatorSpacesFixerTest.php b/tests/Fixer/Operator/BinaryOperatorSpacesFixerTest.php index 732d3dfb5b9..efa0d63e70e 100644 --- a/tests/Fixer/Operator/BinaryOperatorSpacesFixerTest.php +++ b/tests/Fixer/Operator/BinaryOperatorSpacesFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\Operator; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; @@ -21,7 +22,6 @@ * @author Dariusz Rumiński * @author Gregor Harlan * @author Carlos Cirello - * @author SpacePossum * * @internal * @@ -38,7 +38,7 @@ public function testWithTabs(string $expected, ?string $input = null, array $con $this->doTest($expected, $input); } - public function provideWithTabsCases() + public function provideWithTabsCases(): array { return [ [ @@ -75,7 +75,7 @@ public function myFunction() { } /** - * @dataProvider provideTestCases + * @dataProvider provideConfiguredCases */ public function testConfigured(string $expected, ?string $input = null, array $configuration = []): void { @@ -83,7 +83,7 @@ public function testConfigured(string $expected, ?string $input = null, array $c $this->doTest($expected, $input); } - public function provideTestCases() + public function provideConfiguredCases(): array { return [ [ @@ -443,6 +443,35 @@ public function provideTestCases() 'operators' => ['|' => BinaryOperatorSpacesFixer::NO_SPACE], ], ], + [ + ' 1; +echo 1 <=> 2; +echo 2 <=> 1; +echo 2 <=> 1; + +$a = $a ?? $b; +$a = $ab ?? $b; +$a = $ac ?? $b; +$a = $ad ?? $b; +$a = $ae ?? $b; +', + '1; +echo 1 <=>2; +echo 2<=> 1; +echo 2 <=> 1; + +$a = $a ?? $b; +$a = $ab ?? $b; +$a = $ac ?? $b; +$a = $ad ?? $b; +$a = $ae?? $b; +', + ['operators' => ['=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE, '??' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], + ], ]; } @@ -454,7 +483,7 @@ public function testFixDefaults(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -652,7 +681,7 @@ public function testUnalignEquals(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideUnalignEqualsCases() + public function provideUnalignEqualsCases(): array { return [ [ @@ -786,7 +815,7 @@ function b( public function testWrongConfigItem(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( '/^\[binary_operator_spaces\] Invalid configuration: The option "foo" does not exist\. Defined options are: "default", "operators"\.$/' ); @@ -796,7 +825,7 @@ public function testWrongConfigItem(): void public function testWrongConfigTypeForOperators(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( '/^\[binary_operator_spaces\] Invalid configuration: The option "operators" with value true is expected to be of type "array", but is of type "(bool|boolean)"\.$/' ); @@ -806,7 +835,7 @@ public function testWrongConfigTypeForOperators(): void public function testWrongConfigTypeForOperatorsKey(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[binary_operator_spaces\] Invalid configuration: Unexpected "operators" key, expected any of ".*", got "integer#123"\.$/'); $this->fixer->configure(['operators' => [123 => 1]]); @@ -814,7 +843,7 @@ public function testWrongConfigTypeForOperatorsKey(): void public function testWrongConfigTypeForOperatorsKeyValue(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[binary_operator_spaces\] Invalid configuration: Unexpected value for operator "\+", expected any of ".*", got "string#abc"\.$/'); $this->fixer->configure(['operators' => ['+' => 'abc']]); @@ -828,7 +857,7 @@ public function testUnalignDoubleArrow(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideUnalignDoubleArrowCases() + public function provideUnalignDoubleArrowCases(): array { return [ [ @@ -1223,7 +1252,7 @@ public function testFixAlignEquals(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideAlignEqualsCases() + public function provideAlignEqualsCases(): array { return [ [ @@ -1346,7 +1375,7 @@ public function testFixAlignDoubleArrow(string $expected, ?string $input = null) $this->doTest($expected, $input); } - public function provideAlignDoubleArrowCases() + public function provideAlignDoubleArrowCases(): array { return [ [ @@ -1912,42 +1941,6 @@ public function testDoNotTouchEqualsAndArrowByConfig(): void ); } - /** - * @requires PHP 7.0 - */ - public function testPHP70Cases(): void - { - $this->fixer->configure(['operators' => ['=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE, '??' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]]); - $this->doTest( - ' 1; -echo 1 <=> 2; -echo 2 <=> 1; -echo 2 <=> 1; - -$a = $a ?? $b; -$a = $ab ?? $b; -$a = $ac ?? $b; -$a = $ad ?? $b; -$a = $ae ?? $b; -', - '1; -echo 1 <=>2; -echo 2<=> 1; -echo 2 <=> 1; - -$a = $a ?? $b; -$a = $ab ?? $b; -$a = $ac ?? $b; -$a = $ad ?? $b; -$a = $ae?? $b; -' - ); - } - /** * @requires PHP 7.1 * @@ -1959,7 +1952,7 @@ public function testPHP71Cases(string $expected, ?string $input = null, array $c $this->doTest($expected, $input); } - public function providePHP71Cases() + public function providePHP71Cases(): array { return [ 'align array destruction' => [ @@ -2016,7 +2009,7 @@ public function testFixPhp74(string $expected, ?string $input = null, ?array $co $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ @@ -2052,6 +2045,10 @@ class Foo public function bar(TypeA | TypeB|TypeC $x): TypeA|TypeB | TypeC|TypeD { } + public function baz( + callable|array $a, + array|callable $b, + ) {} }' ); } diff --git a/tests/Fixer/Operator/ConcatSpaceFixerTest.php b/tests/Fixer/Operator/ConcatSpaceFixerTest.php index 3d34dabe851..bda8f5cff54 100644 --- a/tests/Fixer/Operator/ConcatSpaceFixerTest.php +++ b/tests/Fixer/Operator/ConcatSpaceFixerTest.php @@ -14,11 +14,11 @@ namespace PhpCsFixer\Tests\Fixer\Operator; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** * @author Dariusz Rumiński - * @author SpacePossum * * @internal * @@ -28,7 +28,7 @@ final class ConcatSpaceFixerTest extends AbstractFixerTestCase { public function testInvalidConfigMissingKey(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[concat_space\] Invalid configuration: The option "a" does not exist\. Defined options are: "spacing"\.$#'); $this->fixer->configure(['a' => 1]); @@ -36,7 +36,7 @@ public function testInvalidConfigMissingKey(): void public function testInvalidConfigValue(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[concat_space\] Invalid configuration: The option "spacing" with value "tabs" is invalid\. Accepted values are: "one", "none"\.$#'); $this->fixer->configure(['spacing' => 'tabs']); @@ -51,7 +51,7 @@ public function testFixWithoutSpace(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideWithoutSpaceCases() + public function provideWithoutSpaceCases(): array { return [ [ @@ -150,7 +150,7 @@ public function testFixWithSpace(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideWithSpaceCases() + public function provideWithSpaceCases(): array { return [ [ diff --git a/tests/Fixer/Operator/IncrementStyleFixerTest.php b/tests/Fixer/Operator/IncrementStyleFixerTest.php index 5237908e7b0..06f161615b0 100644 --- a/tests/Fixer/Operator/IncrementStyleFixerTest.php +++ b/tests/Fixer/Operator/IncrementStyleFixerTest.php @@ -46,14 +46,14 @@ public function testFixPostIncrement(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideFixPostIncrementCases() + public function provideFixPostIncrementCases(): array { - return array_map(static function (array $case) { + return array_map(static function (array $case): array { return array_reverse($case); }, $this->provideFixPreIncrementCases()); } - public function provideFixPreIncrementCases() + public function provideFixPreIncrementCases(): array { $cases = [ [ diff --git a/tests/Fixer/Operator/LogicalOperatorsFixerTest.php b/tests/Fixer/Operator/LogicalOperatorsFixerTest.php index 5bc24a8e505..b001c8cf829 100644 --- a/tests/Fixer/Operator/LogicalOperatorsFixerTest.php +++ b/tests/Fixer/Operator/LogicalOperatorsFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Operator/NewWithBracesFixerTest.php b/tests/Fixer/Operator/NewWithBracesFixerTest.php index ac3f02bda61..7a05025bf9f 100644 --- a/tests/Fixer/Operator/NewWithBracesFixerTest.php +++ b/tests/Fixer/Operator/NewWithBracesFixerTest.php @@ -33,9 +33,9 @@ public function testFixNamedWithDefaultConfiguration(string $expected, ?string $ $this->doTest($expected, $input); } - public function provideNamedWithDefaultConfigurationCases() + public function provideNamedWithDefaultConfigurationCases(): \Generator { - $tests = [ + yield from [ [' $test) { - yield $index => $test; - } - - if (\PHP_VERSION_ID < 80000) { - yield [ - '', - '', - ]; - - yield [ - 'doTest($expected, $input); } - public function provideNamedWithoutBracesCases() + public function provideNamedWithoutBracesCases(): \Generator { - $tests = [ + yield from [ [' $test) { - yield $index => $test; - } - - if (\PHP_VERSION_ID < 80000) { - yield [ - '', - '', - ]; - - yield [ - 'doTest($expected, $input); } - public function provideAnonymousWithDefaultConfigurationCases() + public function provideAnonymousWithDefaultConfigurationCases(): \Generator { - return [ + yield from [ ['doTest($expected, $input); } - public function provideAnonymousWithoutBracesCases() + public function provideAnonymousWithoutBracesCases(): \Generator { - return [ + yield from [ ['doTest($expected, $input); + } + + public function provideFixPre80Cases(): \Generator + { + yield [ + '', + '', + ]; + + yield [ + 'doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'bar(); ', ]; + + yield [ + 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Operator/NotOperatorWithSuccessorSpaceFixerTest.php b/tests/Fixer/Operator/NotOperatorWithSuccessorSpaceFixerTest.php index ececc65f884..83839ecd004 100644 --- a/tests/Fixer/Operator/NotOperatorWithSuccessorSpaceFixerTest.php +++ b/tests/Fixer/Operator/NotOperatorWithSuccessorSpaceFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Operator/ObjectOperatorWithoutWhitespaceFixerTest.php b/tests/Fixer/Operator/ObjectOperatorWithoutWhitespaceFixerTest.php index 3bf3a86f348..686097218ed 100644 --- a/tests/Fixer/Operator/ObjectOperatorWithoutWhitespaceFixerTest.php +++ b/tests/Fixer/Operator/ObjectOperatorWithoutWhitespaceFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -87,7 +87,7 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public static function provideFix80Cases() + public static function provideFix80Cases(): \Generator { yield [ 'method();', diff --git a/tests/Fixer/Operator/OperatorLinebreakFixerTest.php b/tests/Fixer/Operator/OperatorLinebreakFixerTest.php index 8a340205dd6..3ae2ddf9f00 100644 --- a/tests/Fixer/Operator/OperatorLinebreakFixerTest.php +++ b/tests/Fixer/Operator/OperatorLinebreakFixerTest.php @@ -37,7 +37,7 @@ public function testFix(string $expected, ?string $input = null, ?array $configu $this->doTest($expected, $input); } - public static function provideFixCases() + public static function provideFixCases(): \Generator { foreach (static::pairs() as $key => $value) { yield sprintf('%s when position is "beginning"', $key) => $value; @@ -205,7 +205,7 @@ public function testFix71(string $expected, ?string $input = null, ?array $confi $this->doTest($expected, $input); } - public static function provideFix71Cases() + public static function provideFix71Cases(): \Generator { yield 'nullable type when position is "end"' => [ ' [ 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } + yield [ + '{$bar};', - '{$bar} += 1;', - ]; + yield [ + ' 2;', + ]; - yield [ - '{$bar->{$baz}};', - '{$bar->{$baz}} += 1;', - ]; + yield [ + ' 2;', + ]; - yield [ - '$b::$c;', + '$b::$c += 1;', + ]; + + yield [ + '$b::$c->${$d}->${$e}::f(1 + 2 * 3)->$g::$h;', + '$b::$c->${$d}->${$e}::f(1 + 2 * 3)->$g::$h += 1;', + ]; } /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 + * @dataProvider provideFix74Cases + * @requires PHP 7.4 */ - public function testFix70(string $expected, ?string $input = null): void + public function testFix74(string $expected, ?string $input = null): void { $this->doTest($expected, $input); } - public function provideFix70Cases() + public function provideFix74Cases(): array { return [ [ - ' 2;', - ], - [ - ' 2;', - ], - [ - '$b::$c;', - '$b::$c += 1;', - ], - [ - '$b::$c->${$d}->${$e}::f(1 + 2 * 3)->$g::$h;', - '$b::$c->${$d}->${$e}::f(1 + 2 * 3)->$g::$h += 1;', + 'doTest($expected, $input); } - public function provideFix74Cases() + public function provideFixPre80Cases(): \Generator { - return [ - [ - '{$bar};', + '{$bar} += 1;', + ]; + + yield [ + '{$bar->{$baz}};', + '{$bar->{$baz}} += 1;', + ]; + + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'handle goto labels 1' => [ @@ -206,7 +206,7 @@ public function testFix80(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): array { return [ 'nullable types in constructor property promotion' => [ diff --git a/tests/Fixer/Operator/TernaryToElvisOperatorFixerTest.php b/tests/Fixer/Operator/TernaryToElvisOperatorFixerTest.php index 42553103850..e17504a6bb4 100644 --- a/tests/Fixer/Operator/TernaryToElvisOperatorFixerTest.php +++ b/tests/Fixer/Operator/TernaryToElvisOperatorFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Operator\TernaryToElvisOperatorFixer @@ -33,7 +31,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { $operators = ['+=', '-=', '*=', '**=', '/=', '.=', '%=', '&=', '|=', '^=', '<<=', '>>=']; @@ -422,76 +420,74 @@ public function provideFixCases() '', ]; - if (\PHP_VERSION_ID < 80000) { - yield [ - '{$b} ? $bar{0} : $foo;', - ]; - - yield [ - ' [ - '$a[0] ? : 1;', - '$a[0] ? __FILE__.$a.$b{2}.$c->$a[0] : 1;', - ]; - } + yield [ + 'doTest($expected, $input); } - public function provideFix70Cases() + public function provideFixPre80Cases(): \Generator { - return [ - [ - '{$b} ? $bar{0} : $foo;', + ]; + + yield [ + ' [ + '$a[0] ? : 1;', + '$a[0] ? __FILE__.$a.$b{2}.$c->$a[0] : 1;', ]; } @@ -504,7 +500,7 @@ public function test80DoNotFix(string $input): void $this->doTest($input); } - public function provideDoNotFix80Cases() + public function provideDoNotFix80Cases(): array { return [ ['doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ // Do not fix cases. [' $test) { - yield $index => $test; - } + /** + * @dataProvider provideFixPre80Cases + * @requires PHP <8.0 + */ + public function testFixPre80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield ['doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/PhpTag/BlankLineAfterOpeningTagFixerTest.php b/tests/Fixer/PhpTag/BlankLineAfterOpeningTagFixerTest.php index ed337b775c5..7b262e8ee3f 100644 --- a/tests/Fixer/PhpTag/BlankLineAfterOpeningTagFixerTest.php +++ b/tests/Fixer/PhpTag/BlankLineAfterOpeningTagFixerTest.php @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -141,7 +141,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/PhpTag/EchoTagSyntaxFixerTest.php b/tests/Fixer/PhpTag/EchoTagSyntaxFixerTest.php index 0a90d098bce..2de38b64804 100644 --- a/tests/Fixer/PhpTag/EchoTagSyntaxFixerTest.php +++ b/tests/Fixer/PhpTag/EchoTagSyntaxFixerTest.php @@ -35,7 +35,7 @@ public function testLongToShortFormat(string $expected, ?string $input = null, b $this->doTest($expected, $input); } - public function provideLongToShortFormatCases() + public function provideLongToShortFormatCases(): array { return [ ['doTest($expected, $input); } - public function provideShortToLongFormatCases() + public function provideShortToLongFormatCases(): array { $cases = [ [' 1;', 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ ['doTest($expected, $input); } - public function provideFixLT70Cases() + public function provideFixLT70Cases(): array { return [ [ diff --git a/tests/Fixer/PhpTag/LinebreakAfterOpeningTagFixerTest.php b/tests/Fixer/PhpTag/LinebreakAfterOpeningTagFixerTest.php index 0f23f91478a..55a46eba00a 100644 --- a/tests/Fixer/PhpTag/LinebreakAfterOpeningTagFixerTest.php +++ b/tests/Fixer/PhpTag/LinebreakAfterOpeningTagFixerTest.php @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -98,7 +98,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/PhpTag/NoClosingTagFixerTest.php b/tests/Fixer/PhpTag/NoClosingTagFixerTest.php index a75c5b3ccf4..97113cf856e 100644 --- a/tests/Fixer/PhpTag/NoClosingTagFixerTest.php +++ b/tests/Fixer/PhpTag/NoClosingTagFixerTest.php @@ -43,7 +43,7 @@ public function testWithShortOpenTag(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideWithFullOpenTagCases() + public function provideWithFullOpenTagCases(): array { return [ [ @@ -141,7 +141,7 @@ function bar() ]; } - public function provideWithShortOpenTagCases() + public function provideWithShortOpenTagCases(): array { return [ [ diff --git a/tests/Fixer/PhpUnit/PhpUnitConstructFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitConstructFixerTest.php index 74972f8bc78..aecb0858f89 100644 --- a/tests/Fixer/PhpUnit/PhpUnitConstructFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitConstructFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\PhpUnit; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** @@ -42,12 +43,12 @@ public function testFix(string $expected, ?string $input = null): void $this->fixer->configure(['assertions' => [$method]]); $this->doTest( $expected, - $input && false !== strpos($input, $method) ? $input : null + $input && str_contains($input, $method) ? $input : null ); } } - public function provideTestFixCases() + public function provideTestFixCases(): array { $cases = [ ['$sth->assertSame(true, $foo);'], @@ -150,7 +151,7 @@ class FooTest3 extends PHPUnit_Framework_TestCase { public function testFoo(){ $ public function testInvalidConfig(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[php_unit_construct\] Invalid configuration: The option "assertions" .*\.$/'); $this->fixer->configure(['assertions' => ['__TEST__']]); @@ -165,7 +166,7 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ @@ -185,10 +186,27 @@ public function testEmptyAssertions(): void $this->doTest(self::generateTest('$this->assertSame(null, $a);')); } - private function generateCases(string $expectedTemplate, string $inputTemplate) + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + self::generateTest('$this->assertEquals(...);'), + ]; + } + + private function generateCases(string $expectedTemplate, string $inputTemplate): array { - $cases = []; $functionTypes = ['Same' => true, 'NotSame' => false, 'Equals' => true, 'NotEquals' => false]; + $cases = []; + foreach (['true', 'false', 'null'] as $type) { foreach ($functionTypes as $method => $positive) { $cases[] = [ diff --git a/tests/Fixer/PhpUnit/PhpUnitDedicateAssertFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitDedicateAssertFixerTest.php index 4b42acb0510..9f76e93805c 100644 --- a/tests/Fixer/PhpUnit/PhpUnitDedicateAssertFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitDedicateAssertFixerTest.php @@ -14,12 +14,11 @@ namespace PhpCsFixer\Tests\Fixer\PhpUnit; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\PhpUnit\PhpUnitDedicateAssertFixer @@ -35,7 +34,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { $cases = [ [ @@ -234,7 +233,7 @@ public function testNotFix(string $expected): void $this->doTest($expected); } - public function provideNotFixCases() + public function provideNotFixCases(): array { return [ [ @@ -259,7 +258,7 @@ public function provideNotFixCases() public function testInvalidConfig(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[php_unit_dedicate_assert\] Invalid configuration: The option "target" .*\.$/'); $this->fixer->configure(['target' => '_unknown_']); @@ -293,7 +292,7 @@ public function testAssertCountFromSizeOf(string $expected, ?string $input = nul $this->doTest($expected, $input); } - public function provideTestAssertCountCases() + public function provideTestAssertCountCases(): array { return [ // positive fixing @@ -434,7 +433,7 @@ public function testAssertCountFromSizeOfCasing(string $expected, string $input) $this->doTest($expected, $input); } - public function provideTestAssertCountCasingCases() + public function provideTestAssertCountCasingCases(): array { return [ [ @@ -457,7 +456,7 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ @@ -491,6 +490,22 @@ public function provideFix73Cases() ]; } + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + self::generateTest('$a = $this->assertTrue(...);'), + ]; + } + private static function generateTest(string $content): string { return "doTest($expected, $input); } - public function provideTestFixInternalTypeCases() + public function provideTestFixInternalTypeCases(): array { return [ 'skip cases' => [ @@ -153,21 +153,6 @@ public function testMe() } ', ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ 'anonymous class false positive case' => [ 'doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ [ @@ -361,7 +361,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { $expectedTemplate = ' @@ -409,7 +409,7 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ diff --git a/tests/Fixer/PhpUnit/PhpUnitInternalClassFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitInternalClassFixerTest.php index 13de2fbbc47..64fcf3b0274 100644 --- a/tests/Fixer/PhpUnit/PhpUnitInternalClassFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitInternalClassFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'It does not change normal classes' => [ diff --git a/tests/Fixer/PhpUnit/PhpUnitMockFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitMockFixerTest.php index a6902acfa30..47557d42753 100644 --- a/tests/Fixer/PhpUnit/PhpUnitMockFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitMockFixerTest.php @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ [ diff --git a/tests/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixerTest.php index 3dd02ac44e0..1126c34b93a 100644 --- a/tests/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixerTest.php @@ -290,6 +290,21 @@ class FooTest extends TestCase { public function testFoo() { $someMock?->method("someMethod")?->will($this?->returnValue(10)); } +}' + ); + } + + /** + * @requires PHP 8.1 + */ + public function testFix81(): void + { + $this->doTest( + 'method("someMethod")->will($this?->returnValue(...)); + } }' ); } diff --git a/tests/Fixer/PhpUnit/PhpUnitNamespacedFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitNamespacedFixerTest.php index 72b087ffd25..e37ab08b49c 100644 --- a/tests/Fixer/PhpUnit/PhpUnitNamespacedFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitNamespacedFixerTest.php @@ -36,7 +36,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ 'class_mapping' => [ @@ -267,15 +267,35 @@ public function testClassIsFixed(string $class): void static::assertStringNotContainsString('_', $tokens->generateCode()); } - public static function provideClassIsFixedCases() + public static function provideClassIsFixedCases(): \Generator { $classmap = require __DIR__.'/../../../vendor/composer/autoload_classmap.php'; - foreach (array_keys($classmap) as $class) { - if (0 !== strpos($class, 'PHPUnit_')) { - continue; + foreach ($classmap as $class => $file) { + if (str_starts_with($class, 'PHPUnit_')) { + yield $file => [$class]; } - yield [$class]; } } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ 'empty exception message' => [ @@ -688,7 +688,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/PhpUnit/PhpUnitSizeClassFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitSizeClassFixerTest.php index c4ee1c9892d..23d3947683c 100644 --- a/tests/Fixer/PhpUnit/PhpUnitSizeClassFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitSizeClassFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'It does not change normal classes' => [ diff --git a/tests/Fixer/PhpUnit/PhpUnitStrictFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitStrictFixerTest.php index 882af3ada4d..c130ca7b3c5 100644 --- a/tests/Fixer/PhpUnit/PhpUnitStrictFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitStrictFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\PhpUnit; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** @@ -36,7 +37,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { $cases = [ ['foo();'], @@ -47,34 +48,42 @@ public function provideTestFixCases() $cases[] = [self::generateTest("\$sth->{$methodBefore}(1, 1);")]; $cases[] = [self::generateTest("\$sth->{$methodAfter}(1, 1);")]; $cases[] = [self::generateTest("\$this->{$methodBefore}(1, 2, 'message', \$toMuch);")]; + $cases[] = [ self::generateTest("\$this->{$methodAfter}(1, 2);"), self::generateTest("\$this->{$methodBefore}(1, 2);"), ]; + $cases[] = [ self::generateTest("\$this->{$methodAfter}(1, 2); \$this->{$methodAfter}(1, 2);"), self::generateTest("\$this->{$methodBefore}(1, 2); \$this->{$methodBefore}(1, 2);"), ]; + $cases[] = [ self::generateTest("\$this->{$methodAfter}(1, 2, 'descr');"), self::generateTest("\$this->{$methodBefore}(1, 2, 'descr');"), ]; + $cases[] = [ self::generateTest("\$this->/*aaa*/{$methodAfter} \t /**bbb*/ ( /*ccc*/1 , 2);"), self::generateTest("\$this->/*aaa*/{$methodBefore} \t /**bbb*/ ( /*ccc*/1 , 2);"), ]; + $cases[] = [ self::generateTest("\$this->{$methodAfter}(\$expectedTokens->count() + 10, \$tokens->count() ? 10 : 20 , 'Test');"), self::generateTest("\$this->{$methodBefore}(\$expectedTokens->count() + 10, \$tokens->count() ? 10 : 20 , 'Test');"), ]; + $cases[] = [ self::generateTest("self::{$methodAfter}(1, 2);"), self::generateTest("self::{$methodBefore}(1, 2);"), ]; + $cases[] = [ self::generateTest("static::{$methodAfter}(1, 2);"), self::generateTest("static::{$methodBefore}(1, 2);"), ]; + $cases[] = [ self::generateTest("STATIC::{$methodAfter}(1, 2);"), self::generateTest("STATIC::{$methodBefore}(1, 2);"), @@ -95,9 +104,10 @@ public function testNoFixWithWrongNumberOfArguments(string $expected): void $this->doTest($expected); } - public function provideTestNoFixWithWrongNumberOfArgumentsCases() + public function provideTestNoFixWithWrongNumberOfArgumentsCases(): array { $cases = []; + foreach ($this->getMethodsMap() as $candidate => $fix) { $cases[sprintf('do not change call to "%s" without arguments.', $candidate)] = [ self::generateTest(sprintf('$this->%s();', $candidate)), @@ -121,7 +131,7 @@ public function provideTestNoFixWithWrongNumberOfArgumentsCases() public function testInvalidConfig(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[php_unit_strict\] Invalid configuration: The option "assertions" .*\.$/'); $this->fixer->configure(['assertions' => ['__TEST__']]); @@ -136,7 +146,7 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): \Generator { foreach ($this->getMethodsMap() as $methodBefore => $methodAfter) { yield [ diff --git a/tests/Fixer/PhpUnit/PhpUnitTargetVersionTest.php b/tests/Fixer/PhpUnit/PhpUnitTargetVersionTest.php index 3b16183b7bf..2ecb1189049 100644 --- a/tests/Fixer/PhpUnit/PhpUnitTargetVersionTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitTargetVersionTest.php @@ -41,7 +41,7 @@ public function testFulfills(bool $expected, string $candidate, string $target, ); } - public function provideTestFulfillsCases() + public function provideTestFulfillsCases(): array { return [ [true, PhpUnitTargetVersion::VERSION_NEWEST, PhpUnitTargetVersion::VERSION_5_6], diff --git a/tests/Fixer/PhpUnit/PhpUnitTestAnnotationFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitTestAnnotationFixerTest.php index dd78946b72b..930ff5df902 100644 --- a/tests/Fixer/PhpUnit/PhpUnitTestAnnotationFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitTestAnnotationFixerTest.php @@ -988,7 +988,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null, ar $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixerTest.php b/tests/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixerTest.php index f8d052b5a2b..46583e8fe51 100644 --- a/tests/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixerTest.php +++ b/tests/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\PhpUnit; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTestCaseStaticMethodCallsFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PHPUnit\Framework\TestCase; @@ -48,7 +49,7 @@ public function testFixerContainsAllPhpunitStaticMethodsInItsList(): void public function testWrongConfigTypeForMethodsKey(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/Unexpected "methods" key, expected any of ".*", got "integer#123"\.$/'); $this->fixer->configure(['methods' => [123 => 1]]); @@ -56,7 +57,7 @@ public function testWrongConfigTypeForMethodsKey(): void public function testWrongConfigTypeForMethodsValue(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/Unexpected value for method "assertSame", expected any of ".*", got "integer#123"\.$/'); $this->fixer->configure(['methods' => ['assertSame' => 123]]); @@ -71,7 +72,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ [ @@ -500,9 +501,6 @@ public function testFoo() ]; } - /** - * @requires PHP 7.0 - */ public function testAnonymousClassFixing(): void { $this->doTest( @@ -538,4 +536,28 @@ public function assertSame($a, $b) }' ); } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'already with annotation: @covers' => [ @@ -247,7 +247,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/AlignMultilineCommentFixerTest.php b/tests/Fixer/Phpdoc/AlignMultilineCommentFixerTest.php index 97794e50121..30b6497793a 100644 --- a/tests/Fixer/Phpdoc/AlignMultilineCommentFixerTest.php +++ b/tests/Fixer/Phpdoc/AlignMultilineCommentFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\Phpdoc; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\WhitespacesFixerConfig; @@ -28,7 +29,7 @@ final class AlignMultilineCommentFixerTest extends AbstractFixerTestCase { public function testInvalidConfiguration(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->fixer->configure(['a' => 1]); } @@ -41,7 +42,7 @@ public function testDefaults(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideDefaultCases() + public function provideDefaultCases(): array { return [ [ @@ -179,7 +180,7 @@ public function testDocLikeMultilineComments(string $expected, ?string $input = $this->doTest($expected, $input); } - public function provideDocLikeMultilineCommentsCases() + public function provideDocLikeMultilineCommentsCases(): array { return [ [ @@ -227,7 +228,7 @@ public function testMixedContentMultilineComments(string $expected, ?string $inp $this->doTest($expected, $input); } - public function provideMixedContentMultilineCommentsCases() + public function provideMixedContentMultilineCommentsCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/GeneralPhpdocTagRenameFixerTest.php b/tests/Fixer/Phpdoc/GeneralPhpdocTagRenameFixerTest.php index ca88a7ee594..1ca6b60fb24 100644 --- a/tests/Fixer/Phpdoc/GeneralPhpdocTagRenameFixerTest.php +++ b/tests/Fixer/Phpdoc/GeneralPhpdocTagRenameFixerTest.php @@ -36,7 +36,7 @@ public function testFix(string $expected, ?string $input = null, ?array $configu $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -275,7 +275,7 @@ public function testConfigureWithInvalidReplacements(array $replacements, bool $ ]); } - public function provideConfigureWithInvalidReplacementsCases() + public function provideConfigureWithInvalidReplacementsCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixerTest.php b/tests/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixerTest.php index fc619d99fc9..9501b3e6fd6 100644 --- a/tests/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixerTest.php +++ b/tests/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixerTest.php @@ -17,7 +17,7 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * @@ -324,7 +324,7 @@ public function testInlineTypehintingDocsBeforeFlowBreak(string $expected, ?stri $this->doTest($expected, $input); } - public function provideInlineTypehintingDocsBeforeFlowBreakCases() + public function provideInlineTypehintingDocsBeforeFlowBreakCases(): array { $cases = []; diff --git a/tests/Fixer/Phpdoc/NoEmptyPhpdocFixerTest.php b/tests/Fixer/Phpdoc/NoEmptyPhpdocFixerTest.php index 6a7abede202..9e5db73081b 100644 --- a/tests/Fixer/Phpdoc/NoEmptyPhpdocFixerTest.php +++ b/tests/Fixer/Phpdoc/NoEmptyPhpdocFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer @@ -33,7 +31,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixerTest.php b/tests/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixerTest.php index 8105fdda5d6..1ed5a34e3da 100644 --- a/tests/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixerTest.php +++ b/tests/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixerTest.php @@ -32,7 +32,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'no typehint' => [ @@ -1083,22 +1083,6 @@ class Foo { private $bar; }', ], - ]; - } - - /** - * @dataProvider provideFixPhp70Cases - * @requires PHP 7.0 - */ - public function testFixPhp70(string $expected, ?string $input = null, array $config = []): void - { - $this->fixer->configure($config); - $this->doTest($expected, $input); - } - - public function provideFixPhp70Cases() - { - return [ 'same type hint' => [ ' [ + 'multiple different types (with return type)' => [ ' [ + 'with import (with return type)' => [ ' [ + 'with root symbols (with return type)' => [ ' [ + 'with mix of imported and fully qualified symbols (with return type)' => [ ' [ + 'with aliased imported (with return type)' => [ ' true], ], + 'remove_trait_inheritdoc' => [ + ' true], + ], ]; } @@ -1262,7 +1259,7 @@ public function testFixPhp71(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp71Cases() + public function provideFixPhp71Cases(): array { return [ 'same nullable type hint' => [ @@ -1437,7 +1434,7 @@ public function testFixPhp74(string $expected, ?string $input = null, array $con $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ 'some typed static public property' => [ @@ -1713,7 +1710,7 @@ public function testFixPhp80(string $expected, ?string $input = null, array $con $this->doTest($expected, $input); } - public function provideFixPhp80Cases() + public function provideFixPhp80Cases(): array { return [ 'static return' => [ @@ -1733,4 +1730,50 @@ public function foo($foo): static {} ], ]; } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, string $input): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'some readonly properties' => [ + 'expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage(sprintf( '[phpdoc_add_missing_param_annotation] Invalid configuration: The option "%s" does not exist.', $key @@ -48,7 +49,7 @@ public function testConfigureRejectsUnknownConfigurationKey(): void */ public function testConfigureRejectsInvalidConfigurationValue($value, string $expectedMessage): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidConfigurationException::class); + $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessageMatches($expectedMessage); $this->fixer->configure([ @@ -97,7 +98,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -299,23 +300,6 @@ function hello($string) return $string; }', ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null, array $config = []): void - { - $this->fixer->configure($config ?: ['only_untyped' => false]); - - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ [ @@ -412,7 +396,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null, ar $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ @@ -431,7 +415,7 @@ public function testByReference(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideByReferenceCases() + public function provideByReferenceCases(): array { return [ [ @@ -476,7 +460,7 @@ public function testVariableNumberOfArguments(string $expected, string $input): $this->doTest($expected, $input); } - public function provideVariableNumberOfArgumentsCases() + public function provideVariableNumberOfArgumentsCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocAlignFixerTest.php b/tests/Fixer/Phpdoc/PhpdocAlignFixerTest.php index e24c0e71857..44adf788872 100644 --- a/tests/Fixer/Phpdoc/PhpdocAlignFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocAlignFixerTest.php @@ -785,7 +785,7 @@ public function testMessyWhitespaces(array $config, string $expected, string $in $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ @@ -1133,7 +1133,7 @@ public function testVariadicParams(array $config, string $expected, string $inpu $this->doTest($expected, $input); } - public function provideVariadicCases() + public function provideVariadicCases(): array { return [ [ @@ -1255,7 +1255,7 @@ public function testInvalidPhpdocsAreUnchanged(array $config, string $input): vo $this->doTest($input); } - public function provideInvalidPhpdocCases() + public function provideInvalidPhpdocCases(): array { return [ [ @@ -1286,4 +1286,36 @@ public function provideInvalidPhpdocCases() ], ]; } + + public function testTypesContainingCallables(): void + { + $this->doTest( + 'doTest(' $value + */ + /** + * @param array $arrayOfIntegers + * @param array $arrayOfStrings + */ + '); + } } diff --git a/tests/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixerTest.php b/tests/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixerTest.php index 0041cd7ee47..37c2151c875 100644 --- a/tests/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocIndentFixerTest.php b/tests/Fixer/Phpdoc/PhpdocIndentFixerTest.php index 4aef4c66d8e..6a2a45bfdbd 100644 --- a/tests/Fixer/Phpdoc/PhpdocIndentFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocIndentFixerTest.php @@ -33,7 +33,7 @@ public function testFixIndent(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixIndentCases() + public function provideFixIndentCases(): array { $cases = []; diff --git a/tests/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixerTest.php b/tests/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixerTest.php index bcad4dba748..fd2f088f1cd 100644 --- a/tests/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixerTest.php @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null, ?array $configu $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $cases = [ [ @@ -51,7 +51,7 @@ public function provideFixCases() * {@inheritdoc foo bar.} d * {@inheritdoc foo bar.} e * {@inheritdoc test} f - * end comment {@inheritdoc here we are done} @spacepossum {1} + * end comment {@inheritdoc here we are done} @foo {1} */ ', 'doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ 'It can handle constants with visibility' => [ @@ -472,8 +470,6 @@ class Foo /** * @requires PHP 7.4 * @dataProvider provideFixPhp74Cases - * - * @param string $input */ public function testFixPhp74(string $expected, string $input = null, array $config = []): void { @@ -481,7 +477,7 @@ public function testFixPhp74(string $expected, string $input = null, array $conf $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ 'It can handle properties with type declaration' => [ @@ -528,4 +524,98 @@ class Foo ], ]; } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, string $input = null, array $config = []): void + { + $this->fixer->configure($config); + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'readonly' => [ + ' 'single', + ], + ]; + + yield [ + ' + * @author Graham Campbell * * @internal * diff --git a/tests/Fixer/Phpdoc/PhpdocNoAliasTagFixerTest.php b/tests/Fixer/Phpdoc/PhpdocNoAliasTagFixerTest.php index a59665fd0c5..ec1b066e3fe 100644 --- a/tests/Fixer/Phpdoc/PhpdocNoAliasTagFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocNoAliasTagFixerTest.php @@ -14,12 +14,12 @@ namespace PhpCsFixer\Tests\Fixer\Phpdoc; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński - * @author SpacePossum * * @internal * @@ -29,7 +29,7 @@ final class PhpdocNoAliasTagFixerTest extends AbstractFixerTestCase { public function testInvalidConfigCase1(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[phpdoc_no_alias_tag\] Invalid configuration: Tag to replace must be a string\.$#'); $this->fixer->configure(['replacements' => [1 => 'abc']]); @@ -37,7 +37,7 @@ public function testInvalidConfigCase1(): void public function testInvalidConfigCase2(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[phpdoc_no_alias_tag\] Invalid configuration: Tag to replace to from "a" must be a string\.$#'); $this->fixer->configure(['replacements' => ['a' => null]]); @@ -45,7 +45,7 @@ public function testInvalidConfigCase2(): void public function testInvalidConfigCase3(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[phpdoc_no_alias_tag\] Invalid configuration: Tag "see" cannot be replaced by invalid tag "link\*\/"\.$#'); $this->fixer->configure(['replacements' => ['see' => 'link*/']]); @@ -53,7 +53,7 @@ public function testInvalidConfigCase3(): void public function testInvalidConfigCase4(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[phpdoc_no_alias_tag\] Invalid configuration: Cannot change tag "link" to tag "see", as the tag "see" is configured to be replaced to "link"\.$#'); $this->fixer->configure(['replacements' => [ @@ -65,7 +65,7 @@ public function testInvalidConfigCase4(): void public function testInvalidConfigCase5(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[phpdoc_no_alias_tag\] Invalid configuration: Cannot change tag "b" to tag "see", as the tag "see" is configured to be replaced to "link"\.$#'); $this->fixer->configure(['replacements' => [ @@ -77,7 +77,7 @@ public function testInvalidConfigCase5(): void public function testInvalidConfigCase6(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[phpdoc_no_alias_tag\] Invalid configuration: Cannot change tag "see" to tag "link", as the tag "link" is configured to be replaced to "b"\.$#'); $this->fixer->configure(['replacements' => [ @@ -99,7 +99,7 @@ public function testPropertyFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function providePropertyCases() + public function providePropertyCases(): array { return [ [ @@ -137,7 +137,7 @@ public function testTypeToVarFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTypeToVarCases() + public function provideTypeToVarCases(): array { return [ [ @@ -195,7 +195,7 @@ public function testVarToTypeFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideVarToTypeCases() + public function provideVarToTypeCases(): array { return [ [ @@ -261,7 +261,7 @@ public function testDefaultConfig(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideDefaultConfigCases() + public function provideDefaultConfigCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocNoEmptyReturnFixerTest.php b/tests/Fixer/Phpdoc/PhpdocNoEmptyReturnFixerTest.php index 22dcc88476d..a55ce39908d 100644 --- a/tests/Fixer/Phpdoc/PhpdocNoEmptyReturnFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocNoEmptyReturnFixerTest.php @@ -17,7 +17,7 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * diff --git a/tests/Fixer/Phpdoc/PhpdocNoPackageFixerTest.php b/tests/Fixer/Phpdoc/PhpdocNoPackageFixerTest.php index 4138969cc01..b3e345d80b1 100644 --- a/tests/Fixer/Phpdoc/PhpdocNoPackageFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocNoPackageFixerTest.php @@ -17,7 +17,7 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * diff --git a/tests/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixerTest.php b/tests/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixerTest.php index c468079c4ba..28161a13ce5 100644 --- a/tests/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixerTest.php @@ -19,8 +19,6 @@ /** * @internal * - * @author SpacePossum - * * @covers \PhpCsFixer\Fixer\Phpdoc\PhpdocNoUselessInheritdocFixer */ final class PhpdocNoUselessInheritdocFixerTest extends AbstractFixerTestCase @@ -33,7 +31,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -283,21 +281,6 @@ public function importFromTrait() } ', ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ 'doTest($expected, $input); } - public function provideFixWithAuthorCases() + public function provideFixWithAuthorCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -199,7 +199,7 @@ public function testFixWithCovers(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithCoversCases() + public function provideFixWithCoversCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -319,7 +319,7 @@ public function testFixWithCoversNothing(string $expected, ?string $input = null $this->doTest($expected, $input); } - public function provideFixWithCoversNothingCases() + public function provideFixWithCoversNothingCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -439,7 +439,7 @@ public function testFixWithDataProvider(string $expected, ?string $input = null) $this->doTest($expected, $input); } - public function provideFixWithDataProviderCases() + public function provideFixWithDataProviderCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -559,7 +559,7 @@ public function testFixWithDepends(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideFixWithDependsCases() + public function provideFixWithDependsCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -679,7 +679,7 @@ public function testFixWithGroup(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithGroupCases() + public function provideFixWithGroupCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -799,7 +799,7 @@ public function testFixWithInternal(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixWithInternalCases() + public function provideFixWithInternalCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -919,7 +919,7 @@ public function testFixWithMethod(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithMethodCases() + public function provideFixWithMethodCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -1043,7 +1043,7 @@ public function testFixWithProperty(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixWithPropertyCases() + public function provideFixWithPropertyCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -1151,7 +1151,7 @@ public function testFixWithPropertyRead(string $expected, ?string $input = null) $this->doTest($expected, $input); } - public function provideFixWithPropertyReadCases() + public function provideFixWithPropertyReadCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -1259,7 +1259,7 @@ public function testFixWithPropertyWrite(string $expected, ?string $input = null $this->doTest($expected, $input); } - public function provideFixWithPropertyWriteCases() + public function provideFixWithPropertyWriteCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -1367,7 +1367,7 @@ public function testFixWithRequires(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixWithRequiresCases() + public function provideFixWithRequiresCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -1487,7 +1487,7 @@ public function testFixWithThrows(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithThrowsCases() + public function provideFixWithThrowsCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -1623,7 +1623,7 @@ public function testFixWithUses(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithUsesCases() + public function provideFixWithUsesCases(): array { return [ 'skip on 1 or 0 occurrences' => [ @@ -1744,7 +1744,7 @@ public function testFixWithMultipleConfiguredAnnotations(string $expected, ?stri $this->doTest($expected, $input); } - public function provideFixWithMultipleConfiguredAnnotationsCases() + public function provideFixWithMultipleConfiguredAnnotationsCases(): array { return [ 'skip on 1 or 0 occurrences' => [ diff --git a/tests/Fixer/Phpdoc/PhpdocOrderFixerTest.php b/tests/Fixer/Phpdoc/PhpdocOrderFixerTest.php index be4d2fb78e8..04308c979e7 100644 --- a/tests/Fixer/Phpdoc/PhpdocOrderFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocOrderFixerTest.php @@ -17,7 +17,7 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * diff --git a/tests/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixerTest.php b/tests/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixerTest.php index 97333155d5f..f1981d24acc 100644 --- a/tests/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixerTest.php @@ -14,11 +14,10 @@ namespace PhpCsFixer\Tests\Fixer\Phpdoc; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Phpdoc\PhpdocReturnSelfReferenceFixer @@ -37,7 +36,7 @@ public function testFixWithDefaultConfiguration(string $expected, ?string $input $this->doTest($expected, $input); } - public function provideDefaultConfigurationTestCases() + public function provideDefaultConfigurationTestCases(): array { return [ [ @@ -69,7 +68,7 @@ public function testFix(string $expected, ?string $input = null, array $configur $this->doTest($expected, $input); } - public function provideTestCases() + public function provideTestCases(): array { return [ [ @@ -127,7 +126,7 @@ public function AB($self) $this->doTest($expected, $input); } - public function provideGeneratedFixCases() + public function provideGeneratedFixCases(): array { return [ ['$this', 'this'], @@ -144,13 +143,13 @@ public function provideGeneratedFixCases() */ public function testInvalidConfiguration(array $configuration, string $message): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches(sprintf('/^\[phpdoc_return_self_reference\] %s$/', preg_quote($message, '/'))); $this->fixer->configure($configuration); } - public function provideInvalidConfigurationCases() + public function provideInvalidConfigurationCases(): array { return [ [ @@ -166,9 +165,6 @@ public function provideInvalidConfigurationCases() ]; } - /** - * @requires PHP 7.0 - */ public function testAnonymousClassFixing(): void { $this->doTest( diff --git a/tests/Fixer/Phpdoc/PhpdocScalarFixerTest.php b/tests/Fixer/Phpdoc/PhpdocScalarFixerTest.php index 50c054cf2d2..ffe94c1ad19 100644 --- a/tests/Fixer/Phpdoc/PhpdocScalarFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocScalarFixerTest.php @@ -17,7 +17,7 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public static function provideFixCases() + public static function provideFixCases(): \Generator { yield 'basic fix' => [ ' + * @author Graham Campbell * * @internal * @@ -406,7 +406,7 @@ public function testClassDocBlock(): void * @subpackage Foo\Bar * * @author Dariusz Rumiński - * @author Graham Campbell + * @author Graham Campbell * @copyright Foo Bar * @license MIT */ @@ -428,7 +428,7 @@ class Bar {} * @subpackage Foo\Bar * @author Dariusz Rumiński * - * @author Graham Campbell + * @author Graham Campbell * * @copyright Foo Bar * @@ -455,7 +455,7 @@ public function testPoorAlignment(): void * @internal * * @author Dariusz Rumiński - *@author Graham Campbell + *@author Graham Campbell */ class Bar {} @@ -476,7 +476,7 @@ class Bar {} * @author Dariusz Rumiński * * - *@author Graham Campbell + *@author Graham Campbell */ class Bar {} @@ -533,7 +533,7 @@ public function testInheritDoc(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideInheritDocCases() + public function provideInheritDocCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixerTest.php b/tests/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixerTest.php index f754dbddfd6..300e96eca0d 100644 --- a/tests/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Phpdoc\PhpdocSingleLineVarSpacingFixer @@ -33,7 +31,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocSummaryFixerTest.php b/tests/Fixer/Phpdoc/PhpdocSummaryFixerTest.php index c09bf284439..2bf83e61db6 100644 --- a/tests/Fixer/Phpdoc/PhpdocSummaryFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocSummaryFixerTest.php @@ -18,7 +18,7 @@ use PhpCsFixer\WhitespacesFixerConfig; /** - * @author Graham Campbell + * @author Graham Campbell * * @internal * @@ -367,7 +367,7 @@ public function testWithInheritDoc(string $expected): void $this->doTest($expected); } - public function provideInheritDocCases() + public function provideInheritDocCases(): array { return [ [ @@ -410,7 +410,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocTagCasingFixerTest.php b/tests/Fixer/Phpdoc/PhpdocTagCasingFixerTest.php index 63143610887..c6ff88eb0ee 100644 --- a/tests/Fixer/Phpdoc/PhpdocTagCasingFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocTagCasingFixerTest.php @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocTagTypeFixerTest.php b/tests/Fixer/Phpdoc/PhpdocTagTypeFixerTest.php index 379be704b77..31276763e71 100644 --- a/tests/Fixer/Phpdoc/PhpdocTagTypeFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocTagTypeFixerTest.php @@ -36,7 +36,7 @@ public function testFix(string $expected, ?string $input = null, ?array $configu $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -350,6 +350,40 @@ public function provideFixCases() * @return array{0: float, 1: int} */', ], + [ + 'doTest($expected, $input); } - /** - * @dataProvider provideTraitsCases - */ - public function testFixTraits(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideDocblocksCases() + public function provideDocblocksCases(): array { $cases = []; @@ -682,7 +676,7 @@ public function b() return $cases; } - public function provideTraitsCases() + public function provideTraitsCases(): array { return [ [ @@ -700,16 +694,7 @@ public function test() {} ]; } - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() + public function provideFixCases(): array { return [ [ @@ -736,7 +721,7 @@ public function testFix71(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ [ @@ -781,7 +766,7 @@ public function testFix74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ [ @@ -841,7 +826,7 @@ public function testFix80(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixerTest.php b/tests/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixerTest.php index 8fcd6e395d9..6f016b1cbb1 100644 --- a/tests/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'no changes' => [' + * @author Graham Campbell * * @internal * @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -122,7 +122,7 @@ public function testClassDocBlock(): void * @internal * * @author Dariusz Rumiński - * @author Graham Campbell + * @author Graham Campbell */ class Bar {} @@ -141,7 +141,7 @@ class Bar {} * @internal * * @author Dariusz Rumiński - * @author Graham Campbell + * @author Graham Campbell * * * diff --git a/tests/Fixer/Phpdoc/PhpdocTypesFixerTest.php b/tests/Fixer/Phpdoc/PhpdocTypesFixerTest.php index a0de2889591..33d0715c93a 100644 --- a/tests/Fixer/Phpdoc/PhpdocTypesFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocTypesFixerTest.php @@ -14,10 +14,11 @@ namespace PhpCsFixer\Tests\Fixer\Phpdoc; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński * * @internal @@ -256,7 +257,7 @@ public function testWithConfig(): void public function testWrongConfig(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[phpdoc_types\] Invalid configuration: The option "groups" .*\.$/'); $this->fixer->configure(['groups' => ['__TEST__']]); diff --git a/tests/Fixer/Phpdoc/PhpdocTypesOrderFixerTest.php b/tests/Fixer/Phpdoc/PhpdocTypesOrderFixerTest.php index aa3ff840663..e295215795f 100644 --- a/tests/Fixer/Phpdoc/PhpdocTypesOrderFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocTypesOrderFixerTest.php @@ -44,7 +44,7 @@ public function testFixWithNullFirst(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -175,7 +175,7 @@ public function testFixWithNullLast(string $expected, ?string $input = null): vo $this->doTest($expected, $input); } - public function provideFixWithNullLastCases() + public function provideFixWithNullLastCases(): array { return [ [ @@ -293,7 +293,7 @@ public function testFixWithAlphaAlgorithm(string $expected, ?string $input = nul $this->doTest($expected, $input); } - public function provideFixWithAlphaAlgorithmCases() + public function provideFixWithAlphaAlgorithmCases(): array { return [ [ @@ -407,7 +407,7 @@ public function testFixWithAlphaAlgorithmAndNullAlwaysFirst(string $expected, ?s $this->doTest($expected, $input); } - public function provideFixWithAlphaAlgorithmAndNullAlwaysFirstCases() + public function provideFixWithAlphaAlgorithmAndNullAlwaysFirstCases(): array { return [ [ @@ -522,7 +522,7 @@ public function testFixWithAlphaAlgorithmAndNullAlwaysLast(string $expected, ?st $this->doTest($expected, $input); } - public function provideFixWithAlphaAlgorithmAndNullAlwaysLastCases() + public function provideFixWithAlphaAlgorithmAndNullAlwaysLastCases(): array { return [ [ diff --git a/tests/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixerTest.php b/tests/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixerTest.php index 8f2578def0a..ad63070c02b 100644 --- a/tests/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixerTest.php +++ b/tests/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { yield [ // It's @param, we care only about @var ' + * @author Graham Campbell * * @internal * @@ -46,7 +46,7 @@ public function testFixType(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixVarCases() + public function provideFixVarCases(): array { return [ 'testFixVar' => [ @@ -382,21 +382,6 @@ class Foo class Foo{} /** */', ], - ]; - } - - /** - * @requires PHP 7.0 - * @dataProvider provideFixVar70Cases - */ - public function testFixVar70(string $expected, ?string $input = null): void - { - $this->doTest($expected, $input); - } - - public function provideFixVar70Cases() - { - return [ 'anonymousClass' => [ <<<'EOF' [ + ' SKIPPED_TYPES + */ + private const SKIPPED_TYPES = ["a" => true]; +} +', + ], + ]; + } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected, ?string $input = null): void + { + $this->doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'readonly' => [ + ' [ + ' SKIPPED_TYPES + */ + final public const SKIPPED_TYPES = ["a" => true]; +} +', ]; } } diff --git a/tests/Fixer/ReturnNotation/NoUselessReturnFixerTest.php b/tests/Fixer/ReturnNotation/NoUselessReturnFixerTest.php index 6ed84d57415..0aa7163e141 100644 --- a/tests/Fixer/ReturnNotation/NoUselessReturnFixerTest.php +++ b/tests/Fixer/ReturnNotation/NoUselessReturnFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\ReturnNotation\NoUselessReturnFixer @@ -33,7 +31,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/ReturnNotation/ReturnAssignmentFixerTest.php b/tests/Fixer/ReturnNotation/ReturnAssignmentFixerTest.php index 1dbd408d8c2..bc2904db34f 100644 --- a/tests/Fixer/ReturnNotation/ReturnAssignmentFixerTest.php +++ b/tests/Fixer/ReturnNotation/ReturnAssignmentFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\ReturnNotation\ReturnAssignmentFixer @@ -33,7 +31,7 @@ public function testFixNestedFunctions(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixNestedFunctionsCases() + public function provideFixNestedFunctionsCases(): array { return [ [ @@ -193,7 +191,7 @@ public function testFix(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -446,21 +444,6 @@ function a($foos) { }', ], ], - ]; - } - - /** - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $expected, string $input): void - { - $this->doTest($expected, $input); - } - - public function provideFix70Cases() - { - return [ [ 'doTest($expected); } - public function provideDoNotFixCases() + public function provideDoNotFixCases(): array { return [ 'invalid reference stays invalid' => [ @@ -813,7 +796,7 @@ public function testRepetitiveFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideRepetitiveFixCases() + public function provideRepetitiveFixCases(): \Generator { yield [ ' + * @author Graham Campbell * * @internal * @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ // check correct statements aren't changed @@ -64,7 +64,7 @@ public function test71ReturnTypes(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideNullableReturnTypeCases() + public function provideNullableReturnTypeCases(): array { return [ [' - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński * @author Egidijus Girčys * @@ -39,7 +39,7 @@ public function testFixMultiLineWhitespace(string $expected, ?string $input = nu $this->doTest($expected, $input); } - public function provideMultiLineWhitespaceFixCases() + public function provideMultiLineWhitespaceFixCases(): array { return [ [ @@ -212,7 +212,7 @@ public function testMessyWhitespacesMultiLineWhitespace(string $expected, ?strin $this->doTest($expected, $input); } - public function provideMessyWhitespacesMultiLineWhitespaceFixCases() + public function provideMessyWhitespacesMultiLineWhitespaceFixCases(): array { return [ [ @@ -230,7 +230,7 @@ public function testSemicolonForChainedCallsFix(string $expected, ?string $input $this->doTest($expected, $input); } - public function provideSemicolonForChainedCallsFixCases() + public function provideSemicolonForChainedCallsFixCases(): array { return [ [ @@ -852,7 +852,7 @@ public function testMessyWhitespacesSemicolonForChainedCalls(string $expected, ? $this->doTest($expected, $input); } - public function provideMessyWhitespacesSemicolonForChainedCallsFixCases() + public function provideMessyWhitespacesSemicolonForChainedCallsFixCases(): array { return [ [ @@ -880,7 +880,7 @@ public function testFix73(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): array { return [ [ diff --git a/tests/Fixer/Semicolon/NoEmptyStatementFixerTest.php b/tests/Fixer/Semicolon/NoEmptyStatementFixerTest.php index 76762e46f0f..6a0baba348e 100644 --- a/tests/Fixer/Semicolon/NoEmptyStatementFixerTest.php +++ b/tests/Fixer/Semicolon/NoEmptyStatementFixerTest.php @@ -17,7 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum * @author Dariusz Rumiński * * @internal @@ -34,9 +33,9 @@ public function testNoEmptyStatements(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideNoEmptyStatementsCases() + public function provideNoEmptyStatementsCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } - foreach (['break', 'continue'] as $ops) { yield [ sprintf('doTest($expected, $input); } - public function providePHP7Cases() + public function provideFixCases(): array { return [ [ @@ -534,7 +528,7 @@ public function testCasesWithShortOpenTag(string $expected, ?string $input = nul $this->doTest($expected, $input); } - public function provideCasesWithShortOpenTagCases() + public function provideCasesWithShortOpenTagCases(): array { return [ [ @@ -552,7 +546,7 @@ public function testFixMultipleSemicolons(string $expected, ?string $input = nul $this->doTest($expected, $input); } - public function provideFixMultipleSemicolonsCases() + public function provideFixMultipleSemicolonsCases(): array { return [ [ diff --git a/tests/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixerTest.php b/tests/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixerTest.php index 7b040fadd99..31e8ba7fbfb 100644 --- a/tests/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixerTest.php +++ b/tests/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixerTest.php @@ -18,7 +18,7 @@ /** * @author John Kelly - * @author Graham Campbell + * @author Graham Campbell * @author Dariusz Rumiński * * @internal @@ -35,7 +35,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Semicolon/SemicolonAfterInstructionFixerTest.php b/tests/Fixer/Semicolon/SemicolonAfterInstructionFixerTest.php index 75cf466ad39..a5d8691c11e 100644 --- a/tests/Fixer/Semicolon/SemicolonAfterInstructionFixerTest.php +++ b/tests/Fixer/Semicolon/SemicolonAfterInstructionFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Semicolon\SemicolonAfterInstructionFixer @@ -33,9 +31,9 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ 'comment' => [ '', '', @@ -82,17 +80,23 @@ public function provideFixCases() ', ], ]; + } - foreach ($tests as $index => $test) { - yield $index => $test; - } + /** + * @dataProvider provideFixPre80Cases + * @requires PHP <8.0 + */ + public function testFixPre80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID < 80000) { - yield [ - '', - '', - ]; - } + public function provideFixPre80Cases(): \Generator + { + yield [ + '', + '', + ]; } public function testOpenWithEcho(): void diff --git a/tests/Fixer/Semicolon/SpaceAfterSemicolonFixerTest.php b/tests/Fixer/Semicolon/SpaceAfterSemicolonFixerTest.php index 60d02e96fc1..ed33ae2dc02 100644 --- a/tests/Fixer/Semicolon/SpaceAfterSemicolonFixerTest.php +++ b/tests/Fixer/Semicolon/SpaceAfterSemicolonFixerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Semicolon\SpaceAfterSemicolonFixer @@ -44,7 +42,7 @@ public function testFixWithSpacesInEmptyForExpressions(string $expected, ?string $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -292,7 +290,7 @@ public function testFixWithoutSpacesInEmptyForExpressions(string $expected, ?str $this->doTest($expected, $input); } - public function provideFixWithoutSpacesInEmptyForExpressionsCases() + public function provideFixWithoutSpacesInEmptyForExpressionsCases(): array { return [ [ diff --git a/tests/Fixer/Strict/DeclareStrictTypesFixerTest.php b/tests/Fixer/Strict/DeclareStrictTypesFixerTest.php index 7292305b881..0272edd280b 100644 --- a/tests/Fixer/Strict/DeclareStrictTypesFixerTest.php +++ b/tests/Fixer/Strict/DeclareStrictTypesFixerTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\WhitespacesFixerConfig; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer @@ -28,14 +26,13 @@ final class DeclareStrictTypesFixerTest extends AbstractFixerTestCase { /** * @dataProvider provideFixCases - * @requires PHP 7.0 */ public function testFix(string $expected, ?string $input = null): void { $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -132,7 +129,7 @@ public function testDoNotFix(string $input): void $this->doTest($input); } - public function provideDoNotFixCases() + public function provideDoNotFixCases(): array { return [ [' doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/Strict/StrictComparisonFixerTest.php b/tests/Fixer/Strict/StrictComparisonFixerTest.php index a140e62b814..dc77e57e654 100644 --- a/tests/Fixer/Strict/StrictComparisonFixerTest.php +++ b/tests/Fixer/Strict/StrictComparisonFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ ['doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -188,7 +188,7 @@ public function testFix73(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix73Cases() + public function provideFix73Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ [ diff --git a/tests/Fixer/StringNotation/ExplicitStringVariableFixerTest.php b/tests/Fixer/StringNotation/ExplicitStringVariableFixerTest.php index 27405efd94b..8334e3bc180 100644 --- a/tests/Fixer/StringNotation/ExplicitStringVariableFixerTest.php +++ b/tests/Fixer/StringNotation/ExplicitStringVariableFixerTest.php @@ -33,9 +33,10 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { $input = $expected = 'doTest($expected, $input); } - public function provideTestFix71Cases() + public function provideTestFix71Cases(): array { return [ [ diff --git a/tests/Fixer/StringNotation/HeredocToNowdocFixerTest.php b/tests/Fixer/StringNotation/HeredocToNowdocFixerTest.php index 4e4f48da39d..55761c95709 100644 --- a/tests/Fixer/StringNotation/HeredocToNowdocFixerTest.php +++ b/tests/Fixer/StringNotation/HeredocToNowdocFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ [<<<'EOF' diff --git a/tests/Fixer/StringNotation/NoBinaryStringFixerTest.php b/tests/Fixer/StringNotation/NoBinaryStringFixerTest.php index f39d001b8f0..9b0eafa2771 100644 --- a/tests/Fixer/StringNotation/NoBinaryStringFixerTest.php +++ b/tests/Fixer/StringNotation/NoBinaryStringFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ [ diff --git a/tests/Fixer/StringNotation/NoTrailingWhitespaceInStringFixerTest.php b/tests/Fixer/StringNotation/NoTrailingWhitespaceInStringFixerTest.php index 487cb0ac2fe..6cf5d890ae8 100644 --- a/tests/Fixer/StringNotation/NoTrailingWhitespaceInStringFixerTest.php +++ b/tests/Fixer/StringNotation/NoTrailingWhitespaceInStringFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/StringNotation/SingleQuoteFixerTest.php b/tests/Fixer/StringNotation/SingleQuoteFixerTest.php index bd2fc233363..6e03783a39d 100644 --- a/tests/Fixer/StringNotation/SingleQuoteFixerTest.php +++ b/tests/Fixer/StringNotation/SingleQuoteFixerTest.php @@ -33,7 +33,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideTestFixCases() + public function provideTestFixCases(): array { return [ [ @@ -131,7 +131,7 @@ public function testSingleQuoteFix(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideTestSingleQuoteFixCases() + public function provideTestSingleQuoteFixCases(): array { return [ [ diff --git a/tests/Fixer/StringNotation/StringLineEndingFixerTest.php b/tests/Fixer/StringNotation/StringLineEndingFixerTest.php index 019719e84c0..44480b99de6 100644 --- a/tests/Fixer/StringNotation/StringLineEndingFixerTest.php +++ b/tests/Fixer/StringNotation/StringLineEndingFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $heredocTemplate = "doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return $this->withLongArraySyntaxCases([ [ @@ -845,7 +845,7 @@ public function testFixWithTabs(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithTabsCases() + public function provideFixWithTabsCases(): array { return $this->withLongArraySyntaxCases([ [ @@ -896,7 +896,7 @@ public function testFixPhp74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixPhp74Cases() + public function provideFixPhp74Cases(): array { return [ [ @@ -920,7 +920,7 @@ public function provideFixPhp74Cases() ]; } - private function withLongArraySyntaxCases(array $cases) + private function withLongArraySyntaxCases(array $cases): array { $longSyntaxCases = []; @@ -936,7 +936,7 @@ private function withLongArraySyntaxCases(array $cases) return array_merge($cases, $longSyntaxCases); } - private function toLongArraySyntax(string $php) + private function toLongArraySyntax(string $php): string { return strtr($php, [ '[' => 'array(', diff --git a/tests/Fixer/Whitespace/BlankLineBeforeStatementFixerTest.php b/tests/Fixer/Whitespace/BlankLineBeforeStatementFixerTest.php index 0ba7fe16c91..7c9ac91a65c 100644 --- a/tests/Fixer/Whitespace/BlankLineBeforeStatementFixerTest.php +++ b/tests/Fixer/Whitespace/BlankLineBeforeStatementFixerTest.php @@ -21,7 +21,6 @@ /** * @author Dariusz Rumiński * @author Andreas Möller - * @author SpacePossum * * @internal * @@ -465,7 +464,7 @@ public function testFixWithFor(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixWithForCases() + public function provideFixWithForCases(): array { return [ [ @@ -594,7 +593,7 @@ public function testFixWithForEach(string $expected, ?string $input = null): voi $this->doTest($expected, $input); } - public function provideFixWithForEachCases() + public function provideFixWithForEachCases(): array { return [ [ @@ -1098,7 +1097,7 @@ public function testFixWithYield(string $expected, ?string $input = null): void /** * @yield array */ - public function provideFixWithYieldCases() + public function provideFixWithYieldCases(): array { return [ [ @@ -1207,7 +1206,6 @@ function foo() { /** * @dataProvider provideFixWithYieldFromCases - * @requires PHP 7.0 */ public function testFixWithYieldFrom(string $expected, ?string $input = null): void { @@ -1221,7 +1219,7 @@ public function testFixWithYieldFrom(string $expected, ?string $input = null): v /** * @yield array */ - public function provideFixWithYieldFromCases() + public function provideFixWithYieldFromCases(): array { return [ [ @@ -1282,7 +1280,7 @@ public function testFixWithMultipleConfigStatements(array $statements, string $e $this->doTest($expected, $input); } - public function provideFixWithMultipleConfigStatementsCases() + public function provideFixWithMultipleConfigStatementsCases(): array { $statementsWithoutCaseOrDefault = [ 'break', diff --git a/tests/Fixer/Whitespace/CompactNullableTypehintFixerTest.php b/tests/Fixer/Whitespace/CompactNullableTypehintFixerTest.php index 2b98321c907..e94de149a37 100644 --- a/tests/Fixer/Whitespace/CompactNullableTypehintFixerTest.php +++ b/tests/Fixer/Whitespace/CompactNullableTypehintFixerTest.php @@ -35,7 +35,7 @@ public function testFix71(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix71Cases() + public function provideFix71Cases(): array { return [ [ @@ -120,7 +120,7 @@ public function testFix74(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix74Cases() + public function provideFix74Cases(): array { return [ [ diff --git a/tests/Fixer/Whitespace/HeredocIndentationFixerTest.php b/tests/Fixer/Whitespace/HeredocIndentationFixerTest.php index faefa87983e..f51ab2d4454 100644 --- a/tests/Fixer/Whitespace/HeredocIndentationFixerTest.php +++ b/tests/Fixer/Whitespace/HeredocIndentationFixerTest.php @@ -53,7 +53,7 @@ public function testFix(string $expected, ?string $input = null, array $config = $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ diff --git a/tests/Fixer/Whitespace/IndentationTypeFixerTest.php b/tests/Fixer/Whitespace/IndentationTypeFixerTest.php index b994645cf46..7c02e56ca8b 100644 --- a/tests/Fixer/Whitespace/IndentationTypeFixerTest.php +++ b/tests/Fixer/Whitespace/IndentationTypeFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $cases = []; @@ -233,7 +233,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { $cases = []; @@ -307,12 +307,12 @@ public function testMessyWhitespacesReversed(string $expected, ?string $input = $this->doTest($input, $expected); } - public function provideMessyWhitespacesReversedCases() + public function provideMessyWhitespacesReversedCases(): array { return array_filter( $this->provideMessyWhitespacesCases(), - static function (string $key) { - return false === strpos($key, 'mix indentation'); + static function (string $key): bool { + return !str_contains($key, 'mix indentation'); }, ARRAY_FILTER_USE_KEY ); @@ -328,7 +328,7 @@ public function testDoubleSpaceIndent(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideDoubleSpaceIndentCases() + public function provideDoubleSpaceIndentCases(): array { return [ [' - * @author SpacePossum * * @internal * @@ -35,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { $cases = $this->provideCommonCases(); @@ -85,26 +84,24 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): \Generator { - $cases = array_map(static function (array $case) { + yield from array_map(static function (array $case): array { return array_reverse($case); }, $this->provideCommonCases()); - $cases[] = [ + yield [ " [ diff --git a/tests/Fixer/Whitespace/MethodChainingIndentationFixerTest.php b/tests/Fixer/Whitespace/MethodChainingIndentationFixerTest.php index 8ad8ff15488..8440ccce472 100644 --- a/tests/Fixer/Whitespace/MethodChainingIndentationFixerTest.php +++ b/tests/Fixer/Whitespace/MethodChainingIndentationFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -247,7 +247,7 @@ public function testWindowsWhitespaces(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideWindowsWhitespacesCases() + public function provideWindowsWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/Whitespace/NoExtraBlankLinesFixerTest.php b/tests/Fixer/Whitespace/NoExtraBlankLinesFixerTest.php index 20deb0a4786..e9863146d92 100644 --- a/tests/Fixer/Whitespace/NoExtraBlankLinesFixerTest.php +++ b/tests/Fixer/Whitespace/NoExtraBlankLinesFixerTest.php @@ -14,6 +14,7 @@ namespace PhpCsFixer\Tests\Fixer\Whitespace; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\WhitespacesFixerConfig; @@ -103,7 +104,7 @@ public function testWithConfig(array $lineNumberRemoved, array $config): void $this->doTest($this->removeLinesFromString($this->template, $lineNumberRemoved), $this->template); } - public function provideWithConfigCases() + public function provideWithConfigCases(): array { $tests = [ [ @@ -362,7 +363,7 @@ public function testFixWithComments(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideCommentCases() + public function provideCommentCases(): array { return [ [ @@ -416,7 +417,7 @@ public function testFixWithLineBreaks(string $expected, ?string $input = null): $this->doTest($expected, $input); } - public function provideLineBreakCases() + public function provideLineBreakCases(): array { $input = 'expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[no_extra_blank_lines\] Invalid configuration: The option "tokens" .*\.$/'); $this->fixer->configure(['tokens' => ['__TEST__']]); @@ -472,7 +473,7 @@ public function testBetweenUse(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideBetweenUseCases() + public function provideBetweenUseCases(): array { return [ ['fixer->configure(['tokens' => ['use']]); + $this->doTest($expected, $input); + } + + public function provideRemoveLinesBetweenUseStatementsCases(): array + { + return [ + [ + <<<'EOF' fixer->configure(['tokens' => ['use']]); - $this->doTest($expected, $input); - } - - /** - * @dataProvider provideRemoveLinesBetweenUseStatements70Cases - * @requires PHP 7.0 - */ - public function testRemoveLinesBetweenUseStatements70(string $expected, ?string $input = null): void - { - $this->fixer->configure(['tokens' => ['use']]); - $this->doTest($expected, $input); - } - - public function provideRemoveLinesBetweenUseStatements70Cases() - { - return [ + , + ], [ 'doTest($expected); } - public function provideWithoutUsesCases() + public function provideWithoutUsesCases(): array { return [ [ @@ -631,15 +626,17 @@ public function provideWithoutUsesCases() /** * @dataProvider provideRemoveBetweenUseTraitsCases + * @group legacy */ public function testRemoveBetweenUseTraits(string $expected, string $input): void { + $this->expectDeprecation('Option "use_trait" is deprecated, use the rule `class_attributes_separation` with `elements: trait_import` instead.'); $this->fixer->configure(['tokens' => ['use_trait']]); $this->doTest($expected, $input); } - public function provideRemoveBetweenUseTraitsCases() + public function provideRemoveBetweenUseTraitsCases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideOneAndInLineCases() + public function provideOneAndInLineCases(): \Generator { - $tests = [ + yield from [ [ " $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { yield [ "fixer->configure(['tokens' => [ - 'break', - 'continue', - 'return', - 'throw', - 'curly_brace_block', - 'square_brace_block', - 'parenthesis_brace_block', - ]]); - - $this->doTest($expected, $input); - } - - public function provideOneAndInLine70Cases() - { - return [ - [ - "doTest($expected, $input); } - public function provideBraceCases() + public function provideBraceCases(): array { return [ [ @@ -919,7 +888,7 @@ public function testMessyWhitespaces(array $config, string $expected, ?string $i $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ @@ -954,7 +923,7 @@ public function testInSwitchStatement(array $config, string $expected, ?string $ $this->doTest($expected, $input); } - public function provideSwitchCases() + public function provideSwitchCases(): array { return [ [ @@ -1093,7 +1062,7 @@ public function testFix72(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFix72Cases() + public function provideFix72Cases(): \Generator { yield [ 'doTest($expected); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); } - public function provideCommentCases() + public function provideCommentCases(): array { return [ [ @@ -114,9 +115,9 @@ function someFunc() { $someVar = []; } $this->doTest($expected); } - public function provideOutsideCases() + public function provideOutsideCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { yield [ 'doTest($expected, $input); } - public function provideConfigurationCases() + public function provideConfigurationCases(): \Generator { $tests = [ [ @@ -362,7 +359,7 @@ public function provideConfigurationCases() public function testWrongConfig(): void { - $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); + $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[no_spaces_around_offset\] Invalid configuration: The option "positions" .*\.$/'); $this->fixer->configure(['positions' => ['foo']]); @@ -378,7 +375,7 @@ public function testPHP71(array $configuration, string $expected, string $input) $this->doTest($expected, $input); } - public function providePHP71Cases() + public function providePHP71Cases(): array { return [ 'Config "default".' => [ diff --git a/tests/Fixer/Whitespace/NoSpacesInsideParenthesisFixerTest.php b/tests/Fixer/Whitespace/NoSpacesInsideParenthesisFixerTest.php index 937c12d2714..015e8942eb2 100644 --- a/tests/Fixer/Whitespace/NoSpacesInsideParenthesisFixerTest.php +++ b/tests/Fixer/Whitespace/NoSpacesInsideParenthesisFixerTest.php @@ -56,7 +56,7 @@ private function bar() $this->doTest($expected); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -137,11 +137,28 @@ public function testFix80(string $expected, string $input): void $this->doTest($expected, $input); } - public function provideFix80Cases() + public function provideFix80Cases(): \Generator { yield [ 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield 'first callable class' => [ + 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): \Generator { - $tests = [ + yield from [ [ ' $test) { - yield $index => $test; - } + /** + * @dataProvider provideFix80Cases + * @requires PHP 8.0 + */ + public function testFix80(string $expected, string $input = null): void + { + $this->doTest($expected, $input); + } - if (\PHP_VERSION_ID >= 80000) { - yield [ - 'doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ [ @@ -152,7 +152,7 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): array { return [ [ diff --git a/tests/Fixer/Whitespace/SingleBlankLineAtEofFixerTest.php b/tests/Fixer/Whitespace/SingleBlankLineAtEofFixerTest.php index 3cc74487cd9..164ec141da5 100644 --- a/tests/Fixer/Whitespace/SingleBlankLineAtEofFixerTest.php +++ b/tests/Fixer/Whitespace/SingleBlankLineAtEofFixerTest.php @@ -34,7 +34,7 @@ public function testFix(string $expected, ?string $input = null): void $this->doTest($expected, $input); } - public function provideFixCases() + public function provideFixCases(): array { return [ 'Not adding an empty line in empty file.' => [ @@ -156,17 +156,16 @@ public function testMessyWhitespaces(string $expected, ?string $input = null): v $this->doTest($expected, $input); } - public function provideMessyWhitespacesCases() + public function provideMessyWhitespacesCases(): \Generator { - return [ - [ - " + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Fixer\Whitespace; + +use PhpCsFixer\Tests\Test\AbstractFixerTestCase; + +/** + * @internal + * + * @covers \PhpCsFixer\Fixer\Whitespace\TypesSpacesFixer + */ +final class TypesSpacesFixerTest extends AbstractFixerTestCase +{ + /** + * @dataProvider provideFixCases + */ + public function testFix(string $expected, ?string $input = null, array $configuration = []): void + { + $this->fixer->configure($configuration); + $this->doTest($expected, $input); + } + + public function provideFixCases(): \Generator + { + yield [ + ' 'single'], + ]; + + yield [ + ' 'single'], + ]; + } + + /** + * @dataProvider provideFix80Cases + * @requires PHP 8.0 + */ + public function testFix80(string $expected, ?string $input = null, array $configuration = []): void + { + $this->fixer->configure($configuration); + $this->doTest($expected, $input); + } + + public function provideFix80Cases(): \Generator + { + yield [ + ' 'single'], + ]; + + yield [ + ' 'single'], + ]; + + yield [ + ' 'single'], + ]; + + yield [ + 'doTest($expected, $input); + } + + public function provideFix81Cases(): \Generator + { + yield [ + 'getName()); } - public function provideGetNameCases() + public function provideGetNameCases(): array { return [ ['foo'], @@ -55,7 +55,7 @@ public function testGetDescription(string $description): void static::assertSame($description, $option->getDescription()); } - public function provideGetDescriptionCases() + public function provideGetDescriptionCases(): array { return [ ['Foo.'], @@ -71,7 +71,7 @@ public function testHasDefault(bool $hasDefault, AliasedFixerOption $input): voi static::assertSame($hasDefault, $input->hasDefault()); } - public function provideHasDefaultCases() + public function provideHasDefaultCases(): array { return [ [ @@ -95,7 +95,7 @@ public function testGetDefault(string $default): void static::assertSame($default, $option->getDefault()); } - public function provideGetDefaultCases() + public function provideGetDefaultCases(): array { return [ ['baz'], @@ -122,7 +122,7 @@ public function testGetAllowedTypes(?array $allowedTypes): void static::assertSame($allowedTypes, $option->getAllowedTypes()); } - public function provideGetAllowedTypesCases() + public function provideGetAllowedTypesCases(): array { return [ [null], @@ -141,7 +141,7 @@ public function testGetAllowedValues(?array $allowedValues): void static::assertSame($allowedValues, $option->getAllowedValues()); } - public function provideGetAllowedValuesCases() + public function provideGetAllowedValuesCases(): array { return [ [null], @@ -179,7 +179,7 @@ public function testGetAlias(string $alias): void static::assertSame($alias, $options->getAlias()); } - public function provideGetAliasCases() + public function provideGetAliasCases(): array { return [ ['bar'], diff --git a/tests/FixerConfiguration/AllowedValueSubsetTest.php b/tests/FixerConfiguration/AllowedValueSubsetTest.php index 2ebebbb0af0..b243572c00b 100644 --- a/tests/FixerConfiguration/AllowedValueSubsetTest.php +++ b/tests/FixerConfiguration/AllowedValueSubsetTest.php @@ -41,7 +41,7 @@ public function testInvoke($inputValue, bool $expectedResult): void static::assertSame($expectedResult, $subset($inputValue)); } - public function provideInvokeCases() + public function provideInvokeCases(): array { return [ [ diff --git a/tests/FixerConfiguration/DeprecatedFixerOptionTest.php b/tests/FixerConfiguration/DeprecatedFixerOptionTest.php index 88d2c061145..682bd77d27e 100644 --- a/tests/FixerConfiguration/DeprecatedFixerOptionTest.php +++ b/tests/FixerConfiguration/DeprecatedFixerOptionTest.php @@ -71,7 +71,7 @@ public function testHasDefault(bool $isRequired): void static::assertSame(!$isRequired, $option->hasDefault()); } - public function provideHasDefaultCases() + public function provideHasDefaultCases(): array { return [ [true], @@ -94,7 +94,7 @@ public function testGetDefault($default): void static::assertSame($default, $option->getDefault()); } - public function provideGetDefaultCases() + public function provideGetDefaultCases(): array { return [ ['foo'], diff --git a/tests/FixerConfiguration/FixerConfigurationResolverTest.php b/tests/FixerConfiguration/FixerConfigurationResolverTest.php index 5298e9e381d..a7446abe322 100644 --- a/tests/FixerConfiguration/FixerConfigurationResolverTest.php +++ b/tests/FixerConfiguration/FixerConfigurationResolverTest.php @@ -20,6 +20,8 @@ use PhpCsFixer\FixerConfiguration\FixerOption; use PhpCsFixer\Tests\TestCase; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\OptionsResolver\Exception\MissingOptionsException; +use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; use Symfony\Component\OptionsResolver\Options; /** @@ -89,7 +91,7 @@ public function testResolveWithMissingRequiredOption(): void new FixerOption('foo', 'Bar.'), ]); - $this->expectException(\Symfony\Component\OptionsResolver\Exception\MissingOptionsException::class); + $this->expectException(MissingOptionsException::class); $configuration->resolve([]); } @@ -116,7 +118,7 @@ public function testResolveWithAllowedTypes(): void $configuration->resolve(['foo' => 1]) ); - $this->expectException(\Symfony\Component\OptionsResolver\Exception\InvalidOptionsException::class); + $this->expectException(InvalidOptionsException::class); $configuration->resolve(['foo' => '1']); } @@ -131,7 +133,7 @@ public function testResolveWithAllowedValues(): void $configuration->resolve(['foo' => true]) ); - $this->expectException(\Symfony\Component\OptionsResolver\Exception\InvalidOptionsException::class); + $this->expectException(InvalidOptionsException::class); $configuration->resolve(['foo' => 1]); } @@ -146,7 +148,7 @@ public function testResolveWithAllowedValuesSubset(): void $configuration->resolve(['foo' => ['bar']]) ); - $this->expectException(\Symfony\Component\OptionsResolver\Exception\InvalidOptionsException::class); + $this->expectException(InvalidOptionsException::class); $configuration->resolve(['foo' => ['baz']]); } @@ -156,14 +158,14 @@ public function testResolveWithUndefinedOption(): void new FixerOption('bar', 'Bar.'), ]); - $this->expectException(\Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException::class); + $this->expectException(UndefinedOptionsException::class); $configuration->resolve(['foo' => 'foooo']); } public function testResolveWithNormalizers(): void { $configuration = new FixerConfigurationResolver([ - new FixerOption('foo', 'Bar.', true, null, null, null, static function (Options $options, $value) { + new FixerOption('foo', 'Bar.', true, null, null, null, static function (Options $options, $value): int { return (int) $value; }), ]); @@ -196,7 +198,7 @@ public function testResolveWithAliasedDuplicateConfig(): void new AliasedFixerOption(new FixerOption('bar', 'Bar.'), 'baz'), ]); - $this->expectException(\Symfony\Component\OptionsResolver\Exception\InvalidOptionsException::class); + $this->expectException(InvalidOptionsException::class); $this->expectExceptionMessage('Aliased option "bar"/"baz" is passed multiple times'); $configuration->resolve([ diff --git a/tests/FixerConfiguration/InvalidOptionsForEnvExceptionTest.php b/tests/FixerConfiguration/InvalidOptionsForEnvExceptionTest.php index f16654e0786..5e4b76e867f 100644 --- a/tests/FixerConfiguration/InvalidOptionsForEnvExceptionTest.php +++ b/tests/FixerConfiguration/InvalidOptionsForEnvExceptionTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\FixerConfiguration\InvalidOptionsForEnvException diff --git a/tests/FixerFactoryTest.php b/tests/FixerFactoryTest.php index 8b72ab31599..df72d0d921d 100644 --- a/tests/FixerFactoryTest.php +++ b/tests/FixerFactoryTest.php @@ -14,6 +14,9 @@ namespace PhpCsFixer\Tests; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\FixerInterface; use PhpCsFixer\FixerFactory; use PhpCsFixer\RuleSet\RuleSet; use PhpCsFixer\RuleSet\RuleSetInterface; @@ -39,12 +42,14 @@ public function testInterfaceIsFluent(): void $testInstance = $factory->registerCustomFixers( [$this->createFixerDouble('Foo/f1'), $this->createFixerDouble('Foo/f2')] ); + static::assertSame($factory, $testInstance); $testInstance = $factory->registerFixer( $this->createFixerDouble('f3'), false ); + static::assertSame($factory, $testInstance); $ruleSetProphecy = $this->prophesize(RuleSetInterface::class); @@ -52,6 +57,7 @@ public function testInterfaceIsFluent(): void $testInstance = $factory->useRuleSet( $ruleSetProphecy->reveal() ); + static::assertSame($factory, $testInstance); } @@ -63,7 +69,27 @@ public function testRegisterBuiltInFixers(): void $factory = new FixerFactory(); $factory->registerBuiltInFixers(); - static::assertGreaterThan(0, \count($factory->getFixers())); + $fixerClasses = array_filter( + get_declared_classes(), + static function (string $className): bool { + $class = new \ReflectionClass($className); + + return !$class->isAbstract() && $class->implementsInterface(FixerInterface::class) && str_starts_with($class->getNamespaceName(), 'PhpCsFixer\\Fixer\\'); + } + ); + + sort($fixerClasses); + + $fixers = array_map( + static function (FixerInterface $fixer): string { + return \get_class($fixer); + }, + $factory->getFixers() + ); + + sort($fixers); + + static::assertSame($fixerClasses, $fixers); } /** @@ -133,12 +159,14 @@ public function testUseRuleSet(): void ->registerBuiltInFixers() ->useRuleSet(new RuleSet([])) ; + static::assertCount(0, $factory->getFixers()); $factory = (new FixerFactory()) ->registerBuiltInFixers() ->useRuleSet(new RuleSet(['strict_comparison' => true, 'blank_line_before_statement' => false])) ; + $fixers = $factory->getFixers(); static::assertCount(1, $fixers); static::assertSame('strict_comparison', $fixers[0]->getName()); @@ -156,6 +184,7 @@ public function testUseRuleSetWithNonExistingRule(): void ->registerBuiltInFixers() ->useRuleSet(new RuleSet(['non_existing_rule' => true])) ; + $fixers = $factory->getFixers(); static::assertCount(1, $fixers); static::assertSame('strict_comparison', $fixers[0]->getName()); @@ -206,7 +235,7 @@ public function testConflictingFixers(RuleSet $ruleSet): void ->registerBuiltInFixers()->useRuleSet($ruleSet); } - public function provideConflictingFixersCases() + public function provideConflictingFixersCases(): array { return [ [new RuleSet(['no_blank_lines_before_namespace' => true, 'single_blank_line_before_namespace' => true])], @@ -248,7 +277,6 @@ public function testSetWhitespacesConfig(): void $fixer->setWhitespacesConfig($config)->shouldBeCalled(); $factory->registerFixer($fixer->reveal(), false); - $factory->setWhitespacesConfig($config); } @@ -271,12 +299,9 @@ public function testConfigureNonConfigurableFixer(): void $fixer = $this->createFixerDouble('non_configurable'); $factory->registerFixer($fixer, false); - $this->expectException( - \PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class - ); - $this->expectExceptionMessage( - '[non_configurable] Is not configurable.' - ); + $this->expectException(InvalidFixerConfigurationException::class); + + $this->expectExceptionMessage('[non_configurable] Is not configurable.'); $factory->useRuleSet(new RuleSet([ 'non_configurable' => ['bar' => 'baz'], @@ -292,14 +317,13 @@ public function testConfigureFixerWithNonArray($value): void { $factory = new FixerFactory(); - $fixer = $this->prophesize(\PhpCsFixer\Fixer\ConfigurableFixerInterface::class); + $fixer = $this->prophesize(ConfigurableFixerInterface::class); $fixer->getName()->willReturn('foo'); $factory->registerFixer($fixer->reveal(), false); - $this->expectException( - \PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class - ); + $this->expectException(InvalidFixerConfigurationException::class); + $this->expectExceptionMessage( '[foo] Rule must be enabled (true), disabled (false) or configured (non-empty, assoc array). Other values are not allowed.' ); @@ -309,7 +333,7 @@ public function testConfigureFixerWithNonArray($value): void ])); } - public function provideConfigureFixerWithNonArrayCases() + public function provideConfigureFixerWithNonArrayCases(): array { return [ ['bar'], @@ -321,14 +345,12 @@ public function provideConfigureFixerWithNonArrayCases() public function testConfigurableFixerIsConfigured(): void { - $fixer = $this->prophesize(\PhpCsFixer\Fixer\ConfigurableFixerInterface::class); + $fixer = $this->prophesize(ConfigurableFixerInterface::class); $fixer->getName()->willReturn('foo'); $fixer->configure(['bar' => 'baz'])->shouldBeCalled(); $factory = new FixerFactory(); - $factory->registerFixer($fixer->reveal(), false); - $factory->useRuleSet(new RuleSet([ 'foo' => ['bar' => 'baz'], ])); diff --git a/tests/FixerFileProcessedEventTest.php b/tests/FixerFileProcessedEventTest.php index e848763b419..2020536c412 100644 --- a/tests/FixerFileProcessedEventTest.php +++ b/tests/FixerFileProcessedEventTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\FixerFileProcessedEvent; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\FixerFileProcessedEvent diff --git a/tests/FixerNameValidatorTest.php b/tests/FixerNameValidatorTest.php index 63e16fbb07d..4410724a424 100644 --- a/tests/FixerNameValidatorTest.php +++ b/tests/FixerNameValidatorTest.php @@ -35,7 +35,7 @@ public function testIsValid(string $name, bool $isCustom, bool $isValid): void static::assertSame($isValid, $validator->isValid($name, $isCustom)); } - public function provideIsValidCases() + public function provideIsValidCases(): array { return [ ['', true, false], diff --git a/tests/Fixtures/.php-cs-fixer.custom.php b/tests/Fixtures/.php-cs-fixer.custom.php index ba76390b72b..18110526a84 100644 --- a/tests/Fixtures/.php-cs-fixer.custom.php +++ b/tests/Fixtures/.php-cs-fixer.custom.php @@ -15,11 +15,9 @@ /** * Custom config class/file for PHPUnit test. * - * This class does NOT represent a good/sane configuration and is therefor NOT a example. + * This class does NOT represent a good/sane configuration and is therefore NOT an example. * * @internal - * - * @author SpacePossum */ final class CustomConfig implements ConfigInterface { diff --git a/tests/Fixtures/FixCommand/TextDiffTestInput.php b/tests/Fixtures/FixCommand/TextDiffTestInput.php index a3d22178d02..ccd1e5c7ffe 100644 --- a/tests/Fixtures/FixCommand/TextDiffTestInput.php +++ b/tests/Fixtures/FixCommand/TextDiffTestInput.php @@ -13,8 +13,6 @@ /** * Input for @see \PhpCsFixer\Tests\TextDiffTest. * - * @author SpacePossum - * * @internal */ final class TextDiffTestInput diff --git a/tests/Fixtures/Integration/misc/PHP7_0.test b/tests/Fixtures/Integration/misc/PHP7_0.test index afb3e9d9582..643f61949af 100644 --- a/tests/Fixtures/Integration/misc/PHP7_0.test +++ b/tests/Fixtures/Integration/misc/PHP7_0.test @@ -7,8 +7,6 @@ PHP 7.0 test. "random_api_migration": true, "visibility_required": {"elements": ["property", "method"]} } ---REQUIREMENTS-- -{"php": 70000} --EXPECT-- number = $number; } - public function getNumber(): int|float | null + public function getNumber(): int|float|null { return $this->number; } diff --git a/tests/Fixtures/Integration/misc/PHP8_1.test b/tests/Fixtures/Integration/misc/PHP8_1.test new file mode 100644 index 00000000000..b3b179a1ab4 --- /dev/null +++ b/tests/Fixtures/Integration/misc/PHP8_1.test @@ -0,0 +1,75 @@ +--TEST-- +PHP 8.1 test. +--RULESET-- +{ + "@PhpCsFixer": true, + "@PHP81Migration": true +} +--REQUIREMENTS-- +{"php": 80100} +--EXPECT-- +indicator->isPhpUnitClass($tokens, $index)); } - public function provideIsPhpUnitClassCases() + public function provideIsPhpUnitClassCases(): array { return [ 'Test class' => [ @@ -145,7 +143,7 @@ public function testFindPhpUnitClasses(array $expectedIndexes, string $code): vo static::assertSame($expectedIndexes, $classes); } - public function provideFindPhpUnitClassesCases() + public function provideFindPhpUnitClassesCases(): array { return [ 'empty' => [ diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index f37ef589f1a..9b7488b9f28 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -22,8 +22,6 @@ /** * Test that parses and runs the fixture '*.test' files found in '/Fixtures/Integration'. * - * @author SpacePossum - * * @internal * * @coversNothing diff --git a/tests/Linter/AbstractLinterTestCase.php b/tests/Linter/AbstractLinterTestCase.php index ee14567f5d8..2f2fa4efb76 100644 --- a/tests/Linter/AbstractLinterTestCase.php +++ b/tests/Linter/AbstractLinterTestCase.php @@ -15,6 +15,7 @@ namespace PhpCsFixer\Tests\Linter; use PhpCsFixer\Linter\LinterInterface; +use PhpCsFixer\Linter\LintingException; use PhpCsFixer\Tests\TestCase; use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Tokens; @@ -35,7 +36,7 @@ public function testLintingAfterTokenManipulation(): void $tokens = Tokens::fromCode("insertAt(1, new Token([T_NS_SEPARATOR, '\\'])); - $this->expectException(\PhpCsFixer\Linter\LintingException::class); + $this->expectException(LintingException::class); $linter->lintSource($tokens->generateCode())->check(); } @@ -45,7 +46,7 @@ public function testLintingAfterTokenManipulation(): void public function testLintFile(string $file, ?string $errorMessage = null): void { if (null !== $errorMessage) { - $this->expectException(\PhpCsFixer\Linter\LintingException::class); + $this->expectException(LintingException::class); $this->expectExceptionMessage($errorMessage); } else { $this->expectNotToPerformAssertions(); @@ -81,7 +82,7 @@ public function provideLintFileCases(): array public function testLintSource(string $source, ?string $errorMessage = null): void { if (null !== $errorMessage) { - $this->expectException(\PhpCsFixer\Linter\LintingException::class); + $this->expectException(LintingException::class); $this->expectExceptionMessage($errorMessage); } else { $this->expectNotToPerformAssertions(); diff --git a/tests/Linter/CachingLinterTest.php b/tests/Linter/CachingLinterTest.php index 7c2452ef30f..684a03e81b9 100644 --- a/tests/Linter/CachingLinterTest.php +++ b/tests/Linter/CachingLinterTest.php @@ -40,7 +40,7 @@ public function testIsAsync(bool $isAsync): void static::assertSame($isAsync, $linter->isAsync()); } - public function provideIsAsyncCases() + public function provideIsAsyncCases(): array { return [ [true], diff --git a/tests/Linter/ProcessLintingResultTest.php b/tests/Linter/ProcessLintingResultTest.php index 55744792279..209f42ca60c 100644 --- a/tests/Linter/ProcessLintingResultTest.php +++ b/tests/Linter/ProcessLintingResultTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Linter\ProcessLintingResult diff --git a/tests/Linter/TokenizerLintingResultTest.php b/tests/Linter/TokenizerLintingResultTest.php index c73173c42a0..c7bf5614a03 100644 --- a/tests/Linter/TokenizerLintingResultTest.php +++ b/tests/Linter/TokenizerLintingResultTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Linter\TokenizerLintingResult diff --git a/tests/PharCheckerTest.php b/tests/PharCheckerTest.php index e9eba698d83..3b92ce470e9 100644 --- a/tests/PharCheckerTest.php +++ b/tests/PharCheckerTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\PharChecker; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\PharChecker diff --git a/tests/PregTest.php b/tests/PregTest.php index ff51549de88..e78e18fe2db 100644 --- a/tests/PregTest.php +++ b/tests/PregTest.php @@ -46,7 +46,7 @@ public function testMatch(string $pattern, string $subject): void static::assertSame($expectedMatches, $actualMatches); } - public function providePatternValidationCases() + public function providePatternValidationCases(): array { return [ 'invalid_blank' => ['', null, PregException::class], @@ -67,7 +67,7 @@ public function providePatternValidationCases() */ public function testPatternValidation(string $pattern, ?int $expected = null, ?string $expectedException = null, ?string $expectedMessage = null): void { - $setup = function () use ($expectedException, $expectedMessage) { + $setup = function () use ($expectedException, $expectedMessage): bool { $i = 0; if (null !== $expectedException) { @@ -107,7 +107,7 @@ public function testPatternValidation(string $pattern, ?int $expected = null, ?s */ public function testPatternsValidation(string $pattern, ?int $expected = null, ?string $expectedException = null, ?string $expectedMessage = null): void { - $setup = function () use ($expectedException, $expectedMessage) { + $setup = function () use ($expectedException, $expectedMessage): bool { $i = 0; if (null !== $expectedException) { @@ -203,7 +203,7 @@ public function testReplaceCallbackFailing(): void */ public function testReplaceCallback($pattern, $subject): void { - $callback = static function (array $x) { return implode('-', $x); }; + $callback = static function (array $x): string { return implode('-', $x); }; $expectedResult = preg_replace_callback($pattern, $callback, $subject); $actualResult = Preg::replaceCallback($pattern, $callback, $subject); @@ -211,7 +211,7 @@ public function testReplaceCallback($pattern, $subject): void static::assertSame($expectedResult, $actualResult); } - public function provideCommonCases() + public function provideCommonCases(): array { return [ ['/u/u', 'u'], @@ -222,7 +222,7 @@ public function provideCommonCases() ]; } - public function provideArrayOfPatternsCases() + public function provideArrayOfPatternsCases(): array { return [ [['/à/', '/í/'], 'Tàíl'], diff --git a/tests/RuleSet/RuleSetTest.php b/tests/RuleSet/RuleSetTest.php index fa572ceeb50..89c783842ce 100644 --- a/tests/RuleSet/RuleSetTest.php +++ b/tests/RuleSet/RuleSetTest.php @@ -115,21 +115,19 @@ public function testThatThereIsNoDeprecatedFixerInRuleSet(string $setName, strin static::assertNotInstanceOf(DeprecatedFixerInterface::class, $fixer, sprintf('RuleSet "%s" contains deprecated rule "%s".', $setName, $ruleName)); } - public function provideAllRulesFromSetsCases() + public function provideAllRulesFromSetsCases(): \Generator { - $cases = []; foreach (RuleSets::getSetDefinitionNames() as $setName) { $ruleSet = new RuleSet([$setName => true]); + foreach ($ruleSet->getRules() as $rule => $config) { - $cases[] = [ + yield $setName.':'.$rule => [ $setName, $rule, $config, ]; } } - - return $cases; } public function testGetBuildInSetDefinitionNames(): void @@ -289,26 +287,22 @@ public function testRiskyRulesInSet(array $set, bool $safe): void ); } - public function provideSafeSetCases() + public function provideSafeSetCases(): \Generator { - $sets = []; - foreach (RuleSets::getSetDefinitionNames() as $name) { - $sets[$name] = [ + yield $name => [ [$name => true], - false === strpos($name, ':risky'), + !str_contains($name, ':risky'), ]; } - $sets['@Symfony:risky_and_@Symfony'] = [ + yield '@Symfony:risky_and_@Symfony' => [ [ '@Symfony:risky' => true, '@Symfony' => false, ], false, ]; - - return $sets; } public function testInvalidConfigNestedSets(): void @@ -397,17 +391,18 @@ public function testPhpUnitTargetVersionHasSet(string $version): void ); } - public static function providePhpUnitTargetVersionHasSetCases() + public static function providePhpUnitTargetVersionHasSetCases(): \Generator { foreach ((new \ReflectionClass(PhpUnitTargetVersion::class))->getConstants() as $constant) { if ('newest' === $constant) { continue; } + yield [$constant]; } } - private function sortNestedArray(array $array) + private function sortNestedArray(array $array): array { foreach ($array as $key => $element) { if (!\is_array($element)) { @@ -426,7 +421,7 @@ private function sortNestedArray(array $array) return $array; } - private function findInSets(array $sets, string $ruleName, $config) + private function findInSets(array $sets, string $ruleName, $config): array { $duplicates = []; @@ -473,11 +468,11 @@ private function expendSet(array $setDefinitions, array $resolvedSets, string $s return $resolvedSets[$setName]; } - private static function assertSameRules(array $expected, array $actual, string $message = ''): void + private static function assertSameRules(array $expected, array $actual): void { ksort($expected); ksort($actual); - static::assertSame($expected, $actual, $message); + static::assertSame($expected, $actual); } } diff --git a/tests/RuleSet/RuleSetsTest.php b/tests/RuleSet/RuleSetsTest.php index 0e276d14ceb..ffaeaed65d8 100644 --- a/tests/RuleSet/RuleSetsTest.php +++ b/tests/RuleSet/RuleSetsTest.php @@ -110,7 +110,7 @@ public function testHasIntegrationTest(string $setDefinitionName): void */ public function testBuildInSetDefinitionNames(string $setName): void { - static::assertSame('@', substr($setName, 0, 1)); + static::assertStringStartsWith('@', $setName); } /** @@ -141,7 +141,7 @@ public function provideSetDefinitionNameCases(): array { $setDefinitionNames = RuleSets::getSetDefinitionNames(); - return array_map(static function (string $setDefinitionName) { + return array_map(static function (string $setDefinitionName): array { return [$setDefinitionName]; }, $setDefinitionNames); } @@ -167,11 +167,11 @@ public function providePHPUnitMigrationSetDefinitionNameCases(): array { $setDefinitionNames = RuleSets::getSetDefinitionNames(); - $setDefinitionPHPUnitMigrationNames = array_filter($setDefinitionNames, static function (string $setDefinitionName) { + $setDefinitionPHPUnitMigrationNames = array_filter($setDefinitionNames, static function (string $setDefinitionName): bool { return 1 === preg_match('/^@PHPUnit\d{2}Migration:risky$/', $setDefinitionName); }); - return array_map(static function (string $setDefinitionName) { + return array_map(static function (string $setDefinitionName): array { return [$setDefinitionName]; }, $setDefinitionPHPUnitMigrationNames); } @@ -196,7 +196,7 @@ private static function assertPHPUnitVersionIsLargestAllowed(string $setName, st $allowedVersionsForRuleset = array_filter( $allowedVersionsForFixer, - static function (string $version) use ($maximumVersionForRuleset) { + static function (string $version) use ($maximumVersionForRuleset): bool { return strcmp($maximumVersionForRuleset, $version) >= 0; } ); diff --git a/tests/RuleSet/Sets/AbstractSetTest.php b/tests/RuleSet/Sets/AbstractSetTest.php index 244d8b19c00..558c6c2c8d2 100644 --- a/tests/RuleSet/Sets/AbstractSetTest.php +++ b/tests/RuleSet/Sets/AbstractSetTest.php @@ -18,6 +18,7 @@ use PhpCsFixer\FixerFactory; use PhpCsFixer\RuleSet\RuleSet; use PhpCsFixer\RuleSet\RuleSetDescriptionInterface; +use PhpCsFixer\RuleSet\RuleSets; use PhpCsFixer\Tests\TestCase; /** @@ -41,8 +42,7 @@ public function testSet(): void static::assertSanityString($setName); static::assertSanityString($setDescription); static::assertSame('.', substr($setDescription, -1), sprintf('Ruleset description of "%s" must end with ".", got "%s".', $setName, $setDescription)); - static::assertIsBool($isRiskySet); - static::assertIsArray($setRules); + static::assertRules($setRules, $factory, $setName); if (1 === preg_match('/(\d)(\d)Migration/', \get_class($set), $matches)) { static::assertStringEndsWith( @@ -68,6 +68,28 @@ public function testSet(): void } } + private static function assertRules(array $setRules, FixerFactory $factory, string $setName): void + { + $sawRule = false; + + foreach ($setRules as $rule => $config) { + static::assertIsString($rule, $setName); + + if (str_starts_with($rule, '@')) { + static::assertFalse($sawRule, sprintf('Ruleset "%s" should define all sets it extends first and than list by rule configuration overrides.', $setName)); + RuleSets::getSetDefinition($setName); + } else { + $sawRule = true; + static::assertTrue($factory->hasRule($rule), $rule); + } + } + + $setRulesSorted = $setRules; + ksort($setRulesSorted); + + static::assertSame($setRulesSorted, $setRules); + } + private static function assertSanityString(string $string): void { static::assertSame(trim($string), $string); diff --git a/tests/RuleSet/Sets/PHP81MigrationSetTest.php b/tests/RuleSet/Sets/PHP81MigrationSetTest.php new file mode 100644 index 00000000000..34b5cfa80c2 --- /dev/null +++ b/tests/RuleSet/Sets/PHP81MigrationSetTest.php @@ -0,0 +1,24 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\RuleSet\Sets; + +/** + * @internal + * + * @covers \PhpCsFixer\RuleSet\Sets\PHP81MigrationSet + */ +final class PHP81MigrationSetTest extends AbstractSetTest +{ +} diff --git a/tests/Runner/FileFilterIteratorTest.php b/tests/Runner/FileFilterIteratorTest.php index 9c288e2c5c4..c44a09decee 100644 --- a/tests/Runner/FileFilterIteratorTest.php +++ b/tests/Runner/FileFilterIteratorTest.php @@ -20,8 +20,6 @@ use Symfony\Component\EventDispatcher\EventDispatcher; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Runner\FileFilterIterator diff --git a/tests/Runner/FileLintingIteratorTest.php b/tests/Runner/FileLintingIteratorTest.php index 7bff816249e..e718e1200ff 100644 --- a/tests/Runner/FileLintingIteratorTest.php +++ b/tests/Runner/FileLintingIteratorTest.php @@ -20,8 +20,6 @@ use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Runner\FileLintingIterator diff --git a/tests/Smoke/CiIntegrationTest.php b/tests/Smoke/CiIntegrationTest.php index 41375eb6eca..5cc8c544458 100644 --- a/tests/Smoke/CiIntegrationTest.php +++ b/tests/Smoke/CiIntegrationTest.php @@ -192,7 +192,7 @@ public function testIntegration( ); } - public function provideIntegrationCases() + public function provideIntegrationCases(): array { return [ 'random-changes' => [ diff --git a/tests/Smoke/InstallViaComposerTest.php b/tests/Smoke/InstallViaComposerTest.php index 99af5863757..1ce0d014018 100644 --- a/tests/Smoke/InstallViaComposerTest.php +++ b/tests/Smoke/InstallViaComposerTest.php @@ -137,7 +137,7 @@ public function testInstallationViaArtifactIsPossible(): void $cwd = __DIR__.'/../..'; $stepsToInitializeArtifact = [ - // Clone current version of project to new location, as we gonna modify it. + // Clone current version of project to new location, as we are going to modify it. // Warning! Only already committed changes will be cloned! "git clone --depth=1 . {$tmpArtifactPath}", ]; diff --git a/tests/Smoke/StdinTest.php b/tests/Smoke/StdinTest.php index 9ac0e51dafb..01b5362f568 100644 --- a/tests/Smoke/StdinTest.php +++ b/tests/Smoke/StdinTest.php @@ -15,6 +15,7 @@ namespace PhpCsFixer\Tests\Smoke; use Keradus\CliExecutor\CommandExecutor; +use PhpCsFixer\Preg; /** * @author Dariusz Rumiński @@ -45,6 +46,7 @@ public function testFixingStdin(): void '', $fileResult->getError() ); + static::assertSame($expectedError, $stdinResult->getError()); $fileResult = $this->unifyFooter($fileResult->getOutput()); @@ -55,7 +57,11 @@ public function testFixingStdin(): void $fileResult = str_replace("\n+++ ".$path."\n", "\n+++ php://stdin\n", $fileResult); $path = str_replace('/', \DIRECTORY_SEPARATOR, basename(realpath($cwd)).'/'.$inputFile); - $fileResult = str_replace($path, 'php://stdin', $fileResult); + $fileResult = Preg::replace( + '#/?'.preg_quote($path, '#').'#', + 'php://stdin', + $fileResult + ); static::assertSame( $fileResult, diff --git a/tests/Test/AbstractFixerTestCase.php b/tests/Test/AbstractFixerTestCase.php index 64f8458b033..6398765fe65 100644 --- a/tests/Test/AbstractFixerTestCase.php +++ b/tests/Test/AbstractFixerTestCase.php @@ -128,7 +128,7 @@ final public function testFixerDefinitions(): void static::assertNotEmpty($code, sprintf('[%s] Sample #%d', $fixerName, $sampleCounter)); if (!($this->fixer instanceof SingleBlankLineAtEofFixer)) { - static::assertSame("\n", substr($code, -1), sprintf('[%s] Sample #%d must end with linebreak', $fixerName, $sampleCounter)); + static::assertStringEndsWith("\n", $code, sprintf('[%s] Sample #%d must end with linebreak', $fixerName, $sampleCounter)); } $config = $sample->getConfiguration(); @@ -151,7 +151,7 @@ final public function testFixerDefinitions(): void if ($fixerIsConfigurable) { // always re-configure as the fixer might have been configured with diff. configuration form previous sample - $this->fixer->configure(null === $config ? [] : $config); + $this->fixer->configure($config ?? []); } Tokens::clearCache(); @@ -233,7 +233,7 @@ public function testFixerUseInsertSlicesWhenOnlyInsertionsArePerformed(): void $sequences = $this->findAllTokenSequences($tokens, [[T_VARIABLE, '$tokens'], [T_OBJECT_OPERATOR], [T_STRING]]); - $usedMethods = array_unique(array_map(function (array $sequence) { + $usedMethods = array_unique(array_map(static function (array $sequence): string { $last = end($sequence); return $last->getContent(); @@ -246,7 +246,7 @@ public function testFixerUseInsertSlicesWhenOnlyInsertionsArePerformed(): void return; } - $usedMethods = array_filter($usedMethods, function (string $method) { + $usedMethods = array_filter($usedMethods, static function (string $method): bool { return 0 === Preg::match('/^(count|find|generate|get|is|rewind)/', $method); }); @@ -400,7 +400,7 @@ protected function doTest(string $expected, ?string $input = null, ?\SplFileInfo static::assertSame( \count($tokens), - \count(array_unique(array_map(static function (Token $token) { + \count(array_unique(array_map(static function (Token $token): string { return spl_object_hash($token); }, $tokens->toArray()))), 'Token items inside Tokens collection must be unique.' @@ -466,7 +466,7 @@ private static function assertCorrectCasing(string $needle, string $haystack, st static::assertSame(substr_count(strtolower($haystack), strtolower($needle)), substr_count($haystack, $needle), $message); } - private function findAllTokenSequences($tokens, $sequence) + private function findAllTokenSequences($tokens, $sequence): array { $lastIndex = 0; $sequences = []; diff --git a/tests/Test/AbstractIntegrationCaseFactory.php b/tests/Test/AbstractIntegrationCaseFactory.php index c20a36193e2..8f35b4ffc6e 100644 --- a/tests/Test/AbstractIntegrationCaseFactory.php +++ b/tests/Test/AbstractIntegrationCaseFactory.php @@ -148,6 +148,7 @@ protected function determineSettings(SplFileInfo $file, ?string $config): array { $parsed = $this->parseJson($config, [ 'checkPriority' => true, + 'deprecations' => [], ]); if (!\is_bool($parsed['checkPriority'])) { @@ -157,6 +158,23 @@ protected function determineSettings(SplFileInfo $file, ?string $config): array )); } + if (!\is_array($parsed['deprecations'])) { + throw new \InvalidArgumentException(sprintf( + 'Expected array value for "deprecations", got "%s".', + \is_object($parsed['deprecations']) ? \get_class($parsed['deprecations']) : \gettype($parsed['deprecations']).'#'.$parsed['deprecations'] + )); + } + + foreach ($parsed['deprecations'] as $index => $deprecation) { + if (!\is_string($deprecation)) { + throw new \InvalidArgumentException(sprintf( + 'Expected only string value for "deprecations", got "%s" @ index %d.', + \is_object($deprecation) ? \get_class($deprecation) : \gettype($deprecation).'#'.$deprecation, + $index + )); + } + } + return $parsed; } diff --git a/tests/Test/AbstractIntegrationTestCase.php b/tests/Test/AbstractIntegrationTestCase.php index 5309fc93041..5845f6f71d9 100644 --- a/tests/Test/AbstractIntegrationTestCase.php +++ b/tests/Test/AbstractIntegrationTestCase.php @@ -59,8 +59,6 @@ * * Section or any line in it may be omitted. * ** PHP minimum version. Default to current running php version (no effect). * - * @author SpacePossum - * * @internal */ abstract class AbstractIntegrationTestCase extends TestCase @@ -122,9 +120,14 @@ protected function tearDown(): void * * @see doTest() * @large + * @group legacy */ public function testIntegration(IntegrationCase $case): void { + foreach ($case->getSettings()['deprecations'] as $deprecation) { + $this->expectDeprecation($deprecation); + } + $this->doTest($case); } @@ -307,7 +310,7 @@ protected static function assertRevertedOrderFixing(IntegrationCase $case, strin static::assertGreaterThan( 1, \count(array_unique(array_map( - static function (FixerInterface $fixer) { + static function (FixerInterface $fixer): int { return $fixer->getPriority(); }, static::createFixers($case) diff --git a/tests/Test/AbstractTransformerTestCase.php b/tests/Test/AbstractTransformerTestCase.php index 6ff399fec59..adc9b34405e 100644 --- a/tests/Test/AbstractTransformerTestCase.php +++ b/tests/Test/AbstractTransformerTestCase.php @@ -140,7 +140,7 @@ static function ($kindOrPrototype) { sprintf( 'Transformation into "%s" must be allowed in self-documentation of the Transformer, currently allowed custom tokens are: %s', Token::getNameForId($modification), - implode(', ', array_map(function ($ct) { return Token::getNameForId($ct); }, $customTokensOfTransformer)) + implode(', ', array_map(static function ($ct) { return Token::getNameForId($ct); }, $customTokensOfTransformer)) ) ); } else { diff --git a/tests/Test/IntegrationCase.php b/tests/Test/IntegrationCase.php index 3de0d021f14..90b94f4a391 100644 --- a/tests/Test/IntegrationCase.php +++ b/tests/Test/IntegrationCase.php @@ -84,27 +84,27 @@ public function __construct( $this->inputCode = $inputCode; } - public function hasInputCode() + public function hasInputCode(): bool { return null !== $this->inputCode; } - public function getConfig() + public function getConfig(): array { return $this->config; } - public function getExpectedCode() + public function getExpectedCode(): string { return $this->expectedCode; } - public function getFileName() + public function getFileName(): string { return $this->fileName; } - public function getInputCode() + public function getInputCode(): ?string { return $this->inputCode; } @@ -125,22 +125,22 @@ public function getRequirement(string $name) return $this->requirements[$name]; } - public function getRequirements() + public function getRequirements(): array { return $this->requirements; } - public function getRuleset() + public function getRuleset(): RuleSet { return $this->ruleset; } - public function getSettings() + public function getSettings(): array { return $this->settings; } - public function getTitle() + public function getTitle(): string { return $this->title; } diff --git a/tests/Test/TestCaseUtils.php b/tests/Test/TestCaseUtils.php new file mode 100644 index 00000000000..ad6390d9eb3 --- /dev/null +++ b/tests/Test/TestCaseUtils.php @@ -0,0 +1,35 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +/** + * @internal + */ +final class TestCaseUtils +{ + public static function swapExpectedInputTestCases(iterable $cases): iterable + { + foreach ($cases as $case) { + if (1 === \count($case)) { + yield $case; + + continue; + } + + [$case[0], $case[1]] = [$case[1], $case[0]]; + yield $case; + } + } +} diff --git a/tests/TextDiffTest.php b/tests/TextDiffTest.php index f1acc02e1a2..6c26eb1ffe0 100644 --- a/tests/TextDiffTest.php +++ b/tests/TextDiffTest.php @@ -21,8 +21,6 @@ use Symfony\Component\Console\Tester\CommandTester; /** - * @author SpacePossum - * * @internal * * @coversNothing @@ -63,7 +61,7 @@ public function testDiffReportingDecorated(string $expected, string $format, boo static::assertStringMatchesFormat($expected, $commandTester->getDisplay(false)); } - public function provideDiffReportingCases() + public function provideDiffReportingCases(): \Generator { $expected = <<<'TEST' %A$output->writeln(''.(int)$output.'');%A @@ -79,10 +77,9 @@ public function provideDiffReportingCases() } $expected = substr(json_encode($expected), 1, -1); - $cases[] = [$expected, 'json', true]; - $cases[] = [$expected, 'json', false]; - return $cases; + yield [$expected, 'json', true]; + yield [$expected, 'json', false]; } /** diff --git a/tests/Tokenizer/AbstractTransformerTest.php b/tests/Tokenizer/AbstractTransformerTest.php index 3b014a4b5a5..448472fa338 100644 --- a/tests/Tokenizer/AbstractTransformerTest.php +++ b/tests/Tokenizer/AbstractTransformerTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tests\TestCase; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Tokenizer\AbstractTransformer diff --git a/tests/Tokenizer/Analyzer/Analysis/TypeAnalysisTest.php b/tests/Tokenizer/Analyzer/Analysis/TypeAnalysisTest.php index d0782fbc6f0..f90a31b416c 100644 --- a/tests/Tokenizer/Analyzer/Analysis/TypeAnalysisTest.php +++ b/tests/Tokenizer/Analyzer/Analysis/TypeAnalysisTest.php @@ -65,23 +65,24 @@ public function testReserved(string $type, bool $expected): void static::assertSame($expected, $analysis->isReservedType()); } - public function provideReservedCases() + public function provideReservedCases(): array { return [ ['array', true], ['bool', true], ['callable', true], + ['float', true], ['int', true], ['iterable', true], - ['float', true], ['mixed', true], + ['never', true], ['numeric', true], ['object', true], + ['other', false], ['resource', true], ['self', true], ['string', true], ['void', true], - ['other', false], ]; } } diff --git a/tests/Tokenizer/Analyzer/ArgumentsAnalyzerTest.php b/tests/Tokenizer/Analyzer/ArgumentsAnalyzerTest.php index e391d5d5cbe..af7d6e82af5 100644 --- a/tests/Tokenizer/Analyzer/ArgumentsAnalyzerTest.php +++ b/tests/Tokenizer/Analyzer/ArgumentsAnalyzerTest.php @@ -70,7 +70,7 @@ public function testArgumentInfo80(string $code, int $openIndex, int $closeIndex ); } - public function provideArgumentsCases() + public function provideArgumentsCases(): array { return [ ['getArguments($tokens, $openIndex, $closeIndex)); } - public function provideArguments73Cases() + public function provideArguments73Cases(): array { return [ [' 3]], @@ -245,7 +245,7 @@ public function testArguments80(string $code, int $openIndex, int $closeIndex, a static::assertSame($arguments, $analyzer->getArguments($tokens, $openIndex, $closeIndex)); } - public function provideArguments80Cases() + public function provideArguments80Cases(): array { return [ [' 22]], diff --git a/tests/Tokenizer/Analyzer/AttributeAnalyzerTest.php b/tests/Tokenizer/Analyzer/AttributeAnalyzerTest.php new file mode 100644 index 00000000000..362ea5684de --- /dev/null +++ b/tests/Tokenizer/Analyzer/AttributeAnalyzerTest.php @@ -0,0 +1,100 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Tokenizer\Analyzer; + +use PhpCsFixer\Tests\TestCase; +use PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + * + * @covers \PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer + */ +final class AttributeAnalyzerTest extends TestCase +{ + /** + * Check it's not crashing for PHP lower than 8.0 as other tests run for PHP 8.0 only. + */ + public function testNotAnAttribute(): void + { + $tokens = Tokens::fromCode(' $token) { + static::assertFalse(AttributeAnalyzer::isAttribute($tokens, $index)); + } + } + + /** + * @requires PHP 8.0 + * @dataProvider provideIsAttributeCases + */ + public function testIsAttribute(bool $isInAttribute, string $code): void + { + $tokens = Tokens::fromCode($code); + + foreach ($tokens as $index => $token) { + if ($token->equals([T_STRING, 'Foo'])) { + if (isset($testedIndex)) { + static::fail('Test is run against index of "Foo", multiple occurrences found.'); + } + $testedIndex = $index; + } + } + if (!isset($testedIndex)) { + static::fail('Test is run against index of "Foo", but it was not found in the code.'); + } + + static::assertSame($isInAttribute, AttributeAnalyzer::isAttribute($tokens, $testedIndex)); + } + + /** + * Test case requires to having "Foo" as it will be searched for to test its index. + */ + public static function provideIsAttributeCases(): iterable + { + yield [false, 'isBlock($tokens, $openIndex, $closeIndex)); } - public function provideBlocksCases() + public function provideBlocksCases(): array { return [ ['isBlock($tokens, $openIndex, $closeIndex)); } - public function provideNonBlocksCases() + public function provideNonBlocksCases(): array { return [ ['isBlock($tokens, $openIndex, $closeIndex)); } - public function provideBlocksPhp74Cases() + public function provideBlocksPhp74Cases(): array { return [ [' $x + 10;', 6, 8], diff --git a/tests/Tokenizer/Analyzer/ClassyAnalyzerTest.php b/tests/Tokenizer/Analyzer/ClassyAnalyzerTest.php index 4e83044144d..dcb9a2194b0 100644 --- a/tests/Tokenizer/Analyzer/ClassyAnalyzerTest.php +++ b/tests/Tokenizer/Analyzer/ClassyAnalyzerTest.php @@ -35,9 +35,9 @@ public function testIsClassyInvocation(string $source, array $expected): void self::assertClassyInvocation($source, $expected); } - public function provideIsClassyInvocationCases() + public function provideIsClassyInvocationCases(): \Generator { - return [ + yield from [ [ ' true], @@ -82,7 +82,7 @@ public function provideIsClassyInvocationCases() ' false, 9 => true, 12 => false, 14 => true, 18 => true, 21 => true, 25 => true, 32 => true], ], - [ + 'with reference' => [ ' false, 5 => true, 10 => true, 17 => true, 23 => false, 25 => true], ], @@ -103,21 +103,7 @@ public function provideIsClassyInvocationCases() [1 => false, 7 => false], ], ]; - } - - /** - * @param array $expected - * - * @dataProvider provideIsClassyInvocation70Cases - * @requires PHP 7.0 - */ - public function testIsClassyInvocation70(string $source, array $expected): void - { - self::assertClassyInvocation($source, $expected); - } - public function provideIsClassyInvocation70Cases() - { yield [ ' false, 5 => false, 10 => false, 17 => false], @@ -152,7 +138,7 @@ public function testIsClassyInvocation71(string $source, array $expected): void self::assertClassyInvocation($source, $expected); } - public function provideIsClassyInvocation71Cases() + public function provideIsClassyInvocation71Cases(): array { return [ [ @@ -185,7 +171,7 @@ public function testIsClassyInvocation80(string $source, array $expected): void self::assertClassyInvocation($source, $expected); } - public function provideIsClassyInvocation80Cases() + public function provideIsClassyInvocation80Cases(): \Generator { yield [ ' false, 8 => false, 10 => true, 12 => false], ]; + + yield [ + ' true], + ]; + } + + /** + * @param array $expected + * + * @dataProvider provideIsClassyInvocation81Cases + * @requires PHP 8.1 + */ + public function testIsClassyInvocation81(string $source, array $expected): void + { + self::assertClassyInvocation($source, $expected); + } + + public function provideIsClassyInvocation81Cases(): \Generator + { + yield [ + ' false, 8 => false], + ]; } private static function assertClassyInvocation(string $source, array $expected): void diff --git a/tests/Tokenizer/Analyzer/CommentsAnalyzerTest.php b/tests/Tokenizer/Analyzer/CommentsAnalyzerTest.php index 8f18068b8b4..4cd4a5770be 100644 --- a/tests/Tokenizer/Analyzer/CommentsAnalyzerTest.php +++ b/tests/Tokenizer/Analyzer/CommentsAnalyzerTest.php @@ -20,7 +20,6 @@ /** * @author Kuba Werłos - * @author SpacePossum * * @internal * @@ -51,7 +50,7 @@ public function testComments(string $code, int $index, ?array $borders): void static::assertFalse($analyzer->isHeaderComment($tokens, $index)); } - public function provideCommentsCases() + public function provideCommentsCases(): array { return [ 'discover all 4 comments for the 1st comment with slash' => [ @@ -167,7 +166,7 @@ public function testHeaderComment(string $code, int $index): void static::assertTrue($analyzer->isHeaderComment($tokens, $index)); } - public function provideHeaderCommentCases() + public function provideHeaderCommentCases(): array { return [ ['isHeaderComment($tokens, $index)); } - public function provideNotHeaderCommentCases() + public function provideNotHeaderCommentCases(): array { return [ ['isBeforeStructuralElement($tokens, $index)); } - public function providePhpdocCandidateCases() + public function providePhpdocCandidateCases(): array { return [ ['isBeforeStructuralElement($tokens, $index)); } - public function provideNotPhpdocCandidateCases() + public function provideNotPhpdocCandidateCases(): array { return [ ['isBeforeStructuralElement($tokens, $index)); } - public function providePhpdocCandidatePhp74Cases() + public function providePhpdocCandidatePhp74Cases(): array { return [ [' $x + 1;'], @@ -340,7 +339,7 @@ public function testPhpdocCandidatePhp80(string $code): void static::assertTrue($analyzer->isBeforeStructuralElement($tokens, $index)); } - public function providePhpdocCandidatePhp80Cases() + public function providePhpdocCandidatePhp80Cases(): array { return [ ['getNextTokenOfKind(0, [[T_COMMENT], [T_DOC_COMMENT]]); + $analyzer = new CommentsAnalyzer(); + + static::assertTrue($analyzer->isBeforeStructuralElement($tokens, $index)); + } + + public function providePhpdocCandidatePhp81Cases(): \Generator + { + yield 'public readonly' => [ + ' [ + ' [ + ' [ + ' [ + 'isGlobalFunctionCall($tokens, $index)); + self::assertIsGlobalFunctionCall($indices, $code); } - public function provideIsGlobalFunctionCallCases() + public function provideIsGlobalFunctionCallCases(): \Generator { - yield '1' => [ - false, + yield [ ' [ - true, - ' [ - false, - ' [ - true, + yield [ ' [ - false, + yield [ ' [ - false, + yield [ ' [ - false, + yield [ ' [ - false, + yield [ ' [ - false, + yield [ 'bar("baz");', - 3, + [], ]; - yield '10' => [ - false, + yield [ ' [ - false, + yield [ ' [ - false, + yield 'function with ref. return' => [ ' [ - false, + yield [ ' [ - true, + yield [ ' [ - true, + yield [ ' [ - true, + yield [ ' [ - true, + yield [ ' [ - false, + yield [ ' [ - false, + yield [ ' [ - true, + yield 'function signature ref. return, calls itself' => [ ' [ - true, + yield [ ' [ - true, + yield [ ' [ - false, + yield [ ' [ - true, + yield [ ' [ - true, + yield [ ' [ - true, + yield [ ' [ - true, + yield [ ' [ - true, + yield [ 'isGlobalFunctionCall($tokens, $index)); - } - - public function provideIsGlobalFunctionCallPhp70Cases() - { yield [ - true, 'isGlobalFunctionCall($tokens, $index)); + self::assertIsGlobalFunctionCall($indices, $code); } - public function provideIsGlobalFunctionCallPhp74Cases() + public function provideIsGlobalFunctionCallPhp74Cases(): \Generator { yield [ - false, ' false;', - 5, + [], ]; } /** + * @param int[] $indices + * * @dataProvider provideIsGlobalFunctionCallPhp80Cases * @requires PHP 8.0 */ - public function testIsGlobalFunctionCallPhp80(bool $isFunctionIndex, string $code, int $index): void + public function testIsGlobalFunctionCallPhp80(string $code, array $indices): void { - $tokens = Tokens::fromCode($code); - $analyzer = new FunctionsAnalyzer(); - - static::assertSame($isFunctionIndex, $analyzer->isGlobalFunctionCall($tokens, $index)); + self::assertIsGlobalFunctionCall($indices, $code); } - public function provideIsGlobalFunctionCallPhp80Cases() + public function provideIsGlobalFunctionCallPhp80Cases(): \Generator { yield [ - true, 'count();', - 3, + [], + ]; + + yield [ + 'getFunctionArguments($tokens, $methodIndex))); + public function provideIsGlobalFunctionCallPhp81Cases(): \Generator + { + yield 'first class callable cases' => [ + [], + 'method(...); +$obj->$methodStr(...); +($obj->property)(...); +Foo::method(...); +$classStr::$methodStr(...); +self::{$complex . $expression}(...); +\'strlen\'(...); +[$obj, \'method\'](...); +[Foo::class, \'method\'](...); +$c = new class{}; +$b = new class(){}; +$a = new #[foo] +class(){}; +', + ]; } /** - * @param ?array $expected - * - * @dataProvider provideFunctionsWithReturnTypeCases + * @dataProvider provideFunctionsWithArgumentsCases */ - public function testFunctionReturnTypeInfo(string $code, int $methodIndex, ?array $expected): void + public function testFunctionArgumentInfo(string $code, int $methodIndex, array $expected): void { $tokens = Tokens::fromCode($code); $analyzer = new FunctionsAnalyzer(); - $actual = $analyzer->getFunctionReturnType($tokens, $methodIndex); - static::assertSame(serialize($expected), serialize($actual)); + static::assertSame(serialize($expected), serialize($analyzer->getFunctionArguments($tokens, $methodIndex))); } /** - * @dataProvider provideFunctionsWithReturnTypePhp70Cases - * @requires PHP 7.0 + * @dataProvider provideFunctionReturnTypeInfoCases */ - public function testFunctionReturnTypeInfoPhp70(string $code, int $methodIndex, TypeAnalysis $expected): void + public function testFunctionReturnTypeInfo(string $code, int $methodIndex, ?TypeAnalysis $expected): void { $tokens = Tokens::fromCode($code); $analyzer = new FunctionsAnalyzer(); - $actual = $analyzer->getFunctionReturnType($tokens, $methodIndex); + static::assertSame(serialize($expected), serialize($actual)); } - public function provideFunctionsWithArgumentsCases() + public function provideFunctionsWithArgumentsCases(): \Generator { - $tests = [ + yield from [ [' new ArgumentAnalysis( @@ -500,10 +475,6 @@ public function provideFunctionsWithArgumentsCases() ]], ]; - foreach ($tests as $index => $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { yield [' new ArgumentAnalysis( @@ -520,13 +491,9 @@ public function provideFunctionsWithArgumentsCases() } } - public function provideFunctionsWithReturnTypeCases() + public function provideFunctionReturnTypeInfoCases(): \Generator { yield ['getFunctionArguments($tokens, $methodIndex))); } - public function provideFunctionsWithArgumentsPhp74Cases() + public function provideFunctionsWithArgumentsPhp74Cases(): \Generator { - $tests = [ + yield from [ [' null;', 1, []], [' null;', 1, [ '$a' => new ArgumentAnalysis( @@ -632,10 +599,6 @@ public function provideFunctionsWithArgumentsPhp74Cases() ]], ]; - foreach ($tests as $index => $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID < 80000) { yield [' null;', 1, [ '$a' => new ArgumentAnalysis( @@ -653,8 +616,6 @@ public function provideFunctionsWithArgumentsPhp74Cases() } /** - * @param ?TypeAnalysis $expected - * * @dataProvider provideFunctionsWithReturnTypePhp74Cases * @requires PHP 7.4 */ @@ -662,12 +623,12 @@ public function testFunctionReturnTypeInfoPhp74(string $code, int $methodIndex, { $tokens = Tokens::fromCode($code); $analyzer = new FunctionsAnalyzer(); - $actual = $analyzer->getFunctionReturnType($tokens, $methodIndex); + static::assertSame(serialize($expected), serialize($actual)); } - public function provideFunctionsWithReturnTypePhp74Cases() + public function provideFunctionsWithReturnTypePhp74Cases(): \Generator { yield [' null;', 1, null]; yield [' null;', 1, null]; @@ -691,7 +652,7 @@ public function testIsTheSameClassCall(bool $isTheSameClassCall, string $code, i static::assertSame($isTheSameClassCall, $analyzer->isTheSameClassCall($tokens, $index)); } - public function provideIsTheSameClassCallCases() + public function provideIsTheSameClassCallCases(): \Generator { $template = ''), $i, ]; + yield [ 24 === $i, sprintf($template, 'self::'), $i, ]; + yield [ 24 === $i, sprintf($template, 'static::'), @@ -772,7 +735,7 @@ public function testFunctionArgumentInfoPhp80(string $code, int $methodIndex, ar static::assertSame(serialize($expected), serialize($analyzer->getFunctionArguments($tokens, $methodIndex))); } - public function provideFunctionsWithArgumentsPhp80Cases() + public function provideFunctionsWithArgumentsPhp80Cases(): \Generator { yield [' new ArgumentAnalysis( @@ -798,4 +761,30 @@ public function provideFunctionsWithArgumentsPhp80Cases() ), ]]; } + + /** + * @param int[] $expectedIndices + */ + private static function assertIsGlobalFunctionCall(array $expectedIndices, string $code): void + { + $tokens = Tokens::fromCode($code); + $analyzer = new FunctionsAnalyzer(); + $actualIndices = []; + + foreach ($tokens as $index => $token) { + if ($analyzer->isGlobalFunctionCall($tokens, $index)) { + $actualIndices[] = $index; + } + } + + static::assertSame( + $expectedIndices, + $actualIndices, + sprintf( + 'Global function calls found at positions: [%s], expected at [%s].', + implode(', ', $actualIndices), + implode(', ', $expectedIndices) + ) + ); + } } diff --git a/tests/Tokenizer/Analyzer/GotoLabelAnalyzerTest.php b/tests/Tokenizer/Analyzer/GotoLabelAnalyzerTest.php index ae8ea5bbaae..8d592631168 100644 --- a/tests/Tokenizer/Analyzer/GotoLabelAnalyzerTest.php +++ b/tests/Tokenizer/Analyzer/GotoLabelAnalyzerTest.php @@ -43,9 +43,9 @@ public function testGotoLabelAnalyzerTest(string $source, array $expectedTrue): } } - public function provideIsClassyInvocationCases() + public function provideIsClassyInvocationCases(): \Generator { - $tests = [ + yield from [ 'no candidates' => [ ' [ + 'after php tag' => [ ' [ + 'after closing brace' => [ ' [ + 'after statement' => [ ' [ + 'after opening brace' => [ ' [ + ' $test) { - yield $index => $test; - } - if (\PHP_VERSION_ID >= 80000) { yield [ 'doTestCode(true, $code); } - public static function provideReferenceCases() + public static function provideReferenceCases(): \Generator { yield ['doTestCode(false, $code); } - public static function provideNonReferenceCases() + public static function provideNonReferenceCases(): \Generator { yield ['getSwitchAnalysis($tokens, $index)))); } - public static function provideGettingSwitchAnalysisCases() + public static function provideGettingSwitchAnalysisCases(): \Generator { yield 'two cases' => [ new SwitchAnalysis(7, 46, [new CaseAnalysis(12), new CaseAnalysis(39)]), diff --git a/tests/Tokenizer/Analyzer/WhitespacesAnalyzerTest.php b/tests/Tokenizer/Analyzer/WhitespacesAnalyzerTest.php index f34761148d6..cfb0fd0d388 100644 --- a/tests/Tokenizer/Analyzer/WhitespacesAnalyzerTest.php +++ b/tests/Tokenizer/Analyzer/WhitespacesAnalyzerTest.php @@ -35,7 +35,7 @@ public function testIndent(string $code, string $indent, int $index): void static::assertSame($indent, WhitespacesAnalyzer::detectIndent($tokens, $index)); } - public function provideIndentCases() + public function provideIndentCases(): \Generator { yield ['getConstants() as $name => $value) { - $cases[] = [$name, $value]; + yield [$name, $value]; } - - return $cases; } private function getConstants() diff --git a/tests/Tokenizer/CodeHasherTest.php b/tests/Tokenizer/CodeHasherTest.php index c5431bf5890..46d5b9f88ef 100644 --- a/tests/Tokenizer/CodeHasherTest.php +++ b/tests/Tokenizer/CodeHasherTest.php @@ -18,8 +18,6 @@ use PhpCsFixer\Tokenizer\CodeHasher; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\Tokenizer\CodeHasher diff --git a/tests/Tokenizer/Generator/NamespacedStringTokenGeneratorTest.php b/tests/Tokenizer/Generator/NamespacedStringTokenGeneratorTest.php index bf4a531e8c7..2718bc1178d 100644 --- a/tests/Tokenizer/Generator/NamespacedStringTokenGeneratorTest.php +++ b/tests/Tokenizer/Generator/NamespacedStringTokenGeneratorTest.php @@ -28,13 +28,14 @@ final class NamespacedStringTokenGeneratorTest extends TestCase /** * @dataProvider provideGeneratorCases */ - public function testGenerator(string $input, array $expected): void + public function testGenerator(array $expected, string $input): void { $generator = new NamespacedStringTokenGenerator(); + static::assertSame( $expected, array_map( - static function (Token $token) { + static function (Token $token): string { return $token->getContent(); }, $generator->generate($input) @@ -42,12 +43,12 @@ static function (Token $token) { ); } - public function provideGeneratorCases() + public function provideGeneratorCases(): \Generator { - return [ - ['test', ['test']], - ['Some\\Namespace', ['Some', '\\', 'Namespace']], - ['Some\\Bigger\\Namespace', ['Some', '\\', 'Bigger', '\\', 'Namespace']], - ]; + yield [['test'], 'test']; + + yield [['Some', '\\', 'Namespace'], 'Some\\Namespace']; + + yield [['Some', '\\', 'Bigger', '\\', 'Namespace'], 'Some\\Bigger\\Namespace']; } } diff --git a/tests/Tokenizer/Resolver/TypeShortNameResolverTest.php b/tests/Tokenizer/Resolver/TypeShortNameResolverTest.php index c3bbd8c4ba0..f98e1a79bd7 100644 --- a/tests/Tokenizer/Resolver/TypeShortNameResolverTest.php +++ b/tests/Tokenizer/Resolver/TypeShortNameResolverTest.php @@ -36,7 +36,7 @@ public function testResolver(string $code, string $type, string $expected): void static::assertSame($expected, $resolver->resolve($tokens, $type)); } - public function provideResolverCases() + public function provideResolverCases(): array { return [ [ diff --git a/tests/Tokenizer/TokenTest.php b/tests/Tokenizer/TokenTest.php index 1f160ccfeae..01f52de8f14 100644 --- a/tests/Tokenizer/TokenTest.php +++ b/tests/Tokenizer/TokenTest.php @@ -39,7 +39,7 @@ public function testConstructorValidation($input): void new Token($input); } - public function provideConstructorValidationCases() + public function provideConstructorValidationCases(): array { return [ [null], @@ -75,7 +75,7 @@ public function testIsCast(Token $token, bool $isCast): void static::assertSame($isCast, $token->isCast()); } - public function provideIsCastCases() + public function provideIsCastCases(): array { return [ [$this->getBraceToken(), false], @@ -98,7 +98,7 @@ public function testIsClassy(Token $token, bool $isClassy): void static::assertSame($isClassy, $token->isClassy()); } - public function provideIsClassyCases() + public function provideIsClassyCases(): array { return [ [$this->getBraceToken(), false], @@ -117,19 +117,15 @@ public function testIsComment(Token $token, bool $isComment): void static::assertSame($isComment, $token->isComment()); } - public function provideIsCommentCases() + public function provideIsCommentCases(): \Generator { - $tests = [ + yield from [ [$this->getBraceToken(), false], [$this->getForeachToken(), false], [new Token([T_COMMENT, '/* comment */', 1]), true], [new Token([T_DOC_COMMENT, '/** docs */', 1]), true], ]; - foreach ($tests as $index => $test) { - yield $index => $test; - } - // @TODO: drop condition when PHP 8.0+ is required if (\defined('T_ATTRIBUTE')) { yield [new Token([T_ATTRIBUTE, '#[', 1]), false]; @@ -144,9 +140,9 @@ public function testIsObjectOperator(Token $token, bool $isObjectOperator): void static::assertSame($isObjectOperator, $token->isObjectOperator()); } - public function provideIsObjectOperatorCases() + public function provideIsObjectOperatorCases(): \Generator { - $tests = [ + yield from [ [$this->getBraceToken(), false], [$this->getForeachToken(), false], [new Token([T_COMMENT, '/* comment */']), false], @@ -154,10 +150,6 @@ public function provideIsObjectOperatorCases() [new Token([T_OBJECT_OPERATOR, '->']), true], ]; - foreach ($tests as $index => $test) { - yield $index => $test; - } - if (\defined('T_NULLSAFE_OBJECT_OPERATOR')) { yield [new Token([T_NULLSAFE_OBJECT_OPERATOR, '?->']), true]; } @@ -201,7 +193,7 @@ public function testIsMagicConstant(?int $tokenId, string $content, bool $isCons static::assertSame($isConstant, $token->isMagicConstant()); } - public function provideMagicConstantCases() + public function provideMagicConstantCases(): \Generator { $cases = [ [T_CLASS_C, '__CLASS__'], @@ -215,15 +207,13 @@ public function provideMagicConstantCases() ]; foreach ($cases as $case) { - $cases[] = [$case[0], strtolower($case[1])]; + yield [$case[0], strtolower($case[1])]; } foreach ([$this->getForeachToken(), $this->getBraceToken()] as $token) { - $cases[] = [$token->getId(), $token->getContent(), false]; - $cases[] = [$token->getId(), strtolower($token->getContent()), false]; + yield [$token->getId(), $token->getContent(), false]; + yield [$token->getId(), strtolower($token->getContent()), false]; } - - return $cases; } /** @@ -234,7 +224,7 @@ public function testIsNativeConstant(Token $token, bool $isNativeConstant): void static::assertSame($isNativeConstant, $token->isNativeConstant()); } - public function provideIsNativeConstantCases() + public function provideIsNativeConstantCases(): array { return [ [$this->getBraceToken(), false], @@ -260,7 +250,7 @@ public function testIsWhitespace(Token $token, bool $isWhitespace, ?string $whit } } - public function provideIsWhitespaceCases() + public function provideIsWhitespaceCases(): array { return [ [$this->getBraceToken(), false], @@ -283,7 +273,7 @@ public function provideIsWhitespaceCases() */ public function testCreatingToken($prototype, ?int $expectedId, ?string $expectedContent, ?bool $expectedIsArray, ?string $expectedExceptionClass = null): void { - if ($expectedExceptionClass) { + if (null !== $expectedExceptionClass) { $this->expectException($expectedExceptionClass); } @@ -293,7 +283,7 @@ public function testCreatingToken($prototype, ?int $expectedId, ?string $expecte static::assertSame($expectedIsArray, $token->isArray()); } - public function provideCreatingTokenCases() + public function provideCreatingTokenCases(): array { return [ [[T_FOREACH, 'foreach'], T_FOREACH, 'foreach', true], @@ -322,7 +312,7 @@ public function testEquals(Token $token, bool $equals, $other, bool $caseSensiti static::assertSame($equals, $token->equals($other, $caseSensitive)); } - public function provideEqualsCases() + public function provideEqualsCases(): array { $brace = $this->getBraceToken(); $function = new Token([T_FUNCTION, 'function', 1]); @@ -376,7 +366,7 @@ public function testEqualsAny(bool $equalsAny, array $other, bool $caseSensitive static::assertSame($equalsAny, $token->equalsAny($other, $caseSensitive)); } - public function provideEqualsAnyCases() + public function provideEqualsAnyCases(): array { $brace = $this->getBraceToken(); $foreach = $this->getForeachToken(); @@ -403,7 +393,7 @@ public function testIsKeyCaseSensitive(bool $isKeyCaseSensitive, $caseSensitive, static::assertSame($isKeyCaseSensitive, Token::isKeyCaseSensitive($caseSensitive, $key)); } - public function provideIsKeyCaseSensitiveCases() + public function provideIsKeyCaseSensitiveCases(): array { return [ [true, true, 0], @@ -430,7 +420,7 @@ public function testTokenGetNameForId(?string $expected, int $id): void static::assertSame($expected, Token::getNameForId($id)); } - public function provideTokenGetNameCases() + public function provideTokenGetNameCases(): array { return [ [ @@ -456,7 +446,7 @@ public function testGetName(Token $token, ?string $expected = null): void static::assertSame($expected, $token->getName()); } - public function provideGetNameCases() + public function provideGetNameCases(): \Generator { yield [ new Token([T_FUNCTION, 'function', 1]), @@ -482,7 +472,7 @@ public function testToArray(Token $token, array $expected): void static::assertSame($expected, $token->toArray()); } - public function provideToArrayCases() + public function provideToArrayCases(): \Generator { yield [ new Token([T_FUNCTION, 'function', 1]), @@ -518,22 +508,22 @@ public function provideToArrayCases() ]; } - private function getBraceToken() + private function getBraceToken(): Token { return new Token($this->getBraceTokenPrototype()); } - private function getBraceTokenPrototype() + private function getBraceTokenPrototype(): string { return '('; } - private function getForeachToken() + private function getForeachToken(): Token { return new Token($this->getForeachTokenPrototype()); } - private function getForeachTokenPrototype() + private function getForeachTokenPrototype(): array { static $prototype = [T_FOREACH, 'foreach']; diff --git a/tests/Tokenizer/TokensAnalyzerTest.php b/tests/Tokenizer/TokensAnalyzerTest.php index 9e27d83fb7a..6fbf283da00 100644 --- a/tests/Tokenizer/TokensAnalyzerTest.php +++ b/tests/Tokenizer/TokensAnalyzerTest.php @@ -22,7 +22,6 @@ * @author Dariusz Rumiński * @author Max Voloshin * @author Gregor Harlan - * @author SpacePossum * * @internal * @@ -37,13 +36,13 @@ public function testGetClassyElements(array $expectedElements, string $source): { $tokens = Tokens::fromCode($source); - foreach ($expectedElements as $index => $element) { - $expectedElements[$index] = [ - 'token' => $tokens[$index], - 'type' => $element['type'], - 'classIndex' => $element['classIndex'], - ]; - } + array_walk( + $expectedElements, + static function (array &$element, $index) use ($tokens): void { + $element['token'] = $tokens[$index]; + ksort($element); + } + ); $tokensAnalyzer = new TokensAnalyzer($tokens); @@ -53,33 +52,33 @@ public function testGetClassyElements(array $expectedElements, string $source): ); } - public function provideGetClassyElementsCases() + public function provideGetClassyElementsCases(): \Generator { yield 'trait import' => [ [ 10 => [ - 'type' => 'trait_import', 'classIndex' => 4, + 'type' => 'trait_import', ], 19 => [ - 'type' => 'trait_import', 'classIndex' => 4, + 'type' => 'trait_import', ], 24 => [ - 'type' => 'const', 'classIndex' => 4, + 'type' => 'const', ], 35 => [ - 'type' => 'method', 'classIndex' => 4, + 'type' => 'method', ], 55 => [ - 'type' => 'trait_import', 'classIndex' => 49, + 'type' => 'trait_import', ], 64 => [ - 'type' => 'method', 'classIndex' => 49, + 'type' => 'method', ], ], ' [ - 'type' => 'property', 'classIndex' => 1, + 'type' => 'property', ], 14 => [ - 'type' => 'property', 'classIndex' => 1, + 'type' => 'property', ], 19 => [ - 'type' => 'property', 'classIndex' => 1, + 'type' => 'property', ], 28 => [ - 'type' => 'property', 'classIndex' => 1, + 'type' => 'property', ], 42 => [ - 'type' => 'const', 'classIndex' => 1, + 'type' => 'const', ], 53 => [ - 'type' => 'method', 'classIndex' => 1, + 'type' => 'method', ], 83 => [ - 'type' => 'method', 'classIndex' => 1, + 'type' => 'method', ], 140 => [ - 'type' => 'method', 'classIndex' => 1, + 'type' => 'method', ], 164 => [ - 'type' => 'const', 'classIndex' => 158, + 'type' => 'const', ], 173 => [ - 'type' => 'trait_import', 'classIndex' => 158, + 'type' => 'trait_import', ], ], <<<'PHP' @@ -215,24 +214,24 @@ class Foo static::assertSame( [ 11 => [ + 'classIndex' => 1, 'token' => $tokens[11], 'type' => 'property', - 'classIndex' => 1, ], 19 => [ + 'classIndex' => 1, 'token' => $tokens[19], 'type' => 'property', - 'classIndex' => 1, ], 26 => [ + 'classIndex' => 1, 'token' => $tokens[26], 'type' => 'property', - 'classIndex' => 1, ], 41 => [ + 'classIndex' => 1, 'token' => $tokens[41], 'type' => 'property', - 'classIndex' => 1, ], ], $elements @@ -269,34 +268,34 @@ function B() {} // do not count this static::assertSame( [ 9 => [ + 'classIndex' => 1, 'token' => $tokens[9], 'type' => 'property', // $A - 'classIndex' => 1, ], 14 => [ + 'classIndex' => 1, 'token' => $tokens[14], 'type' => 'method', // B - 'classIndex' => 1, ], 33 => [ + 'classIndex' => 26, 'token' => $tokens[33], 'type' => 'property', // $level1 - 'classIndex' => 26, ], 38 => [ + 'classIndex' => 26, 'token' => $tokens[38], 'type' => 'method', // XYZ - 'classIndex' => 26, ], 56 => [ + 'classIndex' => 50, 'token' => $tokens[56], 'type' => 'property', // $level2 - 'classIndex' => 50, ], 74 => [ + 'classIndex' => 1, 'token' => $tokens[74], 'type' => 'method', // C - 'classIndex' => 1, ], ], $elements @@ -382,64 +381,64 @@ public function otherFunction1() static::assertSame( [ 9 => [ + 'classIndex' => 1, 'token' => $tokens[9], 'type' => 'method', - 'classIndex' => 1, ], 27 => [ + 'classIndex' => 21, 'token' => $tokens[27], 'type' => 'method', - 'classIndex' => 21, ], 44 => [ + 'classIndex' => 1, 'token' => $tokens[44], 'type' => 'method', - 'classIndex' => 1, ], 64 => [ + 'classIndex' => 56, 'token' => $tokens[64], 'type' => 'method', - 'classIndex' => 56, ], 82 => [ + 'classIndex' => 76, 'token' => $tokens[82], 'type' => 'method', - 'classIndex' => 76, ], 100 => [ + 'classIndex' => 94, 'token' => $tokens[100], 'type' => 'method', - 'classIndex' => 94, ], 118 => [ + 'classIndex' => 112, 'token' => $tokens[118], 'type' => 'method', - 'classIndex' => 112, ], 139 => [ + 'classIndex' => 112, 'token' => $tokens[139], 'type' => 'method', - 'classIndex' => 112, ], 170 => [ + 'classIndex' => 76, 'token' => $tokens[170], 'type' => 'method', - 'classIndex' => 76, ], 188 => [ + 'classIndex' => 182, 'token' => $tokens[188], 'type' => 'method', - 'classIndex' => 182, ], 206 => [ + 'classIndex' => 200, 'token' => $tokens[206], 'type' => 'method', - 'classIndex' => 200, ], 242 => [ + 'classIndex' => 56, 'token' => $tokens[242], 'type' => 'method', - 'classIndex' => 56, ], ], $elements @@ -474,23 +473,92 @@ class Foo $tokens = Tokens::fromCode($source); $tokensAnalyzer = new TokensAnalyzer($tokens); $elements = $tokensAnalyzer->getClassyElements(); - $expected = []; + foreach ([11, 23, 31, 44, 51, 54, 61, 69] as $index) { $expected[$index] = [ + 'classIndex' => 1, 'token' => $tokens[$index], 'type' => 'property', - 'classIndex' => 1, ]; } static::assertSame($expected, $elements); } + /** + * @dataProvider provideGetClassyElements81Cases + * @requires PHP 8.1 + */ + public function testGetClassyElements81(array $expected, string $source): void + { + $tokens = Tokens::fromCode($source); + $tokensAnalyzer = new TokensAnalyzer($tokens); + $elements = $tokensAnalyzer->getClassyElements(); + + array_walk( + $expected, + static function (array &$element, $index) use ($tokens): void { + $element['token'] = $tokens[$index]; + ksort($element); + } + ); + + static::assertSame($expected, $elements); + } + + public function provideGetClassyElements81Cases(): \Generator + { + yield [ + [ + 11 => [ + 'classIndex' => 1, + 'type' => 'property', // $prop1 + ], + 20 => [ + 'classIndex' => 1, + 'type' => 'property', // $prop2 + ], + 29 => [ + 'classIndex' => 1, + 'type' => 'property', // $prop13 + ], + ], + ' [ + [ + 11 => [ + 'classIndex' => 1, + 'type' => 'const', // A + ], + 24 => [ + 'classIndex' => 1, + 'type' => 'const', // B + ], + ], + ' false], - ], - [ - ' true], - ], - [ - ' true], - ], - [ - ' false, 19 => true], - ], - [ - 'a) implements B{}) extends C{};', - [7 => true, 11 => true], - ], - [ - ' false], - ], + yield [ + [1 => false], + ' true], + ' true], + ' false, 19 => true], + ' true, 11 => true], + 'a) implements B{}) extends C{};', + ]; + + yield [ + [1 => false], + '= 80000) { + yield [ + [11 => true], + ' true], + ' false], + ' false], + ' true], + ' true], + ' true], ' true], ], [ - ' true], + ' $expectedValue) { - static::assertSame($expectedValue, $tokensAnalyzer->isLambda($index)); - } - } - - public function provideIsLambda70Cases() - { - return [ [ + [6 => true], ' true], ], [ + [2 => false], ' false], ], ]; } @@ -615,7 +679,7 @@ function foo (): array { * @dataProvider provideIsLambda74Cases * @requires PHP 7.4 */ - public function testIsLambda74(string $source, array $expected): void + public function testIsLambda74(array $expected, string $source): void { $tokensAnalyzer = new TokensAnalyzer(Tokens::fromCode($source)); @@ -624,16 +688,16 @@ public function testIsLambda74(string $source, array $expected): void } } - public function provideIsLambda74Cases() + public function provideIsLambda74Cases(): array { return [ [ - ' [];', [5 => true], + ' [];', ], [ - ' [];', [5 => true], + ' [];', ], ]; } @@ -642,7 +706,7 @@ public function provideIsLambda74Cases() * @dataProvider provideIsLambda71Cases * @requires PHP 7.1 */ - public function testIsLambda71(string $source, array $expected): void + public function testIsLambda71(array $expected, string $source): void { $tokensAnalyzer = new TokensAnalyzer(Tokens::fromCode($source)); @@ -651,43 +715,43 @@ public function testIsLambda71(string $source, array $expected): void } } - public function provideIsLambda71Cases() + public function provideIsLambda71Cases(): array { return [ [ + [6 => true], ' true], ], [ + [2 => false], ' false], ], [ + [6 => true], ' true], ], [ + [6 => true], ' true], ], [ + [2 => false], ' false], ], ]; } @@ -696,7 +760,7 @@ function foo (): ?int { * @dataProvider provideIsLambda80Cases * @requires PHP 8.0 */ - public function testIsLambda80(string $source, array $expected): void + public function testIsLambda80(array $expected, string $source): void { $tokensAnalyzer = new TokensAnalyzer(Tokens::fromCode($source)); @@ -705,24 +769,25 @@ public function testIsLambda80(string $source, array $expected): void } } - public function provideIsLambda80Cases() + public function provideIsLambda80Cases(): array { return [ [ + [6 => true], ' true], ], [ + [6 => true], ' true], ], [ + [14 => true], ' true], ], ]; } @@ -753,188 +817,183 @@ public function testIsLambdaInvalid(): void /** * @dataProvider provideIsConstantInvocationCases */ - public function testIsConstantInvocation(string $source, array $expected): void + public function testIsConstantInvocation(array $expected, string $source): void { - $this->doIsConstantInvocationTest($source, $expected); + $this->doIsConstantInvocationTest($expected, $source); } - public function provideIsConstantInvocationCases() + public function provideIsConstantInvocationCases(): array { return [ [ - ' true], + ' true], + ' false, 5 => false, 7 => true], + ' true, 7 => true, 11 => true], + ' [ [3 => true, 7 => true, 11 => true], + ' [ [3 => true], + ' true], + ' true, 5 => true], + ' false, 3 => true, 6 => false, 8 => true], + ' true, 8 => true], + ' true, 7 => false, 9 => false, 11 => true], + ' BAR; }', [3 => false, 11 => true, 16 => true, 20 => true], + ' BAR; }', ], [ - ' true], + ' false], + ' false], + ' false, 7 => false, 9 => false], + ' false, 8 => false], + ' false], + ' false], + ' false], + ' false, 7 => false], + ' false, 7 => false], + ' false, 7 => false, 10 => false, 13 => false], + ' false, 9 => false], + ' false, 9 => false], + ' false, 9 => false, 12 => false, 16 => false, 18 => false, 22 => false], + ' false, 6 => false, 11 => false, 17 => false], + ' false], + ' false, 3 => false], + ' false, 3 => false], + ' false], + ' false], + ' false], + ' true], + ' false, 6 => false], + ' false, 3 => true, 7 => true], + ' false, 7 => false, 10 => false, 13 => false], + ' false, 5 => false, 8 => false, 10 => false, 13 => false, 15 => false], + 'doIsConstantInvocationTest($source, $expected); - } - - public function provideIsConstantInvocation70Cases() - { - return [ [ - ' false, 8 => false], + ' false, 5 => false, 8 => false, 11 => false, 15 => false, 18 => false], + ' false, 16 => false, 21 => false], + 'doIsConstantInvocationTest($source, $expected); + $this->doIsConstantInvocationTest($expected, $source); } - public function provideIsConstantInvocation71Cases() + public function provideIsConstantInvocation71Cases(): array { return [ [ - ' false, 6 => false], + ' false, 9 => false], + ' false, 11 => false, 13 => false], + ' false, 11 => false, 16 => false], + ' false, 11 => false, 17 => false], + ' false, 11 => false, 17 => false], + ' false, 11 => false, 18 => false], + 'doIsConstantInvocationTest($source, $expected); - } + /** + * @dataProvider provideIsConstantInvocationPhp80Cases + * @requires PHP 8.0 + */ + public function testIsConstantInvocationPhp80(array $expected, string $source): void + { + $this->doIsConstantInvocationTest($expected, $source); + } + + public function provideIsConstantInvocationPhp80Cases(): \Generator + { + yield [ + [6 => false, 16 => false, 21 => false, 23 => false], + ' false, 8 => false, 10 => false], + 'b?->c;', [3 => false, 5 => false], + 'b?->c;', ]; yield [ - ' false], + ' false], + ' false, 13 => false], + ' false, 5 => false, 10 => false], + ' false, 7 => false], + [2 => false, 7 => false, 14 => false], + 'doIsConstantInvocationTest($expected, $source); + } + + public function provideIsConstantInvocationPhp81Cases(): \Generator + { + yield [ + [5 => false, 15 => false], + ' false, 9 => false], + [4 => false, 12 => false, 23 => false], + 'b?->c;'); - $tokensAnalyzer = new TokensAnalyzer($tokens); foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_STRING)) { continue; } + static::assertFalse($tokensAnalyzer->isConstantInvocation($index)); } } @@ -1053,12 +1162,13 @@ public function testIsConstantInvocationForNullSafeObjectOperator(): void /** * @dataProvider provideIsUnarySuccessorOperatorCases */ - public function testIsUnarySuccessorOperator(string $source, array $expected): void + public function testIsUnarySuccessorOperator(array $expected, string $source): void { $tokensAnalyzer = new TokensAnalyzer(Tokens::fromCode($source)); foreach ($expected as $index => $isUnary) { static::assertSame($isUnary, $tokensAnalyzer->isUnarySuccessorOperator($index)); + if ($isUnary) { static::assertFalse($tokensAnalyzer->isUnaryPredecessorOperator($index)); static::assertFalse($tokensAnalyzer->isBinaryOperator($index)); @@ -1066,44 +1176,44 @@ public function testIsUnarySuccessorOperator(string $source, array $expected): v } } - public function provideIsUnarySuccessorOperatorCases() + public function provideIsUnarySuccessorOperatorCases(): array { return [ [ - ' true], + ' true], + ' true], + ' true, 4 => false], + ' true], + 'bar++;', [4 => true], + 'bar++;', ], [ - '{"bar"}++;', [6 => true], + '{"bar"}++;', ], 'array access' => [ - ' true], + ' [ - ' true], + ' $isUnary) { static::assertSame($isUnary, $tokensAnalyzer->isUnaryPredecessorOperator($index)); + if ($isUnary) { static::assertFalse($tokensAnalyzer->isUnarySuccessorOperator($index)); static::assertFalse($tokensAnalyzer->isBinaryOperator($index)); @@ -1124,68 +1235,68 @@ public function testIsUnaryPredecessorOperator(string $source, array $expected): } } - public function provideIsUnaryPredecessorOperatorCases() + public function provideIsUnaryPredecessorOperatorCases(): array { return [ [ - ' true], + ' true], + ' true], + ' false, 5 => true], + ' true, 2 => true], + ' true], + ' true], + ' true], + ' true, 8 => true], + ' true, 11 => true, 17 => true], + ' true], + ' true, 6 => true], + ' true], + ' true], + ' true], + ' $isBinary) { static::assertSame($isBinary, $tokensAnalyzer->isBinaryOperator($index)); + if ($isBinary) { static::assertFalse($tokensAnalyzer->isUnarySuccessorOperator($index)); static::assertFalse($tokensAnalyzer->isUnaryPredecessorOperator($index)); @@ -1206,127 +1318,127 @@ public function testIsBinaryOperator(string $source, array $expected): void } } - public function provideIsBinaryOperatorCases() + public function provideIsBinaryOperatorCases(): \Generator { $cases = [ [ - ' true], + ' true], + '', [3 => true], + '', ], [ - '', [3 => true], + '', ], [ - ' true], + ' true], + ' true], + ' true], + ' true], + ' true], + ' true], + ' true], + ' true], + ' true], + ' true], + ' true], + ' true], + ' true], ' true], ], [ + [3 => true], ' true], ], [ - ' "c", );', [3 => true, 9 => true, 12 => false], + ' "c", );', ], [ - ' true, 5 => false], + ' true, 5 => false, 8 => true, 10 => false], + ' true, 5 => false], + ' false, 4 => true], + ' true], + ' true], + ' true], + ' true], + ' true], + '', '|', '^', '&=', '&&', '||', '.=', '/=', '==', '>=', '===', '!=', '<>', '!==', '<=', 'and', 'or', 'xor', '-=', '%=', '*=', '|=', '+=', '<<', '<<=', '>>', '>>=', '^', ]; + + yield from $cases; + foreach ($operators as $operator) { - $cases[] = [ - ' true], + ' $isBinary) { - static::assertSame($isBinary, $tokensAnalyzer->isBinaryOperator($index)); - if ($isBinary) { - static::assertFalse($tokensAnalyzer->isUnarySuccessorOperator($index)); - static::assertFalse($tokensAnalyzer->isUnaryPredecessorOperator($index)); - } - } - } + yield [ + [3 => true], + ' $b;', + ]; - public function provideIsBinaryOperator70Cases() - { - return [ - [ - ' $b;', - [3 => true], - ], - [ - ' true], - ], + yield [ + [3 => true], + 'isArray($tokenIndex), 'Expected to be an array.'); static::assertSame($isMultiLineArray, $tokensAnalyzer->isArrayMultiLine($tokenIndex), sprintf('Expected %sto be a multiline array', $isMultiLineArray ? '' : 'not ')); } - public function provideIsArrayCases() + public function provideIsArrayCases(): array { return [ [ @@ -1421,7 +1514,7 @@ public function provideIsArrayCases() ' array(5, 6, 7), -8 => new \Exception(\'Ellow\') +8 => new \Exception(\'Hello\') ); ', 2, true, @@ -1431,7 +1524,7 @@ public function provideIsArrayCases() ' [9, 10, 11], -12 => new \Exception(\'Ellow\') +12 => new \Exception(\'Hello\') ); ', 2, true, @@ -1461,6 +1554,7 @@ public function testIsArray71(string $source, array $tokenIndexes): void foreach ($tokens as $index => $token) { $expect = \in_array($index, $tokenIndexes, true); + static::assertSame( $expect, $tokensAnalyzer->isArray($index), @@ -1469,7 +1563,7 @@ public function testIsArray71(string $source, array $tokenIndexes): void } } - public function provideIsArray71Cases() + public function provideIsArray71Cases(): array { return [ [ @@ -1489,12 +1583,13 @@ public function provideIsArray71Cases() * @dataProvider provideIsBinaryOperator71Cases * @requires PHP 7.1 */ - public function testIsBinaryOperator71(string $source, array $expected): void + public function testIsBinaryOperator71(array $expected, string $source): void { $tokensAnalyzer = new TokensAnalyzer(Tokens::fromCode($source)); foreach ($expected as $index => $isBinary) { static::assertSame($isBinary, $tokensAnalyzer->isBinaryOperator($index)); + if ($isBinary) { static::assertFalse($tokensAnalyzer->isUnarySuccessorOperator($index)); static::assertFalse($tokensAnalyzer->isUnaryPredecessorOperator($index)); @@ -1502,13 +1597,11 @@ public function testIsBinaryOperator71(string $source, array $expected): void } } - public function provideIsBinaryOperator71Cases() + public function provideIsBinaryOperator71Cases(): \Generator { - return [ - [ - ' false], - ], + yield [ + [11 => false], + ' $isBinary) { static::assertSame($isBinary, $tokensAnalyzer->isBinaryOperator($index)); + if ($isBinary) { static::assertFalse($tokensAnalyzer->isUnarySuccessorOperator($index)); static::assertFalse($tokensAnalyzer->isUnaryPredecessorOperator($index)); @@ -1529,13 +1623,52 @@ public function testIsBinaryOperator74(string $source, array $expected): void } } - public function provideIsBinaryOperator74Cases() + public function provideIsBinaryOperator74Cases(): \Generator { - return [ - [ - ' true], - ], + yield [ + [3 => true], + ' $isBinary) { + static::assertSame($isBinary, $tokensAnalyzer->isBinaryOperator($index)); + + if ($isBinary) { + static::assertFalse($tokensAnalyzer->isUnarySuccessorOperator($index)); + static::assertFalse($tokensAnalyzer->isUnaryPredecessorOperator($index)); + } + } + } + + public static function provideIsBinaryOperator80Cases(): iterable + { + yield [ + [6 => false], + ' false], + ' false], + ' false], + 'isArray($tokenIndex)); } @@ -1561,7 +1695,7 @@ public function testIsMultiLineArrayException(string $source, int $tokenIndex): $tokensAnalyzer->isArrayMultiLine($tokenIndex); } - public function provideArrayExceptionsCases() + public function provideArrayExceptionsCases(): array { return [ ['isBlockMultiline($tokens, $tokenIndex)); } - public static function provideIsBlockMultilineCases() + public static function provideIsBlockMultilineCases(): \Generator { yield [ false, @@ -1633,10 +1767,11 @@ public function testGetFunctionProperties(string $source, int $index, array $exp $tokens = Tokens::fromCode($source); $tokensAnalyzer = new TokensAnalyzer($tokens); $attributes = $tokensAnalyzer->getMethodAttributes($index); + static::assertSame($expected, $attributes); } - public function provideGetFunctionPropertiesCases() + public function provideGetFunctionPropertiesCases(): array { $defaultAttributes = [ 'visibility' => null, @@ -1756,6 +1891,7 @@ public function testIsWhilePartOfDoWhile(): void $tokens = Tokens::fromCode($source); $tokensAnalyzer = new TokensAnalyzer($tokens); + foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_WHILE)) { continue; @@ -1776,10 +1912,11 @@ public function testGetImportUseIndexes(array $expected, string $input, bool $pe { $tokens = Tokens::fromCode($input); $tokensAnalyzer = new TokensAnalyzer($tokens); + static::assertSame($expected, $tokensAnalyzer->getImportUseIndexes($perNamespace)); } - public function provideGetImportUseIndexesCases() + public function provideGetImportUseIndexesCases(): array { return [ [ @@ -1838,23 +1975,6 @@ class AnnotatedClass EOF , ], - ]; - } - - /** - * @dataProvider provideGetImportUseIndexesPHP70Cases - * @requires PHP 7.0 - */ - public function testGetImportUseIndexesPHP70(array $expected, string $input, bool $perNamespace = false): void - { - $tokens = Tokens::fromCode($input); - $tokensAnalyzer = new TokensAnalyzer($tokens); - static::assertSame($expected, $tokensAnalyzer->getImportUseIndexes($perNamespace)); - } - - public function provideGetImportUseIndexesPHP70Cases() - { - return [ [ [1, 22, 41], 'getImportUseIndexes($perNamespace)); } - public function provideGetImportUseIndexesPHP72Cases() + public function provideGetImportUseIndexesPHP72Cases(): array { return [ [ @@ -1949,39 +2070,39 @@ public function foo() { static::assertSame([ 13 => [ + 'classIndex' => 1, 'token' => $tokens[13], 'type' => 'method', // setUp - 'classIndex' => 1, ], 46 => [ + 'classIndex' => 1, 'token' => $tokens[46], 'type' => 'method', // testSomethingWithMoney - 'classIndex' => 1, ], 100 => [ + 'classIndex' => 87, 'token' => $tokens[100], // const A 'type' => 'const', - 'classIndex' => 87, ], 115 => [ + 'classIndex' => 65, 'token' => $tokens[115], // const B 'type' => 'const', - 'classIndex' => 65, ], 124 => [ + 'classIndex' => 65, // $a 'token' => $tokens[124], 'type' => 'method', // foo - 'classIndex' => 65, // $a ], 143 => [ + 'classIndex' => 138, 'token' => $tokens[143], // const AA 'type' => 'const', - 'classIndex' => 138, ], 161 => [ + 'classIndex' => 158, 'token' => $tokens[161], // const AB 'type' => 'const', - 'classIndex' => 158, ], ], $elements); } @@ -1997,7 +2118,7 @@ public function testIsSuperGlobal(bool $expected, string $source, int $index): v static::assertSame($expected, $tokensAnalyzer->isSuperGlobal($index)); } - public function provideIsSuperGlobalCases() + public function provideIsSuperGlobalCases(): array { $superNames = [ '$_COOKIE', @@ -2041,7 +2162,7 @@ public function provideIsSuperGlobalCases() return $cases; } - private function doIsConstantInvocationTest(string $source, array $expected): void + private function doIsConstantInvocationTest(array $expected, string $source): void { $tokens = Tokens::fromCode($source); diff --git a/tests/Tokenizer/TokensTest.php b/tests/Tokenizer/TokensTest.php index c14e8add39d..8530700db59 100644 --- a/tests/Tokenizer/TokensTest.php +++ b/tests/Tokenizer/TokensTest.php @@ -21,7 +21,6 @@ /** * @author Dariusz Rumiński - * @author SpacePossum * * @internal * @@ -49,7 +48,6 @@ public function testReadFromCacheAfterClearing(): void /** * @param Token[] $sequence - * @param int $start * @param null|array|bool $caseSensitive * * @dataProvider provideFindSequenceCases @@ -82,7 +80,7 @@ public function testFindSequence( ); } - public function provideFindSequenceCases() + public function provideFindSequenceCases(): array { return [ [ @@ -297,11 +295,11 @@ public function testFindSequenceException(string $message, array $sequence): voi $tokens->findSequence($sequence); } - public function provideFindSequenceExceptionCases() + public function provideFindSequenceExceptionCases(): array { $emptyToken = new Token(''); - $tests = [ + return [ ['Invalid sequence.', []], [ 'Non-meaningful token at position: "0".', @@ -316,10 +314,6 @@ public function provideFindSequenceExceptionCases() ['{', '!', $emptyToken, '}'], ], ]; - - foreach ($tests as $index => $test) { - yield $index => $test; - } } public function testClearRange(): void @@ -341,7 +335,7 @@ public function bar() PHP; $tokens = Tokens::fromCode($source); - list($fooIndex, $barIndex) = array_keys($tokens->findGivenKind(T_PUBLIC)); + [$fooIndex, $barIndex] = array_keys($tokens->findGivenKind(T_PUBLIC)); $tokens->clearRange($fooIndex, $barIndex - 1); @@ -362,7 +356,7 @@ public function testMonolithicPhpDetection(string $source, bool $isMonolithic): static::assertSame($isMonolithic, $tokens->isMonolithicPhp()); } - public function provideMonolithicPhpDetectionCases() + public function provideMonolithicPhpDetectionCases(): array { return [ ["isMonolithicPhp()); } - public function provideShortOpenTagMonolithicPhpDetectionCases() + public function provideShortOpenTagMonolithicPhpDetectionCases(): array { return [ ["isMonolithicPhp()); } - public function provideShortOpenTagEchoMonolithicPhpDetectionCases() + public function provideShortOpenTagEchoMonolithicPhpDetectionCases(): array { return [ ["getId()); - /** @var array $found */ $found = $tokens->findGivenKind([T_CLASS, T_FUNCTION]); static::assertCount(2, $found); static::assertArrayHasKey(T_CLASS, $found); @@ -527,7 +520,7 @@ public function testClearTokenAndMergeSurroundingWhitespace(string $source, arra } } - public function provideGetClearTokenAndMergeSurroundingWhitespaceCases() + public function provideGetClearTokenAndMergeSurroundingWhitespaceCases(): array { $clearToken = new Token(''); @@ -648,7 +641,7 @@ public function testTokenOfKindSibling( static::assertSame($expectedIndex, $tokens->getTokenOfKindSibling($index, $direction, $findTokens, $caseSensitive)); } - public function provideTokenOfKindSiblingCases() + public function provideTokenOfKindSiblingCases(): array { return [ // find next cases @@ -685,7 +678,7 @@ public function testFindBlockEnd(int $expectedIndex, string $source, int $type, static::assertFindBlockEnd($expectedIndex, $source, $type, $searchIndex); } - public function provideFindBlockEndCases() + public function provideFindBlockEndCases(): array { return [ [4, '', Tokens::BLOCK_TYPE_CURLY_BRACE, 5], [11, '{"set_{$name}"}(42);', Tokens::BLOCK_TYPE_DYNAMIC_PROP_BRACE, 3], [19, 'isEmptyAt(0), $token->toJson()); } - public function provideIsEmptyCases() + public function provideIsEmptyCases(): array { return [ [new Token(''), true], @@ -886,11 +865,6 @@ public function testClone(): void } /** - * @param string $expected valid PHP code - * @param string $input valid PHP code - * @param int $index token index - * @param string $whiteSpace white space - * * @dataProvider provideEnsureWhitespaceAtIndexCases */ public function testEnsureWhitespaceAtIndex(string $expected, string $input, int $index, int $offset, string $whiteSpace): void @@ -901,7 +875,7 @@ public function testEnsureWhitespaceAtIndex(string $expected, string $input, int static::assertTokens(Tokens::fromCode($expected), $tokens); } - public function provideEnsureWhitespaceAtIndexCases() + public function provideEnsureWhitespaceAtIndexCases(): array { return [ [ @@ -1054,20 +1028,18 @@ public function __construct($name) /** * @dataProvider provideRemoveLeadingWhitespaceCases - * - * @param string $input */ public function testRemoveLeadingWhitespace(int $index, ?string $whitespaces, string $expected, string $input = null): void { Tokens::clearCache(); - $tokens = Tokens::fromCode(null === $input ? $expected : $input); + $tokens = Tokens::fromCode($input ?? $expected); $tokens->removeLeadingWhitespace($index, $whitespaces); static::assertSame($expected, $tokens->generateCode()); } - public function provideRemoveLeadingWhitespaceCases() + public function provideRemoveLeadingWhitespaceCases(): array { return [ [ @@ -1122,29 +1094,25 @@ public function provideRemoveLeadingWhitespaceCases() /** * @dataProvider provideRemoveTrailingWhitespaceCases - * - * @param string $input */ public function testRemoveTrailingWhitespace(int $index, ?string $whitespaces, string $expected, string $input = null): void { Tokens::clearCache(); - $tokens = Tokens::fromCode(null === $input ? $expected : $input); + $tokens = Tokens::fromCode($input ?? $expected); $tokens->removeTrailingWhitespace($index, $whitespaces); static::assertSame($expected, $tokens->generateCode()); } - public function provideRemoveTrailingWhitespaceCases() + public function provideRemoveTrailingWhitespaceCases(): \Generator { - $cases = []; $leadingCases = $this->provideRemoveLeadingWhitespaceCases(); + foreach ($leadingCases as $leadingCase) { $leadingCase[0] -= 2; - $cases[] = $leadingCase; + yield $leadingCase; } - - return $cases; } public function testRemovingLeadingWhitespaceWithEmptyTokenInCollection(): void @@ -1222,7 +1190,7 @@ public function testDetectBlockType(?array $expected, string $code, int $index): static::assertSame($expected, Tokens::detectBlockType($tokens[$index])); } - public function provideDetectBlockTypeCases() + public function provideDetectBlockTypeCases(): \Generator { yield [ [ @@ -1283,7 +1251,7 @@ public function testOverrideRange(array $expected, string $code, int $indexStart self::assertTokens(Tokens::fromArray($expected), $tokens); } - public function provideOverrideRangeCases() + public function provideOverrideRangeCases(): \Generator { // typically done by transformers, here we test the reverse @@ -1402,7 +1370,7 @@ public function testGetMeaningfulTokenSibling(?int $expectIndex, int $index, int static::assertSame($expectIndex, $tokens->getMeaningfulTokenSibling($index, $direction)); } - public function provideGetMeaningfulTokenSiblingCases() + public function provideGetMeaningfulTokenSiblingCases(): \Generator { yield [null, 0, 1, 'doTest($source, $expectedTokens); } - public function provideProcessCases() + public function provideProcessCases(): \Generator { yield [' CT::T_ATTRIBUTE_CLOSE, ], ]; + + yield [ + ' "The email {{ value }} is not a valid email."])] + private $email; + }', + [ + 21 => CT::T_ATTRIBUTE_CLOSE, + 36 => CT::T_ATTRIBUTE_CLOSE, + ], + ]; + + yield [ + '>9+foo(a)+foo((bool)$b))] // gets removed from AST when >= 7.0 +#[IgnoreRedeclaration] // throws no error when already declared, removes the redeclared thing +function intdiv(int $numerator, int $divisor) { +} + +#[ +Attr1("foo"),Attr2("bar"), +] + +#[PhpAttribute(self::IS_REPEATABLE)] +class Route +{ +} +', + [ + 5 => CT::T_ATTRIBUTE_CLOSE, + 35 => CT::T_ATTRIBUTE_CLOSE, + 41 => CT::T_ATTRIBUTE_CLOSE, + 76 => CT::T_ATTRIBUTE_CLOSE, + 85 => CT::T_ATTRIBUTE_CLOSE, + ], + ]; + + yield [ + ' 1; +', + [ + 3 => CT::T_ATTRIBUTE_CLOSE, + 22 => CT::T_ATTRIBUTE_CLOSE, + 37 => CT::T_ATTRIBUTE_CLOSE, + 47 => CT::T_ATTRIBUTE_CLOSE, + 67 => CT::T_ATTRIBUTE_CLOSE, + 84 => CT::T_ATTRIBUTE_CLOSE, + 101 => CT::T_ATTRIBUTE_CLOSE, + ], + ]; + + yield [ + ' "The email \'{{ value }}\' is not a valid email."])] + private $email; + + #[\Doctrine\ORM\ManyToMany( + targetEntity: User::class, + joinColumn: "group_id", + inverseJoinColumn: "user_id", + cascade: array("persist", "remove") + )] + #[Assert\Valid] + #[JMSSerializer\XmlList(inline: true, entry: "user")] + public $users; +} +', + [ + 15 => CT::T_ATTRIBUTE_CLOSE, + 40 => CT::T_ATTRIBUTE_CLOSE, + 61 => CT::T_ATTRIBUTE_CLOSE, + 76 => CT::T_ATTRIBUTE_CLOSE, + 124 => CT::T_ATTRIBUTE_CLOSE, + 130 => CT::T_ATTRIBUTE_CLOSE, + 148 => CT::T_ATTRIBUTE_CLOSE, + ], + ]; } /** @@ -79,7 +186,7 @@ public function testNotChange(string $source): void } } - public function provideNotChangeCases() + public function provideNotChangeCases(): \Generator { yield [ 'doTest( $source, @@ -401,26 +399,91 @@ public function testProcessPhp80(string $source, array $expectedTokens, array $o ); } - public function provideProcessPhp80Cases() + public function provideProcessPhp80Cases(): \Generator { - return [ + yield [ [ - ' CT::T_BRACE_CLASS_INSTANTIATION_OPEN, - 8 => '(', - 10 => '(', - 11 => ')', - 12 => ')', - 13 => CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, - ], - [ - '(', - ')', - CT::T_BRACE_CLASS_INSTANTIATION_OPEN, - CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, - ], + 5 => CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + 8 => '(', + 10 => '(', + 11 => ')', + 12 => ')', + 13 => CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, + ], + [ + '(', + ')', + CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, + ], + ' CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + 15 => CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, + ], + [ + CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, + ], + '', + ]; + } + + /** + * @param array $expectedTokens + * + * @dataProvider provideProcessPhp81Cases + * @requires PHP 8.1 + */ + public function testProcessPhp81(array $expectedTokens, array $observedKinds, string $source): void + { + $this->doTest( + $source, + $expectedTokens, + $observedKinds + ); + } + + public function provideProcessPhp81Cases(): \Generator + { + yield [ + [ + 20 => CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + 24 => CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, + 43 => CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + 47 => CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, + 54 => CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + 64 => CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, + 107 => CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + 111 => CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, + ], + [ + CT::T_BRACE_CLASS_INSTANTIATION_OPEN, + CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, ], + 'doTest( $source, @@ -42,9 +42,14 @@ public function testProcess(string $source, array $expectedTokens): void ); } - public function provideProcessCases() + public function provideProcessCases(): \Generator { yield [ + [ + 14 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, + 25 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, + 36 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, + ], ' CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, - 25 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, - 36 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, - ], ]; yield [ - ' CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, 22 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, 28 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, ], + 'doTest( + $source, + $expectedTokens, + [ + CT::T_TYPE_ALTERNATION, + ] + ); + } + + public function provideFix81Cases(): \Generator + { + yield 'readonly' => [ + [ + 14 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, + 23 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, + 36 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, + 52 => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, + ], + 'doTest( - $source, - $expectedTokens, - [ - T_CURLY_OPEN, - CT::T_CURLY_CLOSE, - T_DOLLAR_OPEN_CURLY_BRACES, - CT::T_DOLLAR_CLOSE_CURLY_BRACES, - CT::T_DYNAMIC_PROP_BRACE_OPEN, - CT::T_DYNAMIC_PROP_BRACE_CLOSE, - CT::T_DYNAMIC_VAR_BRACE_OPEN, - CT::T_DYNAMIC_VAR_BRACE_CLOSE, - CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN, - CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE, - CT::T_GROUP_IMPORT_BRACE_OPEN, - CT::T_GROUP_IMPORT_BRACE_CLOSE, - ] - ); - } - - public function provideProcessCases() + public function provideProcessCases(): array { return [ 'curly open/close I' => [ @@ -196,20 +170,36 @@ public function provideProcessCases() 39 => CT::T_CURLY_CLOSE, ], ], - 'do not touch' => [' [ + ' [ + '{"set_{$name}"}(42);', + [ + 3 => CT::T_DYNAMIC_PROP_BRACE_OPEN, + 6 => T_CURLY_OPEN, + 8 => CT::T_CURLY_CLOSE, + 10 => CT::T_DYNAMIC_PROP_BRACE_CLOSE, + ], + ], + 'group import' => [ ' CT::T_GROUP_IMPORT_BRACE_OPEN, 19 => CT::T_GROUP_IMPORT_BRACE_CLOSE, ], ], + 'nested curly open + close' => [ + '{"{$bar}"}}";', + [ + 4 => T_CURLY_OPEN, + 7 => CT::T_DYNAMIC_PROP_BRACE_OPEN, + 9 => T_CURLY_OPEN, + 11 => CT::T_CURLY_CLOSE, + 13 => CT::T_DYNAMIC_PROP_BRACE_CLOSE, + 14 => CT::T_CURLY_CLOSE, + ], + ], ]; } @@ -239,7 +229,7 @@ public function testProcess80(string $source, array $expectedTokens = []): void ); } - public static function provideProcess80Cases() + public static function provideProcess80Cases(): array { return [ 'dynamic property brace open/close' => [ diff --git a/tests/Tokenizer/Transformer/FirstClassCallableTransformerTest.php b/tests/Tokenizer/Transformer/FirstClassCallableTransformerTest.php new file mode 100644 index 00000000000..ef889328464 --- /dev/null +++ b/tests/Tokenizer/Transformer/FirstClassCallableTransformerTest.php @@ -0,0 +1,96 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Tokenizer\Transformer; + +use PhpCsFixer\Tests\Test\AbstractTransformerTestCase; +use PhpCsFixer\Tokenizer\CT; + +/** + * @internal + * + * @covers \PhpCsFixer\Tokenizer\Transformer\FirstClassCallableTransformer + */ +final class FirstClassCallableTransformerTest extends AbstractTransformerTestCase +{ + /** + * @dataProvider provideProcessCases + * @requires PHP 8.1 + */ + public function testProcess(array $expectedTokens, string $source): void + { + $this->doTest($source, $expectedTokens, [CT::T_FIRST_CLASS_CALLABLE]); + } + + public function provideProcessCases(): \Generator + { + yield 'set' => [ + [ + 3 => CT::T_FIRST_CLASS_CALLABLE, + 9 => CT::T_FIRST_CLASS_CALLABLE, + 15 => CT::T_FIRST_CLASS_CALLABLE, + 23 => CT::T_FIRST_CLASS_CALLABLE, + 31 => CT::T_FIRST_CLASS_CALLABLE, + 41 => CT::T_FIRST_CLASS_CALLABLE, + 49 => CT::T_FIRST_CLASS_CALLABLE, + 57 => CT::T_FIRST_CLASS_CALLABLE, + 71 => CT::T_FIRST_CLASS_CALLABLE, + 77 => CT::T_FIRST_CLASS_CALLABLE, + 88 => CT::T_FIRST_CLASS_CALLABLE, + 101 => CT::T_FIRST_CLASS_CALLABLE, + ], + 'method(...); +$obj->$methodStr(...); +($obj->property)(...); +Foo::method(...); +$classStr::$methodStr(...); +self::{$complex . $expression}(...); +\'strlen\'(...); +[$obj, \'method\'](...); +[Foo::class, \'method\'](...) ?>', + ]; + + yield 'comments and spacing' => [ + [ + 4 => CT::T_FIRST_CLASS_CALLABLE, + 12 => CT::T_FIRST_CLASS_CALLABLE, + 18 => CT::T_FIRST_CLASS_CALLABLE, + 28 => CT::T_FIRST_CLASS_CALLABLE, + 40 => CT::T_FIRST_CLASS_CALLABLE, + ], + 'method( ... ); +$obj->$methodStr( /* */ ... /* */ ); + ', + ]; + + yield 'not cases' => [ + [], + ' [ @@ -164,101 +164,104 @@ public function testPriority(array $expected, string $source): void self::assertTokens(Tokens::fromArray($expected), Tokens::fromCode($source)); } - public function providePriorityCases() + public function providePriorityCases(): \Generator { - return [ + yield [ [ - [ - new Token([T_OPEN_TAG, 'doTest($source, $expectedTokens); } - public function provideProcessCases() + public function provideProcessCases(): \Generator { yield 'function call' => [ ' [ ' ['doTest( $source, @@ -149,34 +149,71 @@ public function testProcess80(string $source, array $expectedTokens = []): void ); } - public function provideProcess80Cases() + public function provideProcess80Cases(): \Generator { - return [ + yield [ [ - ' CT::T_NULLABLE_TYPE, - 29 => CT::T_NULLABLE_TYPE, - 41 => CT::T_NULLABLE_TYPE, - ], + 17 => CT::T_NULLABLE_TYPE, + 29 => CT::T_NULLABLE_TYPE, + 41 => CT::T_NULLABLE_TYPE, ], + ' CT::T_NULLABLE_TYPE, - ], + 10 => CT::T_NULLABLE_TYPE, + ], + 'doTest( + $source, + $expectedTokens, + [ + CT::T_NULLABLE_TYPE, + ] + ); + } + + public function provideProcess81Cases(): \Generator + { + yield [ + [ + 19 => CT::T_NULLABLE_TYPE, + 33 => CT::T_NULLABLE_TYPE, + 47 => CT::T_NULLABLE_TYPE, ], + ' - * @author SpacePossum * * @internal * @@ -66,7 +65,7 @@ public function testIsShortArray(string $source, array $inspectIndexes, bool $ex } } - public function provideIsShortArrayCases() + public function provideIsShortArrayCases(): array { return [ [' [ @@ -252,7 +251,7 @@ public function testProcess71(string $source, array $expectedTokens): void ); } - public function provideProcess71Cases() + public function provideProcess71Cases(): array { return [ [ @@ -368,7 +367,7 @@ public function testProcess72(string $source, array $expectedTokens): void ); } - public function provideProcess72Cases() + public function provideProcess72Cases(): array { return [ [ diff --git a/tests/Tokenizer/Transformer/TypeAlternationTransformerTest.php b/tests/Tokenizer/Transformer/TypeAlternationTransformerTest.php index f044628defb..0e42e41a6fd 100644 --- a/tests/Tokenizer/Transformer/TypeAlternationTransformerTest.php +++ b/tests/Tokenizer/Transformer/TypeAlternationTransformerTest.php @@ -28,7 +28,6 @@ final class TypeAlternationTransformerTest extends AbstractTransformerTestCase { /** * @dataProvider provideProcessCases - * @requires PHP 7.1 */ public function testProcess(string $source, array $expectedTokens = []): void { @@ -41,7 +40,7 @@ public function testProcess(string $source, array $expectedTokens = []): void ); } - public function provideProcessCases() + public function provideProcessCases(): array { return [ 'no namespace' => [ @@ -98,7 +97,7 @@ public function testProcess80(string $source, array $expectedTokens): void $this->doTest($source, $expectedTokens); } - public function provideProcess80Cases() + public function provideProcess80Cases(): \Generator { yield 'arrow function' => [ ' $item * 2;', @@ -282,5 +281,79 @@ function f4(A|B $x, C|D $y, E|F $z) {}; 66 => CT::T_TYPE_ALTERNATION, ], ]; + + yield 'callable type' => [ + ' CT::T_TYPE_ALTERNATION, + 22 => CT::T_TYPE_ALTERNATION, + 37 => CT::T_TYPE_ALTERNATION, + 52 => CT::T_TYPE_ALTERNATION, + ], + ]; + + yield 'promoted properties' => [ + ' CT::T_TYPE_ALTERNATION, + 26 => CT::T_TYPE_ALTERNATION, + 35 => CT::T_TYPE_ALTERNATION, + ], + ]; + } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(array $expectedTokens, string $source): void + { + $this->doTest( + $source, + $expectedTokens, + [ + CT::T_TYPE_ALTERNATION, + ] + ); + } + + public function provideFix81Cases(): \Generator + { + yield 'readonly' => [ + [ + 12 => CT::T_TYPE_ALTERNATION, + ], + ' [ + [ + 19 => CT::T_TYPE_ALTERNATION, + 30 => CT::T_TYPE_ALTERNATION, + 41 => CT::T_TYPE_ALTERNATION, + ], + ' T_USE, ], ], - ]; - } - - /** - * @param array $expectedTokens index => kind - * - * @dataProvider provideFix70Cases - * @requires PHP 7.0 - */ - public function testFix70(string $source, array $expectedTokens = []): void - { - $this->doTest( - $source, - $expectedTokens, - [ - T_USE, - CT::T_USE_LAMBDA, - CT::T_USE_TRAIT, - ] - ); - } - - public function provideFix70Cases() - { - return [ 'nested anonymous classes' => [ ' [ diff --git a/tests/ToolInfoTest.php b/tests/ToolInfoTest.php index 1ca6b74d3bf..9db083ac3b8 100644 --- a/tests/ToolInfoTest.php +++ b/tests/ToolInfoTest.php @@ -17,8 +17,6 @@ use PhpCsFixer\ToolInfo; /** - * @author SpacePossum - * * @internal * * @covers \PhpCsFixer\ToolInfo diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 6fc776146f2..179c238720a 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -21,7 +21,7 @@ /** * @author Dariusz Rumiński - * @author Graham Campbell + * @author Graham Campbell * @author Odín del Río * * @internal @@ -46,7 +46,6 @@ protected function tearDown(): void /** * @param string $expected Camel case string - * @param string $input Input string * * @dataProvider provideCamelCaseToUnderscoreCases */ @@ -120,7 +119,7 @@ public function testCalculateTrailingWhitespaceIndent(string $spaces, $input): v static::assertSame($spaces, Utils::calculateTrailingWhitespaceIndent($token)); } - public function provideCalculateTrailingWhitespaceIndentCases() + public function provideCalculateTrailingWhitespaceIndentCases(): array { return [ [' ', [T_WHITESPACE, "\n\n "]], @@ -157,7 +156,7 @@ public function testStableSort( ); } - public function provideStableSortCases() + public function provideStableSortCases(): array { return [ [ @@ -169,14 +168,14 @@ static function ($element) { return $element; }, [ ['b', 'd', 'e', 'a', 'c'], ['b', 'd', 'e', 'a', 'c'], - static function ($element) { return 'foo'; }, + static function (): string { return 'foo'; }, 'strcmp', ], [ ['b', 'd', 'e', 'a', 'c'], ['b', 'd', 'e', 'a', 'c'], static function ($element) { return $element; }, - static function ($a, $b) { return 0; }, + static function (): int { return 0; }, ], [ ['bar1', 'baz1', 'foo1', 'bar2', 'baz2', 'foo2'], @@ -222,7 +221,7 @@ public function testNaturalLanguageJoinWithBackticks(string $joined, array $name static::assertSame($joined, Utils::naturalLanguageJoinWithBackticks($names)); } - public function provideNaturalLanguageJoinWithBackticksCases() + public function provideNaturalLanguageJoinWithBackticksCases(): array { return [ [ diff --git a/tests/WhitespacesFixerConfigTest.php b/tests/WhitespacesFixerConfigTest.php index 2c20dff62df..b8a3bdc86d5 100644 --- a/tests/WhitespacesFixerConfigTest.php +++ b/tests/WhitespacesFixerConfigTest.php @@ -41,7 +41,7 @@ public function testCases(string $indent, string $lineEnding, ?string $exception static::assertSame($lineEnding, $config->getLineEnding()); } - public function provideTestCases() + public function provideTestCases(): array { return [ [' ', "\n"],