@@ -470,7 +470,8 @@ TypeParamOrArgInfo computeTypeParamOrArg(
470470/// possible other constructs will pass (e.g., 'a < C, D > 3').
471471TypeParamOrArgInfo computeMethodTypeArguments (Token token) {
472472 TypeParamOrArgInfo typeArg = computeTypeParamOrArg (token);
473- return mayFollowTypeArgs (typeArg.skip (token).next! ) && ! typeArg.recovered
473+ return _mayFollowTypeArgs (typeArg.skip (token).next! .typeIndex) &&
474+ ! typeArg.recovered
474475 ? typeArg
475476 : noTypeParamOrArg;
476477}
@@ -480,8 +481,10 @@ TypeParamOrArgInfo computeMethodTypeArguments(Token token) {
480481/// pattern.
481482const Set <String > illegalPatternIdentifiers = {'when' , 'as' };
482483
483- /// Indicates whether the given [token] is allowed to follow a list of type
484- /// arguments used as a selector after an expression.
484+ /// Indicates whether the given [tokenTypeIndex] is allowed to follow a list of
485+ /// type arguments used as a selector after an expression.
486+ ///
487+ /// Get the index from a token via `Token.typeIndex` .
485488///
486489/// This is used for disambiguating constructs like `f(a<b,c>(d))` and
487490/// `f(a<b,c>-d)` . In the case of `f(a<b,c>(d))` , `true` will be returned,
@@ -490,19 +493,71 @@ const Set<String> illegalPatternIdentifiers = {'when', 'as'};
490493/// function `a` ). In the case of `f(a<b,c>-d)` , `false` will be returned,
491494/// indicating that the `<` and `>` should be interpreted as operators (so two
492495/// arguments are being passed to `f` : `a < b` and `c > -d` ).
493- bool mayFollowTypeArgs (Token token) {
494- const Set <String > continuationTokens = {'(' , '.' , '==' , '!=' };
495- const Set <String > stopTokens = {')' , ']' , '}' , ';' , ':' , ',' };
496- const Set <String > tokensThatMayFollowTypeArg = {
497- ...continuationTokens,
498- ...stopTokens,
499- };
500- if (token.isA (TokenType .EOF )) {
501- // The spec doesn't have anything to say about this case, since an
502- // expression can't occur at the end of a file, but for testing it's to our
503- // advantage to allow EOF after type arguments, so that an isolated `f<x>`
504- // can be parsed as an expression.
505- return true ;
506- }
507- return tokensThatMayFollowTypeArg.contains (token.lexeme);
496+ ///
497+ // DartDocTest(() {
498+ // for (int i = 0; i < 256; i++) {
499+ // if (_mayFollowTypeArgs(i) !=
500+ // _mayFollowTypeArgs_helper_for_testing(i)) {
501+ // return false;
502+ // }
503+ // }
504+ // return true;
505+ // }(), true);
506+ @pragma ("vm:prefer-inline" )
507+ bool _mayFollowTypeArgs (int tokenTypeIndex) {
508+ // Table has size 256 to avoid bounds checks as this is called with
509+ // `Token.typeIndex` which is know to be in [0-255].
510+ const List <bool > table = [
511+ // format hack.
512+ true , false , false , false , false , false , false , false ,
513+ false , false , false , false , false , false , false , false ,
514+ false , false , true , false , false , false , false , false ,
515+ true , true , false , false , true , true , true , false ,
516+ true , false , false , false , false , false , false , false ,
517+ false , false , false , false , false , false , false , false ,
518+ false , false , false , false , true , false , false , false ,
519+ true , false , false , false , false , false , false , false ,
520+ false , true , false , false , false , false , false , false ,
521+ false , false , false , false , false , false , false , false ,
522+ false , false , false , false , false , false , false , false ,
523+ false , false , false , false , false , false , false , false ,
524+ false , false , false , false , false , false , false , false ,
525+ false , false , false , false , false , false , false , false ,
526+ false , false , false , false , false , false , false , false ,
527+ false , false , false , false , false , false , false , false ,
528+ false , false , false , false , false , false , false , false ,
529+ false , false , false , false , false , false , false , false ,
530+ false , false , false , false , false , false , false , false ,
531+ false , false , false , false , false , false , false , false ,
532+ false , false , false , false , false , false , false , false ,
533+ false , false , false , false , false , false , false , false ,
534+ false , false , false , false , false , false , false , false ,
535+ false , false , false , false , false , false , false , false ,
536+ false , false , false , false , false , false , false , false ,
537+ false , false , false , false , false , false , false , false ,
538+ false , false , false , false , false , false , false , false ,
539+ false , false , false , false , false , false , false , false ,
540+ false , false , false , false , false , false , false , false ,
541+ false , false , false , false , false , false , false , false ,
542+ false , false , false , false , false , false , false , false ,
543+ false , false , false , false , false , false , false , false ,
544+ // format hack.
545+ ];
546+
547+ return table[tokenTypeIndex];
548+ }
549+
550+ // ignore: unused_element
551+ bool _mayFollowTypeArgs_helper_for_testing (int tokenTypeIndex) {
552+ return tokenTypeIndex == TokenType .OPEN_PAREN .index ||
553+ tokenTypeIndex == TokenType .PERIOD .index ||
554+ tokenTypeIndex == TokenType .EQ_EQ .index ||
555+ tokenTypeIndex == TokenType .BANG_EQ .index ||
556+ tokenTypeIndex == TokenType .CLOSE_PAREN .index ||
557+ tokenTypeIndex == TokenType .CLOSE_SQUARE_BRACKET .index ||
558+ tokenTypeIndex == TokenType .CLOSE_CURLY_BRACKET .index ||
559+ tokenTypeIndex == TokenType .SEMICOLON .index ||
560+ tokenTypeIndex == TokenType .COLON .index ||
561+ tokenTypeIndex == TokenType .COMMA .index ||
562+ tokenTypeIndex == TokenType .EOF .index;
508563}
0 commit comments