Browse Source

feat: UnaryOperatorSpacesFixer - introduce only_dec_inc config (#7626)

Dariusz Rumiński 1 year ago
parent
commit
99e3a8d591

+ 4 - 1
doc/ruleSets/PSR12.rst

@@ -47,5 +47,8 @@ Rules
 
 - `single_trait_insert_per_statement <./../rules/class_notation/single_trait_insert_per_statement.rst>`_
 - `ternary_operator_spaces <./../rules/operator/ternary_operator_spaces.rst>`_
-- `unary_operator_spaces <./../rules/operator/unary_operator_spaces.rst>`_
+- `unary_operator_spaces <./../rules/operator/unary_operator_spaces.rst>`_ with config:
+
+  ``['only_dec_inc' => true]``
+
 - `visibility_required <./../rules/class_notation/visibility_required.rst>`_

+ 1 - 0
doc/ruleSets/Symfony.rst

@@ -174,6 +174,7 @@ Rules
 - `trim_array_spaces <./../rules/array_notation/trim_array_spaces.rst>`_
 - `type_declaration_spaces <./../rules/whitespace/type_declaration_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>`_
 

+ 60 - 5
doc/rules/operator/unary_operator_spaces.rst

@@ -4,12 +4,26 @@ Rule ``unary_operator_spaces``
 
 Unary operators should be placed adjacent to their operands.
 
+Configuration
+-------------
+
+``only_dec_inc``
+~~~~~~~~~~~~~~~~
+
+Limit to increment and decrement operators.
+
+Allowed types: ``bool``
+
+Default value: ``false``
+
 Examples
 --------
 
 Example #1
 ~~~~~~~~~~
 
+*Default* configuration.
+
 .. code-block:: diff
 
    --- Original
@@ -26,16 +40,57 @@ Example #1
    +$sample = ~$c;
    +function &foo(){}
 
+Example #2
+~~~~~~~~~~
+
+With configuration: ``['only_dec_inc' => false]``.
+
+.. code-block:: diff
+
+   --- Original
+   +++ New
+    <?php
+   -function foo($a, ...   $b) { return (--   $a) * ($b   ++);}
+   +function foo($a, ...$b) { return (--$a) * ($b++);}
+
+Example #3
+~~~~~~~~~~
+
+With configuration: ``['only_dec_inc' => true]``.
+
+.. code-block:: diff
+
+   --- Original
+   +++ New
+    <?php
+   -function foo($a, ...   $b) { return (--   $a) * ($b   ++);}
+   +function foo($a, ...   $b) { return (--$a) * ($b++);}
+
 Rule sets
 ---------
 
 The rule is part of the following rule sets:
 
-- `@PER <./../../ruleSets/PER.rst>`_
-- `@PER-CS <./../../ruleSets/PER-CS.rst>`_
-- `@PER-CS1.0 <./../../ruleSets/PER-CS1.0.rst>`_
-- `@PER-CS2.0 <./../../ruleSets/PER-CS2.0.rst>`_
-- `@PSR12 <./../../ruleSets/PSR12.rst>`_
+- `@PER <./../../ruleSets/PER.rst>`_ with config:
+
+  ``['only_dec_inc' => true]``
+
+- `@PER-CS <./../../ruleSets/PER-CS.rst>`_ with config:
+
+  ``['only_dec_inc' => true]``
+
+- `@PER-CS1.0 <./../../ruleSets/PER-CS1.0.rst>`_ with config:
+
+  ``['only_dec_inc' => true]``
+
+- `@PER-CS2.0 <./../../ruleSets/PER-CS2.0.rst>`_ with config:
+
+  ``['only_dec_inc' => true]``
+
+- `@PSR12 <./../../ruleSets/PSR12.rst>`_ with config:
+
+  ``['only_dec_inc' => true]``
+
 - `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_
 - `@Symfony <./../../ruleSets/Symfony.rst>`_
 

+ 35 - 4
src/Fixer/Operator/UnaryOperatorSpacesFixer.php

@@ -15,6 +15,10 @@ declare(strict_types=1);
 namespace PhpCsFixer\Fixer\Operator;
 
 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;
@@ -22,17 +26,30 @@ use PhpCsFixer\Tokenizer\Tokens;
 use PhpCsFixer\Tokenizer\TokensAnalyzer;
 
 /**
- * Fixer for rules defined in PSR12 ¶6.1.
- *
  * @author Gregor Harlan <gharlan@web.de>
+ * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  */
-final class UnaryOperatorSpacesFixer extends AbstractFixer
+final class UnaryOperatorSpacesFixer extends AbstractFixer implements ConfigurableFixerInterface
 {
     public function getDefinition(): FixerDefinitionInterface
     {
         return new FixerDefinition(
             'Unary operators should be placed adjacent to their operands.',
-            [new CodeSample("<?php\n\$sample ++;\n-- \$sample;\n\$sample = ! ! \$a;\n\$sample = ~  \$c;\nfunction & foo(){}\n")]
+            [
+                new CodeSample("<?php\n\$sample ++;\n-- \$sample;\n\$sample = ! ! \$a;\n\$sample = ~  \$c;\nfunction & foo(){}\n"),
+                new CodeSample(
+                    '<?php
+function foo($a, ...   $b) { return (--   $a) * ($b   ++);}
+',
+                    ['only_dec_inc' => false]
+                ),
+                new CodeSample(
+                    '<?php
+function foo($a, ...   $b) { return (--   $a) * ($b   ++);}
+',
+                    ['only_dec_inc' => true]
+                ),
+            ]
         );
     }
 
@@ -51,11 +68,25 @@ final class UnaryOperatorSpacesFixer extends AbstractFixer
         return true;
     }
 
+    protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
+    {
+        return new FixerConfigurationResolver([
+            (new FixerOptionBuilder('only_dec_inc', 'Limit to increment and decrement operators.'))
+                ->setAllowedTypes(['bool'])
+                ->setDefault(false)
+                ->getOption(),
+        ]);
+    }
+
     protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
     {
         $tokensAnalyzer = new TokensAnalyzer($tokens);
 
         for ($index = $tokens->count() - 1; $index >= 0; --$index) {
+            if (true === $this->configuration['only_dec_inc'] && !$tokens[$index]->isGivenKind([T_DEC, T_INC])) {
+                continue;
+            }
+
             if ($tokensAnalyzer->isUnarySuccessorOperator($index)) {
                 if (!$tokens[$tokens->getPrevNonWhitespace($index)]->isComment()) {
                     $tokens->removeLeadingWhitespace($index);

+ 3 - 1
src/RuleSet/Sets/PSR12Set.php

@@ -64,7 +64,9 @@ final class PSR12Set extends AbstractRuleSetDescription
             'single_import_per_statement' => ['group_to_single_imports' => false],
             'single_trait_insert_per_statement' => true,
             'ternary_operator_spaces' => true,
-            'unary_operator_spaces' => true,
+            'unary_operator_spaces' => [
+                'only_dec_inc' => true,
+            ],
             'visibility_required' => true,
         ];
     }

+ 1 - 0
src/RuleSet/Sets/SymfonySet.php

@@ -215,6 +215,7 @@ final class SymfonySet extends AbstractRuleSetDescription
             'trim_array_spaces' => true,
             'type_declaration_spaces' => true,
             'types_spaces' => true,
+            'unary_operator_spaces' => true,
             'whitespace_after_comma_in_array' => true,
             'yoda_style' => true,
         ];

+ 16 - 1
tests/Fixer/Operator/UnaryOperatorSpacesFixerTest.php

@@ -26,10 +26,13 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
 final class UnaryOperatorSpacesFixerTest extends AbstractFixerTestCase
 {
     /**
+     * @param array<string, mixed> $configuration
+     *
      * @dataProvider provideFixCases
      */
-    public function testFix(string $expected, ?string $input = null): void
+    public function testFix(string $expected, ?string $input = null, array $configuration = []): void
     {
+        $this->fixer->configure($configuration);
         $this->doTest($expected, $input);
     }
 
@@ -137,5 +140,17 @@ final class UnaryOperatorSpacesFixerTest extends AbstractFixerTestCase
             '<?php foo($a, ...$b);',
             '<?php foo($a, ... $b);',
         ];
+
+        yield [
+            '<?php function foo($a, ...$b) { return (--$a) * ($b++);}',
+            '<?php function foo($a, ...   $b) { return (--   $a) * ($b   ++);}',
+            ['only_dec_inc' => false],
+        ];
+
+        yield [
+            '<?php function foo($a, ...   $b) { return (--$a) * ($b++);}',
+            '<?php function foo($a, ...   $b) { return (--   $a) * ($b   ++);}',
+            ['only_dec_inc' => true],
+        ];
     }
 }

+ 2 - 0
tests/Fixtures/Integration/set/@PSR12.test-in.php

@@ -39,4 +39,6 @@ $a = new Foo;
 $b = (boolean) 1;
 $c = true  ? (INT) '1'  :  2;
 
+function callback($a, ...   $b) { return (--   $a) * ($b   ++);}
+
 ?>

+ 5 - 0
tests/Fixtures/Integration/set/@PSR12.test-out.php

@@ -48,3 +48,8 @@ class Aaa implements
 $a = new Foo();
 $b = (bool) 1;
 $c = true ? (int) '1' : 2;
+
+function callback($a, ...   $b)
+{
+    return (--$a) * ($b++);
+}

+ 0 - 2
tests/Fixtures/Integration/set/@PSR12_php70.test-in.php

@@ -4,8 +4,6 @@ declare(strict_types = 1 );
 
 function foo() : void
 {
-    $a =& $b;
-    $c =  &  $d;
 }
 
 $class = new class() {};

Some files were not shown because too many files changed in this diff