Create a common generator class to handle non-lvalues.
This allows all non-lvalue cases to be integrated with the analyzer using a common code path. Change-Id: I15cd2bc07a2d3609e78886609f3e29ee6aa807fc Reviewed-on: https://dart-review.googlesource.com/66402 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
1fe0518d3b
commit
55c0857037
@@ -116,9 +116,11 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
||||
node.rightHandSide.accept(this);
|
||||
|
||||
SyntacticEntity entity = _getAssignmentEntity(node.leftHandSide);
|
||||
var data = _get(entity);
|
||||
node.staticElement = _translateAuxiliaryReference(data.combiner);
|
||||
node.staticType = _translateType(data.inferredType);
|
||||
if (entity != null) {
|
||||
var data = _get(entity);
|
||||
node.staticElement = _translateAuxiliaryReference(data.combiner);
|
||||
node.staticType = _translateType(data.inferredType);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -541,9 +543,11 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
||||
void visitPostfixExpression(PostfixExpression node) {
|
||||
node.operand.accept(this);
|
||||
SyntacticEntity entity = _getAssignmentEntity(node.operand);
|
||||
var data = _get(entity);
|
||||
node.staticElement = _translateAuxiliaryReference(data.combiner);
|
||||
node.staticType = _translateType(data.inferredType);
|
||||
if (entity != null) {
|
||||
var data = _get(entity);
|
||||
node.staticElement = _translateAuxiliaryReference(data.combiner);
|
||||
node.staticType = _translateType(data.inferredType);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -561,9 +565,11 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
||||
// ++v;
|
||||
// This is an assignment, it is associated with the operand.
|
||||
SyntacticEntity entity = _getAssignmentEntity(node.operand);
|
||||
var data = _get(entity);
|
||||
node.staticElement = _translateAuxiliaryReference(data.combiner);
|
||||
node.staticType = _translateType(data.inferredType);
|
||||
if (entity != null) {
|
||||
var data = _get(entity);
|
||||
node.staticElement = _translateAuxiliaryReference(data.combiner);
|
||||
node.staticType = _translateType(data.inferredType);
|
||||
}
|
||||
} else if (tokenType == TokenType.BANG) {
|
||||
// !boolExpression;
|
||||
node.staticType = _translateType(_get(node).inferredType);
|
||||
@@ -732,8 +738,7 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
||||
} else if (leftHandSide is ParenthesizedExpression) {
|
||||
return leftHandSide.rightParenthesis;
|
||||
} else {
|
||||
throw new StateError(
|
||||
'Unexpected LHS (${leftHandSide.runtimeType}) $leftHandSide');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6368,7 +6368,13 @@ class C {
|
||||
''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(
|
||||
source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
source,
|
||||
useCFE
|
||||
? [
|
||||
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
|
||||
CompileTimeErrorCode.NOT_AN_LVALUE
|
||||
]
|
||||
: [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@@ -6382,7 +6388,13 @@ f() {
|
||||
''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(
|
||||
source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
source,
|
||||
useCFE
|
||||
? [
|
||||
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
|
||||
CompileTimeErrorCode.NOT_AN_LVALUE
|
||||
]
|
||||
: [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@@ -6398,7 +6410,13 @@ class C {
|
||||
''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(
|
||||
source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
source,
|
||||
useCFE
|
||||
? [
|
||||
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
|
||||
CompileTimeErrorCode.NOT_AN_LVALUE
|
||||
]
|
||||
: [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@@ -6412,7 +6430,13 @@ f() {
|
||||
''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(
|
||||
source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
source,
|
||||
useCFE
|
||||
? [
|
||||
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
|
||||
CompileTimeErrorCode.NOT_AN_LVALUE
|
||||
]
|
||||
: [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@@ -6625,7 +6649,13 @@ f() {
|
||||
''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(
|
||||
source, [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
source,
|
||||
useCFE
|
||||
? [
|
||||
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
|
||||
CompileTimeErrorCode.NOT_AN_LVALUE
|
||||
]
|
||||
: [CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
|
||||
@@ -837,6 +837,32 @@ void main() {
|
||||
}
|
||||
}
|
||||
|
||||
test_assignment_of_postfix_increment() async {
|
||||
addTestFile('''
|
||||
f(int x, int y) {
|
||||
x++ = y;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var xElement = findElement.parameter('x');
|
||||
assertElement(findNode.simple('x++'), xElement);
|
||||
var yElement = findElement.parameter('y');
|
||||
assertElement(findNode.simple('y;'), yElement);
|
||||
}
|
||||
|
||||
test_assignment_of_unresolved_name() async {
|
||||
addTestFile('''
|
||||
f(int y) {
|
||||
x = y;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var yElement = findElement.parameter('y');
|
||||
assertElement(findNode.simple('y;'), yElement);
|
||||
}
|
||||
|
||||
test_assignment_to_final_parameter() async {
|
||||
addTestFile('''
|
||||
f(final int x) {
|
||||
@@ -963,6 +989,21 @@ main() {
|
||||
expect(xReference.staticType.toString(), useCFE ? 'dynamic' : 'int');
|
||||
}
|
||||
|
||||
test_assignment_to_non_generator() async {
|
||||
addTestFile('''
|
||||
f() {}
|
||||
g(x) {
|
||||
f() = x;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var fElement = findElement.function('f');
|
||||
assertElement(findNode.simple('f() ='), fElement);
|
||||
var xElement = findElement.parameter('x');
|
||||
assertElement(findNode.simple('x;'), xElement);
|
||||
}
|
||||
|
||||
test_assignment_to_prefix() async {
|
||||
var a = _p('/test/lib/a.dart');
|
||||
provider.newFile(a, '''
|
||||
@@ -2039,6 +2080,32 @@ var v = (() => 42)();
|
||||
expect(closureElement.enclosingElement, same(variableInitializer));
|
||||
}
|
||||
|
||||
test_compound_assignment_of_postfix_increment() async {
|
||||
addTestFile('''
|
||||
f(int x, int y) {
|
||||
x++ += y;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var xElement = findElement.parameter('x');
|
||||
assertElement(findNode.simple('x++'), xElement);
|
||||
var yElement = findElement.parameter('y');
|
||||
assertElement(findNode.simple('y;'), yElement);
|
||||
}
|
||||
|
||||
test_compound_assignment_of_unresolved_name() async {
|
||||
addTestFile('''
|
||||
f(int y) {
|
||||
x += y;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var yElement = findElement.parameter('y');
|
||||
assertElement(findNode.simple('y;'), yElement);
|
||||
}
|
||||
|
||||
test_conditionalExpression() async {
|
||||
String content = r'''
|
||||
void main() {
|
||||
@@ -2474,6 +2541,18 @@ main() async {
|
||||
}
|
||||
}
|
||||
|
||||
test_dual_increment() async {
|
||||
addTestFile('''
|
||||
f(int x) {
|
||||
++x++;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var xElement = findElement.parameter('x');
|
||||
assertElement(findNode.simple('x++'), xElement);
|
||||
}
|
||||
|
||||
test_enum_toString() async {
|
||||
addTestFile(r'''
|
||||
enum MyEnum { A, B, C }
|
||||
@@ -6303,6 +6382,43 @@ void f<T, U>(T a, U b) {}
|
||||
}
|
||||
}
|
||||
|
||||
test_null_aware_assignment_of_postfix_increment() async {
|
||||
addTestFile('''
|
||||
f(int x, int y) {
|
||||
x++ ??= y;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var xElement = findElement.parameter('x');
|
||||
assertElement(findNode.simple('x++'), xElement);
|
||||
var yElement = findElement.parameter('y');
|
||||
assertElement(findNode.simple('y;'), yElement);
|
||||
}
|
||||
|
||||
test_postfix_increment_of_non_generator() async {
|
||||
addTestFile('''
|
||||
f() {}
|
||||
g() {
|
||||
f()++;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var fElement = findElement.function('f');
|
||||
assertElement(findNode.simple('f()++;'), fElement);
|
||||
}
|
||||
|
||||
test_postfix_increment_of_unresolved_name() async {
|
||||
addTestFile('''
|
||||
f() {
|
||||
x++;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
}
|
||||
|
||||
test_postfixExpression_local() async {
|
||||
String content = r'''
|
||||
main() {
|
||||
@@ -6377,6 +6493,31 @@ class C {
|
||||
}
|
||||
}
|
||||
|
||||
test_prefix_increment_of_non_generator() async {
|
||||
addTestFile('''
|
||||
f() {}
|
||||
g() {
|
||||
++f();
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
var fReference = findNode.simple('f();');
|
||||
expect(fReference.parent, const TypeMatcher<MethodInvocation>());
|
||||
var fElement = findElement.function('f');
|
||||
assertElement(fReference, fElement);
|
||||
}
|
||||
|
||||
test_prefix_increment_of_unresolved_name() async {
|
||||
addTestFile('''
|
||||
f() {
|
||||
++x;
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
}
|
||||
|
||||
test_prefixedIdentifier_classInstance_instanceField() async {
|
||||
String content = r'''
|
||||
main() {
|
||||
@@ -9431,6 +9572,24 @@ class FindElement {
|
||||
fail('Not found class method: $name');
|
||||
}
|
||||
|
||||
ParameterElement parameter(String name) {
|
||||
ParameterElement parameterElement;
|
||||
for (var function in unitElement.functions) {
|
||||
for (var parameter in function.parameters) {
|
||||
if (parameter.name == name) {
|
||||
if (parameterElement != null) {
|
||||
throw new StateError('Parameter name $name is not unique.');
|
||||
}
|
||||
parameterElement = parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parameterElement != null) {
|
||||
return parameterElement;
|
||||
}
|
||||
fail('No parameter found with name $name');
|
||||
}
|
||||
|
||||
PrefixElement prefix(String name) {
|
||||
for (var import_ in unitElement.library.imports) {
|
||||
var prefix = import_.prefix;
|
||||
|
||||
@@ -6,6 +6,8 @@ library fasta.body_builder;
|
||||
|
||||
import 'dart:core' hide MapEntry;
|
||||
|
||||
import 'package:front_end/src/fasta/kernel/kernel_expression_generator.dart';
|
||||
|
||||
import '../constant_context.dart' show ConstantContext;
|
||||
|
||||
import '../fasta_codes.dart' as fasta;
|
||||
@@ -81,6 +83,7 @@ import 'expression_generator.dart'
|
||||
IndexedAccessGenerator,
|
||||
LargeIntAccessGenerator,
|
||||
LoadLibraryGenerator,
|
||||
NonLvalueGenerator,
|
||||
ParenthesizedExpressionGenerator,
|
||||
PrefixUseGenerator,
|
||||
ReadOnlyAccessGenerator,
|
||||
@@ -1932,20 +1935,27 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
|
||||
pop(); // block
|
||||
}
|
||||
|
||||
Generator popForLvalue(Token token) {
|
||||
Object value = pop();
|
||||
if (value is Generator) {
|
||||
return value.asLvalue();
|
||||
} else {
|
||||
return new NonLvalueGenerator(
|
||||
this,
|
||||
token,
|
||||
buildCompileTimeError(fasta.messageNotAnLvalue, offsetForToken(token),
|
||||
lengthForToken(token)),
|
||||
toValue(value));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleAssignmentExpression(Token token) {
|
||||
debugEvent("AssignmentExpression");
|
||||
Expression value = popForValue();
|
||||
Object generator = pop();
|
||||
if (generator is! Generator) {
|
||||
push(new SyntheticExpressionJudgment(buildCompileTimeError(
|
||||
fasta.messageNotAnLvalue,
|
||||
offsetForToken(token),
|
||||
lengthForToken(token))));
|
||||
} else {
|
||||
push(new DelayedAssignment(
|
||||
this, token, generator, value, token.stringValue));
|
||||
}
|
||||
var generator = popForLvalue(token);
|
||||
push(new DelayedAssignment(
|
||||
this, token, generator, value, token.stringValue));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -2648,27 +2658,17 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
|
||||
@override
|
||||
void handleUnaryPrefixAssignmentExpression(Token token) {
|
||||
debugEvent("UnaryPrefixAssignmentExpression");
|
||||
Object generator = pop();
|
||||
if (generator is Generator) {
|
||||
push(generator.buildPrefixIncrement(incrementOperator(token),
|
||||
offset: token.charOffset));
|
||||
} else {
|
||||
push(
|
||||
wrapInCompileTimeError(toValue(generator), fasta.messageNotAnLvalue));
|
||||
}
|
||||
var generator = popForLvalue(token);
|
||||
push(generator.buildPrefixIncrement(incrementOperator(token),
|
||||
offset: token.charOffset));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleUnaryPostfixAssignmentExpression(Token token) {
|
||||
debugEvent("UnaryPostfixAssignmentExpression");
|
||||
Object generator = pop();
|
||||
if (generator is Generator) {
|
||||
push(new DelayedPostfixIncrement(
|
||||
this, token, generator, incrementOperator(token), null));
|
||||
} else {
|
||||
push(
|
||||
wrapInCompileTimeError(toValue(generator), fasta.messageNotAnLvalue));
|
||||
}
|
||||
var generator = popForLvalue(token);
|
||||
push(new DelayedPostfixIncrement(
|
||||
this, token, generator, incrementOperator(token), null));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -3372,7 +3372,7 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
|
||||
TypePromotionFact fact =
|
||||
typePromoter.getFactForAccess(variable, functionNestingLevel);
|
||||
TypePromotionScope scope = typePromoter.currentScope;
|
||||
syntheticAssignment = lvalue.buildAssignment(
|
||||
syntheticAssignment = lvalue.asLvalue().buildAssignment(
|
||||
new VariableGetJudgment(variable, fact, scope)
|
||||
..fileOffset = inKeyword.offset,
|
||||
voidContext: true);
|
||||
|
||||
@@ -17,6 +17,7 @@ import '../fasta_codes.dart'
|
||||
messageCantUsePrefixWithNullAware,
|
||||
messageInvalidInitializer,
|
||||
messageNotAConstantExpression,
|
||||
messageNotAnLvalue,
|
||||
templateCantUseDeferredPrefixAsConstant,
|
||||
templateDeferredTypeAnnotation,
|
||||
templateIntegerLiteralIsOutOfRange,
|
||||
@@ -66,6 +67,8 @@ import 'kernel_ast_api.dart'
|
||||
DartType,
|
||||
DynamicType,
|
||||
Expression,
|
||||
ExpressionJudgment,
|
||||
IllegalAssignmentJudgment,
|
||||
Initializer,
|
||||
InvalidConstructorInvocationJudgment,
|
||||
InvalidType,
|
||||
@@ -107,6 +110,96 @@ export 'kernel_expression_generator.dart'
|
||||
ThisAccessGenerator,
|
||||
buildIsNull;
|
||||
|
||||
class NonLvalueGenerator extends Generator {
|
||||
final Expression errorExpression;
|
||||
|
||||
final ExpressionJudgment judgment;
|
||||
|
||||
final assignmentOffset;
|
||||
|
||||
NonLvalueGenerator(ExpressionGeneratorHelper helper, Token token,
|
||||
this.errorExpression, this.judgment,
|
||||
{this.assignmentOffset = -1})
|
||||
: super(helper, token);
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
Expression buildAssignment(Expression value, {bool voidContext}) {
|
||||
return makeJudgment(value);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
|
||||
{int offset,
|
||||
bool voidContext,
|
||||
Procedure interfaceTarget,
|
||||
bool isPreIncDec}) {
|
||||
return makeJudgment(value);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildNullAwareAssignment(
|
||||
Expression value, DartType type, int offset,
|
||||
{bool voidContext}) {
|
||||
return makeJudgment(value);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildPostfixIncrement(Name binaryOperator,
|
||||
{int offset, bool voidContext, Procedure interfaceTarget}) {
|
||||
return makeJudgment(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildPrefixIncrement(Name binaryOperator,
|
||||
{int offset, bool voidContext, Procedure interfaceTarget}) {
|
||||
return makeJudgment(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildSimpleRead() {
|
||||
return makeJudgment(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression makeInvalidRead() {
|
||||
return makeJudgment(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression makeInvalidWrite(Expression value) {
|
||||
return makeJudgment(value);
|
||||
}
|
||||
|
||||
@override
|
||||
String get debugName {
|
||||
return unhandled('debugName', 'NonLvalueGenerator', token.offset, uri);
|
||||
}
|
||||
|
||||
@override
|
||||
doInvocation(int offset, Arguments arguments) {
|
||||
return unhandled('doInvocation', 'NonLvalueGenerator', token.offset, uri);
|
||||
}
|
||||
|
||||
Expression makeJudgment(ExpressionJudgment rhs) {
|
||||
return new IllegalAssignmentJudgment(errorExpression, judgment, rhs,
|
||||
assignmentOffset: assignmentOffset);
|
||||
}
|
||||
|
||||
@override
|
||||
String get plainNameForRead {
|
||||
return unhandled(
|
||||
'plainNameForRead', 'NonLvalueGenerator', token.offset, uri);
|
||||
}
|
||||
|
||||
@override
|
||||
void printOn(StringSink sink) {
|
||||
return unhandled('printOn', 'NonLvalueGenerator', token.offset, uri);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ExpressionGenerator {
|
||||
/// Builds a [Expression] representing a read from the generator.
|
||||
Expression buildSimpleRead();
|
||||
@@ -189,6 +282,8 @@ abstract class Generator implements ExpressionGenerator {
|
||||
|
||||
bool get isInitializer => false;
|
||||
|
||||
Generator asLvalue();
|
||||
|
||||
Expression buildForEffect() => buildSimpleRead();
|
||||
|
||||
Initializer buildFieldInitializer(Map<String, int> initializedFields) {
|
||||
@@ -233,6 +328,15 @@ abstract class Generator implements ExpressionGenerator {
|
||||
return new UnexpectedQualifiedUseGenerator(helper, name, this, false);
|
||||
}
|
||||
|
||||
Generator makeNonLValueGenerator() {
|
||||
return new NonLvalueGenerator(
|
||||
helper,
|
||||
token,
|
||||
helper.buildCompileTimeError(
|
||||
messageNotAnLvalue, offsetForToken(token), lengthForToken(token)),
|
||||
buildSimpleRead());
|
||||
}
|
||||
|
||||
Expression invokeConstructor(List<DartType> typeArguments, String name,
|
||||
Arguments arguments, Token nameToken, Constness constness) {
|
||||
if (typeArguments != null) {
|
||||
@@ -277,6 +381,9 @@ abstract class VariableUseGenerator implements Generator {
|
||||
.variableUseGenerator(helper, token, variable, promotedType);
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
String get debugName => "VariableUseGenerator";
|
||||
}
|
||||
@@ -312,6 +419,9 @@ abstract class PropertyAccessGenerator implements Generator {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
String get debugName => "PropertyAccessGenerator";
|
||||
|
||||
@@ -328,6 +438,9 @@ abstract class ThisPropertyAccessGenerator implements Generator {
|
||||
.thisPropertyAccessGenerator(helper, token, name, getter, setter);
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
String get debugName => "ThisPropertyAccessGenerator";
|
||||
|
||||
@@ -348,6 +461,9 @@ abstract class NullAwarePropertyAccessGenerator implements Generator {
|
||||
helper, token, receiverExpression, name, getter, setter, type);
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
String get debugName => "NullAwarePropertyAccessGenerator";
|
||||
}
|
||||
@@ -359,6 +475,9 @@ abstract class SuperPropertyAccessGenerator implements Generator {
|
||||
.superPropertyAccessGenerator(helper, token, name, getter, setter);
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
String get debugName => "SuperPropertyAccessGenerator";
|
||||
}
|
||||
@@ -391,6 +510,9 @@ abstract class IndexedAccessGenerator implements Generator {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
String get plainNameForRead => "[]";
|
||||
|
||||
@@ -410,6 +532,9 @@ abstract class ThisIndexedAccessGenerator implements Generator {
|
||||
.thisIndexedAccessGenerator(helper, token, index, getter, setter);
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
String get plainNameForRead => "[]";
|
||||
|
||||
@@ -427,6 +552,9 @@ abstract class SuperIndexedAccessGenerator implements Generator {
|
||||
.superIndexedAccessGenerator(helper, token, index, getter, setter);
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
String get plainNameForRead => "[]";
|
||||
|
||||
String get plainNameForWrite => "[]=";
|
||||
@@ -466,6 +594,9 @@ abstract class StaticAccessGenerator implements Generator {
|
||||
return new StaticAccessGenerator(helper, token, getter, setter);
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
Member get readTarget;
|
||||
|
||||
@override
|
||||
@@ -478,6 +609,9 @@ abstract class LoadLibraryGenerator implements Generator {
|
||||
return helper.forest.loadLibraryGenerator(helper, token, builder);
|
||||
}
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
@override
|
||||
String get plainNameForRead => 'loadLibrary';
|
||||
|
||||
@@ -496,6 +630,9 @@ abstract class DeferredAccessGenerator implements Generator {
|
||||
|
||||
Generator get suffixGenerator;
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
buildPropertyAccess(
|
||||
IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
|
||||
@@ -572,6 +709,9 @@ abstract class TypeUseGenerator implements Generator {
|
||||
@override
|
||||
String get debugName => "TypeUseGenerator";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
@override
|
||||
DartType buildTypeWithBuiltArguments(List<DartType> arguments,
|
||||
{bool nonInstanceAccessIsError: false, TypeInferrer typeInferrer}) {
|
||||
@@ -674,6 +814,9 @@ abstract class ReadOnlyAccessGenerator implements Generator {
|
||||
|
||||
@override
|
||||
String get debugName => "ReadOnlyAccessGenerator";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
}
|
||||
|
||||
abstract class LargeIntAccessGenerator implements Generator {
|
||||
@@ -689,6 +832,9 @@ abstract class LargeIntAccessGenerator implements Generator {
|
||||
@override
|
||||
String get debugName => "LargeIntAccessGenerator";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
Expression buildError() {
|
||||
return helper.buildCompileTimeError(
|
||||
templateIntegerLiteralIsOutOfRange.withArguments(token),
|
||||
@@ -722,6 +868,9 @@ abstract class ErroneousExpressionGenerator implements Generator {
|
||||
|
||||
withReceiver(Object receiver, int operatorOffset, {bool isNullAware}) => this;
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
Initializer buildFieldInitializer(Map<String, int> initializedFields) {
|
||||
return helper.buildInvalidInitializer(new SyntheticExpressionJudgment(
|
||||
@@ -842,7 +991,7 @@ abstract class UnresolvedNameGenerator implements ErroneousExpressionGenerator {
|
||||
offset ??= offsetForToken(this.token);
|
||||
return helper.throwNoSuchMethodError(
|
||||
forest.literalNull(null)..fileOffset = offset,
|
||||
plainNameForRead,
|
||||
plainNameForRead ?? '',
|
||||
arguments,
|
||||
offset,
|
||||
isGetter: isGetter,
|
||||
@@ -870,6 +1019,9 @@ abstract class UnlinkedGenerator implements Generator {
|
||||
@override
|
||||
String get debugName => "UnlinkedGenerator";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => this;
|
||||
|
||||
@override
|
||||
void printOn(StringSink sink) {
|
||||
sink.write(", name: ");
|
||||
@@ -950,6 +1102,9 @@ abstract class DelayedAssignment implements ContextAwareGenerator {
|
||||
@override
|
||||
String get debugName => "DelayedAssignment";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
@override
|
||||
Expression buildSimpleRead() {
|
||||
return handleAssignment(false);
|
||||
@@ -1035,6 +1190,9 @@ abstract class DelayedPostfixIncrement implements ContextAwareGenerator {
|
||||
@override
|
||||
String get debugName => "DelayedPostfixIncrement";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
@override
|
||||
Expression buildSimpleRead() {
|
||||
return generator.buildPostfixIncrement(binaryOperator,
|
||||
@@ -1074,6 +1232,9 @@ abstract class PrefixUseGenerator implements Generator {
|
||||
@override
|
||||
String get debugName => "PrefixUseGenerator";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
@override
|
||||
Expression buildSimpleRead() => makeInvalidRead();
|
||||
|
||||
@@ -1144,9 +1305,6 @@ abstract class PrefixUseGenerator implements Generator {
|
||||
lengthForToken(token)));
|
||||
}
|
||||
|
||||
@override
|
||||
Expression makeInvalidWrite(Expression value) => makeInvalidRead();
|
||||
|
||||
@override
|
||||
void printOn(StringSink sink) {
|
||||
sink.write(", prefix: ");
|
||||
@@ -1175,6 +1333,9 @@ abstract class UnexpectedQualifiedUseGenerator implements Generator {
|
||||
@override
|
||||
String get debugName => "UnexpectedQualifiedUseGenerator";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
@override
|
||||
Expression buildSimpleRead() => makeInvalidRead();
|
||||
|
||||
|
||||
@@ -96,7 +96,6 @@ export 'kernel_shadow_ast.dart'
|
||||
InvalidStatementJudgment,
|
||||
InvalidSuperInitializerJudgment,
|
||||
InvalidVariableWriteJudgment,
|
||||
InvalidWriteJudgment,
|
||||
ShadowInvalidFieldInitializer,
|
||||
ShadowInvalidInitializer,
|
||||
LabeledStatementJudgment,
|
||||
|
||||
@@ -47,6 +47,7 @@ import 'expression_generator.dart'
|
||||
IndexedAccessGenerator,
|
||||
LargeIntAccessGenerator,
|
||||
LoadLibraryGenerator,
|
||||
NonLvalueGenerator,
|
||||
NullAwarePropertyAccessGenerator,
|
||||
PrefixUseGenerator,
|
||||
PropertyAccessGenerator,
|
||||
@@ -77,13 +78,11 @@ import 'kernel_ast_api.dart'
|
||||
Constructor,
|
||||
DartType,
|
||||
Field,
|
||||
IllegalAssignmentJudgment,
|
||||
IndexAssignmentJudgment,
|
||||
Initializer,
|
||||
InvalidPropertyGetJudgment,
|
||||
InvalidType,
|
||||
InvalidVariableWriteJudgment,
|
||||
InvalidWriteJudgment,
|
||||
Let,
|
||||
LoadLibraryTearOffJudgment,
|
||||
Member,
|
||||
@@ -247,7 +246,7 @@ abstract class KernelExpressionGenerator implements ExpressionGenerator {
|
||||
Expression makeInvalidWrite(Expression value) {
|
||||
return buildInvalidWriteJudgment(helper.throwNoSuchMethodError(
|
||||
forest.literalNull(token),
|
||||
plainNameForRead,
|
||||
plainNameForRead ?? '',
|
||||
forest.arguments(<Expression>[value], noLocation),
|
||||
offsetForToken(token),
|
||||
isSetter: true));
|
||||
@@ -289,8 +288,13 @@ abstract class KernelExpressionGenerator implements ExpressionGenerator {
|
||||
|
||||
/// Creates a data structure for tracking the desugaring of a complex
|
||||
/// assignment expression whose right hand side is [rhs].
|
||||
ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
|
||||
new IllegalAssignmentJudgment(rhs);
|
||||
ComplexAssignmentJudgment startComplexAssignment(Expression rhs) {
|
||||
// This code should never be reached; clients should always use .asLvalue()
|
||||
// prior to starting a complex assignment, and generators returned by
|
||||
// .asLvalue() should always override this method.
|
||||
return unhandled(
|
||||
'startComplexAssignment', '$runtimeType', token.offset, null);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class KernelGenerator = Generator with KernelExpressionGenerator;
|
||||
|
||||
@@ -32,6 +32,9 @@ class ThisAccessGenerator extends KernelGenerator {
|
||||
|
||||
String get debugName => "ThisAccessGenerator";
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
Expression buildSimpleRead() {
|
||||
if (!isSuper) {
|
||||
return forest.thisExpression(token);
|
||||
@@ -129,46 +132,6 @@ class ThisAccessGenerator extends KernelGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
Expression buildAssignment(Expression value, {bool voidContext: false}) {
|
||||
return buildAssignmentError();
|
||||
}
|
||||
|
||||
Expression buildNullAwareAssignment(
|
||||
Expression value, DartType type, int offset,
|
||||
{bool voidContext: false}) {
|
||||
return buildAssignmentError();
|
||||
}
|
||||
|
||||
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
|
||||
{int offset: TreeNode.noOffset,
|
||||
bool voidContext: false,
|
||||
Procedure interfaceTarget,
|
||||
bool isPreIncDec: false,
|
||||
bool isPostIncDec: false}) {
|
||||
return buildAssignmentError();
|
||||
}
|
||||
|
||||
Expression buildPrefixIncrement(Name binaryOperator,
|
||||
{int offset: TreeNode.noOffset,
|
||||
bool voidContext: false,
|
||||
Procedure interfaceTarget}) {
|
||||
return buildAssignmentError();
|
||||
}
|
||||
|
||||
Expression buildPostfixIncrement(Name binaryOperator,
|
||||
{int offset: TreeNode.noOffset,
|
||||
bool voidContext: false,
|
||||
Procedure interfaceTarget}) {
|
||||
return buildAssignmentError();
|
||||
}
|
||||
|
||||
Expression buildAssignmentError() {
|
||||
String message =
|
||||
isSuper ? "Can't assign to 'super'." : "Can't assign to 'this'.";
|
||||
return helper.deprecated_buildCompileTimeError(
|
||||
message, offsetForToken(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void printOn(StringSink sink) {
|
||||
sink.write(", isInitializer: ");
|
||||
@@ -189,6 +152,9 @@ abstract class IncompleteSendGenerator extends KernelGenerator {
|
||||
|
||||
Arguments get arguments => null;
|
||||
|
||||
@override
|
||||
Generator asLvalue() => makeNonLValueGenerator();
|
||||
|
||||
@override
|
||||
void printOn(StringSink sink) {
|
||||
sink.write(", name: ");
|
||||
@@ -378,16 +344,15 @@ class ParenthesizedExpressionGenerator extends KernelReadOnlyAccessGenerator {
|
||||
String get debugName => "ParenthesizedExpressionGenerator";
|
||||
|
||||
@override
|
||||
ComplexAssignmentJudgment startComplexAssignment(Expression rhs) {
|
||||
return new IllegalAssignmentJudgment(rhs,
|
||||
Generator asLvalue() {
|
||||
return new NonLvalueGenerator(
|
||||
helper,
|
||||
token,
|
||||
helper.buildCompileTimeError(
|
||||
messageCannotAssignToParenthesizedExpression,
|
||||
offsetForToken(token),
|
||||
lengthForToken(token)),
|
||||
buildSimpleRead(),
|
||||
assignmentOffset: offsetForToken(token));
|
||||
}
|
||||
|
||||
Expression makeInvalidWrite(Expression value) {
|
||||
var error = helper.buildCompileTimeError(
|
||||
messageCannotAssignToParenthesizedExpression,
|
||||
offsetForToken(token),
|
||||
lengthForToken(token));
|
||||
return new InvalidWriteJudgment(error, expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1574,35 +1574,44 @@ class IfJudgment extends IfStatement implements StatementJudgment {
|
||||
}
|
||||
}
|
||||
|
||||
/// Concrete shadow object representing an assignment to a target for which
|
||||
/// assignment is not allowed.
|
||||
class IllegalAssignmentJudgment extends ComplexAssignmentJudgment {
|
||||
class IllegalAssignmentJudgment extends SyntheticExpressionJudgment {
|
||||
/// The offset at which the invalid assignment should be stored.
|
||||
/// If `-1`, then there is no separate location for invalid assignment.
|
||||
final int assignmentOffset;
|
||||
|
||||
IllegalAssignmentJudgment(ExpressionJudgment rhs, {this.assignmentOffset: -1})
|
||||
: super(rhs) {
|
||||
rhs.parent = this;
|
||||
IllegalAssignmentJudgment(kernel.Expression desugared, this.lhs, this.rhs,
|
||||
{this.assignmentOffset: -1})
|
||||
: super(desugared) {
|
||||
// lhs and rhs may not be hooked up to the expression tree because they're
|
||||
// not meant to be part of the compiled output; they only exist to allow
|
||||
// resolution information to be reported to the analyzer. But type
|
||||
// inference currently requires expressions to have a parent (so that it can
|
||||
// replace them with their desugared equivalents), so create placeholder
|
||||
// parents if needed.
|
||||
if (lhs.parent == null) {
|
||||
new ExpressionStatement(lhs);
|
||||
}
|
||||
if (rhs != null && rhs.parent == null) {
|
||||
new ExpressionStatement(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
DartType _getWriteType(ShadowTypeInferrer inferrer) {
|
||||
return const UnknownType();
|
||||
}
|
||||
final ExpressionJudgment lhs;
|
||||
|
||||
final ExpressionJudgment rhs;
|
||||
|
||||
@override
|
||||
Expression infer<Expression, Statement, Initializer, Type>(
|
||||
ShadowTypeInferrer inferrer,
|
||||
Factory<Expression, Statement, Initializer, Type> factory,
|
||||
DartType typeContext) {
|
||||
if (write != null) {
|
||||
inferrer.inferExpression(factory, write, const UnknownType(), false);
|
||||
}
|
||||
inferrer.inferExpression(factory, lhs, const UnknownType(), false);
|
||||
if (assignmentOffset != -1) {
|
||||
inferrer.listener.invalidAssignment(this, assignmentOffset);
|
||||
}
|
||||
inferrer.inferExpression(factory, rhs, const UnknownType(), false);
|
||||
if (rhs != null) {
|
||||
inferrer.inferExpression(factory, rhs, const UnknownType(), false);
|
||||
}
|
||||
_replaceWithDesugared();
|
||||
inferredType = const DynamicType();
|
||||
return null;
|
||||
@@ -2975,29 +2984,6 @@ class InvalidVariableWriteJudgment extends SyntheticExpressionJudgment {
|
||||
}
|
||||
}
|
||||
|
||||
/// Synthetic judgment class representing an attempt to assign to the
|
||||
/// [expression] which is not assignable.
|
||||
class InvalidWriteJudgment extends SyntheticExpressionJudgment {
|
||||
final ExpressionJudgment expression;
|
||||
|
||||
InvalidWriteJudgment(kernel.Expression desugared, this.expression)
|
||||
: super(desugared);
|
||||
|
||||
@override
|
||||
Expression infer<Expression, Statement, Initializer, Type>(
|
||||
ShadowTypeInferrer inferrer,
|
||||
Factory<Expression, Statement, Initializer, Type> factory,
|
||||
DartType typeContext) {
|
||||
// When a compound assignment, the expression is already wrapping in
|
||||
// VariableDeclaration in _makeRead(). Otherwise, temporary associate
|
||||
// the expression with this node.
|
||||
expression.parent ??= this;
|
||||
|
||||
inferrer.inferExpression(factory, expression, const UnknownType(), false);
|
||||
return super.infer(inferrer, factory, typeContext);
|
||||
}
|
||||
}
|
||||
|
||||
/// Synthetic judgment class representing an attempt reference a member
|
||||
/// that is not allowed at this location.
|
||||
class InvalidPropertyGetJudgment extends SyntheticExpressionJudgment {
|
||||
|
||||
@@ -34,6 +34,7 @@ CantInferPackagesFromPackageUri/example: Fail
|
||||
CantInferTypeDueToCircularity/dart2jsCode: Fail
|
||||
CantInferTypeDueToCircularity/example: Fail
|
||||
CantInferTypeDueToInconsistentOverrides/example: Fail
|
||||
CantUsePrefixAsExpression/script: Fail
|
||||
CantUseSuperBoundedTypeForInstanceCreation/analyzerCode: Fail
|
||||
CantUseSuperBoundedTypeForInstanceCreation/example: Fail
|
||||
ColonInPlaceOfIn/example: Fail
|
||||
|
||||
@@ -96,7 +96,7 @@ rasta/type_with_parse_error: Fail
|
||||
rasta/typedef: Fail
|
||||
rasta/unresolved: Fail
|
||||
rasta/unresolved_constructor: Fail
|
||||
rasta/unresolved_for_in: RuntimeError # Test contains a compile-time error, signaled at run time in the JIT VM
|
||||
rasta/unresolved_for_in: RuntimeError # Test has an intentional error
|
||||
rasta/unresolved_recovery: Fail
|
||||
|
||||
regress/issue_29975: Fail # Issue 29975.
|
||||
|
||||
@@ -23,11 +23,13 @@ class Fisk extends core::Object {
|
||||
core::print(this.key);
|
||||
}
|
||||
for (final dynamic #t2 in x) {
|
||||
let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#Fisk, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t2]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:14:10: Error: Can't assign to this.
|
||||
for (Fisk in x) {
|
||||
^^^^";
|
||||
core::print(self::Fisk);
|
||||
}
|
||||
for (final dynamic #t3 in x) {
|
||||
let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:17:10: Error: A prefix can't be used as an expression.
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:17:10: Error: Can't assign to this.
|
||||
for (collection in x) {
|
||||
^^^^^^^^^^";
|
||||
core::print(invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:18:13: Error: A prefix can't be used as an expression.
|
||||
@@ -35,7 +37,9 @@ class Fisk extends core::Object {
|
||||
^^^^^^^^^^");
|
||||
}
|
||||
for (final dynamic #t4 in x) {
|
||||
let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#VoidFunction, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t4]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:20:10: Error: Can't assign to this.
|
||||
for (VoidFunction in x) {
|
||||
^^^^^^^^^^^^";
|
||||
core::print(() → void);
|
||||
}
|
||||
for (final dynamic #t5 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Can't assign to this, so it can't be used in a for-in loop.
|
||||
@@ -52,11 +56,13 @@ static method main(dynamic arguments) → dynamic {
|
||||
core::print(throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#key, 33, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
|
||||
}
|
||||
for (final dynamic #t7 in arguments) {
|
||||
let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#Fisk, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t7]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:34:8: Error: Can't assign to this.
|
||||
for (Fisk in arguments) {
|
||||
^^^^";
|
||||
core::print(self::Fisk);
|
||||
}
|
||||
for (final dynamic #t8 in arguments) {
|
||||
let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:37:8: Error: A prefix can't be used as an expression.
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:37:8: Error: Can't assign to this.
|
||||
for (collection in arguments) {
|
||||
^^^^^^^^^^";
|
||||
core::print(invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:38:11: Error: A prefix can't be used as an expression.
|
||||
@@ -64,7 +70,9 @@ static method main(dynamic arguments) → dynamic {
|
||||
^^^^^^^^^^");
|
||||
}
|
||||
for (final dynamic #t9 in arguments) {
|
||||
let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#VoidFunction, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t9]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:40:8: Error: Can't assign to this.
|
||||
for (VoidFunction in arguments) {
|
||||
^^^^^^^^^^^^";
|
||||
core::print(() → void);
|
||||
}
|
||||
for (final dynamic #t10 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:43:8: Error: Can't assign to this, so it can't be used in a for-in loop.
|
||||
|
||||
@@ -23,11 +23,13 @@ class Fisk extends core::Object {
|
||||
core::print(this.key);
|
||||
}
|
||||
for (final dynamic #t2 in x) {
|
||||
let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#Fisk, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t2]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:14:10: Error: Can't assign to this.
|
||||
for (Fisk in x) {
|
||||
^^^^";
|
||||
core::print(self::Fisk);
|
||||
}
|
||||
for (final dynamic #t3 in x) {
|
||||
let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:17:10: Error: A prefix can't be used as an expression.
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:17:10: Error: Can't assign to this.
|
||||
for (collection in x) {
|
||||
^^^^^^^^^^";
|
||||
core::print(invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:18:13: Error: A prefix can't be used as an expression.
|
||||
@@ -35,7 +37,9 @@ class Fisk extends core::Object {
|
||||
^^^^^^^^^^");
|
||||
}
|
||||
for (final dynamic #t4 in x) {
|
||||
let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#VoidFunction, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t4]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:20:10: Error: Can't assign to this.
|
||||
for (VoidFunction in x) {
|
||||
^^^^^^^^^^^^";
|
||||
core::print(() → void);
|
||||
}
|
||||
for (final dynamic #t5 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Can't assign to this, so it can't be used in a for-in loop.
|
||||
@@ -52,11 +56,13 @@ static method main(dynamic arguments) → dynamic {
|
||||
core::print(throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#key, 33, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))));
|
||||
}
|
||||
for (final dynamic #t7 in arguments) {
|
||||
let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#Fisk, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t7]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:34:8: Error: Can't assign to this.
|
||||
for (Fisk in arguments) {
|
||||
^^^^";
|
||||
core::print(self::Fisk);
|
||||
}
|
||||
for (final dynamic #t8 in arguments) {
|
||||
let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:37:8: Error: A prefix can't be used as an expression.
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:37:8: Error: Can't assign to this.
|
||||
for (collection in arguments) {
|
||||
^^^^^^^^^^";
|
||||
core::print(invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:38:11: Error: A prefix can't be used as an expression.
|
||||
@@ -64,7 +70,9 @@ static method main(dynamic arguments) → dynamic {
|
||||
^^^^^^^^^^");
|
||||
}
|
||||
for (final dynamic #t9 in arguments) {
|
||||
let dynamic _ = null in throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#VoidFunction, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t9]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
|
||||
invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:40:8: Error: Can't assign to this.
|
||||
for (VoidFunction in arguments) {
|
||||
^^^^^^^^^^^^";
|
||||
core::print(() → void);
|
||||
}
|
||||
for (final dynamic #t10 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:43:8: Error: Can't assign to this, so it can't be used in a for-in loop.
|
||||
|
||||
@@ -18,9 +18,9 @@ static method test1() → core::int {
|
||||
self::i;
|
||||
}
|
||||
static method test2() → core::int {
|
||||
return let final dynamic #t3 = self::i in let final dynamic #t4 = #t3 in let final dynamic #t5 = invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
|
||||
return invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
|
||||
return (i) ++ (i);
|
||||
^" in #t4;
|
||||
^";
|
||||
self::i;
|
||||
}
|
||||
static method main() → dynamic {
|
||||
|
||||
@@ -18,9 +18,9 @@ static method test1() → core::int {
|
||||
self::i;
|
||||
}
|
||||
static method test2() → core::int {
|
||||
return let final dynamic #t3 = self::i in let final dynamic #t4 = #t3 in let final dynamic #t5 = invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
|
||||
return invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
|
||||
return (i) ++ (i);
|
||||
^" in #t4;
|
||||
^";
|
||||
self::i;
|
||||
}
|
||||
static method main() → dynamic {
|
||||
|
||||
@@ -18,9 +18,9 @@ static method test1() → core::int {
|
||||
self::i;
|
||||
}
|
||||
static method test2() → core::int {
|
||||
return (let final dynamic #t3 = self::i in let final dynamic #t4 = #t3 in let final dynamic #t5 = invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
|
||||
return invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
|
||||
return (i) ++ (i);
|
||||
^" in #t4) as{TypeError} core::int;
|
||||
^" as{TypeError} core::int;
|
||||
self::i;
|
||||
}
|
||||
static method main() → dynamic {
|
||||
|
||||
@@ -18,9 +18,9 @@ static method test1() → core::int {
|
||||
self::i;
|
||||
}
|
||||
static method test2() → core::int {
|
||||
return (let final core::int #t3 = self::i in let final core::int #t4 = #t3 in let final dynamic #t5 = invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
|
||||
return invalid-expression "pkg/front_end/testcases/regress/issue_31185.dart:12:12: Error: Can't assign to a parenthesized expression.
|
||||
return (i) ++ (i);
|
||||
^" in #t4) as{TypeError} core::int;
|
||||
^" as{TypeError} core::int;
|
||||
self::i;
|
||||
}
|
||||
static method main() → dynamic {
|
||||
|
||||
@@ -6662,7 +6662,7 @@ TEST_CASE(DartAPI_ImportLibrary3) {
|
||||
if (TestCase::UsingStrongMode()) {
|
||||
EXPECT_ERROR(lib,
|
||||
"Compilation failed file:///test-lib:4:10:"
|
||||
" Error: Setter not found: 'foo'");
|
||||
" Error: Can't assign to this.");
|
||||
return;
|
||||
}
|
||||
EXPECT_VALID(lib);
|
||||
|
||||
Reference in New Issue
Block a user