@@ -268,4 +268,64 @@ private function throwError(int $expectedTokenType, ?string $expectedTokenValue
268
268
);
269
269
}
270
270
271
+ /**
272
+ * Check whether the position is directly preceded by a certain token type.
273
+ *
274
+ * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped
275
+ */
276
+ public function hasTokenImmediatelyBefore (int $ pos , int $ expectedTokenType ): bool
277
+ {
278
+ $ tokens = $ this ->tokens ;
279
+ $ pos --;
280
+ for (; $ pos >= 0 ; $ pos --) {
281
+ $ token = $ tokens [$ pos ];
282
+ $ type = $ token [Lexer::TYPE_OFFSET ];
283
+ if ($ type === $ expectedTokenType ) {
284
+ return true ;
285
+ }
286
+ if (!in_array ($ type , [
287
+ Lexer::TOKEN_HORIZONTAL_WS ,
288
+ Lexer::TOKEN_PHPDOC_EOL ,
289
+ ], true )) {
290
+ break ;
291
+ }
292
+ }
293
+ return false ;
294
+ }
295
+
296
+ /**
297
+ * Check whether the position is directly followed by a certain token type.
298
+ *
299
+ * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped
300
+ */
301
+ public function hasTokenImmediatelyAfter (int $ pos , int $ expectedTokenType ): bool
302
+ {
303
+ $ tokens = $ this ->tokens ;
304
+ $ pos ++;
305
+ for ($ c = count ($ tokens ); $ pos < $ c ; $ pos ++) {
306
+ $ token = $ tokens [$ pos ];
307
+ $ type = $ token [Lexer::TYPE_OFFSET ];
308
+ if ($ type === $ expectedTokenType ) {
309
+ return true ;
310
+ }
311
+ if (!in_array ($ type , [
312
+ Lexer::TOKEN_HORIZONTAL_WS ,
313
+ Lexer::TOKEN_PHPDOC_EOL ,
314
+ ], true )) {
315
+ break ;
316
+ }
317
+ }
318
+
319
+ return false ;
320
+ }
321
+
322
+ /**
323
+ * Whether the given position is immediately surrounded by parenthesis.
324
+ */
325
+ public function hasParentheses (int $ startPos , int $ endPos ): bool
326
+ {
327
+ return $ this ->hasTokenImmediatelyBefore ($ startPos , Lexer::TOKEN_OPEN_PARENTHESES )
328
+ && $ this ->hasTokenImmediatelyAfter ($ endPos , Lexer::TOKEN_CLOSE_PARENTHESES );
329
+ }
330
+
271
331
}
0 commit comments