Skip to content

Commit

Permalink
feat: UnaryOperatorSpacesFixer - introduce only_dec_inc config (#7626)
Browse files Browse the repository at this point in the history
  • Loading branch information
keradus authored Dec 28, 2023
1 parent 50e6a58 commit 99e3a8d
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 16 deletions.
5 changes: 4 additions & 1 deletion doc/ruleSets/PSR12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 change: 1 addition & 0 deletions doc/ruleSets/Symfony.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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>`_

Expand Down
65 changes: 60 additions & 5 deletions doc/rules/operator/unary_operator_spaces.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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>`_

Expand Down
39 changes: 35 additions & 4 deletions src/Fixer/Operator/UnaryOperatorSpacesFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,41 @@
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;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixer\Tokenizer\TokensAnalyzer;

/**
* Fixer for rules defined in PSR12 ¶6.1.
*
* @author Gregor Harlan <[email protected]>
* @author Dariusz Rumiński <[email protected]>
*/
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]
),
]
);
}

Expand All @@ -51,11 +68,25 @@ public function isCandidate(Tokens $tokens): bool
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);
Expand Down
4 changes: 3 additions & 1 deletion src/RuleSet/Sets/PSR12Set.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ public function getRules(): array
'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,
];
}
Expand Down
1 change: 1 addition & 0 deletions src/RuleSet/Sets/SymfonySet.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ public function getRules(): array
'trim_array_spaces' => true,
'type_declaration_spaces' => true,
'types_spaces' => true,
'unary_operator_spaces' => true,
'whitespace_after_comma_in_array' => true,
'yoda_style' => true,
];
Expand Down
17 changes: 16 additions & 1 deletion tests/Fixer/Operator/UnaryOperatorSpacesFixerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@
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);
}

Expand Down Expand Up @@ -137,5 +140,17 @@ public static function provideFixCases(): iterable
'<?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 changes: 2 additions & 0 deletions tests/Fixtures/Integration/set/@PSR12.test-in.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ class Aaa implements
$b = (boolean) 1;
$c = true ? (INT) '1' : 2;

function callback($a, ... $b) { return (-- $a) * ($b ++);}

?>
5 changes: 5 additions & 0 deletions tests/Fixtures/Integration/set/@PSR12.test-out.php
Original file line number Diff line number Diff line change
Expand Up @@ -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++);
}
2 changes: 0 additions & 2 deletions tests/Fixtures/Integration/set/@PSR12_php70.test-in.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

function foo() : void
{
$a =& $b;
$c = & $d;
}

$class = new class() {};
2 changes: 0 additions & 2 deletions tests/Fixtures/Integration/set/@PSR12_php70.test-out.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

function foo(): void
{
$a = &$b;
$c = &$d;
}

$class = new class () {};
5 changes: 5 additions & 0 deletions tests/Fixtures/Integration/set/@Symfony.test-in.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,9 @@ final class FinalClass
final function finalMethod(){}
}

function callback($a, ... $b) { return (-- $a) * ($b ++);}

$a =& $b;
$c = & $d;

echo 1 ?>
8 changes: 8 additions & 0 deletions tests/Fixtures/Integration/set/@Symfony.test-out.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,12 @@ final public function finalMethod()
}
}

function callback($a, ...$b)
{
return (--$a) * ($b++);
}

$a = &$b;
$c = &$d;

echo 1;

0 comments on commit 99e3a8d

Please sign in to comment.