Merge branch 'php-cs-fixer-3'

This commit is contained in:
ErickSkrauch 2022-09-20 02:51:02 +02:00
commit 137a89820c
No known key found for this signature in database
GPG Key ID: 669339FCBB30EE0E
24 changed files with 3142 additions and 1720 deletions

58
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,58 @@
name: CI
on:
push:
pull_request:
jobs:
Build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-versions:
- '7.4'
- '8.0'
- '8.1'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: ctype, mbstring
tools: cs2pr
- name: Get Composer's cache directory
id: composer-cache-path
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache Composer dependencies
uses: actions/cache@v3
id: composer-cache
with:
path: ${{ steps.composer-cache-path.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install
- name: Normalize composer.json
if: matrix.php-versions == '8.1'
run: composer normalize --dry-run
- name: PHP-CS-Fixer
if: matrix.php-versions == '8.1'
run: vendor/bin/php-cs-fixer fix --dry-run --format=checkstyle | cs2pr
# https://github.com/marketplace/actions/setup-php-action#phpunit
- name: Setup problem matchers for PHPUnit
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: PHPUnit
run: vendor/bin/phpunit

5
.gitignore vendored
View File

@ -1,4 +1,5 @@
vendor vendor
dist dist
.php_cs .phpunit.result.cache
.php_cs.cache .php-cs-fixer
.php-cs-fixer.cache

12
.php-cs-fixer.dist.php Normal file
View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
$finder = PhpCsFixer\Finder::create()
->in(__DIR__);
return Ely\CS\Config::create([
// Disable "parameters" and "match" to keep compatibility with PHP 7.4
'trailing_comma_in_multiline' => [
'elements' => ['arrays', 'arguments'],
],
])->setFinder($finder);

View File

@ -1,9 +0,0 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__);
return \Ely\CS\Config::create([
// Disable it for const, 'cause ^7.0 compatibility
'visibility_required' => ['property', 'method'],
])->setFinder($finder);

View File

@ -1,37 +0,0 @@
language: php
php:
- '7.0'
- '7.1'
- '7.2'
- '7.3'
- '7.4'
- '8.0'
cache:
directories:
- vendor
- $HOME/.composer
env:
global:
- DEFAULT_COMPOSER_FLAGS="--optimize-autoloader --no-interaction --no-progress"
before_script:
- composer global show hirak/prestissimo -q || travis_retry composer global require $DEFAULT_COMPOSER_FLAGS hirak/prestissimo
- composer install --no-interaction
stages:
- Static Code Analysis
- Test
jobs:
include:
- stage: Static Code Analysis
php: 7.3
script:
- vendor/bin/php-cs-fixer fix -v --dry-run
allow_failures:
- php: nightly
script:
- vendor/bin/phpunit

View File

@ -12,11 +12,47 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `php_unit_mock_short_will_return` fixer. - `php_unit_mock_short_will_return` fixer.
- `php_unit_dedicate_assert_internal_type` fixer. - `php_unit_dedicate_assert_internal_type` fixer.
- `php_unit_no_expectation_annotation` fixer. - `php_unit_no_expectation_annotation` fixer.
- `modernize_strpos` fixer.
- `no_multiple_statements_per_line` fixer.
- `octal_notation` fixer.
- `class_reference_name_casing` fixer.
- `integer_literal_case` fixer.
- `no_unset_cast` fixer.
- `no_null_property_initialization` fixer.
- `comment_to_phpdoc` fixer.
- `multiline_comment_opening_closing` fixer.
- `no_empty_comment` fixer.
- `single_line_comment_spacing` fixer.
- `single_line_comment_style` fixer.
- `empty_loop_body` fixer.
- `empty_loop_condition` fixer.
- `switch_continue_to_break` fixer.
- `yoda_style` fixer in non-yoda mode.
- `function_typehint_space` fixer.
- `lambda_not_used_import` fixer.
- `no_unneeded_import_alias` fixer.
- `combine_consecutive_unsets` fixer.
- `declare_parentheses` fixer.
- `clean_namespace` fixer.
- `assign_null_coalescing_to_coalesce_equal` fixer.
- `no_useless_nullsafe_operator` fixer.
- `operator_linebreak` fixer.
- `php_unit_fqcn_annotation` fixer.
- `php_unit_test_case_static_method_calls` fixer.
- `simplified_null_return` fixer.
- `no_empty_statement` fixer.
- `no_singleline_whitespace_before_semicolons` fixer.
- `semicolon_after_instruction` fixer.
- `types_spaces` fixer.
- `no_trailing_comma_in_singleline` fixer.
### Changed ### Changed
- `friendsofphp/php-cs-fixer` version bumped to `^2.15.0`. - `friendsofphp/php-cs-fixer` version bumped to `^3`.
- `braces` fixer now enables rule `allow_single_line_anonymous_class_with_empty_body`.
- `class_attributes_separation` fixer now fixes `const` in the `only_if_meta` mode.
### Removed ### Removed
- `Ely/new_with_braces` since all its functionality is now included in the original fixer.
- `self_accessor` fixer because it leads to errors in interfaces, that returns self. - `self_accessor` fixer because it leads to errors in interfaces, that returns self.
## [0.3.0] - 2019-02-23 ## [0.3.0] - 2019-02-23

View File

@ -246,27 +246,6 @@ and `do-while`.
$c = 'next statement'; $c = 'next statement';
``` ```
### `Ely/new_with_braces`
This is the extended version of the original `new_with_braces` fixer. It allows you to remove braces around
an anonymous class declaration in a case when said class constructor doesn't contain any arguments.
```diff
--- Original
+++ New
@@ @@
<?php
-$a = new Foo;
+$a = new Foo();
-$b = new class() extends Foo {};
+$b = new class extends Foo {};
```
**Configuration:**
* `remove_for_anonymous_classes` - if its set to `true`, then braces for anonymous classes without constructor
arguments will be removed. **Default**: `false`.
### `Ely/remove_class_name_method_usages` (Yii2) ### `Ely/remove_class_name_method_usages` (Yii2)
Replaces Yii2 [`BaseObject::className()`](https://github.com/yiisoft/yii2/blob/e53fc0ded1/framework/base/BaseObject.php#L84) Replaces Yii2 [`BaseObject::className()`](https://github.com/yiisoft/yii2/blob/e53fc0ded1/framework/base/BaseObject.php#L84)
@ -286,9 +265,9 @@ usages with native `::class` keyword, introduced in PHP 5.5.
[ico-version]: https://img.shields.io/packagist/v/ely/php-code-style.svg?style=flat-square [ico-version]: https://img.shields.io/packagist/v/ely/php-code-style.svg?style=flat-square
[ico-license]: https://img.shields.io/badge/license-Apache-green.svg?style=flat-square [ico-license]: https://img.shields.io/badge/license-Apache-green.svg?style=flat-square
[ico-downloads]: https://img.shields.io/packagist/dt/ely/php-code-style.svg?style=flat-square [ico-downloads]: https://img.shields.io/packagist/dt/ely/php-code-style.svg?style=flat-square
[ico-build-status]: https://img.shields.io/travis/elyby/php-code-style/master.svg?style=flat-square [ico-build-status]: https://img.shields.io/github/workflow/status/elyby/php-code-style/CI.svg?style=flat-square
[link-packagist]: https://packagist.org/packages/ely/php-code-style [link-packagist]: https://packagist.org/packages/ely/php-code-style
[link-contributors]: ../../contributors [link-contributors]: ../../contributors
[link-downloads]: https://packagist.org/packages/ely/php-code-style/stats [link-downloads]: https://packagist.org/packages/ely/php-code-style/stats
[link-build-status]: https://travis-ci.org/elyby/php-code-style [link-build-status]: https://github.com/elyby/php-code-style/actions

View File

@ -1,8 +1,12 @@
{ {
"name": "ely/php-code-style", "name": "ely/php-code-style",
"description": "Set of PHP-CS-Fixer rules used in the development of Ely.by PHP projects", "description": "Set of PHP-CS-Fixer rules used in the development of Ely.by PHP projects",
"keywords": ["php-cs-fixer", "code style"], "license": "Apache-2.0",
"homepage": "https://github.com/elyby/php-code-style", "type": "library",
"keywords": [
"php-cs-fixer",
"code style"
],
"authors": [ "authors": [
{ {
"name": "Ely.by team", "name": "Ely.by team",
@ -13,14 +17,20 @@
"email": "erickskrauch@ely.by" "email": "erickskrauch@ely.by"
} }
], ],
"license": "Apache-2.0", "homepage": "https://github.com/elyby/php-code-style",
"type": "library",
"require": { "require": {
"php": "^7.0|^8.0", "php": "^7.4 || ^8.0",
"friendsofphp/php-cs-fixer": "^2.15.0" "friendsofphp/php-cs-fixer": "^3"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.5.1" "ergebnis/composer-normalize": "^2.28",
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2",
"phpspec/prophecy": "^1.15",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"phpunitgoodpractices/polyfill": "^1.5",
"phpunitgoodpractices/traits": "^1.9.1",
"symfony/phpunit-bridge": "^6.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -29,12 +39,16 @@
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"Ely\\CS\\Test\\": "tests/" "Ely\\CS\\Test\\": "tests/",
"PhpCsFixer\\Tests\\": "vendor/friendsofphp/php-cs-fixer/tests/"
} }
}, },
"config": { "config": {
"platform": { "allow-plugins": {
"php": "7.0.8" "ergebnis/composer-normalize": true
},
"preferred-install": {
"friendsofphp/php-cs-fixer": "source"
} }
} }
} }

