Skip to content

Commit

Permalink
#11 - fn() spacing (#13)
Browse files Browse the repository at this point in the history
* #11 - fn() spacing

* #11 - custom fixer

* #11 - tests fixed

* #11 - codestyle heh

* Rename arrowfunctions.php to arrow_functions.php
  • Loading branch information
krzysztofrewak authored Mar 29, 2021
1 parent 57206c9 commit 7bc71fe
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 31 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "library",
"require": {
"php": "^8.0",
"symplify/easy-coding-standard": "^9.1"
"symplify/easy-coding-standard": "^9.2"
},
"license": "MIT",
"authors": [
Expand Down
2 changes: 1 addition & 1 deletion ecs.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Blumilk\Codestyle\Configuration\Defaults\Paths;

$config = new Config(
paths: new Paths("src", "tests")
paths: new Paths("examples", "src", "tests")
);

return $config->config();
5 changes: 5 additions & 0 deletions examples/arrow_functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

declare(strict_types=1);

array_filter([1, 2, 3, 4], fn(int $i): bool => $i % 2 === 0);
10 changes: 10 additions & 0 deletions src/Configuration/Defaults/CommonAdditionalRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@

use Blumilk\Codestyle\Configuration\AdditionalRules;
use Blumilk\Codestyle\Fixers\DoubleQuoteFixer;
use Blumilk\Codestyle\Fixers\NoSpacesAfterFunctionNameFixer;
use PhpCsFixer\Fixer\CastNotation\CastSpacesFixer;
use PhpCsFixer\Fixer\FunctionNotation\UseArrowFunctionsFixer;
use PhpCsFixer\Fixer\FunctionNotation\VoidReturnFixer;
use PhpCsFixer\Fixer\Import\FullyQualifiedStrictTypesFixer;
use PhpCsFixer\Fixer\Import\OrderedImportsFixer;
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;

class CommonAdditionalRules extends Rules implements AdditionalRules
Expand All @@ -17,5 +22,10 @@ class CommonAdditionalRules extends Rules implements AdditionalRules
"space" => "none",
],
DoubleQuoteFixer::class => null,
VoidReturnFixer::class => null,
UseArrowFunctionsFixer::class => null,
NoSpacesAfterFunctionNameFixer::class => null,
FullyQualifiedStrictTypesFixer::class => null,
OrderedImportsFixer::class => null,
];
}
133 changes: 133 additions & 0 deletions src/Fixers/NoSpacesAfterFunctionNameFixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

declare(strict_types=1);

namespace Blumilk\Codestyle\Fixers;

use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Tokens;
use SplFileInfo;

final class NoSpacesAfterFunctionNameFixer extends AbstractFixer
{
public function getDefinition(): FixerDefinition
{
return new FixerDefinition(
"When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis.",
[new CodeSample("<?php\nrequire ('sample.php');\necho (test (3));\nexit (1);\n\$func ();\n")]
);
}

public function getPriority(): int
{
return 2;
}

public function isCandidate(Tokens $tokens): bool
{
return $tokens->isAnyTokenKindsFound(array_merge($this->getFunctionyTokenKinds(), [T_STRING]));
}

protected function applyFix(SplFileInfo $file, Tokens $tokens): void
{
$functionyTokens = $this->getFunctionyTokenKinds();
$languageConstructionTokens = $this->getLanguageConstructionTokenKinds();
$braceTypes = $this->getBraceAfterVariableKinds();

foreach ($tokens as $index => $token) {
if (!$token->equals("(")) {
continue;
}

$lastTokenIndex = $tokens->getPrevNonWhitespace($index);

$endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index);
$nextNonWhiteSpace = $tokens->getNextMeaningfulToken($endParenthesisIndex);
if (
$nextNonWhiteSpace !== null
&& $tokens[$nextNonWhiteSpace]->equals("?")
&& $tokens[$lastTokenIndex]->isGivenKind($languageConstructionTokens)
) {
continue;
}

if ($tokens[$lastTokenIndex]->isGivenKind($functionyTokens)) {
$this->fixFunctionCall($tokens, $index);
} elseif ($tokens[$lastTokenIndex]->isGivenKind(T_STRING)) {
$possibleDefinitionIndex = $tokens->getPrevMeaningfulToken($lastTokenIndex);
if (!$tokens[$possibleDefinitionIndex]->isGivenKind(T_FUNCTION)) {
$this->fixFunctionCall($tokens, $index);
}
} elseif ($tokens[$lastTokenIndex]->equalsAny($braceTypes)) {
$block = Tokens::detectBlockType($tokens[$lastTokenIndex]);
if (
$block["type"] === Tokens::BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE
|| $block["type"] === Tokens::BLOCK_TYPE_DYNAMIC_VAR_BRACE
|| $block["type"] === Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE
|| $block["type"] === Tokens::BLOCK_TYPE_PARENTHESIS_BRACE
) {
$this->fixFunctionCall($tokens, $index);
}
}
}
}

private function fixFunctionCall(Tokens $tokens, int $index): void
{
if ($tokens[$index - 1]->isWhitespace()) {
$tokens->clearAt($index - 1);
}
}

private function getBraceAfterVariableKinds(): array
{
static $tokens = [
")",
"]",
[CT::T_DYNAMIC_VAR_BRACE_CLOSE],
[CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE],
];

return $tokens;
}

