Skip to content

Commit

Permalink
Fixes #13. Implemented Ely\multiline_if_statement_braces fixer
Browse files Browse the repository at this point in the history
  • Loading branch information
erickskrauch committed Apr 8, 2023
1 parent e9ad4a9 commit 7d36ce9
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Added
- Enh #12: Implemented `Ely\align_multiline_parameters` fixer.
- Enh #13: Implemented `Ely\multiline_if_statement_braces` fixer.
- Enabled `Ely\align_multiline_parameters` for Ely.by codestyle in `['types' => false, 'defaults' => false]` mode.
- Enabled `Ely\multiline_if_statement_braces` for Ely.by codestyle in `['keep_on_own_line' => true]` mode.
- Enabled
[`PhpCsFixerCustomFixers/multiline_promoted_properties`](https://github.com/kubawerlos/php-cs-fixer-custom-fixers#multilinepromotedpropertiesfixer)
fixer for Ely.by codestyle in 2+ parameters mode.
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,28 @@ and `do-while`.
$c = 'next statement';
```

### `Ely/multiline_if_statement_braces`

Ensures that multiline if statement body curly brace placed on the right line.

```diff
--- Original
+++ New
@@ @@
<?php
if ($condition1 === 123
- && $condition2 = 321) {
+ && $condition2 = 321
+) {
// Do something here
}
```

**Configuration:**

* `keep_on_own_line` - should this place closing bracket on its own line? If it's set to `false`, than
curly bracket will be placed right after the last condition statement. **Default**: `true`.

### `Ely/remove_class_name_method_usages` (Yii2)

Replaces Yii2 [`BaseObject::className()`](https://github.com/yiisoft/yii2/blob/e53fc0ded1/framework/base/BaseObject.php#L84)
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"require": {
"php": "^7.4 || ^8.0",
"friendsofphp/php-cs-fixer": "^3.13",
"kubawerlos/php-cs-fixer-custom-fixers": "^3.13"
"kubawerlos/php-cs-fixer-custom-fixers": "^3.13",
"symfony/polyfill-php80": "^1.15"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.28",
Expand Down
16 changes: 8 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 92 additions & 0 deletions src/Fixer/Whitespace/MultilineIfStatementBracesFixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
declare(strict_types=1);

namespace Ely\CS\Fixer\Whitespace;

use Ely\CS\Fixer\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;
use PhpCsFixer\Tokenizer\TokensAnalyzer;
use SplFileInfo;

final class MultilineIfStatementBracesFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface {

/**
* @internal
*/
public const C_KEEP_ON_OWN_LINE = 'keep_on_own_line';

public function getDefinition(): FixerDefinitionInterface {
return new FixerDefinition(
'Ensures that multiline if statement body curly brace placed on the right line.',
[
new CodeSample(
'<?php
if ($condition1 == true
&& $condition2 === false) {}
',
),
new CodeSample(
'<?php
if ($condition1 == true
&& $condition2 === false
) {}
',
[self::C_KEEP_ON_OWN_LINE => false],
),
],
);
}

public function isCandidate(Tokens $tokens): bool {
return $tokens->isTokenKindFound(T_IF);
}

protected function createConfigurationDefinition(): FixerConfigurationResolverInterface {
return new FixerConfigurationResolver([
(new FixerOptionBuilder(self::C_KEEP_ON_OWN_LINE, 'adjusts the position of condition closing brace.'))
->setAllowedTypes(['bool'])
->setDefault(true)
->getOption(),
]);
}

protected function applyFix(SplFileInfo $file, Tokens $tokens): void {
$keepOnOwnLine = $this->configuration[self::C_KEEP_ON_OWN_LINE];
$tokensAnalyzer = new TokensAnalyzer($tokens);
$eol = $this->whitespacesConfig->getLineEnding();
foreach ($tokens as $i => $token) {
if (!$token->isGivenKind(T_IF)) {
continue;
}

$openBraceIndex = $tokens->getNextTokenOfKind($i, ['(']);
if (!$tokensAnalyzer->isBlockMultiline($tokens, $openBraceIndex)) {
continue;
}

$closingBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openBraceIndex);
/** @var \PhpCsFixer\Tokenizer\Token $statementBeforeClosingBrace */
$statementBeforeClosingBrace = $tokens[$closingBraceIndex - 1];
if ($keepOnOwnLine) {
if (!$statementBeforeClosingBrace->isWhitespace()
|| !str_contains($statementBeforeClosingBrace->getContent(), $eol)
) {
$indent = WhitespacesAnalyzer::detectIndent($tokens, $i);
$tokens->ensureWhitespaceAtIndex($closingBraceIndex, 0, $eol . $indent);
}
} else {
$tokens->removeLeadingWhitespace($closingBraceIndex);
}
}
}

}
1 change: 1 addition & 0 deletions src/Rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ public static function create(array $overwrittenRules = []): array {
],
'Ely/blank_line_before_return' => true,
'Ely/line_break_after_statements' => true,
'Ely/multiline_if_statement_braces' => true,
'Ely/remove_class_name_method_usages' => true,
], $overwrittenRules);
}
Expand Down
68 changes: 68 additions & 0 deletions tests/Fixer/Whitespace/MultilineIfStatementBracesFixerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);

namespace Ely\CS\Test\Fixer\Whitespace;

use Ely\CS\Fixer\Whitespace\MultilineIfStatementBracesFixer;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Tests\Test\AbstractFixerTestCase;

/**
* @covers \Ely\CS\Fixer\Whitespace\MultilineIfStatementBracesFixer
*/
class MultilineIfStatementBracesFixerTest extends AbstractFixerTestCase {

/**
* @dataProvider provideFixCases
*/
public function testFixOnNewLine(string $expected, ?string $input = null): void {
$this->doTest($expected, $input);
}

public function provideFixCases(): iterable {
yield 'simple' => [
'<?php
if ($condition1
&& $condition2
) {}',
'<?php
if ($condition1
&& $condition2) {}',
];

yield 'nested' => [
'<?php
function foo() {
if ($condition1
&& $condition2
) {}
}',
'<?php
function foo() {
if ($condition1
&& $condition2) {}
}',
];
}

/**
* @dataProvider provideInvertedFixCases
*/
public function testFixOnSameLine(string $expected, ?string $input = null): void {
$this->fixer->configure([
MultilineIfStatementBracesFixer::C_KEEP_ON_OWN_LINE => false,
]);
$this->doTest($expected, $input);
}

public function provideInvertedFixCases(): iterable {
foreach ($this->provideFixCases() as $name => $case) {
yield $name => [$case[1], $case[0]];
}
}

protected function createFixer(): AbstractFixer {
return new MultilineIfStatementBracesFixer();
}

}

0 comments on commit 7d36ce9

Please sign in to comment.