3329
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -3,34 +3,25 @@
<phpunit <phpunit
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
beStrictAboutChangesToGlobalState="true" beStrictAboutChangesToGlobalState="true"
beStrictAboutOutputDuringTests="true" beStrictAboutOutputDuringTests="true"
beStrictAboutTestSize="true"
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutTodoAnnotatedTests="true" beStrictAboutTodoAnnotatedTests="true"
bootstrap="./vendor/autoload.php" bootstrap="./vendor/autoload.php"
colors="true" colors="true"
columns="max" columns="max"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
verbose="true" verbose="true"
> >
<testsuites> <testsuites>
<testsuite> <testsuite name="all">
<directory>./tests</directory> <directory>./tests</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter> <coverage>
<whitelist> <include>
<directory>./src</directory> <directory>./src</directory>
</whitelist> </include>
</filter> </coverage>
<php> <php>
<ini name="zend.enable_gc" value="0"/> <ini name="zend.enable_gc" value="0"/>

View File

@ -8,7 +8,7 @@ use PhpCsFixer\Config as PhpCsFixerConfig;
class Config { class Config {
public static function create(array $overwrittenRules = []): PhpCsFixerConfig { public static function create(array $overwrittenRules = []): PhpCsFixerConfig {
return PhpCsFixerConfig::create() return (new PhpCsFixerConfig())
->setRiskyAllowed(true) ->setRiskyAllowed(true)
->registerCustomFixers(new Fixers()) ->registerCustomFixers(new Fixers())
->setRules(Rules::create($overwrittenRules)); ->setRules(Rules::create($overwrittenRules));

View File

@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace Ely\CS\Fixer; namespace Ely\CS\Fixer;
abstract class AbstractFixer extends \PhpCsFixer\AbstractFixer { abstract class AbstractFixer extends \PhpCsFixer\AbstractFixer {
@ -6,7 +8,7 @@ abstract class AbstractFixer extends \PhpCsFixer\AbstractFixer {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getName() { public function getName(): string {
return sprintf('Ely/%s', parent::getName()); return sprintf('Ely/%s', parent::getName());
} }

View File

@ -6,6 +6,7 @@ namespace Ely\CS\Fixer\LanguageConstruct;
use Ely\CS\Fixer\AbstractFixer; use Ely\CS\Fixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\Tokens;
@ -18,10 +19,7 @@ use SplFileInfo;
*/ */
final class RemoveClassNameMethodUsagesFixer extends AbstractFixer { final class RemoveClassNameMethodUsagesFixer extends AbstractFixer {
/** public function getDefinition(): FixerDefinitionInterface {
* @inheritdoc
*/
public function getDefinition() {
return new FixerDefinition( return new FixerDefinition(
'Converts Yii2 `BaseObject::className()` method usage into `::class` keyword.', 'Converts Yii2 `BaseObject::className()` method usage into `::class` keyword.',
[ [
@ -31,30 +29,23 @@ final class RemoveClassNameMethodUsagesFixer extends AbstractFixer {
use Foo\Bar\Baz; use Foo\Bar\Baz;
$className = Baz::className(); $className = Baz::className();
' ',
), ),
] ],
null,
'Risky when the method `className()` is overridden.',
); );
} }
/** public function isCandidate(Tokens $tokens): bool {
* @inheritdoc
*/
public function isCandidate(Tokens $tokens) {
return $tokens->isTokenKindFound(T_STRING); return $tokens->isTokenKindFound(T_STRING);
} }
/** public function isRisky(): bool {
* {@inheritdoc}
*/
public function isRisky() {
return true; return true;
} }
/** protected function applyFix(SplFileInfo $file, Tokens $tokens): void {
* {@inheritdoc}
*/
protected function applyFix(SplFileInfo $file, Tokens $tokens) {
for ($index = $tokens->count() - 4; $index > 0; --$index) { for ($index = $tokens->count() - 4; $index > 0; --$index) {
$candidate = $this->getReplaceCandidate($tokens, $index); $candidate = $this->getReplaceCandidate($tokens, $index);
if ($candidate === null) { if ($candidate === null) {
@ -65,18 +56,12 @@ $className = Baz::className();
$tokens, $tokens,
$index, $index,
$candidate[0], // brace open $candidate[0], // brace open
$candidate[1] // brace close $candidate[1], // brace close
); );
} }
} }
/** private function getReplaceCandidate(Tokens $tokens, int $index): ?array {
* @param Tokens $tokens
* @param int $index
*
* @return null|array
*/
private function getReplaceCandidate(Tokens $tokens, $index) {
if (!$tokens[$index]->isGivenKind(T_STRING)) { if (!$tokens[$index]->isGivenKind(T_STRING)) {
return null; return null;
} }
@ -107,13 +92,12 @@ $className = Baz::className();
]; ];
} }
/** private function fixClassNameMethodUsage(
* @param Tokens $tokens Tokens $tokens,
* @param int $index int $index,
* @param int $braceOpenIndex int $braceOpenIndex,
* @param int $braceCloseIndex int $braceCloseIndex
*/ ): void {
private function fixClassNameMethodUsage(Tokens $tokens, int $index, int $braceOpenIndex, int $braceCloseIndex) {
$tokens->clearTokenAndMergeSurroundingWhitespace($braceCloseIndex); $tokens->clearTokenAndMergeSurroundingWhitespace($braceCloseIndex);
$tokens->clearTokenAndMergeSurroundingWhitespace($braceOpenIndex); $tokens->clearTokenAndMergeSurroundingWhitespace($braceOpenIndex);
$tokens->clearAt($index); $tokens->clearAt($index);

View File

@ -1,179 +0,0 @@
<?php
declare(strict_types=1);
namespace Ely\CS\Fixer\Operator;
use Ely\CS\Fixer\AbstractFixer;
use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
/**
* This is the extended version of the original new_with_braces fixer.
* It allows you to remove braces around an anonymous class declaration in a case
* when said class constructor doesn't contain any arguments.
*
* @url https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/5c5de791ab/src/Fixer/Operator/NewWithBracesFixer.php
*
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
*/
final class NewWithBracesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface {
/**
* {@inheritdoc}
*/
public function getDefinition() {
return new FixerDefinition(
'All instances created with new keyword must be followed by braces.',
[
new CodeSample("<?php \$x = new X;\n"),
]
);
}
/**
* {@inheritdoc}
*/
public function isCandidate(Tokens $tokens) {
return $tokens->isTokenKindFound(T_NEW);
}
/**
* {@inheritdoc}
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens) {
static $nextTokenKinds = null;
if ($nextTokenKinds === null) {
$nextTokenKinds = [
'?',
';',
',',
'(',
')',
'[',
']',
':',
'<',
'>',
'+',
'-',
'*',
'/',
'%',
'&',
'^',
'|',
[T_CLASS],
[T_IS_SMALLER_OR_EQUAL],
[T_IS_GREATER_OR_EQUAL],
[T_IS_EQUAL],
[T_IS_NOT_EQUAL],
[T_IS_IDENTICAL],
[T_IS_NOT_IDENTICAL],
[T_CLOSE_TAG],
[T_LOGICAL_AND],
[T_LOGICAL_OR],
[T_LOGICAL_XOR],
[T_BOOLEAN_AND],
[T_BOOLEAN_OR],
[T_SL],
[T_SR],
[T_INSTANCEOF],
[T_AS],
[T_DOUBLE_ARROW],
[T_POW],
[CT::T_ARRAY_SQUARE_BRACE_OPEN],
[CT::T_ARRAY_SQUARE_BRACE_CLOSE],
[CT::T_BRACE_CLASS_INSTANTIATION_OPEN],
[CT::T_BRACE_CLASS_INSTANTIATION_CLOSE],
];
if (defined('T_SPACESHIP')) {
$nextTokenKinds[] = [T_SPACESHIP];
}
}
for ($index = $tokens->count() - 3; $index > 0; --$index) {
$token = $tokens[$index];
if (!$token->isGivenKind(T_NEW)) {
continue;
}
$nextIndex = $tokens->getNextTokenOfKind($index, $nextTokenKinds);
$nextToken = $tokens[$nextIndex];
// new anonymous class definition
if ($nextToken->isGivenKind(T_CLASS)) {
if ($this->configuration['remove_for_anonymous_classes']) {
$nextTokenIndex = $tokens->getNextMeaningfulToken($nextIndex);
$nextNextTokenIndex = $tokens->getNextMeaningfulToken($nextTokenIndex);
if ($tokens[$nextTokenIndex]->equals('(') && $tokens[$nextNextTokenIndex]->equals(')')) {
$this->removeBracesAfter($tokens, $nextIndex);
}
} else {
if (!$tokens[$tokens->getNextMeaningfulToken($nextIndex)]->equals('(')) {
$this->insertBracesAfter($tokens, $nextIndex);
}
}
continue;
}
// entrance into array index syntax - need to look for exit
while ($nextToken->equals('[')) {
$nextIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $nextIndex) + 1;
$nextToken = $tokens[$nextIndex];
}
// new statement has a gap in it - advance to the next token
if ($nextToken->isWhitespace()) {
$nextIndex = $tokens->getNextNonWhitespace($nextIndex);
$nextToken = $tokens[$nextIndex];
}
// new statement with () - nothing to do
if ($nextToken->equals('(')) {
continue;
}
$this->insertBracesAfter($tokens, $tokens->getPrevMeaningfulToken($nextIndex));
}
}
/**
* {@inheritdoc}
*/
protected function createConfigurationDefinition() {
return new FixerConfigurationResolver([
(new FixerOptionBuilder('remove_for_anonymous_classes', 'when enabled will remove braces around an anonymous class declaration in a case when constructor doesn\'t contain any arguments'))
->setAllowedTypes(['bool'])
->setDefault(false)
->getOption(),
]);
}
/**
* @param Tokens $tokens
* @param int $index
*/
private function insertBracesAfter(Tokens $tokens, $index) {
$tokens->insertAt(++$index, [new Token('('), new Token(')')]);
}
/**
* @param Tokens $tokens
* @param int $index
*/
private function removeBracesAfter(Tokens $tokens, int $index) {
$tokens->clearRange(
$tokens->getNextTokenOfKind($index, ['(']),
$tokens->getNextTokenOfKind($index, [')'])
);
}
}

View File

@ -4,12 +4,14 @@ declare(strict_types=1);
namespace Ely\CS\Fixer\Whitespace; namespace Ely\CS\Fixer\Whitespace;
use Ely\CS\Fixer\AbstractFixer; use Ely\CS\Fixer\AbstractFixer;
use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Preg; use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\Tokens;
@ -20,12 +22,9 @@ use PhpCsFixer\Tokenizer\TokensAnalyzer;
* *
* @author ErickSkrauch <erickskrauch@ely.by> * @author ErickSkrauch <erickskrauch@ely.by>
*/ */
final class BlankLineAroundClassBodyFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface { final class BlankLineAroundClassBodyFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface {
/** public function getDefinition(): FixerDefinitionInterface {
* {@inheritdoc}
*/
public function getDefinition() {
return new FixerDefinition( return new FixerDefinition(
'Ensure that class body contains one blank line after class definition and before its end.', 'Ensure that class body contains one blank line after class definition and before its end.',
[ [
@ -37,7 +36,7 @@ class Sample
{ {
} }
} }
' ',
), ),
new CodeSample( new CodeSample(
'<?php '<?php
@ -49,7 +48,7 @@ new class extends Foo {
}; };
', ',
['apply_to_anonymous_classes' => false] ['apply_to_anonymous_classes' => false],
), ),
new CodeSample( new CodeSample(
'<?php '<?php
@ -59,31 +58,22 @@ new class extends Foo {
} }
}; };
', ',
['apply_to_anonymous_classes' => true] ['apply_to_anonymous_classes' => true],
), ),
] ],
); );
} }
/** public function getPriority(): int {
* {@inheritdoc}
*/
public function getPriority() {
// should be run after the BracesFixer // should be run after the BracesFixer
return -26; return -26;
} }
/** public function isCandidate(Tokens $tokens): bool {
* {@inheritdoc}
*/
public function isCandidate(Tokens $tokens) {
return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds());
} }
/** protected function applyFix(\SplFileInfo $file, Tokens $tokens): void {
* {@inheritdoc}
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens) {
$analyzer = new TokensAnalyzer($tokens); $analyzer = new TokensAnalyzer($tokens);
foreach ($tokens as $index => $token) { foreach ($tokens as $index => $token) {
if (!$token->isClassy()) { if (!$token->isClassy()) {
@ -111,10 +101,7 @@ new class extends Foo {
} }
} }
/** protected function createConfigurationDefinition(): FixerConfigurationResolverInterface {
* {@inheritdoc}
*/
protected function createConfigurationDefinition() {
return new FixerConfigurationResolver([ return new FixerConfigurationResolver([
(new FixerOptionBuilder('blank_lines_count', 'adjusts an amount of the blank lines.')) (new FixerOptionBuilder('blank_lines_count', 'adjusts an amount of the blank lines.'))
->setAllowedTypes(['int']) ->setAllowedTypes(['int'])
@ -127,14 +114,7 @@ new class extends Foo {
]); ]);
} }
/** private function fixBlankLines(Tokens $tokens, int $index, int $countLines): void {
* Cleanup a whitespace token.
*
* @param Tokens $tokens
* @param int $index
* @param int $countLines
*/
private function fixBlankLines(Tokens $tokens, $index, $countLines) {
$content = $tokens[$index]->getContent(); $content = $tokens[$index]->getContent();
// Apply fix only in the case when the count lines do not equals to expected // Apply fix only in the case when the count lines do not equals to expected
if (substr_count($content, "\n") === $countLines + 1) { if (substr_count($content, "\n") === $countLines + 1) {

View File

@ -7,6 +7,7 @@ use Ely\CS\Fixer\AbstractFixer;
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\Tokens;
use SplFileInfo; use SplFileInfo;
@ -23,35 +24,23 @@ use SplFileInfo;
*/ */
final class BlankLineBeforeReturnFixer extends AbstractFixer implements WhitespacesAwareFixerInterface { final class BlankLineBeforeReturnFixer extends AbstractFixer implements WhitespacesAwareFixerInterface {
/** public function getDefinition(): FixerDefinitionInterface {
* {@inheritdoc}
*/
public function getDefinition() {
return new FixerDefinition( return new FixerDefinition(
'An empty line feed should precede a return statement.', 'An empty line feed should precede a return statement.',
[new CodeSample("<?php\nfunction A()\n{\n echo 1;\n return 1;\n}\n")] [new CodeSample("<?php\nfunction A()\n{\n echo 1;\n echo 2;\n return 1;\n}\n")],
); );
} }
/** public function isCandidate(Tokens $tokens): bool {
* @inheritdoc
*/
public function isCandidate(Tokens $tokens) {
return $tokens->isTokenKindFound(T_RETURN); return $tokens->isTokenKindFound(T_RETURN);
} }
/** public function getPriority(): int {
* {@inheritdoc}
*/
public function getPriority() {
// should be run after NoUselessReturnFixer, ClassDefinitionFixer and BracesFixer // should be run after NoUselessReturnFixer, ClassDefinitionFixer and BracesFixer
return -26; return -26;
} }
/** protected function applyFix(SplFileInfo $file, Tokens $tokens): void {
* @inheritdoc
*/
protected function applyFix(SplFileInfo $file, Tokens $tokens) {
for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) {
$token = $tokens[$index]; $token = $tokens[$index];
if (!$token->isGivenKind(T_RETURN)) { if (!$token->isGivenKind(T_RETURN)) {
@ -93,7 +82,7 @@ final class BlankLineBeforeReturnFixer extends AbstractFixer implements Whitespa
} }
} }
} else { } else {
$tokens->insertAt($index, new Token([T_WHITESPACE, $eol . $eol])); $tokens->insertSlices([$index => new Token([T_WHITESPACE, $eol . $eol])]);
++$index; ++$index;
++$limit; ++$limit;
} }

