Handle unresolved identifiers with an accessor.
R=karlklose@google.com
Review-Url: https://codereview.chromium.org/2790743004 .
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index b4f385e..8d93df5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -145,18 +145,7 @@
@override
Expression toValue(Object node) {
- if (node is UnresolvedIdentifier) {
- if (isDartLibrary &&
- node.name.name == "main" &&
- library.uri.path == "_builtin" &&
- member?.name == "_getMainClosure") {
- // TODO(ahe): https://github.com/dart-lang/sdk/issues/28989
- return new NullLiteral()..fileOffset = node.fileOffset;
- }
- return throwNoSuchMethodError(
- node.name.name, new Arguments.empty(), node.fileOffset,
- isGetter: true);
- } else if (node is FastaAccessor) {
+ if (node is FastaAccessor) {
return node.buildSimpleRead();
} else if (node is TypeVariableBuilder) {
TypeParameterType type = node.buildTypesWithBuiltArguments(library, null);
@@ -531,9 +520,6 @@
addCompileTimeError(charOffset, "Not a constant expression.");
}
return receiver.doInvocation(charOffset, arguments);
- } else if (receiver is UnresolvedIdentifier) {
- return throwNoSuchMethodError(
- receiver.name.name, arguments, receiver.fileOffset);
} else {
return buildMethodInvocation(
toValue(receiver), callName, arguments, charOffset);
@@ -761,11 +747,14 @@
addCompileTimeError(charOffset, "Not a constant expression.");
}
return new ThisPropertyAccessor(this, charOffset, n, null, null);
+ } else if (isDartLibrary &&
+ name == "main" &&
+ library.uri.path == "_builtin" &&
+ member?.name == "_getMainClosure") {
+ // TODO(ahe): https://github.com/dart-lang/sdk/issues/28989
+ return new NullLiteral()..fileOffset = charOffset;
} else {
- if (constantExpressionRequired) {
- addCompileTimeError(charOffset, "Not a constant expression.");
- }
- return new UnresolvedIdentifier(n)..fileOffset = charOffset;
+ return new UnresolvedAccessor(this, n, charOffset);
}
} else if (builder.isTypeDeclaration) {
if (constantExpressionRequired && builder.isTypeVariable) {
@@ -1305,9 +1294,6 @@
if (name is FastaAccessor) {
warning("'${beginToken.lexeme}' isn't a type.", beginToken.charOffset);
push(const DynamicType());
- } else if (name is UnresolvedIdentifier) {
- warning("'${name.name}' isn't a type.", beginToken.charOffset);
- push(const DynamicType());
} else if (name is TypeVariableBuilder) {
if (constantExpressionRequired) {
addCompileTimeError(
@@ -2458,15 +2444,6 @@
}
// TODO(ahe): Shouldn't need to be an expression.
-class UnresolvedIdentifier extends InvalidExpression {
- final Name name;
-
- UnresolvedIdentifier(this.name);
-
- String toString() => "unresolved-identifier($name)";
-}
-
-// TODO(ahe): Shouldn't need to be an expression.
class Identifier extends InvalidExpression {
final String name;
@@ -2917,8 +2894,6 @@
String getNodeName(Object node) {
if (node is Identifier) {
return node.name;
- } else if (node is UnresolvedIdentifier) {
- return node.name.name;
} else if (node is TypeDeclarationBuilder) {
return node.name;
} else if (node is PrefixBuilder) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart b/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
index 6bfae59..c6e7e93 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
@@ -88,7 +88,7 @@
isSetter: true);
}
- /* Expression | FastaAccessor */ doInvocation(
+ /* Expression | FastaAccessor | Initializer */ doInvocation(
int offset, Arguments arguments);
/* Expression | FastaAccessor */ buildPropertyAccess(
@@ -106,8 +106,8 @@
/* Expression | FastaAccessor */ buildThrowNoSuchMethodError(
Arguments arguments,
{bool isSuper: false,
- isGetter: false,
- isSetter: false,
+ bool isGetter: false,
+ bool isSetter: false,
String name,
int offset}) {
return helper.throwNoSuchMethodError(
@@ -118,7 +118,7 @@
bool get isThisPropertyAccessor => false;
}
-abstract class CompileTimeErrorAccessor implements FastaAccessor {
+abstract class ErrorAccessor implements FastaAccessor {
@override
Expression get builtBinary => internalError("Unsupported operation.");
@@ -135,23 +135,35 @@
internalError("Unsupported operation.");
}
- Expression buildError();
+ /// Pass [arguments] that must be evaluated before throwing an error. At
+ /// most one of [isGetter] and [isSetter] should be true and they're passed
+ /// to [BuilderHelper.buildThrowNoSuchMethodError] if it is used.
+ Expression buildError(Arguments arguments,
+ {bool isGetter: false, bool isSetter: false, int offset});
Name get name => internalError("Unsupported operation.");
+ @override
String get plainNameForRead => name.name;
withReceiver(Object receiver, {bool isNullAware}) => this;
+ @override
Initializer buildFieldInitializer(
Map<String, FieldInitializer> initializers) {
- return new LocalInitializer(new VariableDeclaration.forValue(buildError()));
+ return new LocalInitializer(new VariableDeclaration.forValue(
+ buildError(new Arguments.empty(), isSetter: true)));
}
- doInvocation(int offset, Arguments arguments) => this;
+ @override
+ doInvocation(int offset, Arguments arguments) {
+ return buildError(arguments, offset: offset);
+ }
+ @override
buildPropertyAccess(IncompleteSend send, bool isNullAware) => this;
+ @override
buildThrowNoSuchMethodError(Arguments arguments,
{bool isSuper: false,
isGetter: false,
@@ -161,41 +173,55 @@
return this;
}
+ @override
Expression buildAssignment(Expression value, {bool voidContext: false}) {
- return buildError();
+ return buildError(new Arguments(<Expression>[value]), isSetter: true);
}
+ @override
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget}) {
- return buildError();
+ return buildError(new Arguments(<Expression>[value]), isGetter: true);
}
+ @override
Expression buildPrefixIncrement(Name binaryOperator,
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget}) {
- return buildError();
+ return buildError(new Arguments(<Expression>[new IntLiteral(1)]),
+ isGetter: true);
}
+ @override
Expression buildPostfixIncrement(Name binaryOperator,
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget}) {
- return buildError();
+ return buildError(new Arguments(<Expression>[new IntLiteral(1)]),
+ isGetter: true);
}
+ @override
Expression buildNullAwareAssignment(Expression value, DartType type,
{bool voidContext: false}) {
- return buildError();
+ return buildError(new Arguments(<Expression>[value]), isSetter: true);
}
- Expression buildSimpleRead() => buildError();
+ @override
+ Expression buildSimpleRead() =>
+ buildError(new Arguments.empty(), isGetter: true);
- Expression makeInvalidRead() => buildError();
+ @override
+ Expression makeInvalidRead() =>
+ buildError(new Arguments.empty(), isGetter: true);
- Expression makeInvalidWrite(Expression value) => buildError();
+ @override
+ Expression makeInvalidWrite(Expression value) {
+ return buildError(new Arguments(<Expression>[value]), isSetter: true);
+ }
}
class ThisAccessor extends FastaAccessor {
@@ -361,15 +387,20 @@
withReceiver(Object receiver, {bool isNullAware});
}
-class IncompleteError extends IncompleteSend with CompileTimeErrorAccessor {
+class IncompleteError extends IncompleteSend with ErrorAccessor {
final Object error;
IncompleteError(BuilderHelper helper, int offset, this.error)
: super(helper, offset, null);
- Expression buildError() {
- return helper.buildCompileTimeError(error, offset);
+ @override
+ Expression buildError(Arguments arguments,
+ {bool isGetter: false, bool isSetter: false, int offset}) {
+ return helper.buildCompileTimeError(error, offset ?? this.offset);
}
+
+ @override
+ doInvocation(int offset, Arguments arguments) => this;
}
class SendAccessor extends IncompleteSend {
@@ -408,7 +439,7 @@
Expression result;
if (receiver is KernelClassBuilder) {
Builder builder = receiver.findStaticBuilder(name.name, offset, uri);
- if (builder == null) {
+ if (builder == null || builder is AccessErrorBuilder) {
return buildThrowNoSuchMethodError(arguments);
}
if (builder.hasProblem) {
@@ -802,6 +833,31 @@
}
}
+class UnresolvedAccessor extends FastaAccessor with ErrorAccessor {
+ @override
+ final int offset;
+
+ @override
+ final BuilderHelper helper;
+
+ @override
+ final Name name;
+
+ UnresolvedAccessor(this.helper, this.name, this.offset);
+
+ Expression doInvocation(int charOffset, Arguments arguments) {
+ return buildError(arguments, offset: charOffset);
+ }
+
+ @override
+ Expression buildError(Arguments arguments,
+ {bool isGetter: false, bool isSetter: false, int offset}) {
+ return helper.throwNoSuchMethodError(
+ plainNameForRead, arguments, offset ?? this.offset,
+ isGetter: isGetter, isSetter: isSetter);
+ }
+}
+
bool isFieldOrGetter(Member member) {
return member is Field || (member is Procedure && member.isGetter);
}
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 3859231..786598e 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -86,15 +86,6 @@
Language/Enums/restrictions_t08: MissingCompileTimeError
Language/Expressions/Assignment/expression_assignment_failed_t03: CompileTimeError
Language/Expressions/Assignment/expression_assignment_t07: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t01: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t02: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t03: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t04: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t05: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t06: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t07: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t08: CompileTimeError
-Language/Expressions/Assignment/no_such_method_t09: CompileTimeError
Language/Expressions/Assignment/static_type_t06: CompileTimeError
Language/Expressions/Assignment/super_assignment_failed_t01: RuntimeError
Language/Expressions/Assignment/super_assignment_failed_t02: RuntimeError
@@ -293,7 +284,6 @@
Language/Mixins/declaring_constructor_t08: MissingCompileTimeError
Language/Mixins/declaring_constructor_t09: MissingCompileTimeError
Language/Mixins/declaring_constructor_t10: MissingCompileTimeError
-Language/Overview/Privacy/private_and_public_t04: CompileTimeError
Language/Overview/Privacy/private_and_public_t06: RuntimeError
Language/Overview/Privacy/private_and_public_t09: RuntimeError
Language/Overview/Privacy/private_and_public_t10: RuntimeError
@@ -324,23 +314,18 @@
Language/Statements/Continue/label_t10: MissingCompileTimeError
Language/Statements/Continue/label_t11: MissingCompileTimeError
Language/Statements/Do/execution_t04: Crash
-Language/Statements/For/syntax_t07: CompileTimeError
Language/Statements/For/syntax_t12: MissingCompileTimeError
Language/Statements/For/syntax_t13: MissingCompileTimeError
Language/Statements/For/syntax_t19: MissingCompileTimeError
Language/Statements/For/syntax_t20: MissingCompileTimeError
Language/Statements/If/execution_t03: Crash
-Language/Statements/Labels/scope_t01: CompileTimeError
+Language/Statements/Labels/scope_t01: RuntimeError
Language/Statements/Labels/scope_t05: MissingCompileTimeError
-Language/Statements/Labels/scope_t07: CompileTimeError
+Language/Statements/Labels/scope_t07: RuntimeError
Language/Statements/Labels/syntax_t03: Pass # OK
Language/Statements/Local_Function_Declaration/reference_before_declaration_t01: MissingCompileTimeError
Language/Statements/Local_Function_Declaration/reference_before_declaration_t03: MissingCompileTimeError
-Language/Statements/Local_Variable_Declaration/syntax_t05: CompileTimeError
-Language/Statements/Local_Variable_Declaration/syntax_t06: CompileTimeError
Language/Statements/Local_Variable_Declaration/syntax_t11: MissingCompileTimeError
-Language/Statements/Local_Variable_Declaration/syntax_t18: CompileTimeError
-Language/Statements/Local_Variable_Declaration/syntax_t19: CompileTimeError
Language/Statements/Local_Variable_Declaration/syntax_t20: MissingCompileTimeError
Language/Statements/Rethrow/on_catch_clause_t01: Crash
Language/Statements/Rethrow/on_catch_clause_t02: Crash
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index a40c7b4..cadd82a 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -9,7 +9,6 @@
built_in_identifier_test/01: CompileTimeError
call_nonexistent_static_test/01: CompileTimeError
call_nonexistent_static_test/04: CompileTimeError
-call_nonexistent_static_test/06: CompileTimeError
cha_deopt1_test: RuntimeError # Deferred Loading Issue 28335
cha_deopt2_test: RuntimeError # Deferred Loading Issue 28335
cha_deopt3_test: RuntimeError # Deferred Loading Issue 28335
@@ -94,7 +93,6 @@
covariant_test/46: MissingCompileTimeError
covariant_test/46b: MissingCompileTimeError
covariant_test/59: MissingCompileTimeError
-crash_6725_test/01: CompileTimeError
cyclic_constructor_test/01: MissingCompileTimeError
cyclic_type_test/00: RuntimeError
cyclic_type_test/01: RuntimeError