Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Issue 2691613002: Improve compile-time error handling. (Closed)
Patch Set: Update status and expectations for rasta tests. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library fasta.body_builder; 5 library fasta.body_builder;
6 6
7 import 'package:front_end/src/fasta/parser/parser.dart' show 7 import 'package:front_end/src/fasta/parser/parser.dart' show
8 FormalParameterType, 8 FormalParameterType,
9 optional; 9 optional;
10 10
(...skipping 20 matching lines...) Expand all
31 import 'package:front_end/src/fasta/scanner/token.dart' show 31 import 'package:front_end/src/fasta/scanner/token.dart' show
32 BeginGroupToken, 32 BeginGroupToken,
33 Token, 33 Token,
34 isBinaryOperator, 34 isBinaryOperator,
35 isMinusOperator; 35 isMinusOperator;
36 36
37 import '../errors.dart' show 37 import '../errors.dart' show
38 InputError, 38 InputError,
39 internalError; 39 internalError;
40 40
41 import '../errors.dart' as errors show
42 inputError;
43
44 import '../source/scope_listener.dart' show 41 import '../source/scope_listener.dart' show
45 JumpTargetKind, 42 JumpTargetKind,
46 NullValue, 43 NullValue,
47 ScopeListener; 44 ScopeListener;
48 45
49 import '../builder/scope.dart' show 46 import '../builder/scope.dart' show
50 AccessErrorBuilder, 47 AccessErrorBuilder,
51 AmbiguousBuilder, 48 AmbiguousBuilder,
52 Scope; 49 Scope;
53 50
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 } else { 409 } else {
413 if (node is !Throw) { 410 if (node is !Throw) {
414 node = wrapInvalid(node); 411 node = wrapInvalid(node);
415 } 412 }
416 initializer = 413 initializer =
417 new LocalInitializer(new VariableDeclaration.forValue(node)); 414 new LocalInitializer(new VariableDeclaration.forValue(node));
418 } 415 }
419 if (member is KernelConstructorBuilder) { 416 if (member is KernelConstructorBuilder) {
420 member.addInitializer(initializer); 417 member.addInitializer(initializer);
421 } else { 418 } else {
422 inputError("Can't have initializers: ${member.name}", token.charOffset); 419 addCompileTimeError(token.charOffset,
420 "Can't have initializers: ${member.name}");
423 } 421 }
424 } 422 }
425 423
426 @override 424 @override
427 void handleNoInitializers() { 425 void handleNoInitializers() {
428 debugEvent("NoInitializers"); 426 debugEvent("NoInitializers");
429 } 427 }
430 428
431 @override 429 @override
432 void endInitializers(int count, Token beginToken, Token endToken) { 430 void endInitializers(int count, Token beginToken, Token endToken) {
433 debugEvent("Initializers"); 431 debugEvent("Initializers");
434 } 432 }
435 433
436 @override 434 @override
437 void finishFunction(FormalParameters formals, 435 void finishFunction(FormalParameters formals,
438 AsyncMarker asyncModifier, Statement body) { 436 AsyncMarker asyncModifier, Statement body) {
439 debugEvent("finishFunction"); 437 debugEvent("finishFunction");
440 KernelFunctionBuilder builder = member; 438 KernelFunctionBuilder builder = member;
441 if (builder is KernelConstructorBuilder) { 439 if (builder is KernelConstructorBuilder) {
442 if (asyncModifier != AsyncMarker.Sync) { 440 if (asyncModifier != AsyncMarker.Sync) {
443 // TODO(ahe): Change this to a null check. 441 // TODO(ahe): Change this to a null check.
444 inputError("Can't be marked as ${asyncModifier}: ${builder.name}", 442 addCompileTimeError(body?.fileOffset,
445 body?.fileOffset); 443 "Can't be marked as ${asyncModifier}: ${builder.name}");
446 } 444 }
447 } else if (builder is KernelProcedureBuilder) { 445 } else if (builder is KernelProcedureBuilder) {
448 builder.asyncModifier = asyncModifier; 446 builder.asyncModifier = asyncModifier;
449 } else { 447 } else {
450 internalError("Unhandled: ${builder.runtimeType}"); 448 internalError("Unhandled: ${builder.runtimeType}");
451 } 449 }
452 builder.body = body; 450 builder.body = body;
453 if (formals?.optional != null) { 451 if (formals?.optional != null) {
454 Iterator<FormalParameterBuilder> formalBuilders = 452 Iterator<FormalParameterBuilder> formalBuilders =
455 builder.formals.skip(formals.required.length).iterator; 453 builder.formals.skip(formals.required.length).iterator;
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 } 1159 }
1162 1160
1163 @override 1161 @override
1164 void endType(Token beginToken, Token endToken) { 1162 void endType(Token beginToken, Token endToken) {
1165 // TODO(ahe): The scope is wrong for return types of generic functions. 1163 // TODO(ahe): The scope is wrong for return types of generic functions.
1166 debugEvent("Type"); 1164 debugEvent("Type");
1167 List<DartType> arguments = pop(); 1165 List<DartType> arguments = pop();
1168 var name = pop(); 1166 var name = pop();
1169 if (name is List) { 1167 if (name is List) {
1170 if (name.length != 2) { 1168 if (name.length != 2) {
1171 return internalError("Unexpected: $name.length"); 1169 internalError("Unexpected: $name.length");
1172 } 1170 }
1173 var prefix = name[0]; 1171 var prefix = name[0];
1174 if (prefix is Identifier) { 1172 if (prefix is Identifier) {
1175 prefix = prefix.name; 1173 prefix = prefix.name;
1176 } 1174 }
1177 var suffix = name[1]; 1175 var suffix = name[1];
1178 if (suffix is Identifier) { 1176 if (suffix is Identifier) {
1179 suffix = suffix.name; 1177 suffix = suffix.name;
1180 } 1178 }
1181 Builder builder; 1179 Builder builder;
1182 if (prefix is Builder) { 1180 if (prefix is Builder) {
1183 builder = prefix; 1181 builder = prefix;
1184 } else { 1182 } else {
1185 builder = scope.lookup(prefix, beginToken.charOffset, uri); 1183 builder = scope.lookup(prefix, beginToken.charOffset, uri);
1186 } 1184 }
1187 if (builder is PrefixBuilder) { 1185 if (builder is PrefixBuilder) {
1188 name = builder.exports[suffix]; 1186 name = builder.exports[suffix];
1189 } else { 1187 } else {
1190 return inputError( 1188 push(const DynamicType());
1191 "Can't be used as a type: '${debugName(prefix, suffix)}'.", 1189 addCompileTimeError(beginToken.charOffset,
1192 beginToken.charOffset); 1190 "Can't be used as a type: '${debugName(prefix, suffix)}'.");
1191 return;
1193 } 1192 }
1194 } 1193 }
1195 if (name is Identifier) { 1194 if (name is Identifier) {
1196 name = name.name; 1195 name = name.name;
1197 } 1196 }
1198 if (name is BuilderAccessor) { 1197 if (name is BuilderAccessor) {
1199 warning("'${beginToken.value}' isn't a type.", beginToken.charOffset); 1198 warning("'${beginToken.value}' isn't a type.", beginToken.charOffset);
1200 push(const DynamicType()); 1199 push(const DynamicType());
1201 } else if (name is UnresolvedIdentifier) { 1200 } else if (name is UnresolvedIdentifier) {
1202 warning("'${name.name}' isn't a type.", beginToken.charOffset); 1201 warning("'${name.name}' isn't a type.", beginToken.charOffset);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 push(new Throw(expression)); 1263 push(new Throw(expression));
1265 } 1264 }
1266 1265
1267 @override 1266 @override
1268 void endFormalParameter(Token thisKeyword) { 1267 void endFormalParameter(Token thisKeyword) {
1269 debugEvent("FormalParameter"); 1268 debugEvent("FormalParameter");
1270 // TODO(ahe): Need beginToken here. 1269 // TODO(ahe): Need beginToken here.
1271 int charOffset = thisKeyword?.charOffset; 1270 int charOffset = thisKeyword?.charOffset;
1272 if (thisKeyword != null) { 1271 if (thisKeyword != null) {
1273 if (!inConstructor) { 1272 if (!inConstructor) {
1274 return inputError("'this' parameters can only be used on constructors.", 1273 addCompileTimeError(thisKeyword.charOffset,
1275 thisKeyword.charOffset); 1274 "'this' parameters can only be used on constructors.");
1275 thisKeyword = null;
1276 } 1276 }
1277 } 1277 }
1278 Identifier name = pop(); 1278 Identifier name = pop();
1279 DartType type = pop(); 1279 DartType type = pop();
1280 pop(); // Modifiers. 1280 pop(); // Modifiers.
1281 ignore(Unhandled.Metadata); 1281 ignore(Unhandled.Metadata);
1282 VariableDeclaration variable; 1282 VariableDeclaration variable;
1283 if (!inCatchClause && functionNestingLevel == 0) { 1283 if (!inCatchClause && functionNestingLevel == 0) {
1284 var builder = formalParameterScope.lookup(name.name, charOffset, uri); 1284 var builder = formalParameterScope.lookup(name.name, charOffset, uri);
1285 if (builder == null) { 1285 if (builder == null) {
1286 return inputError("'${name.name}' isn't a field in this class.", 1286 if (thisKeyword == null) {
1287 name.fileOffset); 1287 internalError("Internal error: formal missing for '${name.name}'");
1288 } 1288 } else {
1289 if (thisKeyword == null) { 1289 addCompileTimeError(thisKeyword.charOffset,
1290 "'${name.name}' isn't a field in this class.");
1291 thisKeyword = null;
1292 }
1293 } else if (thisKeyword == null) {
1290 variable = builder.build(); 1294 variable = builder.build();
1291 variable.initializer = name.initializer; 1295 variable.initializer = name.initializer;
1292 } else if (builder.isField && builder.parent == classBuilder) { 1296 } else if (builder.isField && builder.parent == classBuilder) {
1293 FieldBuilder field = builder; 1297 FieldBuilder field = builder;
1294 if (type != null) { 1298 if (type != null) {
1295 nit("Ignoring type on 'this' parameter '${name.name}'.", 1299 nit("Ignoring type on 'this' parameter '${name.name}'.",
1296 name.fileOffset); 1300 name.fileOffset);
1297 } 1301 }
1298 type = field.target.type ?? const DynamicType(); 1302 type = field.target.type ?? const DynamicType();
1299 variable = new VariableDeclaration(name.name, type: type, 1303 variable = new VariableDeclaration(name.name, type: type,
1300 initializer: name.initializer); 1304 initializer: name.initializer);
1301 } else { 1305 } else {
1302 return inputError("'${name.name}' isn't a field in this class.", 1306 addCompileTimeError(name.fileOffset,
1303 name.fileOffset); 1307 "'${name.name}' isn't a field in this class.");
1304 } 1308 }
1305 } else {
1306 variable = new VariableDeclaration(name.name,
1307 type: type ?? const DynamicType(), initializer: name.initializer);
1308 } 1309 }
1310 variable ??= new VariableDeclaration(name.name,
1311 type: type ?? const DynamicType(), initializer: name.initializer);
1309 push(variable); 1312 push(variable);
1310 } 1313 }
1311 1314
1312 @override 1315 @override
1313 void endOptionalFormalParameters( 1316 void endOptionalFormalParameters(
1314 int count, Token beginToken, Token endToken) { 1317 int count, Token beginToken, Token endToken) {
1315 debugEvent("OptionalFormalParameters"); 1318 debugEvent("OptionalFormalParameters");
1316 FormalParameterType kind = optional("{", beginToken) 1319 FormalParameterType kind = optional("{", beginToken)
1317 ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL; 1320 ? FormalParameterType.NAMED : FormalParameterType.POSITIONAL;
1318 push(new OptionalFormals(kind, popList(count))); 1321 push(new OptionalFormals(kind, popList(count)));
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
1845 /// lvalue = #t; 1848 /// lvalue = #t;
1846 /// body; 1849 /// body;
1847 /// } 1850 /// }
1848 variable = new VariableDeclaration.forValue(null); 1851 variable = new VariableDeclaration.forValue(null);
1849 body = combineStatements( 1852 body = combineStatements(
1850 new ExpressionStatement( 1853 new ExpressionStatement(
1851 lvalue.buildAssignment( 1854 lvalue.buildAssignment(
1852 new VariableGet(variable), voidContext: true)), 1855 new VariableGet(variable), voidContext: true)),
1853 body); 1856 body);
1854 } else { 1857 } else {
1855 throw inputError("Expected lvalue, but got ${lvalue}", 1858 variable = new VariableDeclaration.forValue(
1856 forToken.next.next.charOffset); 1859 buildCompileTimeError("Expected lvalue, but got ${lvalue}",
1860 forToken.next.next.charOffset));
1857 } 1861 }
1858 Statement result = new ForInStatement(variable, expression, body, 1862 Statement result = new ForInStatement(variable, expression, body,
1859 isAsync: awaitToken != null); 1863 isAsync: awaitToken != null);
1860 if (breakTarget.hasUsers) { 1864 if (breakTarget.hasUsers) {
1861 result = new LabeledStatement(result); 1865 result = new LabeledStatement(result);
1862 breakTarget.resolveBreaks(result); 1866 breakTarget.resolveBreaks(result);
1863 } 1867 }
1864 exitLoopOrSwitch(result); 1868 exitLoopOrSwitch(result);
1865 } 1869 }
1866 1870
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
2229 return internalError("Unhandled: ${builder.runtimeType}"); 2233 return internalError("Unhandled: ${builder.runtimeType}");
2230 } 2234 }
2231 } 2235 }
2232 2236
2233 @override 2237 @override
2234 void handleOperator(Token token) { 2238 void handleOperator(Token token) {
2235 debugEvent("Operator"); 2239 debugEvent("Operator");
2236 push(new Operator(token.stringValue)..fileOffset = token.charOffset); 2240 push(new Operator(token.stringValue)..fileOffset = token.charOffset);
2237 } 2241 }
2238 2242
2239 dynamic inputError(String message, [int charOffset = -1]) { 2243 dynamic addCompileTimeError(int charOffset, String message) {
2240 return errors.inputError(uri, charOffset, message); 2244 return library.addCompileTimeError(charOffset, message, uri);
2241 } 2245 }
2242 2246
2243 @override 2247 @override
2244 void handleInvalidFunctionBody(Token token) { 2248 void handleInvalidFunctionBody(Token token) {
2245 if (!lastErrorWasNativeFunctionBody) { 2249 if (!lastErrorWasNativeFunctionBody) {
2246 push(new Block(<Statement>[new InvalidStatement()])); 2250 push(new Block(<Statement>[new InvalidStatement()]));
2247 } 2251 }
2248 lastErrorWasNativeFunctionBody = false; 2252 lastErrorWasNativeFunctionBody = false;
2249 } 2253 }
2250 2254
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
2697 } else if (node is TypeDeclarationBuilder) { 2701 } else if (node is TypeDeclarationBuilder) {
2698 return node.name; 2702 return node.name;
2699 } else if (node is PrefixBuilder) { 2703 } else if (node is PrefixBuilder) {
2700 return node.name; 2704 return node.name;
2701 } else if (node is ThisPropertyAccessor) { 2705 } else if (node is ThisPropertyAccessor) {
2702 return node.name.name; 2706 return node.name.name;
2703 } else { 2707 } else {
2704 return internalError("Unhandled: ${node.runtimeType}"); 2708 return internalError("Unhandled: ${node.runtimeType}");
2705 } 2709 }
2706 } 2710 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698