private function getFunctionyTokenKinds(): array
{
static $tokens = [
T_ARRAY,
T_ECHO,
T_EMPTY,
T_EVAL,
T_EXIT,
T_INCLUDE,
T_INCLUDE_ONCE,
T_ISSET,
T_LIST,
T_PRINT,
T_REQUIRE,
T_REQUIRE_ONCE,
T_UNSET,
T_VARIABLE,
T_FN,
];

return $tokens;
}

private function getLanguageConstructionTokenKinds(): array
{
static $languageConstructionTokens = [
T_ECHO,
T_PRINT,
T_INCLUDE,
T_INCLUDE_ONCE,
T_REQUIRE,
T_REQUIRE_ONCE,
];

return $languageConstructionTokens;
}
}
97 changes: 68 additions & 29 deletions tests/AdditionalRulesConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
use Blumilk\Codestyle\Configuration\Defaults\CommonAdditionalRules;
use Blumilk\Codestyle\Configuration\Utils\Rule;
use Blumilk\Codestyle\Fixers\DoubleQuoteFixer;
use Blumilk\Codestyle\Fixers\NoSpacesAfterFunctionNameFixer;
use PhpCsFixer\Fixer\Alias\NoMixedEchoPrintFixer;
use PhpCsFixer\Fixer\CastNotation\CastSpacesFixer;
use PhpCsFixer\Fixer\FunctionNotation\UseArrowFunctionsFixer;
use PhpCsFixer\Fixer\FunctionNotation\VoidReturnFixer;
use PhpCsFixer\Fixer\Import\FullyQualifiedStrictTypesFixer;
use PhpCsFixer\Fixer\Import\OrderedImportsFixer;
use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer;
use PhpCsFixer\Fixer\StringNotation\HeredocToNowdocFixer;
use PHPUnit\Framework\TestCase;
Expand All @@ -19,13 +24,21 @@ public function testAdditionalRulesConfiguration(): void
$rules = new CommonAdditionalRules();
$config = new Config(rules: $rules);

$this->assertSame([
DeclareStrictTypesFixer::class => null,
CastSpacesFixer::class => [
"space" => "none",
$this->assertSame(
[
DeclareStrictTypesFixer::class => null,
CastSpacesFixer::class => [
"space" => "none",
],
DoubleQuoteFixer::class => null,
VoidReturnFixer::class => null,
UseArrowFunctionsFixer::class => null,
NoSpacesAfterFunctionNameFixer::class => null,
FullyQualifiedStrictTypesFixer::class => null,
OrderedImportsFixer::class => null,
],
DoubleQuoteFixer::class => null,
], $config->options()["rules"]);
$config->options()["rules"]
);
}

public function testClearingAdditionalRulesConfiguration(): void
Expand All @@ -41,10 +54,18 @@ public function testFilteringAdditionalRulesConfiguration(): void
$rules = new CommonAdditionalRules();
$config = new Config(rules: $rules->filter(CastSpacesFixer::class));

$this->assertSame([
DeclareStrictTypesFixer::class => null,
DoubleQuoteFixer::class => null,
], $config->options()["rules"]);
$this->assertSame(
[
DeclareStrictTypesFixer::class => null,
DoubleQuoteFixer::class => null,
VoidReturnFixer::class => null,
UseArrowFunctionsFixer::class => null,
NoSpacesAfterFunctionNameFixer::class => null,
FullyQualifiedStrictTypesFixer::class => null,
OrderedImportsFixer::class => null,
],
$config->options()["rules"]
);
}

public function testExtendingAdditionalRulesConfiguration(): void
Expand All @@ -54,34 +75,52 @@ public function testExtendingAdditionalRulesConfiguration(): void
rules: $rules->add(new Rule(HeredocToNowdocFixer::class))
);

$this->assertSame([
DeclareStrictTypesFixer::class => null,
CastSpacesFixer::class => [
"space" => "none",
$this->assertSame(
[
DeclareStrictTypesFixer::class => null,
CastSpacesFixer::class => [
"space" => "none",
],
DoubleQuoteFixer::class => null,
VoidReturnFixer::class => null,
UseArrowFunctionsFixer::class => null,
NoSpacesAfterFunctionNameFixer::class => null,
FullyQualifiedStrictTypesFixer::class => null,
OrderedImportsFixer::class => null,
HeredocToNowdocFixer::class => null,
],
DoubleQuoteFixer::class => null,
HeredocToNowdocFixer::class => null,
], $config->options()["rules"]);
$config->options()["rules"]
);
}

public function testExtendingWithOptionsAdditionalRulesConfiguration(): void
{
$rules = new CommonAdditionalRules();
$rule = new Rule(NoMixedEchoPrintFixer::class, [
"use" => "echo",
]);

$config = new Config(
rules: $rules->add(new Rule(NoMixedEchoPrintFixer::class, [
"use" => "echo",
]))
rules: $rules->add($rule)
);

$this->assertSame([
DeclareStrictTypesFixer::class => null,
CastSpacesFixer::class => [
"space" => "none",
],
DoubleQuoteFixer::class => null,
NoMixedEchoPrintFixer::class => [
"use" => "echo",
$this->assertSame(
[
DeclareStrictTypesFixer::class => null,
CastSpacesFixer::class => [
"space" => "none",
],
DoubleQuoteFixer::class => null,
VoidReturnFixer::class => null,
UseArrowFunctionsFixer::class => null,
NoSpacesAfterFunctionNameFixer::class => null,
FullyQualifiedStrictTypesFixer::class => null,
OrderedImportsFixer::class => null,
NoMixedEchoPrintFixer::class => [
"use" => "echo",
],
],
], $config->options()["rules"]);
$config->options()["rules"]
);
}
}

0 comments on commit 7bc71fe

Please sign in to comment.