Chromium Code Reviews| Index: pkg/compiler/lib/src/scanner/parser.dart |
| diff --git a/pkg/compiler/lib/src/scanner/parser.dart b/pkg/compiler/lib/src/scanner/parser.dart |
| index 2d7efe98c717a8fe91bdd7997dd32d15cdde24f1..18c88201b929e77b1533d2aff369052a38715b66 100644 |
| --- a/pkg/compiler/lib/src/scanner/parser.dart |
| +++ b/pkg/compiler/lib/src/scanner/parser.dart |
| @@ -684,6 +684,12 @@ class Parser { |
| if (identifiers.isEmpty) { |
| return listener.expectedDeclaration(start); |
| } |
| + Token afterName = identifiers.head; |
| + identifiers = identifiers.tail; |
| + |
| + if (identifiers.isEmpty) { |
| + return listener.expectedDeclaration(start); |
| + } |
| Token name = identifiers.head; |
| identifiers = identifiers.tail; |
| Token getOrSet; |
| @@ -702,7 +708,7 @@ class Parser { |
| } |
| } |
| - token = name.next; |
| + token = afterName; |
| bool isField; |
| while (true) { |
| // Loop to allow the listener to rewrite the token stream for |
| @@ -866,6 +872,7 @@ class Parser { |
| Token type, |
| Token getOrSet, |
| Token name) { |
| + |
| Token externalModifier; |
| for (Token modifier in modifiers) { |
| if (externalModifier == null && optional('external', modifier)) { |
| @@ -905,19 +912,70 @@ class Parser { |
| return token; |
| } |
| + /// Looks ahead to find the name of a member. Returns a link of the modifiers, |
| + /// set/get, (operator) name, and either the start of the method body or the |
| + /// end of the declaration. |
| + /// |
| + /// Examples: |
| + /// |
| + /// int get foo; |
| + /// results in |
| + /// [';', 'foo', 'get', 'int'] |
| + /// |
| + /// |
| + /// static const List<int> foo = null; |
| + /// results in |
| + /// ['=', 'foo', 'List', 'const', 'static'] |
| + /// |
| + /// |
| + /// get foo async* { return null } |
| + /// results in |
| + /// ['{', 'foo', 'get'] |
| + /// |
| + /// |
| + /// operator *(arg) => null; |
| + /// results in |
| + /// ['(', '*', 'operator'] |
| + /// |
| Link<Token> findMemberName(Token token) { |
| Token start = token; |
| Link<Token> identifiers = const Link<Token>(); |
| + |
| + // `true` if 'get' has been seen. |
| + bool isGetter = false; |
| + // `true` if an identifier has been seen after 'get'. |
| + bool hasName = false; |
| + // `true` if 'sync' or 'async' has been seen after a name. |
| + bool hasAsync = false; |
|
floitsch
2015/01/30 10:48:13
So far this seems unused.
Johnni Winther
2015/01/30 12:16:33
Removed.
|
| + |
| while (!identical(token.kind, EOF_TOKEN)) { |
| String value = token.stringValue; |
| - if ((identical(value, '(')) || (identical(value, '{')) |
| - || (identical(value, '=>'))) { |
| + if (identical(value, 'get')) { |
|
floitsch
2015/01/30 10:48:13
Why is this "identical"?
(it was already there be
Johnni Winther
2015/01/30 12:16:33
The pattern is from when identical on String was f
floitsch
2015/01/30 12:18:14
It might still be, but it feels error-prone to dep
Johnni Winther
2015/01/30 15:40:16
According to http://dartbug.com/15514 the problem
|
| + isGetter = true; |
| + } else if (hasName && |
| + (identical(value, 'sync') || identical(value, 'async'))) { |
| + // Skip. |
| + token = token.next; |
|
floitsch
2015/01/30 10:48:13
shouldn't you set the 'hasAsync' to true?
Johnni Winther
2015/01/30 12:16:33
Wasn't needed after all.
|
| + value = token.stringValue; |
| + if (identical(value, '*')) { |
| + // Skip. |
| + token = token.next; |
| + } |
| + continue; |
| + } else if (identical(value, '(') || |
| + identical(value, '{') || |
| + identical(value, '=>')) { |
| // A method. |
| + identifiers = identifiers.prepend(token); |
| return identifiers; |
| - } else if ((identical(value, '=')) || (identical(value, ';')) |
| - || (identical(value, ','))) { |
| + } else if (identical(value, '=') || |
| + identical(value, ';') || |
| + identical(value, ',')) { |
| // A field or abstract getter. |
| + identifiers = identifiers.prepend(token); |
| return identifiers; |
| + } else if (isGetter) { |
| + hasName = true; |
| } |
| identifiers = identifiers.prepend(token); |
| if (isValidTypeReference(token)) { |
| @@ -1114,8 +1172,13 @@ class Parser { |
| if (identifiers.isEmpty) { |
| return listener.expectedDeclaration(start); |
| } |
| + Token afterName = identifiers.head; |
| + identifiers = identifiers.tail; |
| + |
| + if (identifiers.isEmpty) { |
| + return listener.expectedDeclaration(start); |
| + } |
| Token name = identifiers.head; |
| - Token afterName = name.next; |
| identifiers = identifiers.tail; |
| if (!identifiers.isEmpty) { |
| if (optional('operator', identifiers.head)) { |
| @@ -1302,14 +1365,27 @@ class Parser { |
| Token parseFunction(Token token, Token getOrSet) { |
| listener.beginFunction(token); |
| token = parseModifiers(token); |
| - if (identical(getOrSet, token)) token = token.next; |
| - if (optional('operator', token)) { |
| + if (identical(getOrSet, token)) { |
| + // get <name> => ... |
| + token = token.next; |
| + listener.handleNoType(token); |
| + listener.beginFunctionName(token); |
| + if (optional('operator', token)) { |
| + token = parseOperatorName(token); |
| + } else { |
| + token = parseIdentifier(token); |
| + } |
| + } else if (optional('operator', token)) { |
| + // operator <op> (... |
| listener.handleNoType(token); |
| listener.beginFunctionName(token); |
| token = parseOperatorName(token); |
| } else { |
| + // <type>? <get>? <name> |
| token = parseReturnTypeOpt(token); |
| - if (identical(getOrSet, token)) token = token.next; |
| + if (identical(getOrSet, token)) { |
| + token = token.next; |
| + } |
| listener.beginFunctionName(token); |
| if (optional('operator', token)) { |
| token = parseOperatorName(token); |