mirror of
https://github.com/elyby/php-code-style.git
synced 2025-05-31 14:12:05 +05:30
First implementation
This commit is contained in:
17
src/Config.php
Normal file
17
src/Config.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ely\CS;
|
||||
|
||||
use PhpCsFixer\Config as PhpCsFixerConfig;
|
||||
|
||||
class Config {
|
||||
|
||||
public static function create(array $overwrittenRules = []): PhpCsFixerConfig {
|
||||
return PhpCsFixerConfig::create()
|
||||
->setRiskyAllowed(true)
|
||||
->registerCustomFixers(new Fixers())
|
||||
->setRules(Rules::create($overwrittenRules));
|
||||
}
|
||||
|
||||
}
|
13
src/Fixer/AbstractFixer.php
Normal file
13
src/Fixer/AbstractFixer.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace Ely\CS\Fixer;
|
||||
|
||||
abstract class AbstractFixer extends \PhpCsFixer\AbstractFixer {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName() {
|
||||
return sprintf('Ely/%s', parent::getName());
|
||||
}
|
||||
|
||||
}
|
179
src/Fixer/Operator/NewWithBracesFixer.php
Normal file
179
src/Fixer/Operator/NewWithBracesFixer.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?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, [')'])
|
||||
);
|
||||
}
|
||||
|
||||
}
|
150
src/Fixer/Whitespace/BlankLineAroundClassBodyFixer.php
Normal file
150
src/Fixer/Whitespace/BlankLineAroundClassBodyFixer.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ely\CS\Fixer\Whitespace;
|
||||
|
||||
use Ely\CS\Fixer\AbstractFixer;
|
||||
use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface;
|
||||
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
|
||||
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
|
||||
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
use PhpCsFixer\Tokenizer\TokensAnalyzer;
|
||||
use PhpCsFixer\Utils;
|
||||
|
||||
/**
|
||||
* This is copy of the PR https://github.com/FriendsOfPHP/PHP-CS-Fixer/pull/3688
|
||||
*
|
||||
* @author ErickSkrauch <erickskrauch@ely.by>
|
||||
*/
|
||||
final class BlankLineAroundClassBodyFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition() {
|
||||
return new FixerDefinition(
|
||||
'Ensure that class body contains one blank line after class definition and before its end.',
|
||||
[
|
||||
new CodeSample(
|
||||
'<?php
|
||||
class Sample
|
||||
{
|
||||
protected function foo()
|
||||
{
|
||||
}
|
||||
}
|
||||
'
|
||||
),
|
||||
new CodeSample(
|
||||
'<?php
|
||||
new class extends Foo {
|
||||
|
||||
protected function foo()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
',
|
||||
['apply_to_anonymous_classes' => false]
|
||||
),
|
||||
new CodeSample(
|
||||
'<?php
|
||||
new class extends Foo {
|
||||
protected function foo()
|
||||
{
|
||||
}
|
||||
};
|
||||
',
|
||||
['apply_to_anonymous_classes' => true]
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPriority() {
|
||||
// should be run after the BracesFixer
|
||||
return -26;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens) {
|
||||
return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens) {
|
||||
$analyzer = new TokensAnalyzer($tokens);
|
||||
foreach ($tokens as $index => $token) {
|
||||
if (!$token->isClassy()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$countLines = $this->configuration['blank_lines_count'];
|
||||
if (!$this->configuration['apply_to_anonymous_classes'] && $analyzer->isAnonymousClass($index)) {
|
||||
$countLines = 0;
|
||||
}
|
||||
|
||||
$startBraceIndex = $tokens->getNextTokenOfKind($index, ['{']);
|
||||
if ($tokens[$startBraceIndex + 1]->isWhitespace()) {
|
||||
$nextStatementIndex = $tokens->getNextMeaningfulToken($startBraceIndex);
|
||||
// Traits should be placed right after a class opening brace,
|
||||
if ($tokens[$nextStatementIndex]->getContent() !== 'use') {
|
||||
$this->fixBlankLines($tokens, $startBraceIndex + 1, $countLines);
|
||||
}
|
||||
}
|
||||
|
||||
$endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startBraceIndex);
|
||||
if ($tokens[$endBraceIndex - 1]->isWhitespace()) {
|
||||
$this->fixBlankLines($tokens, $endBraceIndex - 1, $countLines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createConfigurationDefinition() {
|
||||
return new FixerConfigurationResolver([
|
||||
(new FixerOptionBuilder('blank_lines_count', 'adjusts an amount of the blank lines.'))
|
||||
->setAllowedTypes(['int'])
|
||||
->setDefault(1)
|
||||
->getOption(),
|
||||
(new FixerOptionBuilder('apply_to_anonymous_classes', 'whether this fixer should be applied to anonymous classes.'))
|
||||
->setAllowedTypes(['bool'])
|
||||
->setDefault(true)
|
||||
->getOption(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup a whitespace token.
|
||||
*
|
||||
* @param Tokens $tokens
|
||||
* @param int $index
|
||||
* @param int $countLines
|
||||
*/
|
||||
private function fixBlankLines(Tokens $tokens, $index, $countLines) {
|
||||
$content = $tokens[$index]->getContent();
|
||||
// Apply fix only in the case when the count lines do not equals to expected
|
||||
if (substr_count($content, "\n") === $countLines + 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The final bit of the whitespace must be the next statement's indentation
|
||||
$lines = Utils::splitLines($content);
|
||||
$eol = $this->whitespacesConfig->getLineEnding();
|
||||
$tokens[$index] = new Token([T_WHITESPACE, str_repeat($eol, $countLines + 1) . end($lines)]);
|
||||
}
|
||||
|
||||
}
|
103
src/Fixer/Whitespace/BlankLineBeforeReturnFixer.php
Normal file
103
src/Fixer/Whitespace/BlankLineBeforeReturnFixer.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ely\CS\Fixer\Whitespace;
|
||||
|
||||
use Ely\CS\Fixer\AbstractFixer;
|
||||
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
use SplFileInfo;
|
||||
|
||||
/**
|
||||
* This is extended version of the original `blank_line_before_statement` fixer.
|
||||
* It applies only to `return` statements and only in cases, when on the current nesting level more than one statements.
|
||||
*
|
||||
* @url https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/5c5de791ab/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php
|
||||
*
|
||||
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
* @author Andreas Möller <am@localheinz.com>
|
||||
* @author SpacePossum
|
||||
*/
|
||||
final class BlankLineBeforeReturnFixer extends AbstractFixer implements WhitespacesAwareFixerInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition() {
|
||||
return new FixerDefinition(
|
||||
'An empty line feed should precede a return statement.',
|
||||
[new CodeSample("<?php\nfunction A()\n{\n echo 1;\n return 1;\n}\n")]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens) {
|
||||
return $tokens->isTokenKindFound(T_RETURN);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPriority() {
|
||||
// should be run after NoUselessReturnFixer, ClassDefinitionFixer and BracesFixer
|
||||
return -26;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function applyFix(SplFileInfo $file, Tokens $tokens) {
|
||||
for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) {
|
||||
$token = $tokens[$index];
|
||||
if (!$token->isGivenKind(T_RETURN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$eol = $this->whitespacesConfig->getLineEnding();
|
||||
|
||||
$prevNonWhitespaceToken = $tokens[$tokens->getPrevNonWhitespace($index)];
|
||||
if (!$prevNonWhitespaceToken->equalsAny([';', '}'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$prevIndex = $index - 1;
|
||||
$prevToken = $tokens[$prevIndex];
|
||||
if ($prevToken->isWhitespace()) {
|
||||
$countParts = substr_count($prevToken->getContent(), "\n");
|
||||
if ($countParts === 0) {
|
||||
$tokens[$prevIndex] = new Token([T_WHITESPACE, rtrim($prevToken->getContent(), " \t") . $eol . $eol]);
|
||||
} elseif ($countParts === 1) {
|
||||
$backwardIndex = $prevIndex;
|
||||
do {
|
||||
if (--$backwardIndex < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$backwardToken = $tokens[$backwardIndex];
|
||||
if ($backwardToken->getContent() === '{') {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($backwardToken->isWhitespace()) {
|
||||
$countParts += substr_count($backwardToken->getContent(), "\n");
|
||||
}
|
||||
} while ($countParts < 3);
|
||||
|
||||
if ($countParts !== 2) {
|
||||
$tokens[$prevIndex] = new Token([T_WHITESPACE, $eol . $prevToken->getContent()]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$tokens->insertAt($index, new Token([T_WHITESPACE, $eol . $eol]));
|
||||
++$index;
|
||||
++$limit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
163
src/Fixer/Whitespace/LineBreakAfterStatementsFixer.php
Normal file
163
src/Fixer/Whitespace/LineBreakAfterStatementsFixer.php
Normal file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ely\CS\Fixer\Whitespace;
|
||||
|
||||
use Ely\CS\Fixer\AbstractFixer;
|
||||
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
use PhpCsFixer\Utils;
|
||||
use SplFileInfo;
|
||||
|
||||
/**
|
||||
* This is rewritten version of the original fixer created by @PedroTroller with improved cases validation and
|
||||
* targeted to the PHP-CS-Fixer 2.11 version.
|
||||
*
|
||||
* @url https://github.com/PedroTroller/PhpCSFixer-Custom-Fixers/blob/affdf99f51/src/PedroTroller/CS/Fixer/CodingStyle/LineBreakBetweenStatementsFixer.php
|
||||
*
|
||||
* @author ErickSkrauch <erickskrauch@ely.by>
|
||||
*/
|
||||
final class LineBreakAfterStatementsFixer extends AbstractFixer implements WhitespacesAwareFixerInterface {
|
||||
|
||||
/**
|
||||
* There is no 'do', 'cause the processing of the 'while' also includes do {} while (); construction
|
||||
*/
|
||||
const STATEMENTS = [
|
||||
T_IF,
|
||||
T_SWITCH,
|
||||
T_FOR,
|
||||
T_FOREACH,
|
||||
T_WHILE,
|
||||
];
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDefinition() {
|
||||
return new FixerDefinition(
|
||||
'Ensures that there is one blank line above the control statements',
|
||||
[
|
||||
new CodeSample(
|
||||
'<?php
|
||||
class Foo
|
||||
{
|
||||
/**
|
||||
* @return null
|
||||
*/
|
||||
public function foo() {
|
||||
do {
|
||||
// ...
|
||||
} while (true);
|
||||
foreach (["foo", "bar"] as $str) {
|
||||
// ...
|
||||
}
|
||||
if (true === false) {
|
||||
// ...
|
||||
}
|
||||
foreach (["foo", "bar"] as $str) {
|
||||
if ($str === "foo") {
|
||||
// smth
|
||||
}
|
||||
|
||||
}
|
||||
while (true) {
|
||||
// ...
|
||||
}
|
||||
switch("123") {
|
||||
case "123":
|
||||
break;
|
||||
}
|
||||
$a = "next statement";
|
||||
}
|
||||
}
|
||||
'
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens) {
|
||||
return $tokens->isAnyTokenKindsFound(self::STATEMENTS);
|
||||
}
|
||||
|
||||
protected function applyFix(SplFileInfo $file, Tokens $tokens) {
|
||||
foreach ($tokens as $index => $token) {
|
||||
if (!$token->isGivenKind(self::STATEMENTS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$endStatementIndex = $this->findStatementEnd($tokens, $index);
|
||||
$nextStatementIndex = $tokens->getNextNonWhitespace($endStatementIndex);
|
||||
if ($nextStatementIndex === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($tokens[$nextStatementIndex]->equals('}')) {
|
||||
$this->fixBlankLines($tokens, $endStatementIndex + 1, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->fixBlankLines($tokens, $endStatementIndex + 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private function fixBlankLines(Tokens $tokens, $index, $countLines) {
|
||||
$content = $tokens[$index]->getContent();
|
||||
// Apply fix only in the case when the count lines do not equals to expected
|
||||
if (substr_count($content, "\n") === $countLines + 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The final bit of the whitespace must be the next statement's indentation
|
||||
$lines = Utils::splitLines($content);
|
||||
$eol = $this->whitespacesConfig->getLineEnding();
|
||||
$tokens[$index] = new Token([T_WHITESPACE, str_repeat($eol, $countLines + 1) . end($lines)]);
|
||||
}
|
||||
|
||||
private function findStatementEnd(Tokens $tokens, int $index): int {
|
||||
$nextIndex = $tokens->getNextMeaningfulToken($index);
|
||||
$nextToken = $tokens[$nextIndex];
|
||||
|
||||
if ($nextToken->equals('(')) {
|
||||
$parenthesisEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextIndex);
|
||||
$possibleStartBraceIndex = $tokens->getNextNonWhitespace($parenthesisEndIndex);
|
||||
} else {
|
||||
$possibleStartBraceIndex = $nextIndex;
|
||||
}
|
||||
|
||||
// `do {} while ();`
|
||||
if ($tokens[$index]->isGivenKind(T_WHILE) && $tokens[$possibleStartBraceIndex]->equals(';')) {
|
||||
return $possibleStartBraceIndex;
|
||||
}
|
||||
|
||||
$blockEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $possibleStartBraceIndex);
|
||||
$nextStatementIndex = $tokens->getNextMeaningfulToken($blockEnd);
|
||||
if ($nextStatementIndex === null) {
|
||||
return $blockEnd;
|
||||
}
|
||||
|
||||
// `if () {} elseif {}`
|
||||
if ($tokens[$nextStatementIndex]->isGivenKind(T_ELSEIF)) {
|
||||
return $this->findStatementEnd($tokens, $nextStatementIndex);
|
||||
}
|
||||
|
||||
// `if () {} else if {}` or simple `if () {} else {}`
|
||||
if ($tokens[$nextStatementIndex]->isGivenKind(T_ELSE)) {
|
||||
$nextNextStatementIndex = $tokens->getNextMeaningfulToken($nextStatementIndex);
|
||||
if ($tokens[$nextNextStatementIndex]->isGivenKind(T_IF)) {
|
||||
return $this->findStatementEnd($tokens, $nextNextStatementIndex);
|
||||
}
|
||||
|
||||
return $this->findStatementEnd($tokens, $nextStatementIndex);
|
||||
}
|
||||
|
||||
return $blockEnd;
|
||||
}
|
||||
|
||||
}
|
39
src/Fixers.php
Normal file
39
src/Fixers.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ely\CS;
|
||||
|
||||
use ArrayIterator;
|
||||
use IteratorAggregate;
|
||||
use PhpCsFixer\Finder;
|
||||
use PhpCsFixer\Fixer\FixerInterface;
|
||||
use ReflectionClass;
|
||||
use Traversable;
|
||||
|
||||
class Fixers implements IteratorAggregate {
|
||||
|
||||
public function getIterator(): Traversable {
|
||||
$finder = new Finder();
|
||||
$finder->in(__DIR__ . '/Fixer')->name('*.php');
|
||||
$classes = [];
|
||||
foreach ($finder as $file) {
|
||||
$class = '\\Ely\\CS' . str_replace('/', '\\', mb_substr($file->getPathname(), mb_strlen(__DIR__), -4));
|
||||
if (!class_exists($class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$rfl = new ReflectionClass($class);
|
||||
if (!$rfl->implementsInterface(FixerInterface::class) || $rfl->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classes[] = $class;
|
||||
}
|
||||
|
||||
return new ArrayIterator(array_map(function($class) {
|
||||
return new $class();
|
||||
}, $classes));
|
||||
}
|
||||
|
||||
}
|
74
src/Rules.php
Normal file
74
src/Rules.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ely\CS;
|
||||
|
||||
class Rules {
|
||||
|
||||
private static $rules = [
|
||||
'@PSR2' => true,
|
||||
'binary_operator_spaces' => true,
|
||||
'braces' => [
|
||||
'position_after_functions_and_oop_constructs' => 'same',
|
||||
],
|
||||
'cast_spaces' => [
|
||||
'space' => 'none',
|
||||
],
|
||||
'class_attributes_separation' => [
|
||||
'elements' => ['method', 'property'],
|
||||
],
|
||||
'compact_nullable_typehint' => true,
|
||||
'concat_space' => [
|
||||
'spacing' => 'one',
|
||||
],
|
||||
'declare_equal_normalize' => true,
|
||||
'function_declaration' => [
|
||||
'closure_function_spacing' => 'none',
|
||||
],
|
||||
'function_to_constant' => true,
|
||||
'include' => true,
|
||||
'linebreak_after_opening_tag' => true,
|
||||
'method_chaining_indentation' => true,
|
||||
'modernize_types_casting' => true,
|
||||
'no_short_bool_cast' => true,
|
||||
'no_trailing_comma_in_singleline_array' => true,
|
||||
'no_unneeded_final_method' => true,
|
||||
'no_unused_imports' => true,
|
||||
'no_useless_else' => true,
|
||||
'no_whitespace_before_comma_in_array' => true,
|
||||
'no_whitespace_in_blank_line' => true,
|
||||
'non_printable_character' => [
|
||||
'use_escape_sequences_in_strings' => true,
|
||||
],
|
||||
'object_operator_without_whitespace' => true,
|
||||
'ordered_class_elements' => true,
|
||||
'ordered_imports' => true,
|
||||
'random_api_migration' => true,
|
||||
'return_type_declaration' => [
|
||||
'space_before' => 'none',
|
||||
],
|
||||
'single_quote' => true,
|
||||
'strict_comparison' => true,
|
||||
'ternary_operator_spaces' => true,
|
||||
'ternary_to_null_coalescing' => true,
|
||||
'trailing_comma_in_multiline_array' => true,
|
||||
'visibility_required' => [
|
||||
'elements' => ['property', 'method', 'const'],
|
||||
],
|
||||
'whitespace_after_comma_in_array' => true,
|
||||
// Our custom or extended fixers
|
||||
'Ely/blank_line_around_class_body' => [
|
||||
'apply_to_anonymous_classes' => false,
|
||||
],
|
||||
'Ely/blank_line_before_return' => true,
|
||||
'Ely/line_break_after_statements' => true,
|
||||
'Ely/new_with_braces' => [
|
||||
'remove_for_anonymous_classes' => true,
|
||||
],
|
||||
];
|
||||
|
||||
public static function create(array $overwrittenRules = []): array {
|
||||
return array_merge(self::$rules, $overwrittenRules);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user