Skip to content

Commit 9592757

Browse files
committed
Expanded test & src order of class elements
2 parents f9094db + ec00329 commit 9592757

12 files changed

Lines changed: 675 additions & 389 deletions
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Polymorphine/Dev package.
5+
*
6+
* (c) Shudd3r <q3.shudder@gmail.com>
7+
*
8+
* This source file is subject to the MIT license that is bundled
9+
* with this source code in the file LICENSE.
10+
*/
11+
12+
namespace Polymorphine\Dev\Fixer;
13+
14+
use PhpCsFixer\Fixer\FixerInterface;
15+
use PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer;
16+
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
17+
use PhpCsFixer\Tokenizer\Tokens;
18+
use SplFileInfo;
19+
20+
21+
class MultiOrderedClassElementsFixer implements FixerInterface
22+
{
23+
private string $testPath;
24+
private OrderedClassElementsFixer $srcFixer;
25+
private OrderedClassElementsFixer $testFixer;
26+
27+
/**
28+
* @param string $testPath
29+
* @param array $srcOrder
30+
* @param array $testOrder
31+
*/
32+
public function __construct(string $testPath, array $srcOrder, array $testOrder)
33+
{
34+
$this->testPath = $testPath;
35+
$this->srcFixer = new OrderedClassElementsFixer();
36+
$this->testFixer = new OrderedClassElementsFixer();
37+
38+
$this->srcFixer->configure(['order' => $srcOrder, 'sort_algorithm' => 'none']);
39+
$this->testFixer->configure(['order' => $testOrder, 'sort_algorithm' => 'none']);
40+
}
41+
42+
public function getName(): string
43+
{
44+
return 'Polymorphine/multi_ordered_class_elements';
45+
}
46+
47+
public function getDefinition(): FixerDefinitionInterface
48+
{
49+
return $this->srcFixer->getDefinition();
50+
}
51+
52+
public function isCandidate(Tokens $tokens): bool
53+
{
54+
return $this->srcFixer->isCandidate($tokens);
55+
}
56+
57+
public function isRisky(): bool
58+
{
59+
return false;
60+
}
61+
62+
public function fix(SplFileInfo $file, Tokens $tokens): void
63+
{
64+
strpos($file->getPathname(), $this->testPath) === 0 && $this->isTestClass($tokens)
65+
? $this->testFixer->fix($file, $tokens)
66+
: $this->srcFixer->fix($file, $tokens);
67+
}
68+
69+
public function getPriority(): int
70+
{
71+
return $this->srcFixer->getPriority();
72+
}
73+
74+
public function supports(SplFileInfo $file): bool
75+
{
76+
return $this->srcFixer->supports($file);
77+
}
78+
79+
private function isTestClass(Tokens $tokens): bool
80+
{
81+
$classIdx = $tokens->getNextTokenOfKind(0, [[T_CLASS]]);
82+
if (!$classIdx) { return false; }
83+
84+
$className = $tokens[$classIdx + 2]->getContent();
85+
return substr($className, -4) === 'Test' || substr($className, -5) === 'Tests';
86+
}
87+
}

src/Fixer/ConstructorsFirstFixer.php renamed to src/Fixer/NamedConstructorsFirstStaticFixer.php

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@
1818
use SplFileInfo;
1919

2020

