12
12
* with this source code in the file LICENSE.
13
13
*/
14
14
15
+ // PhpCsFixer\Fixer\Basic;
15
16
namespace NetteCodingStandard \Fixer \Basic ;
16
17
17
18
use PhpCsFixer \AbstractFixer ;
18
19
use PhpCsFixer \Fixer \ConfigurableFixerInterface ;
20
+ use PhpCsFixer \Fixer \ConfigurableFixerTrait ;
19
21
use PhpCsFixer \Fixer \Indentation ;
20
22
use PhpCsFixer \Fixer \WhitespacesAwareFixerInterface ;
21
23
use PhpCsFixer \FixerConfiguration \FixerConfigurationResolver ;
24
26
use PhpCsFixer \FixerDefinition \CodeSample ;
25
27
use PhpCsFixer \FixerDefinition \FixerDefinition ;
26
28
use PhpCsFixer \FixerDefinition \FixerDefinitionInterface ;
27
- use PhpCsFixer \FixerDefinition \VersionSpecification ;
28
- use PhpCsFixer \FixerDefinition \VersionSpecificCodeSample ;
29
29
use PhpCsFixer \Preg ;
30
30
use PhpCsFixer \Tokenizer \CT ;
31
31
use PhpCsFixer \Tokenizer \Token ;
32
32
use PhpCsFixer \Tokenizer \Tokens ;
33
33
use PhpCsFixer \Tokenizer \TokensAnalyzer ;
34
34
35
- final class CurlyBracesPositionFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface
35
+ /**
36
+ * @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
37
+ *
38
+ * @phpstan-type _AutogeneratedInputConfiguration array{
39
+ * allow_single_line_anonymous_functions?: bool,
40
+ * allow_single_line_empty_anonymous_classes?: bool,
41
+ * anonymous_classes_opening_brace?: 'next_line_unless_newline_at_signature_end'|'same_line',
42
+ * anonymous_functions_opening_brace?: 'next_line_unless_newline_at_signature_end'|'same_line',
43
+ * classes_opening_brace?: 'next_line_unless_newline_at_signature_end'|'same_line',
44
+ * control_structures_opening_brace?: 'next_line_unless_newline_at_signature_end'|'same_line',
45
+ * functions_opening_brace?: 'next_line_unless_newline_at_signature_end'|'same_line'
46
+ * }
47
+ * @phpstan-type _AutogeneratedComputedConfiguration array{
48
+ * allow_single_line_anonymous_functions: bool,
49
+ * allow_single_line_empty_anonymous_classes: bool,
50
+ * anonymous_classes_opening_brace: 'next_line_unless_newline_at_signature_end'|'same_line',
51
+ * anonymous_functions_opening_brace: 'next_line_unless_newline_at_signature_end'|'same_line',
52
+ * classes_opening_brace: 'next_line_unless_newline_at_signature_end'|'same_line',
53
+ * control_structures_opening_brace: 'next_line_unless_newline_at_signature_end'|'same_line',
54
+ * functions_opening_brace: 'next_line_unless_newline_at_signature_end'|'same_line'
55
+ * }
56
+ */
57
+ final class BracesPositionFixer extends AbstractFixer implements ConfigurableFixerInterface, WhitespacesAwareFixerInterface
36
58
{
59
+ /** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
60
+ use ConfigurableFixerTrait;
61
+
37
62
use Indentation;
38
63
39
64
/**
@@ -46,13 +71,10 @@ final class CurlyBracesPositionFixer extends AbstractFixer implements Configurab
46
71
*/
47
72
public const SAME_LINE = 'same_line ' ;
48
73
49
- /**
50
- * {@inheritdoc}
51
- */
52
74
public function getDefinition (): FixerDefinitionInterface
53
75
{
54
76
return new FixerDefinition (
55
- 'Curly braces must be placed as configured. ' ,
77
+ 'Braces must be placed as configured. ' ,
56
78
[
57
79
new CodeSample (
58
80
'<?php
@@ -70,15 +92,11 @@ function foo() {
70
92
{
71
93
bar();
72
94
}
73
- '
74
- ),
75
- new VersionSpecificCodeSample (
76
- '<?php
95
+
77
96
$foo = new class
78
97
{
79
98
};
80
- ' ,
81
- new VersionSpecification (70000 )
99
+ '
82
100
),
83
101
new CodeSample (
84
102
'<?php
@@ -111,20 +129,18 @@ class Foo
111
129
' ,
112
130
['classes_opening_brace ' => self ::SAME_LINE ]
113
131
),
114
- new VersionSpecificCodeSample (
132
+ new CodeSample (
115
133
'<?php
116
134
$foo = new class {
117
135
};
118
136
' ,
119
- new VersionSpecification (70000 ),
120
137
['anonymous_classes_opening_brace ' => self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END ]
121
138
),
122
- new VersionSpecificCodeSample (
139
+ new CodeSample (
123
140
'<?php
124
141
$foo = new class { };
125
142
$bar = new class { private $baz; };
126
143
' ,
127
- new VersionSpecification (70000 ),
128
144
['allow_single_line_empty_anonymous_classes ' => true ]
129
145
),
130
146
new CodeSample (
@@ -139,9 +155,6 @@ class Foo
139
155
);
140
156
}
141
157
142
- /**
143
- * {@inheritdoc}
144
- */
145
158
public function isCandidate (Tokens $ tokens ): bool
146
159
{
147
160
return $ tokens ->isTokenKindFound ('{ ' );
@@ -150,16 +163,49 @@ public function isCandidate(Tokens $tokens): bool
150
163
/**
151
164
* {@inheritdoc}
152
165
*
153
- * Must run after ControlStructureBracesFixer.
166
+ * Must run before SingleLineEmptyBodyFixer, StatementIndentationFixer.
167
+ * Must run after ControlStructureBracesFixer, NoMultipleStatementsPerLineFixer.
154
168
*/
155
169
public function getPriority (): int
156
170
{
157
- return parent ::getPriority ();
171
+ return -2 ;
172
+ }
173
+
174
+ /** @protected */
175
+ public function createConfigurationDefinition (): FixerConfigurationResolverInterface
176
+ {
177
+ return new FixerConfigurationResolver ([
178
+ (new FixerOptionBuilder ('control_structures_opening_brace ' , 'The position of the opening brace of control structures‘ body. ' ))
179
+ ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
180
+ ->setDefault (self ::SAME_LINE )
181
+ ->getOption (),
182
+ (new FixerOptionBuilder ('functions_opening_brace ' , 'The position of the opening brace of functions‘ body. ' ))
183
+ ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
184
+ ->setDefault (self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END )
185
+ ->getOption (),
186
+ (new FixerOptionBuilder ('anonymous_functions_opening_brace ' , 'The position of the opening brace of anonymous functions‘ body. ' ))
187
+ ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
188
+ ->setDefault (self ::SAME_LINE )
189
+ ->getOption (),
190
+ (new FixerOptionBuilder ('classes_opening_brace ' , 'The position of the opening brace of classes‘ body. ' ))
191
+ ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
192
+ ->setDefault (self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END )
193
+ ->getOption (),
194
+ (new FixerOptionBuilder ('anonymous_classes_opening_brace ' , 'The position of the opening brace of anonymous classes‘ body. ' ))
195
+ ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
196
+ ->setDefault (self ::SAME_LINE )
197
+ ->getOption (),
198
+ (new FixerOptionBuilder ('allow_single_line_empty_anonymous_classes ' , 'Allow anonymous classes to have opening and closing braces on the same line. ' ))
199
+ ->setAllowedTypes (['bool ' ])
200
+ ->setDefault (true )
201
+ ->getOption (),
202
+ (new FixerOptionBuilder ('allow_single_line_anonymous_functions ' , 'Allow anonymous functions to have opening and closing braces on the same line. ' ))
203
+ ->setAllowedTypes (['bool ' ])
204
+ ->setDefault (true )
205
+ ->getOption (),
206
+ ]);
158
207
}
159
208
160
- /**
161
- * {@inheritdoc}
162
- */
163
209
protected function applyFix (\SplFileInfo $ file , Tokens $ tokens ): void
164
210
{
165
211
$ classyTokens = Token::getClassyTokenKinds ();
@@ -181,7 +227,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
181
227
$ openBraceIndex = $ tokens ->getNextTokenOfKind ($ index , ['{ ' ]);
182
228
183
229
if ($ tokensAnalyzer ->isAnonymousClass ($ index )) {
184
- $ allowSingleLineIfEmpty = $ this ->configuration ['allow_single_line_empty_anonymous_classes ' ];
230
+ $ allowSingleLineIfEmpty = true === $ this ->configuration ['allow_single_line_empty_anonymous_classes ' ];
185
231
$ positionOption = 'anonymous_classes_opening_brace ' ;
186
232
} else {
187
233
$ positionOption = 'classes_opening_brace ' ;
@@ -194,7 +240,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
194
240
}
195
241
196
242
if ($ tokensAnalyzer ->isLambda ($ index )) {
197
- $ allowSingleLine = $ this ->configuration ['allow_single_line_anonymous_functions ' ];
243
+ $ allowSingleLine = true === $ this ->configuration ['allow_single_line_anonymous_functions ' ];
198
244
$ positionOption = 'anonymous_functions_opening_brace ' ;
199
245
} else {
200
246
$ positionOption = 'functions_opening_brace ' ;
@@ -223,7 +269,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
223
269
224
270
if (
225
271
($ allowSingleLineIfEmpty && !$ tokenInsideBraces ->isWhitespace () && !$ tokenInsideBraces ->isComment ())
226
- || ($ tokenInsideBraces ->isWhitespace () && 1 === Preg::match ('/\R/ ' , $ tokenInsideBraces ->getContent ()))
272
+ || ($ tokenInsideBraces ->isWhitespace () && Preg::match ('/\R/ ' , $ tokenInsideBraces ->getContent ()))
227
273
) {
228
274
$ addNewlinesInsideBraces = true ;
229
275
@@ -252,20 +298,18 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
252
298
if (self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END === $ this ->configuration [$ positionOption ]) {
253
299
$ whitespace = $ this ->whitespacesConfig ->getLineEnding ().$ this ->getLineIndentation ($ tokens , $ index );
254
300
255
- $ colon = false ;
256
301
$ previousTokenIndex = $ openBraceIndex ;
257
302
do {
258
303
$ previousTokenIndex = $ tokens ->getPrevMeaningfulToken ($ previousTokenIndex );
259
- $ colon = $ colon || $ tokens [$ previousTokenIndex ]->isGivenKind ([CT ::T_TYPE_COLON ]);
260
- } while ($ tokens [$ previousTokenIndex ]->isGivenKind ([CT ::T_TYPE_COLON , CT ::T_NULLABLE_TYPE , T_STRING , T_NS_SEPARATOR , CT ::T_ARRAY_TYPEHINT , T_STATIC , CT ::T_TYPE_ALTERNATION , CT ::T_TYPE_INTERSECTION ]));
304
+ } while ($ tokens [$ previousTokenIndex ]->isGivenKind ([CT ::T_TYPE_COLON , CT ::T_NULLABLE_TYPE , T_STRING , T_NS_SEPARATOR , CT ::T_ARRAY_TYPEHINT , T_STATIC , CT ::T_TYPE_ALTERNATION , CT ::T_TYPE_INTERSECTION , T_CALLABLE , CT ::T_DISJUNCTIVE_NORMAL_FORM_TYPE_PARENTHESIS_OPEN , CT ::T_DISJUNCTIVE_NORMAL_FORM_TYPE_PARENTHESIS_CLOSE ]));
261
305
262
- if (! $ colon && $ tokens [$ previousTokenIndex ]->equals (') ' )) {
306
+ if ($ tokens [$ previousTokenIndex ]->equals (') ' )) {
263
307
if ($ tokens [--$ previousTokenIndex ]->isComment ()) {
264
308
--$ previousTokenIndex ;
265
309
}
266
310
if (
267
311
$ tokens [$ previousTokenIndex ]->isWhitespace ()
268
- && 1 === Preg::match ('/\R/ ' , $ tokens [$ previousTokenIndex ]->getContent ())
312
+ && Preg::match ('/\R/ ' , $ tokens [$ previousTokenIndex ]->getContent ())
269
313
) {
270
314
$ whitespace = ' ' ;
271
315
}
@@ -314,7 +358,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
314
358
} else {
315
359
$ tokens ->clearAt ($ openBraceIndex + 1 );
316
360
}
317
- } else {
361
+ } elseif ( $ tokens [ $ openBraceIndex - 1 ]-> isWhitespace ()) {
318
362
$ tokens ->clearAt ($ openBraceIndex - 1 );
319
363
}
320
364
}
@@ -344,10 +388,14 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
344
388
continue ;
345
389
}
346
390
347
- for ($ prevIndex = $ closeBraceIndex - 1 ; $ tokens ->isEmptyAt ($ prevIndex ); --$ prevIndex );
391
+ $ prevIndex = $ closeBraceIndex - 1 ;
392
+ while ($ tokens ->isEmptyAt ($ prevIndex )) {
393
+ --$ prevIndex ;
394
+ }
348
395
349
396
$ prevToken = $ tokens [$ prevIndex ];
350
- if ($ prevToken ->isWhitespace () && 1 === Preg::match ('/\R/ ' , $ prevToken ->getContent ())) {
397
+
398
+ if ($ prevToken ->isWhitespace () && Preg::match ('/\R/ ' , $ prevToken ->getContent ())) {
351
399
continue ;
352
400
}
353
401
@@ -356,43 +404,6 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
356
404
}
357
405
}
358
406
359
- /**
360
- * {@inheritdoc}
361
- */
362
- protected function createConfigurationDefinition (): FixerConfigurationResolverInterface
363
- {
364
- return new FixerConfigurationResolver ([
365
- (new FixerOptionBuilder ('control_structures_opening_brace ' , 'the position of the opening brace of control structures body. ' ))
366
- ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
367
- ->setDefault (self ::SAME_LINE )
368
- ->getOption (),
369
- (new FixerOptionBuilder ('functions_opening_brace ' , 'the position of the opening brace of functions body. ' ))
370
- ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
371
- ->setDefault (self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END )
372
- ->getOption (),
373
- (new FixerOptionBuilder ('anonymous_functions_opening_brace ' , 'the position of the opening brace of anonymous functions body. ' ))
374
- ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
375
- ->setDefault (self ::SAME_LINE )
376
- ->getOption (),
377
- (new FixerOptionBuilder ('classes_opening_brace ' , 'the position of the opening brace of classes body. ' ))
378
- ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
379
- ->setDefault (self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END )
380
- ->getOption (),
381
- (new FixerOptionBuilder ('anonymous_classes_opening_brace ' , 'the position of the opening brace of anonymous classes body. ' ))
382
- ->setAllowedValues ([self ::NEXT_LINE_UNLESS_NEWLINE_AT_SIGNATURE_END , self ::SAME_LINE ])
383
- ->setDefault (self ::SAME_LINE )
384
- ->getOption (),
385
- (new FixerOptionBuilder ('allow_single_line_empty_anonymous_classes ' , 'allow anonymous classes to have opening and closing braces on the same line. ' ))
386
- ->setAllowedTypes (['bool ' ])
387
- ->setDefault (true )
388
- ->getOption (),
389
- (new FixerOptionBuilder ('allow_single_line_anonymous_functions ' , 'allow anonymous functions to have opening and closing braces on the same line. ' ))
390
- ->setAllowedTypes (['bool ' ])
391
- ->setDefault (true )
392
- ->getOption (),
393
- ]);
394
- }
395
-
396
407
private function findParenthesisEnd (Tokens $ tokens , int $ structureTokenIndex ): int
397
408
{
398
409
$ nextIndex = $ tokens ->getNextMeaningfulToken ($ structureTokenIndex );
@@ -411,7 +422,7 @@ private function isFollowedByNewLine(Tokens $tokens, int $index): bool
411
422
for (++$ index , $ max = \count ($ tokens ) - 1 ; $ index < $ max ; ++$ index ) {
412
423
$ token = $ tokens [$ index ];
413
424
if (!$ token ->isComment ()) {
414
- return $ token ->isWhitespace () && 1 === Preg::match ('/\R/ ' , $ token ->getContent ());
425
+ return $ token ->isWhitespace () && Preg::match ('/\R/ ' , $ token ->getContent ());
415
426
}
416
427
}
417
428
@@ -422,15 +433,10 @@ private function hasCommentOnSameLine(Tokens $tokens, int $index): bool
422
433
{
423
434
$ token = $ tokens [$ index + 1 ];
424
435
425
- if ($ token ->isWhitespace () && 1 !== Preg::match ('/\R/ ' , $ token ->getContent ())) {
436
+ if ($ token ->isWhitespace () && ! Preg::match ('/\R/ ' , $ token ->getContent ())) {
426
437
$ token = $ tokens [$ index + 2 ];
427
438
}
428
439
429
440
return $ token ->isComment ();
430
441
}
431
-
432
- public function getName (): string
433
- {
434
- return 'Nette/ ' . parent ::getName ();
435
- }
436
442
}
0 commit comments