Skip to content

Commit 79579b7

Browse files
author
David Kurka
committed
feat: add support for typed constants in AlphabeticallyOrderedConstantsSniff
1 parent be52c85 commit 79579b7

File tree

3 files changed

+62
-12
lines changed

3 files changed

+62
-12
lines changed

src/Cdn77/Sniffs/Ordering/AlphabeticallyOrderedConstantsSniff.php

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,15 @@
3030
use const T_WHITESPACE;
3131

3232
/**
33-
* @phpstan-type NameWithValueShape array{
33+
* @phpstan-type TypeNameValueShape array{
34+
* type: TypeShape|null,
3435
* name: NameShape,
3536
* value: ValueShape
3637
* }
38+
* @phpstan-type TypeShape array{
39+
* content: string,
40+
* ptr: int
41+
* }
3742
* @phpstan-type NameShape array{
3843
* content: string,
3944
* lowercaseContent: string,
@@ -89,7 +94,7 @@ public function process(File $phpcsFile, mixed $stackPtr): void
8994
}
9095
}
9196

92-
/** @param list<NameWithValueShape> $namesWithValues */
97+
/** @param list<TypeNameValueShape> $namesWithValues */
9398
private function fix(File $file, array $namesWithValues): void
9499
{
95100
$fixer = $file->fixer;
@@ -104,9 +109,19 @@ private function fix(File $file, array $namesWithValues): void
104109
foreach ($namesWithValues as $key => $nameWithValue) {
105110
$sortedNameAndValueToken = $sortedNameAndValueTokens[$key];
106111

112+
$typePointer = $nameWithValue['type']['ptr'] ?? null;
107113
$namePointer = $nameWithValue['name']['ptr'];
108-
FixerHelper::removeBetweenIncluding($file, $namePointer, $namePointer);
109-
$fixer->addContent($namePointer, $sortedNameAndValueToken['name']['content']);
114+
FixerHelper::removeBetweenIncluding($file, $typePointer ?? $namePointer, $namePointer);
115+
$fixer->addContent(
116+
$typePointer ?? $namePointer,
117+
$sortedNameAndValueToken['type'] === null ?
118+
$sortedNameAndValueToken['name']['content']
119+
: sprintf(
120+
'%s %s',
121+
$sortedNameAndValueToken['type']['content'],
122+
$sortedNameAndValueToken['name']['content'],
123+
),
124+
);
110125

111126
$value = $nameWithValue['value'];
112127
FixerHelper::removeBetweenIncluding($file, $value['startPtr'], $value['endPtr']);
@@ -116,7 +131,7 @@ private function fix(File $file, array $namesWithValues): void
116131
$fixer->endChangeset();
117132
}
118133

119-
/** @return array<string, list<NameWithValueShape>> */
134+
/** @return array<string, list<TypeNameValueShape>> */
120135
private function findConstantNamesWithValuesByVisibility(File $phpcsFile): array
121136
{
122137
$constantNamesWithValues = [];
@@ -128,7 +143,8 @@ private function findConstantNamesWithValuesByVisibility(File $phpcsFile): array
128143
}
129144

130145
$visibility = $this->getVisibility($phpcsFile, $stackPtr);
131-
$constantName = $this->findConstantName($phpcsFile, $stackPtr);
146+
$type = $this->findType($phpcsFile, $stackPtr);
147+
$constantName = $this->findConstantName($phpcsFile, $type['ptr'] ?? $stackPtr);
132148

133149
if ($constantName === null) {
134150
continue;
@@ -147,6 +163,7 @@ private function findConstantNamesWithValuesByVisibility(File $phpcsFile): array
147163
}
148164

149165
$constantNamesWithValues[$visibility][] = [
166+
'type' => $type,
150167
'name' => $constantName,
151168
'value' => $value,
152169
];
@@ -170,13 +187,46 @@ private function getVisibility(File $phpcsFile, int $constStackPtr): string
170187
: 'public';
171188
}
172189

190+
/** @phpstan-return TypeShape|null */
191+
private function findType(File $phpcsFile, int $constStackPtr): array|null
192+
{
193+
$tokens = $phpcsFile->getTokens();
194+
$possibleTypeTokenPointer = $phpcsFile->findNext(
195+
types: Tokens::$emptyTokens,
196+
start: $constStackPtr + 1,
197+
exclude: true,
198+
local: true,
199+
);
200+
201+
if ($possibleTypeTokenPointer === false || $tokens[$possibleTypeTokenPointer]['code'] !== T_STRING) {
202+
return null;
203+
}
204+
205+
$possibleTypeToken = $tokens[$possibleTypeTokenPointer];
206+
$afterPossibleTypeTokenPointer = $phpcsFile->findNext(
207+
types: Tokens::$emptyTokens,
208+
start: $possibleTypeTokenPointer + 1,
209+
exclude: true,
210+
local: true,
211+
);
212+
213+
if ($afterPossibleTypeTokenPointer === false || $tokens[$afterPossibleTypeTokenPointer]['code'] !== T_STRING) {
214+
return null;
215+
}
216+
217+
return [
218+
'content' => $possibleTypeToken['content'],
219+
'ptr' => $possibleTypeTokenPointer,
220+
];
221+
}
222+
173223
/** @phpstan-return NameShape|null */
174-
private function findConstantName(File $phpcsFile, int $constStackPtr): array|null
224+
private function findConstantName(File $phpcsFile, int $constOrTypeStackPtr): array|null
175225
{
176226
$tokens = $phpcsFile->getTokens();
177227
$constantNameTokenPointer = $phpcsFile->findNext(
178228
types: Tokens::$emptyTokens,
179-
start: $constStackPtr + 1,
229+
start: $constOrTypeStackPtr + 1,
180230
exclude: true,
181231
local: true,
182232
);

tests/Sniffs/Ordering/data/AlphabeticallyOrderedConstantsSniffTest.fixed.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ final class TestClass
1616
public const C = 'c' . PHP_EOL;
1717
public const D = [123, 'test'];
1818

19-
protected const E = 'e';
20-
protected const F = 'f';
19+
protected const string E = 'e';
20+
protected const int F = 123;
2121
protected const G = 'g';
2222
protected const Ha = 'h';
2323
protected const HB = 'h';

tests/Sniffs/Ordering/data/AlphabeticallyOrderedConstantsSniffTest.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ final class TestClass
1616
public const D = [123, 'test'];
1717
public const B = 'b';
1818

19-
protected const E = 'e';
2019
protected const G = 'g';
21-
protected const F = 'f';
20+
protected const string E = 'e';
21+
protected const int F = 123;
2222
protected const HB = 'h';
2323
protected const Ha = 'h';
2424

0 commit comments

Comments
 (0)