21-
final class ConstructorsFirstFixer implements FixerInterface
21+
final class NamedConstructorsFirstStaticFixer implements FixerInterface
2222
{
2323
private Tokens $tokens;
2424

2525
public function getName(): string
2626
{
27-
return 'Polymorphine/constructors_first';
27+
return 'Polymorphine/named_constructors_first_static';
2828
}
2929

3030
public function getDefinition(): FixerDefinitionInterface
3131
{
32-
return new FixerDefinition('Moves constructor methods (including static named constructors) to the top.', []);
32+
return new FixerDefinition('Moves named static constructor methods to the top.', []);
3333
}
3434

3535
public function getPriority(): int
@@ -56,24 +56,16 @@ public function fix(SplFileInfo $file, Tokens $tokens): void
5656
{
5757
$this->tokens = $tokens;
5858

59-
$classIdx = $this->tokens->getNextTokenOfKind(0, [[T_CLASS]]) + 2;
60-
$isConstruct = fn ($idx) => $this->tokens[$idx + 2]->getContent() === '__construct';
61-
$insertIdx = $this->getMethodIdx($classIdx, $isConstruct, false);
62-
if (!$insertIdx) { return; }
63-
64-
$construct = $this->getMethodIdx($classIdx, $isConstruct);
65-
if ($insertIdx < $construct) {
66-
$insertIdx = $this->moveMethod($construct, $insertIdx);
67-
}
68-
69-
$classTypes = $this->getClassTypes($classIdx);
70-
$isStaticConstructor = fn (int $idx) => $this->isStaticConstructor($idx, $classTypes);
59+
$classIdx = $this->tokens->getNextTokenOfKind(0, [[T_CLASS]]) + 2;
60+
$staticIdx = $this->getMethodIdx($classIdx, fn (int $idx) => $this->tokens[$idx - 2]->isGivenKind(T_STATIC));
61+
if (!$staticIdx) { return; }
7162

72-
$insertIdx = $this->getMethodIdx($insertIdx, $isStaticConstructor, false);
63+
$classTypes = $this->getClassTypes($classIdx);
64+
$insertIdx = $this->getMethodIdx($staticIdx, fn (int $idx) => !$this->isStaticConstructor($idx, $classTypes));
7365
if (!$insertIdx) { return; }
7466

7567
$idx = $insertIdx;
76-
while ($idx = $this->getMethodIdx($idx + 10, $isStaticConstructor)) {
68+
while ($idx = $this->getMethodIdx($idx + 10, fn (int $idx) => $this->isStaticConstructor($idx, $classTypes))) {
7769
$insertIdx = $this->moveMethod($idx, $insertIdx);
7870
}
7971
}
@@ -89,10 +81,10 @@ private function isStaticConstructor(int $idx, array $classTypes): bool
8981
return $returnType->isGivenKind(T_STRING) && isset($classTypes[$returnType->getContent()]);
9082
}
9183

92-
private function getMethodIdx(int $start, ?callable $condition = null, bool $expected = true): int
84+
private function getMethodIdx(int $start, callable $condition): int
9385
{
9486
$idx = $this->tokens->getNextTokenOfKind($start, [[T_FUNCTION]]);
95-
while ($idx && $condition && $condition($idx) !== $expected) {
87+
while ($idx && !$condition($idx)) {
9688
$idx = $this->tokens->getNextTokenOfKind($idx, [[T_FUNCTION]]);
9789
}
9890

src/FixerFactory.php

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ final class FixerFactory
5050
'no_useless_else' => true,
5151
'no_useless_return' => true,
5252
'non_printable_character' => ['use_escape_sequences_in_strings' => true],
53-
'ordered_class_elements' => true,
53+
'ordered_class_elements' => false,
5454
'ordered_imports' => false,
5555
'php_unit_strict' => false,
5656
'php_unit_method_casing' => false,
@@ -76,6 +76,7 @@ final class FixerFactory
7676
public static function createFor(string $launchFile): Config
7777
{
7878
$workingDir = dirname($launchFile);
79+
$testsPath = $workingDir . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR;
7980

8081
self::setHeaderFrom($launchFile);
8182

@@ -84,9 +85,28 @@ public static function createFor(string $launchFile): Config
8485
'square_brace_block', 'curly_brace_block'
8586
];
8687

88+
$srcOrder = [
89+
'use_trait', 'case', 'constant_public', 'constant_protected', 'constant_private',
90+
'property_public_static', 'property_protected_static', 'property_private_static',
91+
'method_public_static', 'method_protected_static', 'method_private_static',
92+
'property_public', 'property_protected', 'property_private',
93+
'construct', 'magic', 'method_public', 'destruct', 'method_protected', 'method_private'
94+
];
95+
96+
$testOrder = [
97+
'use_trait', 'constant_public', 'constant_protected', 'constant_private',
98+
'property_public_static', 'property_protected_static', 'property_private_static',
99+
'property_public', 'property_protected', 'property_private',
100+
'construct', 'phpunit', 'magic', 'destruct',
101+
'method_public', 'method_public_static',
102+
'method_protected', 'method_protected_static',
103+
'method_private', 'method_private_static'
104+
];
105+
87106
self::$rules['Polymorphine/double_line_before_class_definition'] = true;
88107
self::$rules['Polymorphine/no_trailing_comma_after_multiline_array'] = true;
89-
self::$rules['Polymorphine/constructors_first'] = true;
108+
self::$rules['Polymorphine/multi_ordered_class_elements'] = true;
109+
self::$rules['Polymorphine/named_constructors_first_static'] = true;
90110
self::$rules['Polymorphine/aligned_method_chain'] = true;
91111
self::$rules['Polymorphine/aligned_assignments'] = true;
92112
self::$rules['Polymorphine/aligned_array_values'] = true;
@@ -95,9 +115,8 @@ public static function createFor(string $launchFile): Config
95115
self::$rules['Polymorphine/declare_strict_first_line'] = true;
96116
self::$rules['Polymorphine/brace_after_multiline_param_method'] = true;
97117

98-
$excludeSamples = function (SplFileInfo $file) use ($workingDir) {
118+
$excludeSamples = function (SplFileInfo $file) use ($testsPath) {
99119
$filePath = $file->getPath();
100-
$testsPath = $workingDir . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR;
101120
$samplesDir = DIRECTORY_SEPARATOR . 'code-samples' . DIRECTORY_SEPARATOR;
102121
return strpos($filePath, $testsPath) !== 0 || strpos($filePath, $samplesDir) === false;
103122
};
@@ -111,7 +130,8 @@ public static function createFor(string $launchFile): Config
111130
->registerCustomFixers([
112131
new Fixer\DoubleLineBeforeClassDefinitionFixer(),
113132
new Fixer\NoTrailingCommaInMultilineArrayFixer(),
114-
new Fixer\ConstructorsFirstFixer(),
133+
new Fixer\MultiOrderedClassElementsFixer($testsPath, $srcOrder, $testOrder),
134+
new Fixer\NamedConstructorsFirstStaticFixer(),
115135
new Fixer\AlignedMethodChainFixer(),
116136
new Fixer\AlignedAssignmentsFixer(),
117137
new Fixer\AlignedArrayValuesFixer(),

0 commit comments

Comments
 (0)