1616final class OperatorLinebreakFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, DeprecatingFixerInterface
1717{
1818 private const BOOLEAN_OPERATORS = [
19- '&& ' ,
20- '|| ' ,
21- 'and ' ,
22- 'or ' ,
23- 'xor ' ,
19+ '&& ' => T_BOOLEAN_AND ,
20+ '|| ' => T_BOOLEAN_OR ,
21+ 'and ' => T_LOGICAL_AND ,
22+ 'or ' => T_LOGICAL_OR ,
23+ 'xor ' => T_LOGICAL_XOR ,
2424 ];
2525
2626 private const NON_BOOLEAN_OPERATORS = [
27- '= ' ,
28- '* ' ,
29- '/ ' ,
30- '% ' ,
31- '< ' ,
32- '> ' ,
33- '| ' ,
34- '^ ' ,
35- '+ ' ,
36- '- ' ,
37- '& ' ,
38- '&= ' ,
39- '.= ' ,
40- '/= ' ,
41- '=> ' ,
42- '== ' ,
43- '>= ' ,
44- '=== ' ,
45- '!= ' ,
46- '<> ' ,
47- '!== ' ,
48- '<= ' ,
49- '-= ' ,
50- '%= ' ,
51- '*= ' ,
52- '|= ' ,
53- '+= ' ,
54- '<< ' ,
55- '<<= ' ,
56- '>> ' ,
57- '>>= ' ,
58- '^= ' ,
59- '** ' ,
60- '**= ' ,
61- '<=> ' ,
62- '?? ' ,
27+ '= ' => true ,
28+ '* ' => true ,
29+ '/ ' => true ,
30+ '% ' => true ,
31+ '< ' => true ,
32+ '> ' => true ,
33+ '| ' => true ,
34+ '^ ' => true ,
35+ '+ ' => true ,
36+ '- ' => true ,
37+ '& ' => true ,
38+ '&= ' => true ,
39+ '.= ' => true ,
40+ '/= ' => true ,
41+ '=> ' => true ,
42+ '== ' => true ,
43+ '>= ' => true ,
44+ '=== ' => true ,
45+ '!= ' => true ,
46+ '<> ' => true ,
47+ '!== ' => true ,
48+ '<= ' => true ,
49+ '-= ' => true ,
50+ '%= ' => true ,
51+ '*= ' => true ,
52+ '|= ' => true ,
53+ '+= ' => true ,
54+ '<< ' => true ,
55+ '<<= ' => true ,
56+ '>> ' => true ,
57+ '>>= ' => true ,
58+ '^= ' => true ,
59+ '** ' => true ,
60+ '**= ' => true ,
61+ '<=> ' => true ,
62+ '?? ' => true ,
63+ '? ' => true ,
64+ ': ' => true ,
6365 ];
6466
65- /** @var string[] */
67+ /** @var array< string, int|true> */
6668 private $ operators ;
6769
6870 /** @var string */
@@ -140,21 +142,17 @@ public function getPullRequestId(): int
140142 private function fixMoveToTheBeginning (Tokens $ tokens ): void
141143 {
142144 for ($ index = 0 ; $ index < $ tokens ->count (); $ index ++) {
143- $ tokenContent = \strtolower ($ tokens [$ index ]->getContent ());
144-
145- if (!\in_array ($ tokenContent , $ this ->operators , true )) {
145+ $ indices = $ this ->getOperatorIndices ($ tokens , $ index );
146+ if ($ indices === null ) {
146147 continue ;
147148 }
148149
149- $ nextIndex = $ tokens ->getNextMeaningfulToken ($ index );
150+ $ nextIndex = $ tokens ->getNextMeaningfulToken (\max ( $ indices ) );
150151 for ($ i = $ nextIndex - 1 ; $ i > $ index ; $ i --) {
151- if ($ tokens [$ i ]->isWhitespace () && Preg::match ('/\R/ ' , $ tokens [$ i ]->getContent ()) === 1 ) {
152- $ operator = clone $ tokens [$ index ];
153- $ tokens ->clearAt ($ index );
154- if ($ tokens [$ index - 1 ]->isWhitespace ()) {
155- $ tokens ->clearTokenAndMergeSurroundingWhitespace ($ index - 1 );
156- }
157- $ tokens ->insertAt ($ nextIndex , [$ operator , new Token ([T_WHITESPACE , ' ' ])]);
152+ if ($ tokens [$ i ]->isWhitespace () && Preg::match ('/\R/u ' , $ tokens [$ i ]->getContent ()) === 1 ) {
153+ $ operators = $ this ->getReplacementsAndClear ($ tokens , $ indices , -1 );
154+ $ tokens ->insertAt ($ nextIndex , \array_merge ($ operators , [new Token ([T_WHITESPACE , ' ' ])]));
155+
158156 break ;
159157 }
160158 }
@@ -165,25 +163,68 @@ private function fixMoveToTheBeginning(Tokens $tokens): void
165163 private function fixMoveToTheEnd (Tokens $ tokens ): void
166164 {
167165 for ($ index = $ tokens ->count () - 1 ; $ index > 0 ; $ index --) {
168- $ tokenContent = \strtolower ($ tokens [$ index ]->getContent ());
169-
170- if (!\in_array ($ tokenContent , $ this ->operators , true )) {
166+ $ indices = $ this ->getOperatorIndices ($ tokens , $ index );
167+ if ($ indices === null ) {
171168 continue ;
172169 }
173170
174- $ prevIndex = $ tokens ->getPrevMeaningfulToken ($ index );
171+ $ prevIndex = $ tokens ->getPrevMeaningfulToken (\min ( $ indices ) );
175172 for ($ i = $ prevIndex + 1 ; $ i < $ index ; $ i ++) {
176- if ($ tokens [$ i ]->isWhitespace () && Preg::match ('/\R/ ' , $ tokens [$ i ]->getContent ()) === 1 ) {
177- $ operator = clone $ tokens [$ index ];
178- $ tokens ->clearAt ($ index );
179- if ($ tokens [$ index + 1 ]->isWhitespace ()) {
180- $ tokens ->clearTokenAndMergeSurroundingWhitespace ($ index + 1 );
181- }
182- $ tokens ->insertAt ($ prevIndex + 1 , [new Token ([T_WHITESPACE , ' ' ]), $ operator ]);
173+ if ($ tokens [$ i ]->isWhitespace () && Preg::match ('/\R/u ' , $ tokens [$ i ]->getContent ()) === 1 ) {
174+ $ operators = $ this ->getReplacementsAndClear ($ tokens , $ indices , 1 );
175+ $ tokens ->insertAt ($ prevIndex + 1 , \array_merge ([new Token ([T_WHITESPACE , ' ' ])], $ operators ));
176+
183177 break ;
184178 }
185179 }
186180 $ index = $ prevIndex ;
187181 }
188182 }
183+
184+ /**
185+ * @return null|int[]
186+ */
187+ private function getOperatorIndices (Tokens $ tokens , int $ index ): ?array
188+ {
189+ if (!isset ($ this ->operators [\strtolower ($ tokens [$ index ]->getContent ())])) {
190+ return null ;
191+ }
192+
193+ if (isset ($ this ->operators ['? ' ]) && $ tokens [$ index ]->getContent () === '? ' ) {
194+ $ nextIndex = $ tokens ->getNextMeaningfulToken ($ index );
195+ if ($ tokens [$ nextIndex ]->getContent () === ': ' ) {
196+ return [$ index , $ nextIndex ];
197+ }
198+ }
199+
200+ if (isset ($ this ->operators [': ' ]) && $ tokens [$ index ]->getContent () === ': ' ) {
201+ $ prevIndex = $ tokens ->getPrevMeaningfulToken ($ index );
202+ if ($ tokens [$ prevIndex ]->getContent () === '? ' ) {
203+ return [$ prevIndex , $ index ];
204+ }
205+ }
206+
207+ return [$ index ];
208+ }
209+
210+ /**
211+ * @param int[] $indices
212+ *
213+ * @return Token[]
214+ */
215+ private function getReplacementsAndClear (Tokens $ tokens , array $ indices , int $ direction ): array
216+ {
217+ return \array_map (
218+ static function ($ index ) use ($ tokens , $ direction ) {
219+ $ clone = $ tokens [$ index ];
220+ if ($ tokens [$ index + $ direction ]->isWhitespace ()) {
221+ $ tokens ->clearAt ($ index + $ direction );
222+ }
223+ $ tokens ->clearAt ($ index );
224+
225+ return $ clone ;
226+ },
227+ $ indices
228+ );
229+ }
189230}
0 commit comments