Elements. Migrate InterfaceLeastUpperBoundHelper.

Change-Id: I23faf1777e9fda023eeb00d548c27f39ad055cf5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/404400
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
index d43cb0c..5f64449b 100644
--- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -2,13 +2,11 @@
 // 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.
 
-// ignore_for_file: analyzer_use_new_elements
-
 import 'dart:math' show max;
 
 import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart'
     show Variance;
-import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/element2.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/extensions.dart';
@@ -61,10 +59,10 @@
       return type1.withNullability(nullability);
     }
 
-    if (type1.element == type2.element) {
+    if (type1.element3 == type2.element3) {
       var args1 = type1.typeArguments;
       var args2 = type2.typeArguments;
-      var params = type1.element.typeParameters;
+      var params = type1.element3.typeParameters2;
       assert(args1.length == args2.length);
       assert(args1.length == params.length);
 
@@ -93,8 +91,8 @@
         }
       }
 
-      return InterfaceTypeImpl(
-        element: type1.element,
+      return InterfaceTypeImpl.v2(
+        element: type1.element3,
         typeArguments: args,
         nullabilitySuffix: nullability,
       );
@@ -124,7 +122,7 @@
       return;
     }
 
-    if (type.element is ExtensionTypeElement) {
+    if (type.element3 is ExtensionTypeElement2) {
       set.add(typeSystem.objectQuestion);
     }
 
@@ -180,7 +178,7 @@
   /// Object.
   @visibleForTesting
   static int computeLongestInheritancePathToObject(InterfaceType type) {
-    return _computeLongestInheritancePathToObject(type, <InterfaceElement>{});
+    return _computeLongestInheritancePathToObject(type, <InterfaceElement2>{});
   }
 
   static NullabilitySuffix _chooseNullability(
@@ -202,8 +200,8 @@
   /// The set of [visitedElements] is used to prevent infinite recursion in the
   /// case of a cyclic type structure.
   static int _computeLongestInheritancePathToObject(
-      InterfaceType type, Set<InterfaceElement> visitedElements) {
-    var element = type.element;
+      InterfaceType type, Set<InterfaceElement2> visitedElements) {
+    var element = type.element3;
     // recursion
     if (visitedElements.contains(element)) {
       return 0;
@@ -213,14 +211,14 @@
       return 1;
     }
     // Object case
-    if (element is ClassElement) {
+    if (element is ClassElement2) {
       if (element.isDartCoreObject) {
         return type.nullabilitySuffix == NullabilitySuffix.none ? 1 : 0;
       }
     }
 
     // Extension type without interfaces, implicit `Object?`
-    if (element is ExtensionTypeElement) {
+    if (element is ExtensionTypeElement2) {
       if (element.interfaces.isEmpty) {
         return 1;
       }
@@ -232,7 +230,7 @@
 
       // loop through each of the superinterfaces recursively calling this
       // method and keeping track of the longest path to return
-      if (element is MixinElement) {
+      if (element is MixinElement2) {
         for (InterfaceType interface in element.superclassConstraints) {
           var pathLength = _computeLongestInheritancePathToObject(
               interface, visitedElements);
@@ -248,7 +246,7 @@
         longestPath = max(longestPath, 1 + pathLength);
       }
 
-      if (element is! ClassElement) {
+      if (element is! ClassElement2) {
         return longestPath;
       }
 
@@ -321,7 +319,7 @@
   LeastUpperBoundHelper(this._typeSystem);
 
   InterfaceType get _interfaceTypeFunctionNone {
-    return _typeSystem.typeProvider.functionType.element.instantiate(
+    return _typeSystem.typeProvider.functionType.element3.instantiate(
       typeArguments: const [],
       nullabilitySuffix: NullabilitySuffix.none,
     );
@@ -625,8 +623,8 @@
   /// https://github.com/dart-lang/language
   /// See `resources/type-system/upper-lower-bounds.md`
   DartType _functionType(FunctionType f, FunctionType g) {
-    var fTypeFormals = f.typeFormals;
-    var gTypeFormals = g.typeFormals;
+    var fTypeFormals = f.typeParameters;
+    var gTypeFormals = g.typeParameters;
 
     // The number of type parameters must be the same.
     // Otherwise the result is `Function`.
@@ -636,7 +634,10 @@
 
     // The bounds of type parameters must be equal.
     // Otherwise the result is `Function`.
-    var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+    var fresh = _typeSystem.relateTypeParameters2(
+      f.typeParameters,
+      g.typeParameters,
+    );
     if (fresh == null) {
       return _interfaceTypeFunctionNone;
     }
@@ -644,10 +645,10 @@
     f = f.instantiate(fresh.typeParameterTypes);
     g = g.instantiate(fresh.typeParameterTypes);
 
-    var fParameters = f.parameters;
-    var gParameters = g.parameters;
+    var fParameters = f.formalParameters;
+    var gParameters = g.formalParameters;
 
-    var parameters = <ParameterElement>[];
+    var parameters = <FormalParameterElement>[];
     var fIndex = 0;
     var gIndex = 0;
     while (fIndex < fParameters.length && gIndex < gParameters.length) {
@@ -679,7 +680,13 @@
         }
       } else if (fParameter.isNamed) {
         if (gParameter.isNamed) {
-          var compareNames = fParameter.name.compareTo(gParameter.name);
+          var fName = fParameter.name3;
+          var gName = gParameter.name3;
+          if (fName == null || gName == null) {
+            return _interfaceTypeFunctionNone;
+          }
+
+          var compareNames = fName.compareTo(gName);
           if (compareNames == 0) {
             fIndex++;
             gIndex++;
@@ -729,9 +736,9 @@
 
     var returnType = getLeastUpperBound(f.returnType, g.returnType);
 
-    return FunctionTypeImpl(
-      typeFormals: fresh.typeParameters,
-      parameters: parameters,
+    return FunctionTypeImpl.v2(
+      typeParameters: fresh.typeParameters,
+      formalParameters: parameters,
       returnType: returnType,
       nullabilitySuffix: NullabilitySuffix.none,
     );
@@ -787,7 +794,7 @@
     return null;
   }
 
-  DartType _parameterType(ParameterElement a, ParameterElement b) {
+  DartType _parameterType(FormalParameterElement a, FormalParameterElement b) {
     return _typeSystem.greatestLowerBound(a.type, b.type);
   }
 
@@ -841,7 +848,7 @@
 
   /// Return the promoted or declared bound of the type parameter.
   DartType _typeParameterBound(TypeParameterTypeImpl type) {
-    var bound = type.promotedBound ?? type.element.bound;
+    var bound = type.promotedBound ?? type.element3.bound;
     if (bound != null) {
       return bound;
     }
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index e228b7c..974a723 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -70,15 +70,7 @@
     List<TypeParameterElement2> typeParameters) {
   var freshParameters = List<TypeParameterElementImpl2>.generate(
     typeParameters.length,
-    (i) {
-      var name = typeParameters[i].name3;
-      var fragment = TypeParameterElementImpl(name ?? '', -1);
-      return TypeParameterElementImpl2(
-        firstFragment: fragment,
-        name3: name,
-        bound: null,
-      );
-    },
+    (i) => typeParameters[i].freshCopy(),
     growable: false,
   );
 
diff --git a/pkg/analyzer/lib/src/utilities/extensions/element.dart b/pkg/analyzer/lib/src/utilities/extensions/element.dart
index 916d557..ccdb366 100644
--- a/pkg/analyzer/lib/src/utilities/extensions/element.dart
+++ b/pkg/analyzer/lib/src/utilities/extensions/element.dart
@@ -570,11 +570,13 @@
   }
 
   TypeParameterElementImpl2 freshCopy() {
+    var fragment = TypeParameterElementImpl(
+      name3 ?? '',
+      -1,
+    );
+    fragment.bound = bound;
     return TypeParameterElementImpl2(
-      firstFragment: TypeParameterElementImpl(
-        name3 ?? '',
-        -1,
-      ),
+      firstFragment: fragment,
       name3: name3,
       bound: bound,
     );
diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart
index dc1a413..2c0dd91 100644
--- a/pkg/analyzer/test/generated/elements_types_mixin.dart
+++ b/pkg/analyzer/test/generated/elements_types_mixin.dart
@@ -676,6 +676,11 @@
       ];
     }
   }
+
+  void updateElement() {
+    element.interfaces = interfaces;
+    element.mixins = mixins;
+  }
 }
 
 extension MixinElementImplExtension on MixinElementImpl {
diff --git a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
index 00b9939..64790cc 100644
--- a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
@@ -11,6 +11,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../generated/elements_types_mixin.dart';
 import '../../../generated/type_system_base.dart';
 
 main() {
@@ -135,6 +136,10 @@
       interfaceTypeNone(classB),
       interfaceTypeNone(classD)
     ];
+    classB.updateElement();
+    classC.updateElement();
+    classD.updateElement();
+    classE.updateElement();
     // assertion: even though the longest path to Object for typeB is 2, and
     // typeE implements typeB, the longest path for typeE is 4 since it also
     // implements typeD
@@ -163,6 +168,7 @@
     ClassElementImpl classE =
         class_(name: "E", superType: interfaceTypeNone(classB));
     classE.interfaces = <InterfaceType>[interfaceTypeNone(classD)];
+    classE.updateElement();
     // assertion: even though the longest path to Object for typeB is 2, and
     // typeE extends typeB, the longest path for typeE is 4 since it also
     // implements typeD
@@ -202,8 +208,10 @@
     ClassElementImpl classA = class_(name: "A");
     ClassElementImpl classB = class_(name: "B");
     ClassElementImpl classC = class_(name: "C");
-    classB.interfaces = <InterfaceType>[interfaceTypeNone(classA)];
-    classC.interfaces = <InterfaceType>[interfaceTypeNone(classB)];
+    classB.interfaces = [interfaceTypeNone(classA)];
+    classC.interfaces = [interfaceTypeNone(classB)];
+    classB.updateElement();
+    classC.updateElement();
     expect(_toElement(classA), 2);
     expect(_toElement(classB), 3);
     expect(_toElement(classC), 4);