mirror of
https://github.com/elyby/php-code-style.git
synced 2024-11-06 00:04:41 +05:30
Resolves #4. Add fixer to replace ::className() method usages with ::class keyword.
This commit is contained in:
parent
76bd14c167
commit
59e9994662
16
README.md
16
README.md
@ -261,3 +261,19 @@ an anonymous class declaration in a case when said class constructor doesn't con
|
||||
|
||||
* `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)
|
||||
|
||||
Replaces Yii2 [`BaseObject::className()`](https://github.com/yiisoft/yii2/blob/e53fc0ded1/framework/base/BaseObject.php#L84)
|
||||
usages with native `::class` keyword, introduced in PHP 5.5.
|
||||
|
||||
```diff
|
||||
--- Original
|
||||
+++ New
|
||||
@@ @@
|
||||
<?php
|
||||
use common\models\User;
|
||||
|
||||
- $className = User::className();
|
||||
+ $className = User::class;
|
||||
```
|
||||
|
123
src/Fixer/LanguageConstruct/RemoveClassNameMethodUsagesFixer.php
Normal file
123
src/Fixer/LanguageConstruct/RemoveClassNameMethodUsagesFixer.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ely\CS\Fixer\LanguageConstruct;
|
||||
|
||||
use Ely\CS\Fixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\Tokenizer\CT;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
use SplFileInfo;
|
||||
|
||||
/**
|
||||
* Replaces Yii2 BaseObject::className() usages with native ::class keyword, introduced in PHP 5.5.
|
||||
*
|
||||
* @author ErickSkrauch <erickskrauch@ely.by>
|
||||
*/
|
||||
final class RemoveClassNameMethodUsagesFixer extends AbstractFixer {
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDefinition() {
|
||||
return new FixerDefinition(
|
||||
'Converts Yii2 `BaseObject::className()` method usage into `::class` keyword.',
|
||||
[
|
||||
new CodeSample(
|
||||
'<?php
|
||||
|
||||
use Foo\Bar\Baz;
|
||||
|
||||
$className = Baz::className();
|
||||
'
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens) {
|
||||
return $tokens->isTokenKindFound(T_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isRisky() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(SplFileInfo $file, Tokens $tokens) {
|
||||
for ($index = $tokens->count() - 4; $index > 0; --$index) {
|
||||
$candidate = $this->getReplaceCandidate($tokens, $index);
|
||||
if ($candidate === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->fixClassNameMethodUsage(
|
||||
$tokens,
|
||||
$index,
|
||||
$candidate[0], // brace open
|
||||
$candidate[1] // brace close
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tokens $tokens
|
||||
* @param int $index
|
||||
*
|
||||
* @return null|array
|
||||
*/
|
||||
private function getReplaceCandidate(Tokens $tokens, $index) {
|
||||
if (!$tokens[$index]->isGivenKind(T_STRING)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$braceOpenIndex = $tokens->getNextMeaningfulToken($index);
|
||||
if (!$tokens[$braceOpenIndex]->equals('(')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$braceCloseIndex = $tokens->getNextMeaningfulToken($braceOpenIndex);
|
||||
if (!$tokens[$braceCloseIndex]->equals(')')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$doubleColon = $tokens->getPrevMeaningfulToken($index);
|
||||
if (!$tokens[$doubleColon]->isGivenKind([T_DOUBLE_COLON])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$methodName = $tokens[$index]->getContent();
|
||||
if ($methodName !== 'className') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
$braceOpenIndex,
|
||||
$braceCloseIndex,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tokens $tokens
|
||||
* @param int $index
|
||||
* @param int $braceOpenIndex
|
||||
* @param int $braceCloseIndex
|
||||
*/
|
||||
private function fixClassNameMethodUsage(Tokens $tokens, int $index, int $braceOpenIndex, int $braceCloseIndex) {
|
||||
$tokens->clearTokenAndMergeSurroundingWhitespace($braceCloseIndex);
|
||||
$tokens->clearTokenAndMergeSurroundingWhitespace($braceOpenIndex);
|
||||
$tokens->clearAt($index);
|
||||
$tokens->insertAt($index, new Token([CT::T_CLASS_CONSTANT, 'class']));
|
||||
}
|
||||
|
||||
}
|
@ -65,6 +65,7 @@ class Rules {
|
||||
'Ely/new_with_braces' => [
|
||||
'remove_for_anonymous_classes' => true,
|
||||
],
|
||||
'Ely/remove_class_name_method_usages' => true,
|
||||
];
|
||||
|
||||
public static function create(array $overwrittenRules = []): array {
|
||||
|
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ely\CS\Test\Fixer\Operator;
|
||||
|
||||
use Ely\CS\Fixer\LanguageConstruct\RemoveClassNameMethodUsagesFixer;
|
||||
use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
|
||||
|
||||
/**
|
||||
* @covers \Ely\CS\Fixer\LanguageConstruct\RemoveClassNameMethodUsagesFixer
|
||||
*/
|
||||
class RemoveClassNameMethodUsagesFixerTest extends AbstractFixerTestCase {
|
||||
|
||||
/**
|
||||
* @param string $expected
|
||||
* @param null|string $input
|
||||
*
|
||||
* @dataProvider provideFixCases
|
||||
*/
|
||||
public function testFix($expected, $input = null) {
|
||||
$this->doTest($expected, $input);
|
||||
}
|
||||
|
||||
public function provideFixCases() {
|
||||
return [
|
||||
[
|
||||
'<?php echo className();',
|
||||
],
|
||||
[
|
||||
'<?php
|
||||
use Foo\Bar\Baz;
|
||||
|
||||
$exceptionString = Baz::classname();
|
||||
',
|
||||
],
|
||||
[
|
||||
'<?php
|
||||
use Foo\Bar\Baz;
|
||||
|
||||
$className = Baz::class;
|
||||
',
|
||||
'<?php
|
||||
use Foo\Bar\Baz;
|
||||
|
||||
$className = Baz::className();
|
||||
',
|
||||
],
|
||||
[
|
||||
'<?php
|
||||
use Foo\Bar\Baz;
|
||||
|
||||
$exceptionString = "The class should be instance of " . Baz::class . " and nothing else";
|
||||
',
|
||||
'<?php
|
||||
use Foo\Bar\Baz;
|
||||
|
||||
$exceptionString = "The class should be instance of " . Baz::className() . " and nothing else";
|
||||
',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function createFixer() {
|
||||
return new RemoveClassNameMethodUsagesFixer();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user