@@ -268,4 +268,64 @@ private function throwError(int $expectedTokenType, ?string $expectedTokenValue
268268 );
269269 }
270270
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+
271331}
0 commit comments