Skip to content

Commit

Permalink
NewWithBracesFixer - add no braces support
Browse files Browse the repository at this point in the history
- NewWithBracesFixer - add PSR-12 support
- Revert disabling NewWithBraces fixer for anonymous classes.
- NewWithBraces configuration wording
  • Loading branch information
jrmajor committed Oct 26, 2021
1 parent 66d103e commit 2282dad
Show file tree
Hide file tree
Showing 3 changed files with 456 additions and 16 deletions.
65 changes: 60 additions & 5 deletions doc/rules/operator/new_with_braces.rst
Expand Up @@ -4,29 +4,84 @@ Rule ``new_with_braces``

All instances created with new keyword must be followed by braces.

Configuration
-------------

``named_class``
~~~~~~~~~~~~~~~

Whether named classes should be followed by parentheses.

Allowed types: ``bool``

Default value: ``true``

``anonymous_class``
~~~~~~~~~~~~~~~~~~~

Whether anonymous classes should be followed by parentheses.

Allowed types: ``bool``

Default value: ``true``

Examples
--------

Example #1
~~~~~~~~~~

*Default* configuration.

.. code-block:: diff
--- Original
+++ New
-<?php $x = new X;
+<?php $x = new X();
<?php
-$x = new X;
-$y = new class {};
+$x = new X();
+$y = new class() {};
Example #2
~~~~~~~~~~

With configuration: ``['anonymous_class' => false]``.

.. code-block:: diff
--- Original
+++ New
<?php
-$y = new class() {};
+$y = new class {};
Example #3
~~~~~~~~~~

With configuration: ``['named_class' => false]``.

.. code-block:: diff
--- Original
+++ New
<?php
-$x = new X();
+$x = new X;
Rule sets
---------

The rule is part of the following rule sets:

@PSR12
Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``new_with_braces`` rule.
Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``new_with_braces`` rule with the default config.

@PhpCsFixer
Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``new_with_braces`` rule.
Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``new_with_braces`` rule with the default config.

@Symfony
Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``new_with_braces`` rule.
Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``new_with_braces`` rule with the default config.
82 changes: 75 additions & 7 deletions src/Fixer/Operator/NewWithBracesFixer.php
Expand Up @@ -15,6 +15,10 @@
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;
Expand All @@ -25,7 +29,7 @@
/**
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*/
final class NewWithBracesFixer extends AbstractFixer
final class NewWithBracesFixer extends AbstractFixer implements ConfigurableFixerInterface
{
/**
* {@inheritdoc}
Expand All @@ -34,7 +38,17 @@ public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'All instances created with new keyword must be followed by braces.',
[new CodeSample("<?php \$x = new X;\n")]
[
new CodeSample("<?php\n\n\$x = new X;\n\$y = new class {};\n"),
new CodeSample(
"<?php\n\n\$y = new class() {};\n",
['anonymous_class' => false]
),
new CodeSample(
"<?php\n\n\$x = new X();\n",
['named_class' => false]
),
]
);
}

Expand Down Expand Up @@ -110,8 +124,28 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void

// new anonymous class definition
if ($nextToken->isGivenKind(T_CLASS)) {
if (!$tokens[$tokens->getNextMeaningfulToken($nextIndex)]->equals('(')) {
$this->insertBracesAfter($tokens, $nextIndex);
$nextIndex = $tokens->getNextMeaningfulToken($nextIndex);
$nextToken = $tokens[$nextIndex];

// add braces to anonymous class definition
if ($this->configuration['anonymous_class'] && !$nextToken->equals('(')) {
$this->insertBracesAfter($tokens, $tokens->getPrevMeaningfulToken($nextIndex));

continue;
}

// remove braces from anonymous class definition
if (!$this->configuration['anonymous_class'] && $nextToken->equals('(')) {
$openingIndex = $nextIndex;
$closingIndex = $tokens->getNextMeaningfulToken($openingIndex);

// constructor has arguments - braces can not be removed
if (null === $closingIndex || !$tokens[$closingIndex]->equals(')')) {
continue;
}

$tokens->clearAt($closingIndex);
$tokens->clearTokenAndMergeSurroundingWhitespace($openingIndex);
}

continue;
Expand All @@ -129,15 +163,49 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
$nextToken = $tokens[$nextIndex];
}

// new statement with () - nothing to do
if ($nextToken->equals('(') || $nextToken->isObjectOperator()) {
// new statement without ()
if ($this->configuration['named_class']) {
if (!$nextToken->equals('(') && !$nextToken->isObjectOperator()) {
$this->insertBracesAfter($tokens, $tokens->getPrevMeaningfulToken($nextIndex));
}

continue;
}

if (!$tokens[$nextIndex]->equals('(')) {
continue;
}

$openingIndex = $nextIndex;
$closingIndex = $tokens->getNextMeaningfulToken($openingIndex);

// constructor has arguments - braces can not be removed
if (null === $closingIndex || !$tokens[$closingIndex]->equals(')')) {
continue;
}

$this->insertBracesAfter($tokens, $tokens->getPrevMeaningfulToken($nextIndex));
$tokens->clearAt($closingIndex);
$tokens->clearTokenAndMergeSurroundingWhitespace($openingIndex);
}
}

/**
* {@inheritdoc}
*/
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('named_class', 'Whether named classes should be followed by parentheses.'))
->setAllowedTypes(['bool'])
->setDefault(true)
->getOption(),
(new FixerOptionBuilder('anonymous_class', 'Whether anonymous classes should be followed by parentheses.'))
->setAllowedTypes(['bool'])
->setDefault(true)
->getOption(),
]);
}

private function insertBracesAfter(Tokens $tokens, int $index): void
{
$tokens->insertAt(++$index, [new Token('('), new Token(')')]);
Expand Down

0 comments on commit 2282dad

Please sign in to comment.