View File

@ -7,6 +7,7 @@ use Ely\CS\Fixer\AbstractFixer;
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
use PhpCsFixer\FixerDefinition\CodeSample; use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Preg; use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\Tokens;
@ -25,7 +26,7 @@ final class LineBreakAfterStatementsFixer extends AbstractFixer implements White
/** /**
* There is no 'do', 'cause the processing of the 'while' also includes do {} while (); construction * There is no 'do', 'cause the processing of the 'while' also includes do {} while (); construction
*/ */
const STATEMENTS = [ public const STATEMENTS = [
T_IF, T_IF,
T_SWITCH, T_SWITCH,
T_FOR, T_FOR,
@ -33,12 +34,9 @@ final class LineBreakAfterStatementsFixer extends AbstractFixer implements White
T_WHILE, T_WHILE,
]; ];
/** public function getDefinition(): FixerDefinitionInterface {
* @inheritdoc
*/
public function getDefinition() {
return new FixerDefinition( return new FixerDefinition(
'Ensures that there is one blank line above the control statements', 'Ensures that there is one blank line above the control statements.',
[ [
new CodeSample( new CodeSample(
'<?php '<?php
@ -73,28 +71,22 @@ class Foo
$a = "next statement"; $a = "next statement";
} }
} }
' ',
), ),
] ],
); );
} }
/** public function isCandidate(Tokens $tokens): bool {
* @inheritdoc
*/
public function isCandidate(Tokens $tokens) {
return $tokens->isAnyTokenKindsFound(self::STATEMENTS); return $tokens->isAnyTokenKindsFound(self::STATEMENTS);
} }
/** public function getPriority(): int {
* {@inheritdoc}
*/
public function getPriority() {
// for the best result should be run after the BracesFixer // for the best result should be run after the BracesFixer
return -26; return -26;
} }
protected function applyFix(SplFileInfo $file, Tokens $tokens) { protected function applyFix(SplFileInfo $file, Tokens $tokens): void {
foreach ($tokens as $index => $token) { foreach ($tokens as $index => $token) {
if (!$token->isGivenKind(self::STATEMENTS)) { if (!$token->isGivenKind(self::STATEMENTS)) {
continue; continue;
@ -115,7 +107,7 @@ class Foo
} }
} }
private function fixBlankLines(Tokens $tokens, $index, $countLines) { private function fixBlankLines(Tokens $tokens, int $index, int $countLines): void {
$content = $tokens[$index]->getContent(); $content = $tokens[$index]->getContent();
// Apply fix only in the case when the count lines do not equals to expected // Apply fix only in the case when the count lines do not equals to expected
if (substr_count($content, "\n") === $countLines + 1) { if (substr_count($content, "\n") === $countLines + 1) {

View File

@ -22,7 +22,6 @@ class Fixers implements IteratorAggregate {
continue; continue;
} }
/** @noinspection PhpUnhandledExceptionInspection */
$rfl = new ReflectionClass($class); $rfl = new ReflectionClass($class);
if (!$rfl->implementsInterface(FixerInterface::class) || $rfl->isAbstract()) { if (!$rfl->implementsInterface(FixerInterface::class) || $rfl->isAbstract()) {
continue; continue;
@ -31,9 +30,7 @@ class Fixers implements IteratorAggregate {
$classes[] = $class; $classes[] = $class;
} }
return new ArrayIterator(array_map(function($class) { return new ArrayIterator(array_map(fn($class) => new $class(), $classes));
return new $class();
}, $classes));
} }
} }

View File

@ -5,95 +5,15 @@ namespace Ely\CS;
class Rules { class Rules {
private static $rules = [ public static function create(array $overwrittenRules = []): array {
return array_merge([
'@PSR2' => true, '@PSR2' => true,
'array_indentation' => true,
'array_syntax' => [ // Alias
'syntax' => 'short',
],
'binary_operator_spaces' => true,
'braces' => [
'position_after_functions_and_oop_constructs' => 'same',
],
'cast_spaces' => [
'space' => 'none',
],
'class_attributes_separation' => [
'elements' => ['method', 'property'],
],
'combine_consecutive_issets' => true,
'combine_nested_dirname' => true,
'compact_nullable_typehint' => true,
'concat_space' => [
'spacing' => 'one',
],
'declare_equal_normalize' => true,
'dir_constant' => true,
'ereg_to_preg' => true, 'ereg_to_preg' => true,
'explicit_string_variable' => true, // Should be configurable to choose between ${var} and {$var} 'modernize_strpos' => PHP_MAJOR_VERSION >= 8,
'function_declaration' => [
'closure_function_spacing' => 'none',
],
'function_to_constant' => true,
'implode_call' => true,
'include' => true,
'is_null' => true,
'linebreak_after_opening_tag' => true,
'list_syntax' => [
'syntax' => 'short',
],
'logical_operators' => true,
'lowercase_cast' => true,
'lowercase_static_reference' => true,
'magic_constant_casing' => true,
'magic_method_casing' => true,
'method_chaining_indentation' => true,
'modernize_types_casting' => true,
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'native_function_casing' => true,
'native_function_type_declaration_casing' => true,
'no_alternative_syntax' => true,
'no_homoglyph_names' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_mixed_echo_print' => true, 'no_mixed_echo_print' => true,
'no_multiline_whitespace_around_double_arrow' => true,
'no_php4_constructor' => true,
'no_short_bool_cast' => true,
'no_spaces_around_offset' => true,
'no_superfluous_elseif' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_unneeded_control_parentheses' => true,
'no_unneeded_final_method' => true,
'no_unused_imports' => true,
'no_useless_else' => true,
'no_useless_return' => true,
'no_whitespace_before_comma_in_array' => true,
'no_whitespace_in_blank_line' => true,
'non_printable_character' => [
'use_escape_sequences_in_strings' => true,
],
'normalize_index_brace' => true,
'object_operator_without_whitespace' => true,
'ordered_class_elements' => true,
'ordered_imports' => [
'imports_order' => ['class', 'function', 'const'],
],
'php_unit_construct' => true,
'php_unit_dedicate_assert_internal_type' => true,
'php_unit_expectation' => true,
'php_unit_method_casing' => true,
'php_unit_mock' => true,
'php_unit_mock_short_will_return' => true,
'php_unit_namespaced' => true,
'php_unit_no_expectation_annotation' => true,
'php_unit_set_up_tear_down_visibility' => true,
'php_unit_strict' => true,
'pow_to_exponentiation' => true, 'pow_to_exponentiation' => true,
'psr4' => true,
'return_assignment' => true,
'random_api_migration' => [ 'random_api_migration' => [
'replacements' => [ 'replacements' => [
'getrandmax' => 'mt_getrandmax', 'getrandmax' => 'mt_getrandmax',
@ -101,41 +21,205 @@ class Rules {
'srand' => 'mt_srand', 'srand' => 'mt_srand',
], ],
], ],
'return_type_declaration' => [
'space_before' => 'none',
],
'set_type_to_cast' => true, 'set_type_to_cast' => true,
// Array Notation
'array_syntax' => [
'syntax' => 'short',
],
'no_multiline_whitespace_around_double_arrow' => true,
'no_whitespace_before_comma_in_array' => true,
'normalize_index_brace' => true,
'trim_array_spaces' => true,
'whitespace_after_comma_in_array' => true,
// Basic
'braces' => [
'allow_single_line_anonymous_class_with_empty_body' => true,
'position_after_functions_and_oop_constructs' => 'same',
],
'no_multiple_statements_per_line' => true,
'no_trailing_comma_in_singleline' => true,
'non_printable_character' => [
'use_escape_sequences_in_strings' => true,
],
'octal_notation' => PHP_MAJOR_VERSION >= 8 && PHP_MINOR_VERSION >= 1,
'psr_autoloading' => true,
// Casing
'class_reference_name_casing' => true,
'integer_literal_case' => true,
'lowercase_static_reference' => true,
'magic_constant_casing' => true,
'magic_method_casing' => true,
'native_function_casing' => true,
'native_function_type_declaration_casing' => true,
// Cast Notation
'cast_spaces' => [
'space' => 'none',
],
'lowercase_cast' => true,
'modernize_types_casting' => true,
'no_short_bool_cast' => true,
'no_unset_cast' => true,
'short_scalar_cast' => true, 'short_scalar_cast' => true,
'simple_to_complex_string_variable' => true,
// Class Notation
'class_attributes_separation' => [
'elements' => [
'method' => 'one',
'property' => 'one',
'const' => 'only_if_meta', // TODO: check on the real code base
],
],
'no_null_property_initialization' => true, // TODO: check against yii2 default overrides
'no_php4_constructor' => true,
'no_unneeded_final_method' => true,
'ordered_class_elements' => true,
'single_trait_insert_per_statement' => true, 'single_trait_insert_per_statement' => true,
'single_quote' => true, 'visibility_required' => true,
'space_after_semicolon' => true,
// Comment
'comment_to_phpdoc' => true,
'multiline_comment_opening_closing' => true,
'no_empty_comment' => true,
'single_line_comment_spacing' => true,
'single_line_comment_style' => true,
// Control Structure
'empty_loop_body' => true,
'empty_loop_condition' => true,
'include' => true,
'no_alternative_syntax' => true,
'no_superfluous_elseif' => true,
'no_unneeded_control_parentheses' => true,
'no_useless_else' => true,
'switch_continue_to_break' => true,
'trailing_comma_in_multiline' => [
'elements' => PHP_MAJOR_VERSION >= 8
? ['arrays', 'arguments', 'parameters', 'match']
: ['arrays', 'parameters'],
],
'yoda_style' => [
'equal' => false,
'identical' => false,
'less_and_greater' => false,
],
// Function Notation
'combine_nested_dirname' => true,
'function_declaration' => [
'closure_function_spacing' => 'none',
],
'function_typehint_space' => true,
'implode_call' => true,
'lambda_not_used_import' => true,
'return_type_declaration' => true,
// Import
'no_leading_import_slash' => true,
'no_unneeded_import_alias' => true,
'no_unused_imports' => true,
'ordered_imports' => [
'imports_order' => ['class', 'function', 'const'],
],
// Language Construct
'combine_consecutive_issets' => true,
'combine_consecutive_unsets' => true,
'declare_equal_normalize' => true,
'declare_parentheses' => true,
'dir_constant' => true,
'function_to_constant' => true,
'is_null' => true,
// List Notation
'list_syntax' => true,
// Namespace Notation
'clean_namespace' => true,
'no_leading_namespace_whitespace' => true,
// Naming
'no_homoglyph_names' => true,
// Operator
'assign_null_coalescing_to_coalesce_equal' => true,
'binary_operator_spaces' => true,
'concat_space' => [
'spacing' => 'one',
],
'logical_operators' => true,
'new_with_braces' => [
'anonymous_class' => false,
],
'no_useless_nullsafe_operator' => true,
'object_operator_without_whitespace' => true,
'operator_linebreak' => true,
'standardize_increment' => true, 'standardize_increment' => true,
'standardize_not_equals' => true, 'standardize_not_equals' => true,
'strict_comparison' => true,
'ternary_operator_spaces' => true, 'ternary_operator_spaces' => true,
'ternary_to_null_coalescing' => true, 'ternary_to_null_coalescing' => true,
'trailing_comma_in_multiline_array' => true,
'trim_array_spaces' => true,
'unary_operator_spaces' => true, 'unary_operator_spaces' => true,
'visibility_required' => [
'elements' => ['property', 'method', 'const'], // PHP Tag
'linebreak_after_opening_tag' => true,
// PHPUnit
'php_unit_construct' => true,
'php_unit_dedicate_assert_internal_type' => true,
'php_unit_expectation' => true,
'php_unit_fqcn_annotation' => true,
'php_unit_method_casing' => true,
'php_unit_mock' => true,
'php_unit_mock_short_will_return' => true,
'php_unit_namespaced' => true,
'php_unit_no_expectation_annotation' => true,
'php_unit_set_up_tear_down_visibility' => true,
'php_unit_strict' => true,
'php_unit_test_case_static_method_calls' => [
'call_type' => 'this',
], ],
'whitespace_after_comma_in_array' => true,
// Return Notation
'no_useless_return' => true,
'return_assignment' => true,
'simplified_null_return' => true,
// Semicolon
'multiline_whitespace_before_semicolons' => true,
'no_empty_statement' => true,
'no_singleline_whitespace_before_semicolons' => true,
'semicolon_after_instruction' => true,
'space_after_semicolon' => true,
// Strict
'strict_comparison' => true,
// String notation
'explicit_string_variable' => true,
'simple_to_complex_string_variable' => true,
'single_quote' => true,
// Whitespace
'array_indentation' => true,
'compact_nullable_typehint' => true,
'method_chaining_indentation' => true,
'no_spaces_around_offset' => true,
'no_whitespace_in_blank_line' => true,
'types_spaces' => [
'space_multiple_catch' => 'none',
],
// Our custom or extended fixers // Our custom or extended fixers
'Ely/blank_line_around_class_body' => [ 'Ely/blank_line_around_class_body' => [
'apply_to_anonymous_classes' => false, 'apply_to_anonymous_classes' => false,
], ],
'Ely/blank_line_before_return' => true, 'Ely/blank_line_before_return' => true,
'Ely/line_break_after_statements' => true, 'Ely/line_break_after_statements' => true,
'Ely/new_with_braces' => [
'remove_for_anonymous_classes' => true,
],
'Ely/remove_class_name_method_usages' => true, 'Ely/remove_class_name_method_usages' => true,
]; ], $overwrittenRules);
public static function create(array $overwrittenRules = []): array {
return array_merge(self::$rules, $overwrittenRules);
} }
} }

View File

@ -1,9 +1,10 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Ely\CS\Test\Fixer\Operator; namespace Ely\CS\Test\Fixer\LanguageConstruct;
use Ely\CS\Fixer\LanguageConstruct\RemoveClassNameMethodUsagesFixer; use Ely\CS\Fixer\LanguageConstruct\RemoveClassNameMethodUsagesFixer;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
/** /**
@ -12,28 +13,26 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
class RemoveClassNameMethodUsagesFixerTest extends AbstractFixerTestCase { class RemoveClassNameMethodUsagesFixerTest extends AbstractFixerTestCase {
/** /**
* @param string $expected
* @param null|string $input
*
* @dataProvider provideFixCases * @dataProvider provideFixCases
*/ */
public function testFix($expected, $input = null) { public function testFix(string $expected, ?string $input = null): void {
$this->doTest($expected, $input); $this->doTest($expected, $input);
} }
public function provideFixCases() { public function provideFixCases(): iterable {
return [ yield [
[
'<?php echo className();', '<?php echo className();',
], ];
[
yield [
'<?php '<?php
use Foo\Bar\Baz; use Foo\Bar\Baz;
$exceptionString = Baz::classname(); $exceptionString = Baz::classname();
', ',
], ];
[
yield [
'<?php '<?php
use Foo\Bar\Baz; use Foo\Bar\Baz;
@ -44,8 +43,9 @@ use Foo\Bar\Baz;
$className = Baz::className(); $className = Baz::className();
', ',
], ];
[
yield [
'<?php '<?php
use Foo\Bar\Baz; use Foo\Bar\Baz;
@ -56,11 +56,10 @@ use Foo\Bar\Baz;
$exceptionString = "The class should be instance of " . Baz::className() . " and nothing else"; $exceptionString = "The class should be instance of " . Baz::className() . " and nothing else";
', ',
],
]; ];
} }
protected function createFixer() { protected function createFixer(): AbstractFixer {
return new RemoveClassNameMethodUsagesFixer(); return new RemoveClassNameMethodUsagesFixer();
} }

View File

@ -1,319 +0,0 @@
<?php
declare(strict_types=1);
namespace Ely\CS\Test\Fixer\Operator;
use Ely\CS\Fixer\Operator\NewWithBracesFixer;
use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
/**
* Original file copied from:
* @url https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/5c5de791ab/tests/Fixer/Operator/NewWithBracesFixerTest.php
*
* @covers \Ely\CS\Fixer\Operator\NewWithBracesFixer
*/
class NewWithBracesFixerTest extends AbstractFixerTestCase {
private static $removeForAnonymousClasses = ['remove_for_anonymous_classes' => true];
/**
* @param string $expected
* @param null|string $input
*
* @dataProvider provideFixCases
*/
public function testFix($expected, $input = null) {
$this->doTest($expected, $input);
}
/**
* @param string $expected
* @param null|string $input
*
* @dataProvider provideFix70Cases
* @requires PHP 7.0
*/
public function testFix70($expected, $input = null, array $configuration = null) {
if ($configuration !== null) {
$this->fixer->configure($configuration);
}
$this->doTest($expected, $input);
}
public function provideFixCases() {
return [
[
'<?php class A { public function B(){ $static = new static(new \SplFileInfo(__FILE__)); }}',
],
[
'<?php $static = new self(new \SplFileInfo(__FILE__));',
],
[
'<?php $x = new X/**/ /**/ /**//**//**/ /**//**/ (/**/ /**/ /**//**//**/ /**//**/)/**/ /**/ /**//**//**/ /**//**/;/**/ /**/ /**//**//**/ /**//**/',
],
[
'<?php $x = new X();',
'<?php $x = new X;',
],
[
'<?php $y = new Y() ;',
'<?php $y = new Y ;',
],
[
'<?php $x = new Z() /**/;//',
'<?php $x = new Z /**/;//',
],
[
'<?php $foo = new $foo();',
'<?php $foo = new $foo;',
],
[
'<?php $xyz = new X(new Y(new Z()));',
'<?php $xyz = new X(new Y(new Z));',
],
[
'<?php $foo = (new $bar())->foo;',
'<?php $foo = (new $bar)->foo;',
],
[
'<?php $foo = (new $bar((new Foo())->bar))->foo;',
'<?php $foo = (new $bar((new Foo)->bar))->foo;',
],
[
'<?php $self = new self();',
'<?php $self = new self;',
],
[
'<?php $static = new static();',
'<?php $static = new static;',
],
[
'<?php $a = array( "key" => new DateTime(), );',
'<?php $a = array( "key" => new DateTime, );',
],
[
'<?php $a = array( "key" => new DateTime() );',
'<?php $a = array( "key" => new DateTime );',
],
[
'<?php $a = new $b[$c]();',
'<?php $a = new $b[$c];',
],
[
'<?php $a = new $b[$c[$d ? foo() : bar("bar[...]") - 1]]();',
'<?php $a = new $b[$c[$d ? foo() : bar("bar[...]") - 1]];',
],
[
'<?php $a = new $b[\'class\']();',
'<?php $a = new $b[\'class\'];',
],
[
'<?php $a = new $b[\'class\'] ($foo[\'bar\']);',
],
[
'<?php $a = new $b[\'class\'] () ;',
],
[
'<?php $a = new $b[$c] ($hello[$world]) ;',
],
[
"<?php \$a = new \$b['class']()\r\n\t ;",
"<?php \$a = new \$b['class']\r\n\t ;",
],
[
'<?php $a = $b ? new DateTime() : $b;',
'<?php $a = $b ? new DateTime : $b;',
],
[
'<?php new self::$adapters[$name]["adapter"]();',
'<?php new self::$adapters[$name]["adapter"];',
],
[
'<?php $a = new \Exception()?> <?php echo 1;',
'<?php $a = new \Exception?> <?php echo 1;',
],
[
'<?php $b = new \StdClass() /**/?>',
'<?php $b = new \StdClass /**/?>',
],
[
'<?php $a = new Foo() instanceof Foo;',
'<?php $a = new Foo instanceof Foo;',
],
[
'<?php
$a = new Foo() + 1;
$a = new Foo() - 1;
$a = new Foo() * 1;
$a = new Foo() / 1;
$a = new Foo() % 1;
',
'<?php
$a = new Foo + 1;
$a = new Foo - 1;
$a = new Foo * 1;
$a = new Foo / 1;
$a = new Foo % 1;
',
],
[
'<?php
$a = new Foo() & 1;
$a = new Foo() | 1;
$a = new Foo() ^ 1;
$a = new Foo() << 1;
$a = new Foo() >> 1;
',
'<?php
$a = new Foo & 1;
$a = new Foo | 1;
$a = new Foo ^ 1;
$a = new Foo << 1;
$a = new Foo >> 1;
',
],
[
'<?php
$a = new Foo() and 1;
$a = new Foo() or 1;
$a = new Foo() xor 1;
$a = new Foo() && 1;
$a = new Foo() || 1;
',
'<?php
$a = new Foo and 1;
$a = new Foo or 1;
$a = new Foo xor 1;
$a = new Foo && 1;
$a = new Foo || 1;
',
],
[
'<?php
if (new DateTime() > $this->startDate) {}
if (new DateTime() >= $this->startDate) {}
if (new DateTime() < $this->startDate) {}
if (new DateTime() <= $this->startDate) {}
if (new DateTime() == $this->startDate) {}
if (new DateTime() != $this->startDate) {}
if (new DateTime() <> $this->startDate) {}
if (new DateTime() === $this->startDate) {}
if (new DateTime() !== $this->startDate) {}
',
'<?php
if (new DateTime > $this->startDate) {}
if (new DateTime >= $this->startDate) {}
if (new DateTime < $this->startDate) {}
if (new DateTime <= $this->startDate) {}
if (new DateTime == $this->startDate) {}
if (new DateTime != $this->startDate) {}
if (new DateTime <> $this->startDate) {}
if (new DateTime === $this->startDate) {}
if (new DateTime !== $this->startDate) {}
',
],
[
'<?php $a = new \stdClass() ? $b : $c;',
'<?php $a = new \stdClass ? $b : $c;',
],
[
'<?php foreach (new Collection() as $x) {}',
'<?php foreach (new Collection as $x) {}',
],
[
'<?php $a = [(string) new Foo() => 1];',
'<?php $a = [(string) new Foo => 1];',
],
[
'<?php $a = [ "key" => new DateTime(), ];',
'<?php $a = [ "key" => new DateTime, ];',
],
[
'<?php $a = [ "key" => new DateTime() ];',
'<?php $a = [ "key" => new DateTime ];',
],
[
'<?php
$a = new Foo() ** 1;
',
'<?php
$a = new Foo ** 1;
',
],
];
}
public function provideFix70Cases() {
return [
[
'<?php
$a = new Foo() <=> 1;
',
'<?php
$a = new Foo <=> 1;
',
],
[
'<?php
$a = new class() {use SomeTrait;};
$a = new class() implements Foo{};
$a = new class() /**/ extends Bar1{};
$a = new class() extends Bar2 implements Foo{};
$a = new class() extends Bar3 implements Foo, Foo2{};
$a = new class() {}?>
',
'<?php
$a = new class {use SomeTrait;};
$a = new class implements Foo{};
$a = new class /**/ extends Bar1{};
$a = new class extends Bar2 implements Foo{};
$a = new class extends Bar3 implements Foo, Foo2{};
$a = new class {}?>
',
],
[
'<?php
class A {
public function B() {
$static = new static(new class(){});
}
}
',
'<?php
class A {
public function B() {
$static = new static(new class{});
}
}
',
],
[
'<?php
$a = new class {use SomeTrait;};
$a = new class implements Foo{};
$a = new class /**/ extends Bar1{};
$a = new class extends Bar2 implements Foo{};
$a = new class extends Bar3 implements Foo, Foo2{};
$a = new class {};
$a = new class {};
',
'<?php
$a = new class() {use SomeTrait;};
$a = new class() implements Foo{};
$a = new class() /**/ extends Bar1{};
$a = new class() extends Bar2 implements Foo{};
$a = new class() extends Bar3 implements Foo, Foo2{};
$a = new class() {};
$a = new class( ) {};
',
self::$removeForAnonymousClasses,
],
];
}
protected function createFixer() {
return new NewWithBracesFixer();
}
}

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Ely\CS\Test\Fixer\Whitespace; namespace Ely\CS\Test\Fixer\Whitespace;
use Ely\CS\Fixer\Whitespace\BlankLineAroundClassBodyFixer; use Ely\CS\Fixer\Whitespace\BlankLineAroundClassBodyFixer;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
use PhpCsFixer\WhitespacesFixerConfig; use PhpCsFixer\WhitespacesFixerConfig;
@ -19,40 +20,18 @@ final class BlankLineAroundClassBodyFixerTest extends AbstractFixerTestCase {
private static $configurationTwoEmptyLines = ['blank_lines_count' => 2]; private static $configurationTwoEmptyLines = ['blank_lines_count' => 2];
/** /**
* @param string $expected
* @param null|string $input
* @param null|array $configuration
*
* @dataProvider provideFixCases * @dataProvider provideFixCases
*/ */
public function testFix($expected, $input = null, array $configuration = null) { public function testFix(string $expected, ?string $input = null, array $configuration = null): void {
if (null !== $configuration) { if ($configuration !== null) {
$this->fixer->configure($configuration); $this->fixer->configure($configuration);
} }
$this->doTest($expected, $input); $this->doTest($expected, $input);
} }
/** public function provideFixCases(): iterable {
* @param string $expected yield [
* @param null|string $input
* @param array $configuration
*
* @dataProvider provideAnonymousClassesCases
* @requires PHP 7.0
*/
public function testFixAnonymousClasses($expected, $input = null, array $configuration = null) {
if (null !== $configuration) {
$this->fixer->configure($configuration);
}
$this->doTest($expected, $input);
}
public function provideFixCases() {
$cases = [];
$cases[] = [
'<?php '<?php
class Good class Good
{ {
@ -72,7 +51,8 @@ class Good
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Good class Good
{ {
@ -98,7 +78,8 @@ class Good
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Good class Good
{ {
@ -130,7 +111,8 @@ class Good
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
interface Good interface Good
{ {
@ -150,7 +132,8 @@ interface Good
public function firstMethod(); public function firstMethod();
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
trait Good trait Good
{ {
@ -170,7 +153,8 @@ trait Good
public function firstMethod() {} public function firstMethod() {}
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Good class Good
{ {
@ -193,7 +177,8 @@ class Good
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Good class Good
{ {
@ -218,7 +203,8 @@ class Good
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Good class Good
{ {
@ -247,7 +233,8 @@ class Good
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Good class Good
{ {
@ -272,7 +259,7 @@ class Good
]; ];
// check if some fancy whitespaces aren't modified // check if some fancy whitespaces aren't modified
$cases[] = [ yield [
'<?php '<?php
class Good class Good
{public {public
@ -287,13 +274,7 @@ class Good
}', }',
]; ];
return $cases; yield [
}
public function provideAnonymousClassesCases() {
$cases = [];
$cases[] = [
'<?php '<?php
$class = new class extends \Foo { $class = new class extends \Foo {
@ -309,7 +290,8 @@ $class = new class extends \Foo {
public function firstMethod() {} public function firstMethod() {}
};', };',
]; ];
$cases[] = [
yield [
'<?php '<?php
$class = new class extends \Foo { $class = new class extends \Foo {
public $field; public $field;
@ -326,17 +308,12 @@ $class = new class extends \Foo {
};', };',
self::$configurationDoNotApplyForAnonymousClasses, self::$configurationDoNotApplyForAnonymousClasses,
]; ];
return $cases;
} }
/** /**
* @param string $expected
* @param null|string $input
*
* @dataProvider provideMessyWhitespacesCases * @dataProvider provideMessyWhitespacesCases
*/ */
public function testMessyWhitespaces($expected, $input = null) { public function testMessyWhitespaces(string $expected, ?string $input = null): void {
/** @var \PhpCsFixer\Fixer\WhitespacesAwareFixerInterface $fixer */ /** @var \PhpCsFixer\Fixer\WhitespacesAwareFixerInterface $fixer */
$fixer = $this->fixer; $fixer = $this->fixer;
$fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n")); $fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n"));
@ -344,20 +321,19 @@ $class = new class extends \Foo {
$this->doTest($expected, $input); $this->doTest($expected, $input);
} }
public function provideMessyWhitespacesCases() { public function provideMessyWhitespacesCases(): iterable {
return [ yield [
[
"<?php\nclass Foo\n{\r\n\r\n public function bar() {}\r\n\r\n}", "<?php\nclass Foo\n{\r\n\r\n public function bar() {}\r\n\r\n}",
"<?php\nclass Foo\n{\n public function bar() {}\n}", "<?php\nclass Foo\n{\n public function bar() {}\n}",
], ];
[
yield [
"<?php\nclass Foo\n{\r\n\r\n public function bar() {}\r\n\r\n}", "<?php\nclass Foo\n{\r\n\r\n public function bar() {}\r\n\r\n}",
"<?php\nclass Foo\n{\r\n\r\n\n\n public function bar() {}\n\n\n\n}", "<?php\nclass Foo\n{\r\n\r\n\n\n public function bar() {}\n\n\n\n}",
],
]; ];
} }
protected function createFixer() { protected function createFixer(): AbstractFixer {
return new BlankLineAroundClassBodyFixer(); return new BlankLineAroundClassBodyFixer();
} }

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Ely\CS\Test\Fixer\Whitespace; namespace Ely\CS\Test\Fixer\Whitespace;
use Ely\CS\Fixer\Whitespace\BlankLineBeforeReturnFixer; use Ely\CS\Fixer\Whitespace\BlankLineBeforeReturnFixer;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
use PhpCsFixer\WhitespacesFixerConfig; use PhpCsFixer\WhitespacesFixerConfig;
@ -24,23 +25,19 @@ use PhpCsFixer\WhitespacesFixerConfig;
final class BlankLineBeforeReturnFixerTest extends AbstractFixerTestCase { final class BlankLineBeforeReturnFixerTest extends AbstractFixerTestCase {
/** /**
* @param string $expected
* @param null|string $input
*
* @dataProvider provideFixCases * @dataProvider provideFixCases
*/ */
public function testFix($expected, $input = null) { public function testFix(string $expected, ?string $input = null): void {
$this->doTest($expected, $input); $this->doTest($expected, $input);
} }
public function provideFixCases() { public function provideFixCases(): iterable {
$cases = []; yield [
$cases[] = [
'$a = $a; '$a = $a;
return $a; return $a;
', ',
]; ];
$cases[] = [ yield [
'<?php '<?php
$a = $a; $a = $a;
@ -48,7 +45,7 @@ return $a;',
'<?php '<?php
$a = $a; return $a;', $a = $a; return $a;',
]; ];
$cases[] = [ yield [
'<?php '<?php
$b = $b; $b = $b;
@ -56,7 +53,7 @@ return $b;',
'<?php '<?php
$b = $b;return $b;', $b = $b;return $b;',
]; ];
$cases[] = [ yield [
'<?php '<?php
$c = $c; $c = $c;
@ -65,7 +62,7 @@ return $c;',
$c = $c; $c = $c;
return $c;', return $c;',
]; ];
$cases[] = [ yield [
'<?php '<?php
$d = $d; $d = $d;
@ -74,19 +71,19 @@ return $c;',
$d = $d; $d = $d;
return $d;', return $d;',
]; ];
$cases[] = [ yield [
'<?php '<?php
if (true) { if (true) {
return 1; return 1;
}', }',
]; ];
$cases[] = [ yield [
'<?php '<?php
if (true) if (true)
return 1; return 1;
', ',
]; ];
$cases[] = [ yield [
'<?php '<?php
if (true) { if (true) {
return 1; return 1;
@ -94,7 +91,7 @@ return $c;',
return 2; return 2;
}', }',
]; ];
$cases[] = [ yield [
'<?php '<?php
if (true) if (true)
return 1; return 1;
@ -102,7 +99,7 @@ return $c;',
return 2; return 2;
', ',
]; ];
$cases[] = [ yield [
'<?php '<?php
if (true) { if (true) {
return 1; return 1;
@ -110,7 +107,7 @@ return $c;',
return 2; return 2;
}', }',
]; ];
$cases[] = [ yield [
'<?php '<?php
if (true) if (true)
return 1; return 1;
@ -118,11 +115,11 @@ return $c;',
return 2; return 2;
', ',
]; ];
$cases[] = [ yield [
'<?php '<?php
throw new Exception("return true;");', throw new Exception("return true;");',
]; ];
$cases[] = [ yield [
'<?php '<?php
function foo() function foo()
{ {
@ -130,7 +127,7 @@ return $c;',
return "foo"; return "foo";
}', }',
]; ];
$cases[] = [ yield [
'<?php '<?php
function foo() function foo()
{ {
@ -139,7 +136,7 @@ return $c;',
return "bar"; return "bar";
}', }',
]; ];
$cases[] = [ yield [
'<?php '<?php
function foo() function foo()
{ {
@ -147,7 +144,7 @@ return $c;',
return "bar"; return "bar";
}', }',
]; ];
$cases[] = [ yield [
'<?php '<?php
function foo() { function foo() {
$a = "a"; $a = "a";
@ -162,14 +159,14 @@ return $c;',
return $a . $b; return $a . $b;
}', }',
]; ];
$cases[] = [ yield [
'<?php '<?php
function foo() { function foo() {
$b = "b"; $b = "b";
return $a . $b; return $a . $b;
}', }',
]; ];
$cases[] = [ yield [
'<?php '<?php
function foo() { function foo() {
$a = "a"; $a = "a";
@ -183,40 +180,33 @@ return $c;',
} }
', ',
]; ];
return $cases;
} }
/** /**
* @param string $expected
* @param null|string $input
*
* @dataProvider provideMessyWhitespacesCases * @dataProvider provideMessyWhitespacesCases
*/ */
public function testMessyWhitespaces($expected, $input = null) { public function testMessyWhitespaces(string $expected, ?string $input = null): void {
$this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n")); $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n"));
$this->doTest($expected, $input); $this->doTest($expected, $input);
} }
public function provideMessyWhitespacesCases() { public function provideMessyWhitespacesCases(): iterable {
return [ yield [
[
"<?php\r\n\$a = \$a;\r\n\r\nreturn \$a;", "<?php\r\n\$a = \$a;\r\n\r\nreturn \$a;",
"<?php\r\n\$a = \$a; return \$a;", "<?php\r\n\$a = \$a; return \$a;",
], ];
[ yield [
"<?php\r\n\$b = \$b;\r\n\r\nreturn \$b;", "<?php\r\n\$b = \$b;\r\n\r\nreturn \$b;",
"<?php\r\n\$b = \$b;return \$b;", "<?php\r\n\$b = \$b;return \$b;",
], ];
[ yield [
"<?php\r\n\$c = \$c;\r\n\r\nreturn \$c;", "<?php\r\n\$c = \$c;\r\n\r\nreturn \$c;",
"<?php\r\n\$c = \$c;\r\nreturn \$c;", "<?php\r\n\$c = \$c;\r\nreturn \$c;",
],
]; ];
} }
protected function createFixer() { protected function createFixer(): AbstractFixer {
return new BlankLineBeforeReturnFixer(); return new BlankLineBeforeReturnFixer();
} }

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Ely\CS\Test\Fixer\Whitespace; namespace Ely\CS\Test\Fixer\Whitespace;
use Ely\CS\Fixer\Whitespace\LineBreakAfterStatementsFixer; use Ely\CS\Fixer\Whitespace\LineBreakAfterStatementsFixer;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
/** /**
@ -14,20 +15,15 @@ use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
class LineBreakAfterStatementsFixerTest extends AbstractFixerTestCase { class LineBreakAfterStatementsFixerTest extends AbstractFixerTestCase {
/** /**
* @param string $expected
* @param string $input
*
* @dataProvider provideFixCases * @dataProvider provideFixCases
*/ */
public function testFix(string $expected, $input = null) { public function testFix(string $expected, ?string $input = null): void {
$this->doTest($expected, $input); $this->doTest($expected, $input);
} }
public function provideFixCases() { public function provideFixCases(): iterable {
$cases = [];
// Simple cases // Simple cases
$cases[] = [ yield [
'<?php '<?php
class Foo class Foo
{ {
@ -52,7 +48,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -81,7 +78,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -106,7 +104,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -131,7 +130,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -156,7 +156,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -181,7 +182,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -216,8 +218,9 @@ class Foo
} }
}', }',
]; ];
// Extended cases // Extended cases
$cases[] = [ yield [
'<?php '<?php
class Foo class Foo
{ {
@ -250,7 +253,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -283,7 +287,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -310,7 +315,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -351,7 +357,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
$a = "prev statement"; $a = "prev statement";
foreach ($coordinates as $coordinate) { foreach ($coordinates as $coordinate) {
@ -359,8 +366,9 @@ foreach ($coordinates as $coordinate) {
} }
', ',
]; ];
// Issue 5 // Issue 5
$cases[] = [ yield [
'<?php '<?php
class Foo class Foo
{ {
@ -383,7 +391,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -410,7 +419,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -433,7 +443,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -456,7 +467,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -479,7 +491,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -504,7 +517,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -535,7 +549,8 @@ class Foo
} }
}', }',
]; ];
$cases[] = [
yield [
'<?php '<?php
class Foo class Foo
{ {
@ -560,11 +575,9 @@ class Foo
} }
}', }',
]; ];
return $cases;
} }
protected function createFixer() { protected function createFixer(): AbstractFixer {
return new LineBreakAfterStatementsFixer(); return new LineBreakAfterStatementsFixer();
} }