Skip to content

Commit b422c03

Browse files
davidxkurkaDavid Kurka
andauthored
feat: add support for typed constants in AlphabeticallyOrderedConstantsSniff (#142)
Co-authored-by: David Kurka <[email protected]>
1 parent be52c85 commit b422c03

File tree

3 files changed

+69
-22
lines changed

3 files changed

+69
-22
lines changed

src/Cdn77/Sniffs/Ordering/AlphabeticallyOrderedConstantsSniff.php

Lines changed: 65 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,19 @@
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 TypeNameShape array{
39+
* type: TypeShape|null,
40+
* name: NameShape
41+
* }
42+
* @phpstan-type TypeShape array{
43+
* content: string,
44+
* ptr: int
45+
* }
3746
* @phpstan-type NameShape array{
3847
* content: string,
3948
* lowercaseContent: string,
@@ -89,7 +98,7 @@ public function process(File $phpcsFile, mixed $stackPtr): void
8998
}
9099
}
91100

92-
/** @param list<NameWithValueShape> $namesWithValues */
101+
/** @param list<TypeNameValueShape> $namesWithValues */
93102
private function fix(File $file, array $namesWithValues): void
94103
{
95104
$fixer = $file->fixer;
@@ -104,9 +113,19 @@ private function fix(File $file, array $namesWithValues): void
104113
foreach ($namesWithValues as $key => $nameWithValue) {
105114
$sortedNameAndValueToken = $sortedNameAndValueTokens[$key];
106115

116+
$typePointer = $nameWithValue['type']['ptr'] ?? null;
107117
$namePointer = $nameWithValue['name']['ptr'];
108-
FixerHelper::removeBetweenIncluding($file, $namePointer, $namePointer);
109-
$fixer->addContent($namePointer, $sortedNameAndValueToken['name']['content']);
118+
FixerHelper::removeBetweenIncluding($file, $typePointer ?? $namePointer, $namePointer);
119+
$fixer->addContent(
120+
$typePointer ?? $namePointer,
121+
$sortedNameAndValueToken['type'] === null ?
122+
$sortedNameAndValueToken['name']['content']
123+
: sprintf(
124+
'%s %s',
125+
$sortedNameAndValueToken['type']['content'],
126+
$sortedNameAndValueToken['name']['content'],
127+
),
128+
);
110129

111130
$value = $nameWithValue['value'];
112131
FixerHelper::removeBetweenIncluding($file, $value['startPtr'], $value['endPtr']);
@@ -116,7 +135,7 @@ private function fix(File $file, array $namesWithValues): void
116135
$fixer->endChangeset();
117136
}
118137

119-
/** @return array<string, list<NameWithValueShape>> */
138+
/** @return array<string, list<TypeNameValueShape>> */
120139
private function findConstantNamesWithValuesByVisibility(File $phpcsFile): array
121140
{
122141
$constantNamesWithValues = [];
@@ -128,13 +147,13 @@ private function findConstantNamesWithValuesByVisibility(File $phpcsFile): array
128147
}
129148

130149
$visibility = $this->getVisibility($phpcsFile, $stackPtr);
131-
$constantName = $this->findConstantName($phpcsFile, $stackPtr);
150+
$typeAndConstantName = $this->findTypeAndConstantName($phpcsFile, $stackPtr);
132151

133-
if ($constantName === null) {
152+
if ($typeAndConstantName === null) {
134153
continue;
135154
}
136155

137-
$equalsTokenPointer = $this->findEqualsPointer($phpcsFile, $constantName['ptr']);
156+
$equalsTokenPointer = $this->findEqualsPointer($phpcsFile, $typeAndConstantName['name']['ptr']);
138157

139158
if ($equalsTokenPointer === null) {
140159
continue;
@@ -147,7 +166,8 @@ private function findConstantNamesWithValuesByVisibility(File $phpcsFile): array
147166
}
148167

149168
$constantNamesWithValues[$visibility][] = [
150-
'name' => $constantName,
169+
'type' => $typeAndConstantName['type'],
170+
'name' => $typeAndConstantName['name'],
151171
'value' => $value,
152172
];
153173
}
@@ -170,25 +190,52 @@ private function getVisibility(File $phpcsFile, int $constStackPtr): string
170190
: 'public';
171191
}
172192

173-
/** @phpstan-return NameShape|null */
174-
private function findConstantName(File $phpcsFile, int $constStackPtr): array|null
193+
/** @phpstan-return TypeNameShape|null */
194+
private function findTypeAndConstantName(File $phpcsFile, int $constStackPtr): array|null
175195
{
176196
$tokens = $phpcsFile->getTokens();
177-
$constantNameTokenPointer = $phpcsFile->findNext(
178-
types: Tokens::$emptyTokens,
197+
$assignmentOperatorTokenPtr = $phpcsFile->findNext(
198+
types: [T_EQUAL, T_SEMICOLON],
179199
start: $constStackPtr + 1,
200+
);
201+
202+
if ($assignmentOperatorTokenPtr === false || $tokens[$assignmentOperatorTokenPtr]['code'] !== T_EQUAL) {
203+
return null;
204+
}
205+
206+
$constNameTokenPtr = $phpcsFile->findPrevious(
207+
types: Tokens::$emptyTokens,
208+
start: $assignmentOperatorTokenPtr - 1,
209+
end: $constStackPtr + 1,
180210
exclude: true,
181-
local: true,
182211
);
183212

184-
if ($constantNameTokenPointer === false || $tokens[$constantNameTokenPointer]['code'] !== T_STRING) {
213+
if ($constNameTokenPtr === false || $tokens[$constNameTokenPtr]['code'] !== T_STRING) {
185214
return null;
186215
}
187216

217+
$type = null;
218+
$typeTokenPtr = $phpcsFile->findPrevious(
219+
types: Tokens::$emptyTokens,
220+
start: $constNameTokenPtr - 1,
221+
end: $constStackPtr,
222+
exclude: true,
223+
);
224+
225+
if ($typeTokenPtr !== false && $tokens[$typeTokenPtr]['code'] === T_STRING) {
226+
$type = [
227+
'content' => $tokens[$typeTokenPtr]['content'],
228+
'ptr' => $typeTokenPtr,
229+
];
230+
}
231+
188232
return [
189-
'content' => $tokens[$constantNameTokenPointer]['content'],
190-
'lowercaseContent' => strtolower($tokens[$constantNameTokenPointer]['content']),
191-
'ptr' => $constantNameTokenPointer,
233+
'type' => $type,
234+
'name' => [
235+
'content' => $tokens[$constNameTokenPtr]['content'],
236+
'lowercaseContent' => strtolower($tokens[$constNameTokenPtr]['content']),
237+
'ptr' => $constNameTokenPtr,
238+
],
192239
];
193240
}
194241

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)