Skip to content

Commit 547b2cd

Browse files
Implement generalized function types.
Fixes #6972 Fixes #26581 [email protected] Review-Url: https://codereview.chromium.org/2876813002 .
1 parent a52cc66 commit 547b2cd

35 files changed

+589
-590
lines changed

pkg/analyzer/lib/src/fasta/ast_builder.dart

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import 'package:analyzer/dart/ast/token.dart' as analyzer show Token;
1111
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
1212
import 'package:analyzer/dart/element/element.dart' show Element;
1313
import 'package:front_end/src/fasta/parser/parser.dart'
14-
show FormalParameterType, Parser;
14+
show FormalParameterType, MemberKind, Parser;
1515
import 'package:front_end/src/fasta/scanner/string_scanner.dart';
1616
import 'package:front_end/src/fasta/scanner/token.dart'
1717
show BeginGroupToken, CommentToken;
@@ -851,8 +851,8 @@ class AstBuilder extends ScopeListener {
851851
}
852852
}
853853

854-
void endFormalParameter(Token covariantKeyword, Token thisKeyword,
855-
Token nameToken, FormalParameterType kind) {
854+
void endFormalParameter(Token thisKeyword, Token nameToken,
855+
FormalParameterType kind, MemberKind memberKind) {
856856
debugEvent("FormalParameter");
857857
_ParameterDefaultValue defaultValue = pop();
858858

@@ -868,6 +868,7 @@ class AstBuilder extends ScopeListener {
868868
TypeAnnotation type = pop();
869869
_Modifiers modifiers = pop();
870870
Token keyword = modifiers?.finalConstOrVarKeyword;
871+
Token covariantKeyword = modifiers?.covariantKeyword;
871872
pop(); // TODO(paulberry): Metadata.
872873
Comment comment = pop();
873874
if (thisKeyword == null) {
@@ -908,21 +909,16 @@ class AstBuilder extends ScopeListener {
908909

909910
@override
910911
void endFunctionTypedFormalParameter(
911-
Token covariantKeyword, Token thisKeyword, FormalParameterType kind) {
912+
Token thisKeyword, FormalParameterType kind) {
912913
debugEvent("FunctionTypedFormalParameter");
913914

914915
FormalParameterList formalParameters = pop();
915916
TypeParameterList typeParameters = pop();
916917
SimpleIdentifier name = pop();
917918
TypeAnnotation returnType = pop();
918919

919-
{
920-
_Modifiers modifiers = pop();
921-
if (modifiers != null) {
922-
// TODO(scheglov): Report error.
923-
internalError('Unexpected modifier. Report an error.');
924-
}
925-
}
920+
_Modifiers modifiers = pop();
921+
Token covariantKeyword = modifiers?.covariantKeyword;
926922

927923
pop(); // TODO(paulberry): Metadata.
928924
Comment comment = pop();
@@ -956,7 +952,8 @@ class AstBuilder extends ScopeListener {
956952
push(node);
957953
}
958954

959-
void endFormalParameters(int count, Token beginToken, Token endToken) {
955+
void endFormalParameters(
956+
int count, Token beginToken, Token endToken, MemberKind kind) {
960957
debugEvent("FormalParameters");
961958
List rawParameters = popList(count) ?? const <Object>[];
962959
List<FormalParameter> parameters = <FormalParameter>[];
@@ -1834,14 +1831,14 @@ class AstBuilder extends ScopeListener {
18341831
}
18351832

18361833
@override
1837-
void endFields(
1838-
int count, Token covariantKeyword, Token beginToken, Token endToken) {
1834+
void endFields(int count, Token beginToken, Token endToken) {
18391835
debugEvent("Fields");
18401836
List<VariableDeclaration> variables = popList(count);
18411837
TypeAnnotation type = pop();
18421838
_Modifiers modifiers = pop();
18431839
var variableList = ast.variableDeclarationList(null, null,
18441840
toAnalyzerToken(modifiers?.finalConstOrVarKeyword), type, variables);
1841+
Token covariantKeyword = modifiers?.covariantKeyword;
18451842
List<Annotation> metadata = pop();
18461843
Comment comment = pop();
18471844
push(ast.fieldDeclaration2(
@@ -2069,6 +2066,7 @@ class _Modifiers {
20692066
Token externalKeyword;
20702067
Token finalConstOrVarKeyword;
20712068
Token staticKeyword;
2069+
Token covariantKeyword;
20722070

20732071
_Modifiers(List<Token> modifierTokens) {
20742072
// No need to check the order and uniqueness of the modifiers, or that
@@ -2088,6 +2086,8 @@ class _Modifiers {
20882086
staticKeyword = token;
20892087
} else if (identical('var', s)) {
20902088
finalConstOrVarKeyword = token;
2089+
} else if (identical('covariant', s)) {
2090+
covariantKeyword = token;
20912091
} else {
20922092
internalError('Unhandled modifier: $s');
20932093
}

pkg/analyzer/test/generated/parser_fasta_test.dart

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,11 @@ class FastaParserTestCase extends Object
465465
return _runParser(
466466
code,
467467
(parser) => (analyzer.Token token) {
468-
return parser.parseFormalParameters(token,
469-
inFunctionType: inFunctionType);
468+
return parser.parseFormalParameters(
469+
token,
470+
inFunctionType
471+
? fasta.MemberKind.GeneralizedFunctionType
472+
: fasta.MemberKind.NonStaticMethod);
470473
},
471474
errorCodes) as FormalParameterList;
472475
}
@@ -929,13 +932,6 @@ class TopLevelParserTest_Fasta extends FastaParserTestCase
929932
super.test_parseCompilationUnit_exportAsPrefix_parameterized();
930933
}
931934

932-
@override
933-
@failingTest
934-
void test_parseCompilationUnit_typedefAsPrefix() {
935-
// TODO(paulberry): As of commit 5de9108 this syntax is invalid.
936-
super.test_parseCompilationUnit_typedefAsPrefix();
937-
}
938-
939935
@override
940936
@failingTest
941937
void test_parseDirectives_mixed() {

pkg/compiler/lib/src/parser/diet_parser_task.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ import '../id_generator.dart';
1212
import 'package:front_end/src/fasta/scanner.dart' show Token;
1313
import 'element_listener.dart' show ElementListener, ScannerOptions;
1414
import 'package:front_end/src/fasta/parser.dart'
15-
show Listener, ParserError, TopLevelParser;
15+
show Listener, MemberKind, ParserError, TopLevelParser;
1616

1717
class PartialParser extends TopLevelParser {
1818
PartialParser(Listener listener) : super(listener);
1919

20-
Token parseFormalParameters(Token token, {bool inFunctionType: false}) {
21-
return skipFormalParameters(token);
20+
Token parseFormalParameters(Token token, MemberKind kind) {
21+
return skipFormalParameters(token, kind);
2222
}
2323
}
2424

pkg/compiler/lib/src/parser/element_listener.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,9 @@ class ElementListener extends Listener {
706706

707707
case "FASTA_IGNORED":
708708
return null; // Ignored. This error is already implemented elsewhere.
709+
710+
default:
711+
throw "Unexpected message code: ${message.code}";
709712
}
710713
SourceSpan span = reporter.spanFromToken(token);
711714
reportError(span, errorCode, arguments);

pkg/compiler/lib/src/parser/member_listener.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,9 @@ class MemberListener extends NodeListener {
116116
}
117117

118118
@override
119-
void endFields(
120-
int count, Token covariantKeyword, Token beginToken, Token endToken) {
119+
void endFields(int count, Token beginToken, Token endToken) {
121120
bool hasParseError = memberErrors.head;
122-
super.endFields(count, covariantKeyword, beginToken, endToken);
121+
super.endFields(count, beginToken, endToken);
123122
VariableDefinitions variableDefinitions = popNode();
124123
Modifiers modifiers = variableDefinitions.modifiers;
125124
pushNode(null);

pkg/compiler/lib/src/parser/node_listener.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
library dart2js.parser.node_listener;
66

77
import 'package:front_end/src/fasta/parser/parser.dart'
8-
show FormalParameterType;
8+
show FormalParameterType, MemberKind;
99
import 'package:front_end/src/fasta/parser/identifier_context.dart'
1010
show IdentifierContext;
1111
import 'package:front_end/src/fasta/scanner.dart' show SymbolToken, Token;
@@ -229,8 +229,8 @@ class NodeListener extends ElementListener {
229229
}
230230

231231
@override
232-
void endFormalParameter(Token covariantKeyword, Token thisKeyword,
233-
Token nameToken, FormalParameterType kind) {
232+
void endFormalParameter(Token thisKeyword, Token nameToken,
233+
FormalParameterType kind, MemberKind memberKind) {
234234
Expression name = popNode();
235235
if (thisKeyword != null) {
236236
Identifier thisIdentifier = new Identifier(thisKeyword);
@@ -248,12 +248,13 @@ class NodeListener extends ElementListener {
248248
}
249249

250250
@override
251-
void endFormalParameters(int count, Token beginToken, Token endToken) {
251+
void endFormalParameters(
252+
int count, Token beginToken, Token endToken, MemberKind kind) {
252253
pushNode(makeNodeList(count, beginToken, endToken, ","));
253254
}
254255

255256
@override
256-
void handleNoFormalParameters(Token token) {
257+
void handleNoFormalParameters(Token token, MemberKind kind) {
257258
pushNode(null);
258259
}
259260

@@ -668,8 +669,7 @@ class NodeListener extends ElementListener {
668669
}
669670

670671
@override
671-
void endFields(
672-
int count, Token covariantKeyword, Token beginToken, Token endToken) {
672+
void endFields(int count, Token beginToken, Token endToken) {
673673
NodeList variables = makeNodeList(count, null, endToken, ",");
674674
TypeAnnotation type = popNode();
675675
Modifiers modifiers = popNode();
@@ -768,7 +768,7 @@ class NodeListener extends ElementListener {
768768

769769
@override
770770
void endFunctionTypedFormalParameter(
771-
Token covariantKeyword, Token thisKeyword, FormalParameterType kind) {
771+
Token thisKeyword, FormalParameterType kind) {
772772
NodeList formals = popNode();
773773
NodeList typeVariables = popNode();
774774
Identifier name = popNode();

pkg/compiler/lib/src/parser/partial_elements.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ import 'package:front_end/src/fasta/scanner.dart' show Token;
3535
import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN;
3636
import '../tree/tree.dart';
3737
import 'package:front_end/src/fasta/parser.dart'
38-
show ClassMemberParser, Listener, Parser, ParserError;
38+
show ClassMemberParser, Listener, MemberKind, Parser, ParserError;
3939
import 'member_listener.dart' show MemberListener;
4040
import 'node_listener.dart' show NodeListener;
4141

4242
class ClassElementParser extends ClassMemberParser {
4343
ClassElementParser(Listener listener) : super(listener);
4444

45-
Token parseFormalParameters(Token token, {bool inFunctionType: false}) {
46-
return skipFormalParameters(token);
45+
Token parseFormalParameters(Token token, MemberKind kind) {
46+
return skipFormalParameters(token, kind);
4747
}
4848
}
4949

@@ -95,8 +95,10 @@ abstract class PartialFunctionMixin implements BaseFunctionElementX {
9595
parseFunction(Parser p) {
9696
if (isClassMember && modifiers.isFactory) {
9797
p.parseFactoryMethod(beginToken);
98+
} else if (isClassMember) {
99+
p.parseMember(beginToken);
98100
} else {
99-
p.parseFunction(beginToken, getOrSet);
101+
p.parseTopLevelMember(beginToken);
100102
}
101103
}
102104

pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ class ResolvedAstDeserializer {
536536
}
537537
}
538538
return doParse((parser) {
539-
parser.parseFunction(beginToken, getOrSet);
539+
parser.parseMember(beginToken);
540540
});
541541
}
542542
}

pkg/compiler/lib/src/tree/nodes.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,7 @@ class Modifiers extends Node {
19771977
static const int FLAG_CONST = FLAG_VAR << 1;
19781978
static const int FLAG_FACTORY = FLAG_CONST << 1;
19791979
static const int FLAG_EXTERNAL = FLAG_FACTORY << 1;
1980+
static const int FLAG_COVARIANT = FLAG_EXTERNAL << 1;
19801981

19811982
Modifiers(NodeList nodes) : this.withFlags(nodes, computeFlags(nodes.nodes));
19821983

@@ -2000,6 +2001,8 @@ class Modifiers extends Node {
20002001
flags |= FLAG_FACTORY;
20012002
else if (identical(value, 'external'))
20022003
flags |= FLAG_EXTERNAL;
2004+
else if (identical(value, 'covariant'))
2005+
flags |= FLAG_COVARIANT;
20032006
else
20042007
throw 'internal error: ${nodes.head}';
20052008
}
@@ -2036,6 +2039,7 @@ class Modifiers extends Node {
20362039
bool get isConst => (flags & FLAG_CONST) != 0;
20372040
bool get isFactory => (flags & FLAG_FACTORY) != 0;
20382041
bool get isExternal => (flags & FLAG_EXTERNAL) != 0;
2042+
bool get isCovariant => (flags & FLAG_COVARIANT) != 0;
20392043

20402044
Node getStatic() => findModifier('static');
20412045

@@ -2053,7 +2057,8 @@ class Modifiers extends Node {
20532057
isVar: isVar,
20542058
isConst: isConst,
20552059
isFactory: isFactory,
2056-
isExternal: isExternal);
2060+
isExternal: isExternal,
2061+
isCovariant: isCovariant);
20572062
}
20582063
}
20592064

pkg/compiler/lib/src/util/util.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ String modifiersToString(
191191
bool isVar: false,
192192
bool isConst: false,
193193
bool isFactory: false,
194-
bool isExternal: false}) {
194+
bool isExternal: false,
195+
bool isCovariant: false}) {
195196
LinkBuilder<String> builder = new LinkBuilder<String>();
196197
if (isStatic) builder.addLast('static');
197198
if (isAbstract) builder.addLast('abstract');
@@ -200,6 +201,7 @@ String modifiersToString(
200201
if (isConst) builder.addLast('const');
201202
if (isFactory) builder.addLast('factory');
202203
if (isExternal) builder.addLast('external');
204+
if (isCovariant) builder.addLast('covariant');
203205
StringBuffer buffer = new StringBuffer();
204206
builder.toLink().printOn(buffer, ', ');
205207
return buffer.toString();

pkg/front_end/lib/src/fasta/errors.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ dynamic internalError(Object error, [Uri uri, int charOffset = -1]) {
5151
/// handled correctly, the user will never see a stack trace that says "user
5252
/// error".
5353
dynamic inputError(Uri uri, int charOffset, Object error) {
54+
if (errorsAreFatal && isVerbose) {
55+
print(StackTrace.current);
56+
}
5457
throw new InputError(uri, charOffset, error);
5558
}
5659

pkg/front_end/lib/src/fasta/fasta_codes.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import 'package:front_end/src/scanner/token.dart' show Token;
99
part 'fasta_codes_generated.dart';
1010

1111
class FastaCode<T> {
12+
final String name;
13+
1214
final String template;
1315

1416
final String tip;
@@ -19,12 +21,14 @@ class FastaCode<T> {
1921

2022
final T format;
2123

22-
const FastaCode(
24+
const FastaCode(this.name,
2325
{this.template,
2426
this.tip,
2527
this.analyzerCode,
2628
this.dart2jsCode,
2729
this.format});
30+
31+
String toString() => name;
2832
}
2933

3034
class FastaMessage {

0 commit comments

Comments
 (0)