Version 2.12.0-216.0.dev

Merge commit '8b0fba90a68943649471e3fc3fbec7f44b90df3e' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart b/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
index efe93db..946989a 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
@@ -13,6 +13,7 @@
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart' show LibraryElement;
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:meta/meta.dart';
@@ -24,7 +25,6 @@
 
   @override
   Iterable<CorrectionProducer> get producers sync* {
-    var name = _name;
     var importedUris = <Uri>[];
     var library = resolvedResult.libraryElement;
     for (var importElement in library.imports) {
@@ -36,8 +36,16 @@
         importedUris.add(Uri.parse(uri));
       }
     }
+    var components = _computeComponents();
+    if (components == null) {
+      // If we couldn't compute the components it's because the node doesn't
+      // represent an element that can be transformed.
+      return;
+    }
     var matcher = ElementMatcher(
-        importedUris: importedUris, name: name, kinds: _kindsForNode(node));
+        importedUris: importedUris,
+        components: components,
+        kinds: _kindsForNode(node));
     for (var set in _availableTransformSetsForLibrary(library)) {
       for (var transform
           in set.transformsFor(matcher, applyingBulkFixes: applyingBulkFixes)) {
@@ -46,48 +54,6 @@
     }
   }
 
-  /// Return the name of the element that was changed.
-  String get _name {
-    String nameFromParent(AstNode node) {
-      var parent = node.parent;
-      if (parent is MethodInvocation) {
-        return parent.methodName.name;
-      } else if (parent is InstanceCreationExpression) {
-        var constructorName = parent.constructorName;
-        if (constructorName.name != null) {
-          return constructorName.name.name;
-        }
-        return constructorName.type.name.name;
-      } else if (parent is ExtensionOverride) {
-        return parent.extensionName.name;
-      }
-      return null;
-    }
-
-    var node = this.node;
-    if (node is SimpleIdentifier) {
-      var parent = node.parent;
-      if (parent is Label && parent.parent is NamedExpression) {
-        // The parent of the named expression is an argument list. Because we
-        // don't represent parameters as elements, the element we need to match
-        // against is the invocation containing those arguments.
-        return nameFromParent(parent.parent.parent);
-      }
-      return node.name;
-    } else if (node is ConstructorName) {
-      return node.name.name;
-    } else if (node is NamedType) {
-      return node.name.name;
-    } else if (node is TypeArgumentList) {
-      return nameFromParent(node);
-    } else if (node is ArgumentList) {
-      return nameFromParent(node);
-    } else if (node?.parent is ArgumentList) {
-      return nameFromParent(node.parent);
-    }
-    return null;
-  }
-
   /// Return the transform sets that are available for fixing issues in the
   /// given [library].
   List<TransformSet> _availableTransformSetsForLibrary(LibraryElement library) {
@@ -97,6 +63,89 @@
     return TransformSetManager.instance.forLibrary(library);
   }
 
