Fix resolution for IndexExpression in cascade.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I3f5f8dba51bfcda440c37438a0d2463b9829da43
Reviewed-on: https://dart-review.googlesource.com/63302
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/resolution_applier.dart b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
index 3a33ceb3..39bf30a 100644
--- a/pkg/analyzer/lib/src/fasta/resolution_applier.dart
+++ b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
@@ -350,9 +350,9 @@
 
   @override
   void visitIndexExpression(IndexExpression node) {
-    node.target.accept(this);
+    node.target?.accept(this);
 
-    DartType targetType = node.target.staticType;
+    DartType targetType = node.realTarget.staticType;
     var data = _get(node.leftBracket);
     MethodElement element = data.reference;
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 883c655..cc12389 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -40,9 +40,13 @@
   FindNode findNode;
   FindElement findElement;
 
-  DartType get doubleType => typeProvider.doubleType;
+  InterfaceType get doubleType => typeProvider.doubleType;
 
-  DartType get intType => typeProvider.intType;
+  InterfaceType get intType => typeProvider.intType;
+
+  ClassElement get mapElement => typeProvider.mapType.element;
+
+  InterfaceType get mapType => typeProvider.mapType;
 
   TypeProvider get typeProvider => result.unit.element.context.typeProvider;
 
@@ -56,11 +60,27 @@
     expect(actual, isNull);
   }
 
+  void assertMember(
+      Expression node, String expectedDefiningType, Element expectedBase) {
+    Member actual = getNodeElement(node);
+    expect(actual.definingType.toString(), expectedDefiningType);
+    expect(actual.baseElement, same(expectedBase));
+  }
+
   void assertType(Expression expression, String expected) {
     DartType actual = expression.staticType;
     expect(actual?.toString(), expected);
   }
 
+  /// Test that [argumentList] has exactly two type items `int` and `double`.
+  void assertTypeArguments(
+      TypeArgumentList argumentList, List<DartType> expectedTypes) {
+    expect(argumentList.arguments, hasLength(expectedTypes.length));
+    for (int i = 0; i < expectedTypes.length; i++) {
+      _assertTypeNameSimple(argumentList.arguments[i], expectedTypes[i]);
+    }
+  }
+
   void assertTypeDynamic(Expression expression) {
     DartType actual = expression.staticType;
     expect(actual, isDynamicType);
@@ -2222,6 +2242,30 @@
     expect(actualElement.parameters[0].type, intType);
   }
 
+  test_indexExpression_cascade_assign() async {
+    addTestFile(r'''
+main() {
+  <int, int>{}..[1] = 10;
+}
+''');
+    await resolveTestFile();
+
+    var cascade = findNode.cascade('<int, int>');
+    assertType(cascade, 'Map<int, int>');
+
+    MapLiteral map = cascade.target;
+    assertType(map, 'Map<int, int>');
+    assertTypeArguments(map.typeArguments, [intType, intType]);
+
+    AssignmentExpression assignment = cascade.cascadeSections[0];
+    assertElementNull(assignment);
+    assertType(assignment, 'int');
+
+    IndexExpression indexed = assignment.leftHandSide;
+    assertMember(indexed, 'Map<int, int>', mapElement.getMethod('[]='));
+    assertType(indexed, 'int');
+  }
+
   test_instanceCreation_factory() async {
     String content = r'''
 class C {
@@ -6454,8 +6498,7 @@
       expect(typeIdentifier.staticType, isDynamicType);
     }
 
-    _assertInvocationTypeArguments(
-        typeName.typeArguments, [intType, doubleType]);
+    assertTypeArguments(typeName.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(creation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -6504,8 +6547,7 @@
       expect(typePrefix.staticType, isDynamicType);
     }
 
-    _assertInvocationTypeArguments(
-        typeName.typeArguments, [intType, doubleType]);
+    assertTypeArguments(typeName.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(creation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -6556,8 +6598,7 @@
       expect(typePrefix.staticType, isDynamicType);
     }
 
-    _assertInvocationTypeArguments(
-        typeName.typeArguments, [intType, doubleType]);
+    assertTypeArguments(typeName.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(creation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -6610,8 +6651,7 @@
       expect(constructorName.name.staticType, isDynamicType);
     }
 
-    _assertInvocationTypeArguments(
-        typeName.typeArguments, [intType, doubleType]);
+    assertTypeArguments(typeName.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(creation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -6665,8 +6705,7 @@
     expect(constructorName.name.staticElement, isNull);
     expect(constructorName.name.staticType, isNull);
 
-    _assertInvocationTypeArguments(
-        typeName.typeArguments, [intType, doubleType]);
+    assertTypeArguments(typeName.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(creation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -6717,8 +6756,7 @@
     expect(constructorName.name.staticElement, isNull);
     expect(constructorName.name.staticType, isNull);
 
-    _assertInvocationTypeArguments(
-        typeName.typeArguments, [intType, doubleType]);
+    assertTypeArguments(typeName.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(creation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -6745,8 +6783,7 @@
     expect(name.staticElement, isNull);
     expect(name.staticType, isDynamicType);
 
-    _assertInvocationTypeArguments(
-        invocation.typeArguments, [intType, doubleType]);
+    assertTypeArguments(invocation.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(invocation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -6789,8 +6826,7 @@
       expect(name.staticType, isDynamicType);
     }
 
-    _assertInvocationTypeArguments(
-        invocation.typeArguments, [intType, doubleType]);
+    assertTypeArguments(invocation.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(invocation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -6820,8 +6856,7 @@
     expect(name.staticElement, isNull);
     expect(name.staticType, isDynamicType);
 
-    _assertInvocationTypeArguments(
-        invocation.typeArguments, [intType, doubleType]);
+    assertTypeArguments(invocation.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(invocation.argumentList,
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
@@ -7070,15 +7105,6 @@
     }
   }
 
-  /// Test that [argumentList] has exactly two type items `int` and `double`.
-  void _assertInvocationTypeArguments(
-      TypeArgumentList argumentList, List<DartType> expectedTypes) {
-    expect(argumentList.arguments, hasLength(expectedTypes.length));
-    for (int i = 0; i < expectedTypes.length; i++) {
-      _assertTypeNameSimple(argumentList.arguments[i], expectedTypes[i]);
-    }
-  }
-
   void _assertParameterElement(ParameterElement element,
       {String name, int offset, ParameterKind kind, DartType type}) {
     expect(element, isNotNull);
@@ -7208,6 +7234,10 @@
     return _node(search).getAncestor((n) => n is AssignmentExpression);
   }
 
+  CascadeExpression cascade(String search) {
+    return _node(search).getAncestor((n) => n is CascadeExpression);
+  }
+
   SimpleIdentifier simple(String search) {
     return _node(search);
   }