Change UnresolvedNameGenerator to use NonLvalueGenerator.

This avoids the need for custom assignment-handling logic in
KernelUnresolvedNameGenerator, and ensures that assignments to
unresloved names work properly with analyzer integration.

Change-Id: I802270987c90043d021f8560b56f47babf72fb1e
Reviewed-on: https://dart-review.googlesource.com/66701
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry
2018-07-25 18:22:45 +00:00
committed by commit-bot@chromium.org
parent e4446d3d0d
commit 232bed3d11
8 changed files with 42 additions and 32 deletions
@@ -6459,6 +6459,19 @@ f(int x, int y) {
assertElement(findNode.simple('y;'), yElement);
}
test_null_aware_assignment_to_unresolved_name() async {
addTestFile('''
f(int y) {
x ??= y;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertElement(findNode.simple('x'), null);
var yElement = findElement.parameter('y');
assertElement(findNode.simple('y;'), yElement);
}
test_postfix_increment_of_non_generator() async {
addTestFile('''
f() {}
@@ -8387,6 +8400,8 @@ main() {
var assignment = findNode.assignment('a = b');
assertElementNull(assignment);
if (useCFE) {
assertType(assignment, 'dynamic');
} else {
assertType(assignment, 'int');
}
@@ -80,6 +80,7 @@ import 'kernel_ast_api.dart'
TreeNode,
TypeParameterType,
UnresolvedTargetInvocationJudgment,
UnresolvedVariableAssignmentJudgment,
UnresolvedVariableUnaryJudgment,
VariableDeclaration;
@@ -868,9 +869,6 @@ 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(
@@ -975,6 +973,20 @@ abstract class UnresolvedNameGenerator implements ErroneousExpressionGenerator {
return helper.forest.unresolvedNameGenerator(helper, token, name);
}
@override
Generator asLvalue() {
return new NonLvalueGenerator(
helper,
token,
buildError(new Arguments([]),
isSetter: true, offset: offsetForToken(token)),
new UnresolvedVariableAssignmentJudgment(
null,
false,
null,
)..fileOffset = token.charOffset);
}
@override
String get debugName => "UnresolvedNameGenerator";
@@ -103,7 +103,6 @@ import 'kernel_ast_api.dart'
Throw,
TreeNode,
TypeParameter,
UnresolvedVariableAssignmentJudgment,
UnresolvedVariableGetJudgment,
VariableAssignmentJudgment,
VariableDeclaration,
@@ -1451,20 +1450,6 @@ class KernelUnresolvedNameGenerator extends KernelGenerator
ExpressionGeneratorHelper helper, Token token, this.name)
: super(helper, token);
@override
Expression buildAssignment(Expression value, {bool voidContext: false}) {
return _buildUnresolvedVariableAssignment(false, value);
}
@override
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget,
bool isPreIncDec: false}) {
return _buildUnresolvedVariableAssignment(true, value);
}
@override
Expression buildSimpleRead() {
Expression error = buildError(forest.argumentsEmpty(token), isGetter: true);
@@ -1487,15 +1472,6 @@ class KernelUnresolvedNameGenerator extends KernelGenerator
sink.write(", name: ");
sink.write(name.name);
}
UnresolvedVariableAssignmentJudgment _buildUnresolvedVariableAssignment(
bool isCompound, Expression value) {
return new UnresolvedVariableAssignmentJudgment(
buildError(forest.arguments(<Expression>[value], token), isSetter: true),
isCompound,
value,
)..fileOffset = token.charOffset;
}
}
class KernelUnlinkedGenerator extends KernelGenerator with UnlinkedGenerator {
@@ -171,6 +171,9 @@ class IncompleteErrorGenerator extends IncompleteSendGenerator
ExpressionGeneratorHelper helper, Token token, this.member, this.message)
: super(helper, token, null);
@override
Generator asLvalue() => this;
String get debugName => "IncompleteErrorGenerator";
@override
@@ -3739,8 +3739,12 @@ class UnresolvedVariableAssignmentJudgment extends SyntheticExpressionJudgment {
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
inferrer.inferExpression(factory, rhs, const UnknownType(), true);
inferredType = isCompound ? const DynamicType() : rhs.inferredType;
if (rhs != null) {
inferrer.inferExpression(factory, rhs, const UnknownType(), true);
inferredType = isCompound ? const DynamicType() : rhs.inferredType;
} else {
inferredType = const DynamicType();
}
inferrer.listener.variableAssign(
this, fileOffset, const DynamicType(), null, null, inferredType);
return super.infer(inferrer, factory, typeContext);
@@ -2,4 +2,4 @@ Errors: {
Setter not found: 'z'. (@0)
}
static method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
return throw new dart.core::NoSuchMethodError::withInvocation(null, new dart.core::_InvocationMirror::_withType(#z, 34, const <dart.core::Type>[], dart.core::List::unmodifiable<dynamic>(<dynamic>[2]), dart.core::Map::unmodifiable<dart.core::Symbol, dynamic>(const <dart.core::Symbol, dynamic>{})));
return throw new dart.core::NoSuchMethodError::withInvocation(null, new dart.core::_InvocationMirror::_withType(#z, 34, const <dart.core::Type>[], const <dynamic>[], dart.core::Map::unmodifiable<dart.core::Symbol, dynamic>(const <dart.core::Symbol, dynamic>{})));
@@ -52,7 +52,7 @@ class Fisk extends core::Object {
static method main(dynamic arguments) → dynamic {
new self::Fisk::•();
for (final dynamic #t6 in arguments) {
throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#key, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t6]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#key, 34, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, 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) {
@@ -52,7 +52,7 @@ class Fisk extends core::Object {
static method main(dynamic arguments) → dynamic {
new self::Fisk::•();
for (final dynamic #t6 in arguments) {
throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#key, 34, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[#t6]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#key, 34, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, 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) {