+  /// Return the components for the element associated with the given [node] by
+  /// looking at the parent of the [node].
+  List<String> _componentsFromParent(AstNode node) {
+    var parent = node.parent;
+    if (parent is ArgumentList) {
+      parent = parent.parent;
+    }
+    if (parent is Annotation) {
+      return [parent.constructorName?.name ?? '', parent.name.name];
+    } else if (parent is ExtensionOverride) {
+      return [parent.extensionName.name];
+    } else if (parent is InstanceCreationExpression) {
+      var constructorName = parent.constructorName;
+      return [constructorName.name?.name ?? '', constructorName.type.name.name];
+    } else if (parent is MethodInvocation) {
+      var target = _nameOfTarget(parent.realTarget);
+      if (target != null) {
+        return [parent.methodName.name, target];
+      }
+      var ancestor = parent.parent;
+      while (ancestor != null) {
+        if (ancestor is ClassOrMixinDeclaration) {
+          return [parent.methodName.name, ancestor.name.name];
+        } else if (ancestor is ExtensionDeclaration) {
+          return [parent.methodName.name, ancestor.name.name];
+        }
+        ancestor = ancestor.parent;
+      }
+      return [parent.methodName.name];
+    } else if (parent is RedirectingConstructorInvocation) {
+      var ancestor = parent.parent;
+      if (ancestor is ConstructorDeclaration) {
+        return [parent.constructorName?.name ?? '', ancestor.returnType.name];
+      }
+    } else if (parent is SuperConstructorInvocation) {
+      var ancestor = parent.parent;
+      if (ancestor is ConstructorDeclaration) {
+        return [parent.constructorName?.name ?? '', ancestor.returnType.name];
+      }
+    }
+    return null;
+  }
+
+  /// Return the components of the path of the element associated with the
+  /// diagnostic. The components are ordered from the most local to the most
+  /// global. For example, for a constructor this would be the name of the
+  /// constructor followed by the name of the class in which the constructor is
+  /// declared (with an empty string for the unnamed constructor).
+  List<String> _computeComponents() {
+    var node = this.node;
+    if (node is SimpleIdentifier) {
+      var parent = node.parent;
+      if (parent is Label && parent.parent is NamedExpression) {
+        // The parent of the named expression is an argument list. Because we
+        // don't represent parameters as elements, the element we need to match
+        // against is the invocation containing those arguments.
+        return _componentsFromParent(parent.parent.parent);
+      } else if (parent is TypeName && parent.parent is ConstructorName) {
+        return ['', node.name];
+      } else if (parent is MethodInvocation) {
+        return _componentsFromParent(node);
+      }
+      return [node.name];
+    } else if (node is PrefixedIdentifier) {
+      var parent = node.parent;
+      if (parent is TypeName && parent.parent is ConstructorName) {
+        return ['', node.identifier.name];
+      }
+      return [node.identifier.name];
+    } else if (node is ConstructorName) {
+      return [node.name.name];
+    } else if (node is NamedType) {
+      return [node.name.name];
+    } else if (node is TypeArgumentList) {
+      return _componentsFromParent(node);
+    } else if (node is ArgumentList) {
+      return _componentsFromParent(node);
+    } else if (node?.parent is ArgumentList) {
+      return _componentsFromParent(node.parent);
+    }
+    return null;
+  }
+
   List<ElementKind> _kindsForNode(AstNode node, {AstNode child}) {
     if (node is ConstructorName) {
       return const [ElementKind.constructorKind];
@@ -158,6 +207,30 @@
     return null;
   }
 
+  /// Return the name of the class associated with the given [target].
+  String _nameOfTarget(Expression target) {
+    if (target is SimpleIdentifier) {
+      var type = target.staticType;
+      if (type != null) {
+        if (type is InterfaceType) {
+          return type.element.name;
+        } else if (type.isDynamic) {
+          // The name is likely to be undefined.
+          return target.name;
+        }
+        return null;
+      }
+      return target.name;
+    } else if (target != null) {
+      var type = target.staticType;
+      if (type is InterfaceType) {
+        return type.element.name;
+      }
+      return null;
+    }
+    return null;
+  }
+
   /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
   static DataDriven newInstance() => DataDriven();
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
index 2520805..ae3f501 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
@@ -16,7 +16,8 @@
   /// The kind of element that was changed.
   final ElementKind kind;
 
-  /// The components that uniquely identify the element within its library.
+  /// The components that uniquely identify the element within its library. The
+  /// components are ordered from the most local to the most global.
   final List<String> components;
 
   /// Initialize a newly created element descriptor to describe an element
@@ -47,27 +48,27 @@
         if (node is Annotation) {
           var className = _nameFromIdentifier(node.name);
           var constructorName = node.constructorName ?? '';
-          if (components[0] == className && components[1] == constructorName) {
+          if (components[0] == constructorName && components[1] == className) {
             return true;
           }
         } else if (node is InstanceCreationExpression) {
           var name = node.constructorName;
           var className = _nameFromIdentifier(name.type.name);
           var constructorName = name.name?.name ?? '';
-          if (components[0] == className && components[1] == constructorName) {
+          if (components[0] == constructorName && components[1] == className) {
             return true;
           }
         } else if (node is MethodInvocation) {
           var target = node.target;
           if (target == null) {
-            if (components[0] == node.methodName.name && components[1] == '') {
+            if (components[0] == '' && components[1] == node.methodName.name) {
               return true;
             }
           } else if (target is Identifier) {
             var className = _nameFromIdentifier(target);
             var constructorName = node.methodName.name;
-            if (components[0] == className &&
-                components[1] == constructorName) {
+            if (components[0] == constructorName &&
+                components[1] == className) {
               return true;
             }
           }
@@ -95,7 +96,7 @@
         return false;
       case ElementKind.methodKind:
         if (node is MethodInvocation) {
-          if (components[1] == node.methodName.name) {
+          if (components[0] == node.methodName.name) {
             var target = node.realTarget;
             if (target == null) {
               // TODO(brianwilkerson) If `node.target == null` then the invocation
@@ -115,12 +116,12 @@
                 // that the method might have been in the element's class.
                 return true;
               }
-              if (components[0] == type.element.name) {
+              if (components[1] == type.element.name) {
                 return true;
               }
               if (type is InterfaceType) {
                 for (var supertype in type.allSupertypes) {
-                  if (components[0] == supertype.element.name) {
+                  if (components[1] == supertype.element.name) {
                     return true;
                   }
                 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
index aac5dff..a938d2c 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
@@ -13,38 +13,74 @@
   /// reference.
   final List<Uri> importedUris;
 
-  /// The name of the element being referenced.
-  final String name;
+  /// The components of the element being referenced. The components are ordered
+  /// from the most local to the most global.
+  final List<String> components;
 
   /// A list of the kinds of elements that are appropriate for some given
   /// location in the code An empty list represents all kinds rather than no
   /// kinds.
-  List<ElementKind> validKinds;
+  final List<ElementKind> validKinds;
 
   /// Initialize a newly created matcher representing a reference to an element
   /// with the given [name] in a library that imports the [importedUris].
   ElementMatcher(
       {@required this.importedUris,
-      @required this.name,
+      @required this.components,
       List<ElementKind> kinds})
-      : validKinds = kinds ?? const [];
+      : assert(components != null && components.isNotEmpty),
+        validKinds = kinds ?? const [];
 
   /// Return `true` if this matcher matches the given [element].
   bool matches(ElementDescriptor element) {
-    var components = element.components;
-    var lastComponent = components.last;
-    if (lastComponent.isEmpty) {
-      if (components[components.length - 2] != name) {
+    //
+    // Check that the components in the element's name match the node.
+    //
+    // This algorithm is probably too general given that there will currently
+    // always be either one or two components.
+    //
+    var elementComponents = element.components;
+    var elementComponentCount = elementComponents.length;
+    var nodeComponentCount = components.length;
+    if (nodeComponentCount == elementComponentCount) {
+      // The component counts are the same, so we can just compare the two
+      // lists.
+      for (var i = 0; i < nodeComponentCount; i++) {
+        if (elementComponents[i] != components[i]) {
+          return false;
+        }
+      }
+    } else if (nodeComponentCount < elementComponentCount) {
+      // The node has fewer components, which can happen, for example, when we
+      // can't figure out the class that used to define a field. We treat the
+      // missing components as wildcards and match the rest.
+      for (var i = 0; i < nodeComponentCount; i++) {
+        if (elementComponents[i] != components[i]) {
+          return false;
+        }
+      }
+    } else {
+      // The node has more components than the element, which can happen when a
+      // constructor is implicitly renamed because the class was renamed.
+      // TODO(brianwilkerson) Figure out whether we want to support this or
+      //  whether we want to require fix data authors to explicitly include the
+      //  change to the constructor. On the one hand it's more work for the
+      //  author, on the other hand it give us more data so we're less likely to
+      //  make apply a fix in invalid circumstances.
+      if (elementComponents[0] != components[1]) {
         return false;
       }
-    } else if (lastComponent != name) {
-      return false;
     }
-
+    //
+    // Check whether the kind of element matches the possible kinds that the
+    // node might have.
+    //
     if (validKinds.isNotEmpty && !validKinds.contains(element.kind)) {
       return false;
     }
-
+    //
+    // Check whether the element is in an imported library.
+    //
     var libraryUris = element.libraryUris;
     for (var importedUri in importedUris) {
       if (libraryUris.contains(importedUri)) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index 351608c..b0c122c 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -657,7 +657,7 @@
             return null;
           }
         } else {
-          components.insert(0, containerName);
+          components.add(containerName);
         }
       }
       if (uris == null) {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart
index 88e911a..f39851f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart
@@ -939,6 +939,44 @@
 }
 ''');
   }
+
+  Future<void> test_rename_removed_onlyFixOne() async {
+    setPackageContent('''
+class A {
+  void n(int x) {}
+}
+class B {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    method: 'o'
+    inClass: 'A'
+  changes:
+    - kind: 'rename'
+      newName: 'n'
+''');
+    await resolveTestCode('''
+import '$importUri';
+
+void f(A a, B b) {
+  a.o(0);
+  b.o(1);
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f(A a, B b) {
+  a.n(0);
+  b.o(1);
+}
+''');
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
index 5ed784f..dcda4bc 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
@@ -483,7 +483,7 @@
           element: ElementDescriptor(
               libraryUris: [Uri.parse(importUri)],
               kind: ElementKindUtilities.fromName(_kind),
-              components: components ?? ['C', 'm']),
+              components: components ?? ['m', 'C']),
           bulkApply: false,
           changesSelector: UnconditionalChangesSelector([
             AddTypeParameter(
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
index cca4aef..f6359cd 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
@@ -1045,7 +1045,6 @@
     await assertNoFix();
   }
 
-  @failingTest
   Future<void> test_material_Scaffold_of_wrongType() async {
     setPackageContent('''
 class Theme {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
index 30f1bce..d67d30e 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
@@ -34,7 +34,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', false, false, null)],
+        ['m', 'C'], [AddParameter(0, 'a', false, false, null)],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -61,7 +61,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', false, true, codeTemplate('0'))],
+        ['m', 'C'], [AddParameter(0, 'a', false, true, codeTemplate('0'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -88,7 +88,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', true, false, codeTemplate('0'))],
+        ['m', 'C'], [AddParameter(0, 'a', true, false, codeTemplate('0'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -115,7 +115,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
+        ['m', 'C'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -142,7 +142,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', false, false, null)],
+        ['m', 'C'], [AddParameter(1, 'b', false, false, null)],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -169,7 +169,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', false, true, codeTemplate('1'))],
+        ['m', 'C'], [AddParameter(1, 'b', false, true, codeTemplate('1'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -196,7 +196,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', true, false, codeTemplate('1'))],
+        ['m', 'C'], [AddParameter(1, 'b', true, false, codeTemplate('1'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -223,7 +223,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', true, true, codeTemplate('1'))],
+        ['m', 'C'], [AddParameter(1, 'b', true, true, codeTemplate('1'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -250,8 +250,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm'
+      'm',
+      'C'
     ], [
       AddParameter(1, 'b', true, true, codeTemplate('1')),
       AddParameter(2, 'c', true, true, codeTemplate('2')),
@@ -280,7 +280,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
+        ['m', 'C'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -305,7 +305,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))]));
+        ['m', 'C'], [AddParameter(0, 'a', true, true, codeTemplate('0'))]));
     await resolveTestCode('''
 import '$importUri';
 
@@ -331,8 +331,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm'
+      'm',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(0)),
       AddParameter(2, 'c', true, true, codeTemplate('2'))
@@ -362,8 +362,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm'
+      'm',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(1)),
       AddParameter(0, 'a', true, true, codeTemplate('0'))
@@ -393,8 +393,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm1'
+      'm1',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(0)),
       RemoveParameter(PositionalParameterReference(1)),
@@ -425,8 +425,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm1'
+      'm1',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(1)),
       RemoveParameter(PositionalParameterReference(2)),
@@ -457,8 +457,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm1'
+      'm1',
+      'C'
     ], [
       AddParameter(0, 'a', true, true, codeTemplate('0')),
       RemoveParameter(PositionalParameterReference(1)),
@@ -490,8 +490,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm1'
+      'm1',
+      'C'
     ], [
       AddParameter(0, 'b', true, false, codeTemplate('0')),
       RemoveParameter(NamedParameterReference('a')),
@@ -521,7 +521,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(NamedParameterReference('a'))],
+        ['m', 'C'], [RemoveParameter(NamedParameterReference('a'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -548,7 +548,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -575,7 +575,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -602,7 +602,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(NamedParameterReference('b'))],
+        ['m', 'C'], [RemoveParameter(NamedParameterReference('b'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -629,7 +629,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(1))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(1))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -656,7 +656,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(1))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(1))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -682,7 +682,7 @@
 }
 ''');
     setPackageData(
-        _modify(['C', 'm'], [RemoveParameter(NamedParameterReference('b'))]));
+        _modify(['m', 'C'], [RemoveParameter(NamedParameterReference('b'))]));
     await resolveTestCode('''
 import '$importUri';
 
@@ -708,8 +708,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm'
+      'm',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(0)),
       RemoveParameter(PositionalParameterReference(2)),
@@ -740,7 +740,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(NamedParameterReference('a'))],
+        ['m', 'C'], [RemoveParameter(NamedParameterReference('a'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -767,7 +767,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(NamedParameterReference('a'))],
+        ['m', 'C'], [RemoveParameter(NamedParameterReference('a'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -794,7 +794,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -822,7 +822,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -849,7 +849,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
index f892cd6..3a189c0 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
@@ -30,7 +30,7 @@
   C.named({int b, @deprecated int a});
 }
 ''');
-    setPackageData(_rename(['C', 'named'], 'a', 'b'));
+    setPackageData(_rename(['named', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -53,7 +53,7 @@
   C.named({int b});
 }
 ''');
-    setPackageData(_rename(['C', 'named'], 'a', 'b'));
+    setPackageData(_rename(['named', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -76,7 +76,7 @@
   C({int b, @deprecated int a});
 }
 ''');
-    setPackageData(_rename(['C', ''], 'a', 'b'));
+    setPackageData(_rename(['', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -99,7 +99,7 @@
   C({int b});
 }
 ''');
-    setPackageData(_rename(['C', ''], 'a', 'b'));
+    setPackageData(_rename(['', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -128,7 +128,7 @@
   int m({int b, @deprecated int a}) => 0;
 }
 ''');
-    setPackageData(_rename(['D', 'm'], 'a', 'nbew'));
+    setPackageData(_rename(['m', 'D'], 'a', 'nbew'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -145,7 +145,7 @@
   int m({int b, @deprecated int a}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -170,7 +170,7 @@
   int m({int b}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -195,7 +195,7 @@
   int m({int b, @deprecated int a}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -218,7 +218,7 @@
   int m({int b}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -241,7 +241,7 @@
   static int m({int b, @deprecated int a}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -264,7 +264,7 @@
   static int m({int b}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
index 2edc72d..6e0ce4a 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
@@ -366,7 +366,7 @@
   C.b();
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -389,7 +389,7 @@
   C.b();
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -414,7 +414,7 @@
   C();
 }
 ''');
-    setPackageData(_rename(['C', 'old'], ''));
+    setPackageData(_rename(['old', 'C'], ''));
     await resolveTestCode('''
 import '$importUri';
 
@@ -437,7 +437,7 @@
   C();
 }
 ''');
-    setPackageData(_rename(['C', 'old'], ''));
+    setPackageData(_rename(['old', 'C'], ''));
     await resolveTestCode('''
 import '$importUri';
 
@@ -462,7 +462,7 @@
   C.a();
 }
 ''');
-    setPackageData(_rename(['C', ''], 'a'));
+    setPackageData(_rename(['', 'C'], 'a'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -485,7 +485,7 @@
   C.a();
 }
 ''');
-    setPackageData(_rename(['C', ''], 'a'));
+    setPackageData(_rename(['', 'C'], 'a'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -606,7 +606,7 @@
   int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -629,7 +629,7 @@
   int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -654,7 +654,7 @@
   static int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -677,7 +677,7 @@
   static int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -702,7 +702,7 @@
   static int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -725,7 +725,7 @@
   static int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -760,7 +760,7 @@
   void a(int b) {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -782,7 +782,7 @@
   D({@deprecated int a; int c});
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -799,7 +799,7 @@
   int get b => 1;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -822,7 +822,7 @@
   int get b => 1;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -850,7 +850,7 @@
   C c() => C();
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -876,7 +876,7 @@
   C c() => C();
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -952,7 +952,7 @@
   int b() => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -977,7 +977,7 @@
   int b() => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -1004,7 +1004,7 @@
   int b() {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -1027,7 +1027,7 @@
   int b() {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -1052,7 +1052,7 @@
   static int b() {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -1075,7 +1075,7 @@
   static int b() {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
index 27d339c..d2789c8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
@@ -728,7 +728,7 @@
       (transform.changesSelector as UnconditionalChangesSelector).changes;
 
   ElementMatcher _matcher(String name) =>
-      ElementMatcher(importedUris: uris, name: name);
+      ElementMatcher(importedUris: uris, components: [name]);
 
   List<Transform> _transforms(String name) =>
       result.transformsFor(_matcher(name), applyingBulkFixes: false);
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index d5a70ba..fcc224f 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -1492,7 +1492,6 @@
     sink.writeEnum(JsNodeKind.literalExpression);
     sink.begin(JsNodeTags.literalExpression);
     sink.writeString(node.template);
-    visitList(node.inputs);
     sink.end(JsNodeTags.literalExpression);
     _writeInfo(node);
   }
@@ -1961,9 +1960,7 @@
         break;
       case JsNodeKind.literalExpression:
         source.begin(JsNodeTags.literalExpression);
-        String template = source.readString();
-        List<js.Expression> inputs = readList();
-        node = new js.LiteralExpression.withData(template, inputs);
+        node = new js.LiteralExpression(source.readString());
         source.end(JsNodeTags.literalExpression);
         break;
       case JsNodeKind.dartYield:
diff --git a/pkg/compiler/lib/src/js/size_estimator.dart b/pkg/compiler/lib/src/js/size_estimator.dart
index 347c146..257fa70 100644
--- a/pkg/compiler/lib/src/js/size_estimator.dart
+++ b/pkg/compiler/lib/src/js/size_estimator.dart
@@ -982,21 +982,7 @@
 
   @override
   void visitLiteralExpression(LiteralExpression node) {
-    String template = node.template;
-    List<Expression> inputs = node.inputs;
-
-    List<String> parts = template.split('#');
-    int inputsLength = inputs == null ? 0 : inputs.length;
-    if (parts.length != inputsLength + 1) {
-      throw UnsupportedError('Wrong number of arguments for JS: $template');
-    }
-    // Code that uses JS must take care of operator precedences, and
-    // put parenthesis if needed.
-    out(parts[0]); // '${parts[0]}'
-    for (int i = 0; i < inputsLength; i++) {
-      visit(inputs[i]);
-      out(parts[i + 1]); // '${parts[i + 1]}'
-    }
+    out(node.template); // '${node.template}'
   }
 
   @override
diff --git a/pkg/dds/test/smoke_test.dart b/pkg/dds/test/smoke_test.dart
index d317893..983a2da 100644
--- a/pkg/dds/test/smoke_test.dart
+++ b/pkg/dds/test/smoke_test.dart
@@ -82,35 +82,6 @@
     createSmokeTest(true, false);
     createSmokeTest(false, false);
     createSmokeTest(true, true);
-
-    test('startup fails when VM service has existing clients', () async {
-      Uri httpToWebSocketUri(Uri httpUri) {
-        final segments = (httpUri.pathSegments.isNotEmpty)
-            ? (httpUri.pathSegments.toList()..removeLast())
-            : <String>[];
-        segments.add('ws');
-        return httpUri.replace(
-          scheme: 'ws',
-          pathSegments: segments,
-        );
-      }
-
-      final _ = await vmServiceConnectUri(
-        httpToWebSocketUri(remoteVmServiceUri).toString(),
-      );
-      try {
-        dds = await DartDevelopmentService.startDartDevelopmentService(
-          remoteVmServiceUri,
-        );
-        fail(
-            'DDS startup should fail if there are existing VM service clients.');
-      } on DartDevelopmentServiceException catch (e) {
-        expect(e.message,
-            'Existing VM service clients prevent DDS from taking control.');
-        expect(e.errorCode,
-            DartDevelopmentServiceException.existingDdsInstanceError);
-      }
-    });
   });
 
   test('Invalid args test', () async {
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index 137bfd4..bdfb6c9 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -906,28 +906,19 @@
 
 class LiteralExpression extends Expression {
   final String template;
-  final List<Expression> inputs;
-
-  LiteralExpression(this.template) : inputs = const [];
-  LiteralExpression.withData(this.template, this.inputs);
+  LiteralExpression(this.template);
 
   @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralExpression(this);
 
   @override
-  void visitChildren(NodeVisitor visitor) {
-    if (inputs != null) {
-      for (Expression expr in inputs) {
-        expr.accept(visitor);
-      }
-    }
-  }
+  void visitChildren(NodeVisitor visitor) {}
 
   @override
-  LiteralExpression _clone() => LiteralExpression.withData(template, inputs);
+  LiteralExpression _clone() => LiteralExpression(template);
 
-  // Code that uses JS must take care of operator precedences, and
-  // put parenthesis if needed.
+  // Code that uses LiteralExpression must take care of operator precedences,
+  // and put parenthesis if needed.
   @override
   int get precedenceLevel => PRIMARY;
 }
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index d62126b..9fabc56 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -1355,21 +1355,7 @@
 
   @override
   visitLiteralExpression(LiteralExpression node) {
-    String template = node.template;
-    List<Expression> inputs = node.inputs;
-
-    List<String> parts = template.split('#');
-    int inputsLength = inputs == null ? 0 : inputs.length;
-    if (parts.length != inputsLength + 1) {
-      context.error('Wrong number of arguments for JS: $template');
-    }
-    // Code that uses JS must take care of operator precedences, and
-    // put parenthesis if needed.
-    out(parts[0]);
-    for (int i = 0; i < inputsLength; i++) {
-      visit(inputs[i]);
-      out(parts[i + 1]);
-    }
+    out(node.template);
   }
 
   @override
diff --git a/pkg/dev_compiler/tool/check_nnbd_sdk.dart b/pkg/dev_compiler/tool/check_nnbd_sdk.dart
index 80ba657..c329e26 100644
--- a/pkg/dev_compiler/tool/check_nnbd_sdk.dart
+++ b/pkg/dev_compiler/tool/check_nnbd_sdk.dart
@@ -134,6 +134,12 @@
 
   // Trim temporary directory paths and sort errors.
   errors = errors.replaceAll(sdkDir, '');
+  if (!(args['keep-lines'] as bool)) {
+    // Golden files change frequenty if line numbers are recorded.
+    // We remove them by default but provide an option to show them if
+    // they can be helpful.
+    errors = errors.replaceAll(RegExp(r'\|[0-9]*\|[0-9]*\|[0-9]*\|'), '|');
+  }
   var errorList = errors.isEmpty ? <String>[] : errors.trim().split('\n');
   var count = errorList.length;
   print('$count analyzer errors.');
@@ -209,4 +215,6 @@
       allowed: ['dartdevc', 'dart2js', 'dart2js_server', 'vm', 'flutter'],
       defaultsTo: 'dartdevc')
   ..addFlag('update-golden', help: 'Update the golden file.', defaultsTo: false)
+  ..addFlag('keep-lines',
+      help: 'Show line numbers on errors.', defaultsTo: false)
   ..addFlag('help', abbr: 'h', help: 'Display this message.');
diff --git a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
index 91c4e1e..960c5e4 100644
--- a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
@@ -1,10 +1,10 @@
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1718|7|5|Superinterfaces don't have a valid override for '&': JSNumber.& (num Function(num)), int.& (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1718|7|5|Superinterfaces don't have a valid override for '<<': JSNumber.<< (num Function(num)), int.<< (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1718|7|5|Superinterfaces don't have a valid override for '>>': JSNumber.>> (num Function(num)), int.>> (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1718|7|5|Superinterfaces don't have a valid override for '\|': JSNumber.\| (num Function(num)), int.\| (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1718|7|5|Superinterfaces don't have a valid override for '^': JSNumber.^ (num Function(num)), int.^ (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1735|28|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1737|27|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1740|17|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1745|18|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1745|44|1|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '&': JSNumber.& (num Function(num)), int.& (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '<<': JSNumber.<< (num Function(num)), int.<< (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '>>': JSNumber.>> (num Function(num)), int.>> (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '\|': JSNumber.\| (num Function(num)), int.\| (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '^': JSNumber.^ (num Function(num)), int.^ (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
diff --git a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
index dd6530e..3adfa76 100644
--- a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
@@ -1,8 +1,8 @@
-ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|3679|5|94|Const constructors can't throw exceptions.
-ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|7888|5|97|Const constructors can't throw exceptions.
-ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|893|5|95|Const constructors can't throw exceptions.
-ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|926|5|94|Const constructors can't throw exceptions.
-ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|3677|3|5|Only redirecting factory constructors can be declared to be 'const'.
-ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|7886|3|5|Only redirecting factory constructors can be declared to be 'const'.
-ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|891|3|5|Only redirecting factory constructors can be declared to be 'const'.
-ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|924|3|5|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|Const constructors can't throw exceptions.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|Only redirecting factory constructors can be declared to be 'const'.
diff --git a/pkg/js_ast/lib/src/equivalence_visitor.dart b/pkg/js_ast/lib/src/equivalence_visitor.dart
index 42801c0..d06f50f 100644
--- a/pkg/js_ast/lib/src/equivalence_visitor.dart
+++ b/pkg/js_ast/lib/src/equivalence_visitor.dart
@@ -341,8 +341,7 @@
   bool visitLiteralExpression(LiteralExpression node, Node arg) {
     if (arg is! LiteralExpression) return failAt(node, arg);
     LiteralExpression other = arg;
-    return testValues(node, node.template, other, other.template) &&
-        testNodeLists(node.inputs, other.inputs);
+    return testValues(node, node.template, other, other.template);
   }
 
   @override
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index 7a9298a..b9cc51f 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -1023,34 +1023,21 @@
 
 class LiteralExpression extends Expression {
   final String template;
-  final List<Expression> inputs;
-
-  LiteralExpression(this.template) : inputs = const [];
-
-  LiteralExpression.withData(this.template, this.inputs);
+  LiteralExpression(this.template);
 
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralExpression(this);
 
   R accept1<R, A>(NodeVisitor1<R, A> visitor, A arg) =>
       visitor.visitLiteralExpression(this, arg);
 
-  void visitChildren<T>(NodeVisitor<T> visitor) {
-    if (inputs != null) {
-      for (Expression expr in inputs) expr.accept(visitor);
-    }
-  }
+  void visitChildren<T>(NodeVisitor<T> visitor) {}
 
-  void visitChildren1<R, A>(NodeVisitor1<R, A> visitor, A arg) {
-    if (inputs != null) {
-      for (Expression expr in inputs) expr.accept1(visitor, arg);
-    }
-  }
+  void visitChildren1<R, A>(NodeVisitor1<R, A> visitor, A arg) {}
 
-  LiteralExpression _clone() =>
-      new LiteralExpression.withData(template, inputs);
+  LiteralExpression _clone() => LiteralExpression(template);
 
-  // Code that uses JS must take care of operator precedences, and
-  // put parenthesis if needed.
+  // Code that uses LiteralExpression must take care of operator precedences,
+  // and put parenthesis if needed.
   int get precedenceLevel => PRIMARY;
 }
 
diff --git a/pkg/js_ast/lib/src/printer.dart b/pkg/js_ast/lib/src/printer.dart
index 400dc42..0d04a21 100644
--- a/pkg/js_ast/lib/src/printer.dart
+++ b/pkg/js_ast/lib/src/printer.dart
@@ -1255,21 +1255,7 @@
 
   @override
   void visitLiteralExpression(LiteralExpression node) {
-    String template = node.template;
-    List<Expression> inputs = node.inputs;
-
-    List<String> parts = template.split('#');
-    int inputsLength = inputs == null ? 0 : inputs.length;
-    if (parts.length != inputsLength + 1) {
-      context.error('Wrong number of arguments for JS: $template');
-    }
-    // Code that uses JS must take care of operator precedences, and
-    // put parenthesis if needed.
-    out(parts[0]);
-    for (int i = 0; i < inputsLength; i++) {
-      visit(inputs[i]);
-      out(parts[i + 1]);
-    }
+    out(node.template);
   }
 
   @override
diff --git a/runtime/observatory/tests/service/dds_disconnects_existing_clients_test.dart b/runtime/observatory/tests/service/dds_disconnects_existing_clients_test.dart
new file mode 100644
index 0000000..584b1cc
--- /dev/null
+++ b/runtime/observatory/tests/service/dds_disconnects_existing_clients_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:dds/dds.dart';
+import 'package:observatory/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+final tests = <VMTest>[
+  (VM vm) async {
+    late DartDevelopmentService dds;
+    final waitForDDS = Completer<void>();
+    final serviceMessageCompleter = Completer<void>();
+
+    // The original VM service client is connected.
+    expect(vm.isConnected, true);
+
+    // A service event is sent to all existing clients when DDS connects before
+    // their connection is closed.
+    await vm.listenEventStream('Service', (ServiceEvent event) async {
+      // Wait for dds to be set before checking the server's URI.
+      await waitForDDS.future;
+      final message =
+          'A Dart Developer Service instance has connected and this direct '
+          'connection to the VM service will now be closed. Please reconnect to '
+          'the Dart Development Service at ${dds.uri}.';
+      expect(event.kind, ServiceEvent.kDartDevelopmentServiceConnected);
+      expect(event.message, message);
+      expect(event.uri, dds.uri);
+      serviceMessageCompleter.complete();
+    });
+
+    // Start DDS, which should result in the original VM service client being
+    // disconnected from the VM service.
+    final remote = Uri.parse(vm.target.networkAddress);
+    dds = await DartDevelopmentService.startDartDevelopmentService(
+      remote.replace(
+        scheme: 'http',
+        pathSegments: remote.pathSegments.sublist(
+          0,
+          remote.pathSegments.length - 1,
+        ),
+      ),
+    );
+    waitForDDS.complete();
+    expect(dds.isRunning, true);
+    await serviceMessageCompleter.future;
+    await vm.onDisconnect;
+    await dds.shutdown();
+  }
+];
+
+main(args) async => runVMTests(
+      args,
+      tests,
+      enableDds: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/dds_disconnects_existing_clients_test.dart b/runtime/observatory_2/tests/service_2/dds_disconnects_existing_clients_test.dart
new file mode 100644
index 0000000..a8b529e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dds_disconnects_existing_clients_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:dds/dds.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+final tests = <VMTest>[
+  (VM vm) async {
+    DartDevelopmentService dds;
+    final waitForDDS = Completer<void>();
+    final serviceMessageCompleter = Completer<void>();
+
+    // The original VM service client is connected.
+    expect(vm.isConnected, true);
+
+    // A service event is sent to all existing clients when DDS connects before
+    // their connection is closed.
+    await vm.listenEventStream('Service', (ServiceEvent event) async {
+      // Wait for dds to be set before checking the server's URI.
+      await waitForDDS.future;
+      final message =
+          'A Dart Developer Service instance has connected and this direct '
+          'connection to the VM service will now be closed. Please reconnect to '
+          'the Dart Development Service at ${dds.uri}.';
+      expect(event.kind, ServiceEvent.kDartDevelopmentServiceConnected);
+      expect(event.message, message);
+      expect(event.uri, dds.uri);
+      serviceMessageCompleter.complete();
+    });
+
+    // Start DDS, which should result in the original VM service client being
+    // disconnected from the VM service.
+    final remote = Uri.parse(vm.target.networkAddress);
+    dds = await DartDevelopmentService.startDartDevelopmentService(
+      remote.replace(
+        scheme: 'http',
+        pathSegments: remote.pathSegments.sublist(
+          0,
+          remote.pathSegments.length - 1,
+        ),
+      ),
+    );
+    waitForDDS.complete();
+    expect(dds.isRunning, true);
+    await serviceMessageCompleter.future;
+    await vm.onDisconnect;
+    await dds.shutdown();
+  }
+];
+
+main(args) async => runVMTests(
+      args,
+      tests,
+      enableDds: false,
+    );
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index a220f97..dfa5bba 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -25216,6 +25216,19 @@
                 Function::Cast(member).ToLibNamePrefixedQualifiedCString(),
                 Function::KindToCString(Function::Cast(member).kind()))
           : member.ToCString();
+  if (!FLAG_verify_entry_points) {
+    // Print a warning, but do not return an error.
+    char const* warning = OS::SCreate(
+        Thread::Current()->zone(),
+        "WARNING: '%s' is accessed through Dart C API without being marked as "
+        "an entry point; its tree-shaken signature cannot be verified.\n"
+        "WARNING: See "
+        "https://github.com/dart-lang/sdk/blob/master/runtime/docs/compiler/"
+        "aot/entry_point_pragma.md\n",
+        member_cstring);
+    OS::PrintErr("%s", warning);
+    return Error::null();
+  }
   char const* error = OS::SCreate(
       Thread::Current()->zone(),
       "ERROR: It is illegal to access '%s' through Dart C API.\n"
diff --git a/sdk/lib/async/schedule_microtask.dart b/sdk/lib/async/schedule_microtask.dart
index 7e2e933..d01b483 100644
--- a/sdk/lib/async/schedule_microtask.dart
+++ b/sdk/lib/async/schedule_microtask.dart
@@ -132,6 +132,7 @@
  * Learn how Dart handles the event queue and microtask queue, so you can write
  * better asynchronous code with fewer surprises.
  */
+@pragma('vm:entry-point', 'call')
 void scheduleMicrotask(void Function() callback) {
   _Zone currentZone = Zone._current;
   if (identical(_rootZone, currentZone)) {
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index f7f4a26..a3f7e8b 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -231,6 +231,28 @@
   Uri? get ddsUri => _ddsUri;
   Uri? _ddsUri;
 
+  void _sendDdsConnectedEvent(Client client, String uri) {
+    final message =
+        'A Dart Developer Service instance has connected and this direct '
+        'connection to the VM service will now be closed. Please reconnect to '
+        'the Dart Development Service at $uri.';
+    final event = Response.json({
+      'jsonrpc': '2.0',
+      'method': 'streamNotify',
+      'params': {
+        'streamId': kServiceStream,
+        'event': {
+          "type": "Event",
+          "kind": "DartDevelopmentServiceConnected",
+          "message": message,
+          "uri": uri,
+          'timestamp': DateTime.now().millisecondsSinceEpoch,
+        }
+      }
+    });
+    client.post(event);
+  }
+
   Future<String> _yieldControlToDDS(Message message) async {
     final acceptNewWebSocketConnections =
         VMServiceEmbedderHooks.acceptNewWebSocketConnections;
@@ -249,14 +271,16 @@
     if (uri == null) {
       return encodeMissingParamError(message, 'uri');
     }
-    // DDS can only take control if there is no other clients connected
-    // directly to the VM service.
-    if (clients.length > 1) {
-      return encodeRpcError(message, kFeatureDisabled,
-          details:
-              'Existing VM service clients prevent DDS from taking control.');
-    }
     acceptNewWebSocketConnections(false);
+    // Note: we call clients.toList() to avoid concurrent modification errors.
+    for (final client in clients.toList()) {
+      // This is the DDS client.
+      if (message.client == client) {
+        continue;
+      }
+      _sendDdsConnectedEvent(client, uri);
+      client.disconnect();
+    }
     _ddsUri = Uri.parse(uri);
     await VMServiceEmbedderHooks.ddsConnected!();
     return encodeSuccess(message);
diff --git a/tools/VERSION b/tools/VERSION
index 2a0644f..ccecce5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 215
+PRERELEASE 216
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/flutter/analyze_flutter_flutter.sh b/tools/bots/flutter/analyze_flutter_flutter.sh
index e639f93..adca5cb 100755
--- a/tools/bots/flutter/analyze_flutter_flutter.sh
+++ b/tools/bots/flutter/analyze_flutter_flutter.sh
@@ -32,4 +32,10 @@
 
 bin/flutter update-packages
 
+# Analyze the flutter/flutter source code.
 $dart --enable-asserts dev/bots/analyze.dart --dart-sdk $sdk
+
+# Test flutter's use of data-driven fixes.
+pushd packages/flutter/test_fixes
+../../../bin/dart fix --compare-to-golden
+popd