 Chromium Code Reviews
 Chromium Code Reviews Issue 2931363003:
  Add type inference for assignments to properties.  (Closed)
    
  
    Issue 2931363003:
  Add type inference for assignments to properties.  (Closed) 
  | Index: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart | 
| diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart | 
| index 8c96d393783ad53ba4043da27a4b8a9d02cef848..8b23acdd43189d8c84f16120a6be06240e5fe98d 100644 | 
| --- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart | 
| +++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart | 
| @@ -912,12 +912,10 @@ class KernelIfStatement extends IfStatement implements KernelStatement { | 
| /// Concrete shadow object representing an assignment to a target of the form | 
| /// `a[b]`. | 
| class KernelIndexAssign extends KernelComplexAssignment { | 
| - /// The receiver of the assignment target (e.g. `a` in `a[b] = c`), or `null` | 
| - /// if there is no receiver. | 
| + /// The receiver of the assignment target (e.g. `a` in `a[b] = c`). | 
| Expression receiver; | 
| - /// In an assignment to an index expression, the index expression, or `null` | 
| - /// if this is not an assignment to an index expression. | 
| + /// In an assignment to an index expression, the index expression. | 
| Expression index; | 
| KernelIndexAssign(this.receiver, this.index, Expression rhs) : super(rhs); | 
| @@ -1449,6 +1447,64 @@ abstract class KernelStatement extends Statement { | 
| void _inferStatement(KernelTypeInferrer inferrer); | 
| } | 
| +/// Concrete shadow object representing an assignment to a property. | 
| +class KernelPropertyAssign extends KernelComplexAssignment { | 
| + /// The receiver of the assignment target (e.g. `a` in `a.b = c`), or `null` | 
| + /// if there is no receiver (implicit `this`). | 
| + Expression receiver; | 
| + | 
| + /// If this assignment uses null-aware access (`?.`), the conditional | 
| + /// expression that guards the access; otherwise `null`. | 
| + Expression nullAwareGuard; | 
| + | 
| + /// Indicates whether this assignment uses `super`. | 
| + final bool isSuper; | 
| + | 
| + KernelPropertyAssign(this.receiver, Expression rhs, {this.isSuper: false}) | 
| + : super(rhs); | 
| + | 
| + @override | 
| + List<String> _getToStringParts() { | 
| + var parts = super._getToStringParts(); | 
| + if (receiver != null) parts.add('receiver=$receiver'); | 
| + if (nullAwareGuard != null) parts.add('nullAwareGuard=nullAwareGuard'); | 
| 
scheglov
2017/06/12 18:19:02
'nullAwareGuard=$nullAwareGuard'
 | 
| + return parts; | 
| + } | 
| + | 
| + @override | 
| + DartType _inferExpression( | 
| + KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { | 
| + typeNeeded = | 
| + inferrer.listener.propertyAssignEnter(desugared, typeContext) || | 
| + typeNeeded; | 
| + // TODO(paulberry): record the appropriate types on let variables and | 
| + // conditional expressions. | 
| + DartType receiverType; | 
| + if (receiver != null) { | 
| + receiverType = inferrer.inferExpression(receiver, null, true); | 
| + } else if (isSuper) { | 
| + receiverType = inferrer.classHierarchy.getTypeAsInstanceOf( | 
| + inferrer.thisType, inferrer.thisType.classNode.supertype.classNode); | 
| + } else { | 
| + receiverType = inferrer.thisType; | 
| + } | 
| + if (read != null) { | 
| + inferrer.findPropertyGetMember(receiverType, read, silent: true); | 
| + } | 
| + Member writeMember; | 
| + if (write != null) { | 
| + writeMember = inferrer.findPropertySetMember(receiverType, write); | 
| + } | 
| + // To replicate analyzer behavior, we base type inference on the write | 
| + // member. TODO(paulberry): would it be better to use the read member when | 
| + // doing compound assignment? | 
| + var writeContext = writeMember?.setterType; | 
| + var inferredType = _inferRhs(inferrer, writeContext); | 
| + inferrer.listener.propertyAssignExit(desugared, inferredType); | 
| + return inferredType; | 
| + } | 
| +} | 
| + | 
| /// Concrete shadow object representing an assignment to a static variable. | 
| class KernelStaticAssignment extends KernelComplexAssignment { | 
| KernelStaticAssignment(Expression rhs) : super(rhs); |