Index: packages/analyzer/lib/src/generated/parser.dart |
diff --git a/packages/analyzer/lib/src/generated/parser.dart b/packages/analyzer/lib/src/generated/parser.dart |
index 113da91847e6b132e5a0828d103377c01fb88867..76f9dc7e76e32af10ddc3113de95be5c22ab1a81 100644 |
--- a/packages/analyzer/lib/src/generated/parser.dart |
+++ b/packages/analyzer/lib/src/generated/parser.dart |
@@ -4038,22 +4038,52 @@ class Parser { |
TokenType.INDEX |
]); |
} |
+ bool allowAdditionalTokens = true; |
// We know that we have an identifier, and need to see whether it might be |
// a type name. |
+ if (_currentToken.type != TokenType.IDENTIFIER) { |
+ allowAdditionalTokens = false; |
+ } |
Token token = _skipTypeName(_currentToken); |
if (token == null) { |
// There was no type name, so this can't be a declaration. |
return false; |
} |
+ if (token.type != TokenType.IDENTIFIER) { |
+ allowAdditionalTokens = false; |
+ } |
token = _skipSimpleIdentifier(token); |
if (token == null) { |
return false; |
} |
TokenType type = token.type; |
- return type == TokenType.EQ || |
+ // Usual cases in valid code: |
+ // String v = ''; |
+ // String v, v2; |
+ // String v; |
+ // for (String item in items) {} |
+ if (type == TokenType.EQ || |
type == TokenType.COMMA || |
type == TokenType.SEMICOLON || |
- _tokenMatchesKeyword(token, Keyword.IN); |
+ _tokenMatchesKeyword(token, Keyword.IN)) { |
+ return true; |
+ } |
+ // It is OK to parse as a variable declaration in these cases: |
+ // String v } |
+ // String v if (true) print('OK'); |
+ // String v { print(42); } |
+ // ...but not in these cases: |
+ // get getterName { |
+ // String get getterName |
+ if (allowAdditionalTokens) { |
+ if (type == TokenType.CLOSE_CURLY_BRACKET || |
+ type == TokenType.KEYWORD || |
+ type == TokenType.IDENTIFIER || |
+ type == TokenType.OPEN_CURLY_BRACKET) { |
+ return true; |
+ } |
+ } |
+ return false; |
} |
bool _isLikelyParameterList() { |
@@ -5829,12 +5859,12 @@ class Parser { |
_reportErrorForToken( |
ParserErrorCode.INVALID_AWAIT_IN_FOR, awaitKeyword); |
} |
- Token leftSeparator = _expect(TokenType.SEMICOLON); |
+ Token leftSeparator = _expectSemicolon(); |
Expression condition = null; |
if (!_matches(TokenType.SEMICOLON)) { |
condition = parseExpression2(); |
} |
- Token rightSeparator = _expect(TokenType.SEMICOLON); |
+ Token rightSeparator = _expectSemicolon(); |
List<Expression> updaters = null; |
if (!_matches(TokenType.CLOSE_PAREN)) { |
updaters = _parseExpressionList(); |
@@ -8281,8 +8311,7 @@ class Parser { |
*/ |
Token _skipSimpleIdentifier(Token startToken) { |
if (_tokenMatches(startToken, TokenType.IDENTIFIER) || |
- (_tokenMatches(startToken, TokenType.KEYWORD) && |
- (startToken as KeywordToken).keyword.isPseudoKeyword)) { |
+ _tokenMatchesPseudoKeyword(startToken)) { |
return startToken.next; |
} |
return null; |
@@ -8506,8 +8535,7 @@ class Parser { |
*/ |
bool _tokenMatchesIdentifier(Token token) => |
_tokenMatches(token, TokenType.IDENTIFIER) || |
- (_tokenMatches(token, TokenType.KEYWORD) && |
- (token as KeywordToken).keyword.isPseudoKeyword); |
+ _tokenMatchesPseudoKeyword(token); |
/** |
* Return `true` if the given [token] matches the given [keyword]. |
@@ -8517,6 +8545,13 @@ class Parser { |
(token as KeywordToken).keyword == keyword; |
/** |
+ * Return `true` if the given [token] matches a pseudo keyword. |
+ */ |
+ bool _tokenMatchesPseudoKeyword(Token token) => |
+ _tokenMatches(token, TokenType.KEYWORD) && |
+ (token as KeywordToken).keyword.isPseudoKeyword; |
+ |
+ /** |
* Return `true` if the given [token] matches the given [identifier]. |
*/ |
bool _tokenMatchesString(Token token, String identifier) => |