@@ -2602,7 +2602,9 @@ protected function processAdditional()
2602
2602
2603
2603
$ this ->createAttributesNestingMap ();
2604
2604
2605
- $ numTokens = count ($ this ->tokens );
2605
+ $ numTokens = count ($ this ->tokens );
2606
+ $ lastSeenTypeToken = $ numTokens ;
2607
+
2606
2608
for ($ i = ($ numTokens - 1 ); $ i >= 0 ; $ i --) {
2607
2609
// Check for any unset scope conditions due to alternate IF/ENDIF syntax.
2608
2610
if (isset ($ this ->tokens [$ i ]['scope_opener ' ]) === true
@@ -3036,9 +3038,14 @@ protected function processAdditional()
3036
3038
continue ;
3037
3039
} else if ($ this ->tokens [$ i ]['code ' ] === T_BITWISE_OR
3038
3040
|| $ this ->tokens [$ i ]['code ' ] === T_BITWISE_AND
3039
- || $ this ->tokens [$ i ]['code ' ] === T_OPEN_PARENTHESIS
3040
3041
|| $ this ->tokens [$ i ]['code ' ] === T_CLOSE_PARENTHESIS
3041
3042
) {
3043
+ if ($ lastSeenTypeToken < $ i ) {
3044
+ // We've already examined this code to check if it is a type declaration and concluded it wasn't.
3045
+ // No need to do it again.
3046
+ continue ;
3047
+ }
3048
+
3042
3049
/*
3043
3050
Convert "|" to T_TYPE_UNION or leave as T_BITWISE_OR.
3044
3051
Convert "&" to T_TYPE_INTERSECTION or leave as T_BITWISE_AND.
@@ -3133,9 +3140,14 @@ protected function processAdditional()
3133
3140
3134
3141
$ typeTokenCountBefore = 0 ;
3135
3142
$ typeOperators = [$ i ];
3143
+ $ parenthesesCount = 0 ;
3136
3144
$ confirmed = false ;
3137
3145
$ maybeNullable = null ;
3138
3146
3147
+ if ($ this ->tokens [$ i ]['code ' ] === T_OPEN_PARENTHESIS || $ this ->tokens [$ i ]['code ' ] === T_CLOSE_PARENTHESIS ) {
3148
+ ++$ parenthesesCount ;
3149
+ }
3150
+
3139
3151
for ($ x = ($ i - 1 ); $ x >= 0 ; $ x --) {
3140
3152
if (isset (Tokens::$ emptyTokens [$ this ->tokens [$ x ]['code ' ]]) === true ) {
3141
3153
continue ;
@@ -3167,7 +3179,7 @@ protected function processAdditional()
3167
3179
$ confirmed = true ;
3168
3180
break ;
3169
3181
} else {
3170
- // This may still be an arrow function which hasn't be handled yet.
3182
+ // This may still be an arrow function which hasn't been handled yet.
3171
3183
for ($ y = ($ x - 1 ); $ y > 0 ; $ y --) {
3172
3184
if (isset (Tokens::$ emptyTokens [$ this ->tokens [$ y ]['code ' ]]) === false
3173
3185
&& $ this ->tokens [$ y ]['code ' ] !== T_BITWISE_AND
@@ -3202,11 +3214,13 @@ protected function processAdditional()
3202
3214
continue ;
3203
3215
}
3204
3216
3205
- if ($ this ->tokens [$ x ]['code ' ] === T_BITWISE_OR
3206
- || $ this ->tokens [$ x ]['code ' ] === T_BITWISE_AND
3207
- || $ this ->tokens [$ x ]['code ' ] === T_OPEN_PARENTHESIS
3208
- || $ this ->tokens [$ x ]['code ' ] === T_CLOSE_PARENTHESIS
3209
- ) {
3217
+ if ($ this ->tokens [$ x ]['code ' ] === T_BITWISE_OR || $ this ->tokens [$ x ]['code ' ] === T_BITWISE_AND ) {
3218
+ $ typeOperators [] = $ x ;
3219
+ continue ;
3220
+ }
3221
+
3222
+ if ($ this ->tokens [$ x ]['code ' ] === T_OPEN_PARENTHESIS || $ this ->tokens [$ x ]['code ' ] === T_CLOSE_PARENTHESIS ) {
3223
+ ++$ parenthesesCount ;
3210
3224
$ typeOperators [] = $ x ;
3211
3225
continue ;
3212
3226
}
@@ -3244,6 +3258,9 @@ protected function processAdditional()
3244
3258
break ;
3245
3259
}//end for
3246
3260
3261
+ // Remember the last token we examined as part of the (non-)"type declaration".
3262
+ $ lastSeenTypeToken = $ x ;
3263
+
3247
3264
if ($ confirmed === false
3248
3265
&& $ suspectedType === 'property or parameter '
3249
3266
&& isset ($ this ->tokens [$ i ]['nested_parenthesis ' ]) === true
@@ -3288,8 +3305,8 @@ protected function processAdditional()
3288
3305
unset($ parens , $ last );
3289
3306
}//end if
3290
3307
3291
- if ($ confirmed === false ) {
3292
- // Not a union or intersection type after all, move on.
3308
+ if ($ confirmed === false || ( $ parenthesesCount % 2 ) !== 0 ) {
3309
+ // Not a (valid) union, intersection or DNF type after all, move on.
3293
3310
continue ;
3294
3311
}
3295
3312
0 commit comments