Move getSubstitutionMap to KernelClassBuilder

Also, change the signature to return a kernel substitution map.

This prepares for fixing issue https://github.com/dart-lang/sdk/issues/34856,
as DillClassBuilders don't have builder wrappers for type variables and
supertypes.

Change-Id: Ia3f2458852ffaad766c44f62fd93e68234650126
Reviewed-on: https://dart-review.googlesource.com/c/81002
Reviewed-by: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 6c2bb49..8414d55 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -13,8 +13,6 @@
         LibraryBuilder,
         MemberBuilder,
         MetadataBuilder,
-        MixinApplicationBuilder,
-        NamedTypeBuilder,
         Scope,
         ScopeBuilder,
         TypeBuilder,
@@ -22,11 +20,7 @@
         TypeVariableBuilder;
 
 import '../fasta_codes.dart'
-    show
-        LocatedMessage,
-        Message,
-        templateInternalProblemNotFoundIn,
-        templateInternalProblemSuperclassNotFound;
+    show LocatedMessage, Message, templateInternalProblemNotFoundIn;
 
 abstract class ClassBuilder<T extends TypeBuilder, R>
     extends TypeDeclarationBuilder<T, R> {
@@ -129,94 +123,6 @@
     return constructors.lookup(name, charOffset, uri);
   }
 
-  /// Returns a map which maps the type variables of [superclass] to their
-  /// respective values as defined by the superclass clause of this class (and
-  /// its superclasses).
-  ///
-  /// It's assumed that [superclass] is a superclass of this class.
-  ///
-  /// For example, given:
-  ///
-  ///     class Box<T> {}
-  ///     class BeatBox extends Box<Beat> {}
-  ///     class Beat {}
-  ///
-  /// We have:
-  ///
-  ///     [[BeatBox]].getSubstitutionMap([[Box]]) -> {[[Box::T]]: Beat]]}.
-  ///
-  /// This method returns null if the map is empty, and it's an error if
-  /// [superclass] isn't a superclass.
-  Map<TypeVariableBuilder, TypeBuilder> getSubstitutionMap(
-      ClassBuilder superclass,
-      Uri fileUri,
-      int charOffset,
-      TypeBuilder dynamicType) {
-    TypeBuilder supertype = this.supertype;
-    Map<TypeVariableBuilder, TypeBuilder> substitutionMap;
-    List arguments;
-    List variables;
-    Declaration declaration;
-
-    /// If [application] is mixing in [superclass] directly or via other named
-    /// mixin applications, return it.
-    NamedTypeBuilder findSuperclass(MixinApplicationBuilder application) {
-      for (TypeBuilder t in application.mixins) {
-        if (t is NamedTypeBuilder) {
-          if (t.declaration == superclass) return t;
-        } else if (t is MixinApplicationBuilder) {
-          NamedTypeBuilder s = findSuperclass(t);
-          if (s != null) return s;
-        }
-      }
-      return null;
-    }
-
-    void handleNamedTypeBuilder(NamedTypeBuilder t) {
-      declaration = t.declaration;
-      arguments = t.arguments ?? const [];
-      if (declaration is ClassBuilder) {
-        ClassBuilder cls = declaration;
-        variables = cls.typeVariables;
-        supertype = cls.supertype;
-      }
-    }
-
-    while (declaration != superclass) {
-      variables = null;
-      if (supertype is NamedTypeBuilder) {
-        handleNamedTypeBuilder(supertype);
-      } else if (supertype is MixinApplicationBuilder) {
-        MixinApplicationBuilder t = supertype;
-        NamedTypeBuilder s = findSuperclass(t);
-        if (s != null) {
-          handleNamedTypeBuilder(s);
-        }
-        supertype = t.supertype;
-      } else {
-        internalProblem(
-            templateInternalProblemSuperclassNotFound
-                .withArguments(superclass.fullNameForErrors),
-            charOffset,
-            fileUri);
-      }
-      if (variables != null) {
-        Map<TypeVariableBuilder, TypeBuilder> directSubstitutionMap =
-            <TypeVariableBuilder, TypeBuilder>{};
-        for (int i = 0; i < variables.length; i++) {
-          TypeBuilder argument =
-              i < arguments.length ? arguments[i] : dynamicType;
-          if (substitutionMap != null) {
-            argument = argument.subst(substitutionMap);
-          }
-          directSubstitutionMap[variables[i]] = argument;
-        }
-        substitutionMap = directSubstitutionMap;
-      }
-    }
-    return substitutionMap;
-  }
-
   void forEach(void f(String name, MemberBuilder builder)) {
     scope.forEach(f);
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index dce8ac3..b913847 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -41,7 +41,10 @@
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
-import 'package:kernel/type_algebra.dart' show Substitution, getSubstitutionMap;
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+import 'package:kernel/type_algebra.dart' as type_algebra
+    show getSubstitutionMap;
 
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
 
@@ -61,15 +64,16 @@
         templateFactoryRedirecteeHasTooFewPositionalParameters,
         templateFactoryRedirecteeInvalidReturnType,
         templateGenericFunctionTypeInferredAsActualTypeArgument,
+        templateIllegalMixinDueToConstructors,
+        templateIllegalMixinDueToConstructorsCause,
         templateImplementsRepeated,
         templateImplementsSuperClass,
         templateImplicitMixinOverrideContext,
-        templateInterfaceCheckContext,
         templateIncorrectTypeArgument,
         templateIncorrectTypeArgumentInSupertype,
         templateIncorrectTypeArgumentInSupertypeInferred,
-        templateIllegalMixinDueToConstructors,
-        templateIllegalMixinDueToConstructorsCause,
+        templateInterfaceCheckContext,
+        templateInternalProblemSuperclassNotFound,
         templateMissingImplementationCause,
         templateMissingImplementationNotAbstract,
         templateMixinApplicationIncompatibleSupertype,
@@ -92,7 +96,8 @@
 
 import '../names.dart' show noSuchMethodName;
 
-import '../problems.dart' show unexpected, unhandled, unimplemented;
+import '../problems.dart'
+    show internalProblem, unexpected, unhandled, unimplemented;
 
 import '../type_inference/type_schema.dart' show UnknownType;
 
@@ -101,18 +106,21 @@
         ClassBuilder,
         ConstructorReferenceBuilder,
         Declaration,
-        KernelLibraryBuilder,
         KernelFunctionBuilder,
+        KernelLibraryBuilder,
+        KernelNamedTypeBuilder,
         KernelProcedureBuilder,
         KernelRedirectingFactoryBuilder,
-        KernelNamedTypeBuilder,
         KernelTypeBuilder,
         KernelTypeVariableBuilder,
         LibraryBuilder,
         MemberBuilder,
         MetadataBuilder,
+        MixinApplicationBuilder,
+        NamedTypeBuilder,
         ProcedureBuilder,
         Scope,
+        TypeBuilder,
         TypeVariableBuilder;
 
 import 'redirecting_factory_body.dart'
@@ -723,7 +731,7 @@
   void addNoSuchMethodForwarderForProcedure(Member noSuchMethod,
       KernelTarget target, Procedure procedure, ClassHierarchy hierarchy) {
     CloneWithoutBody cloner = new CloneWithoutBody(
-        typeSubstitution: getSubstitutionMap(
+        typeSubstitution: type_algebra.getSubstitutionMap(
             hierarchy.getClassAsInstanceOf(cls, procedure.enclosingClass)),
         cloneAnnotations: false);
     Procedure cloned = cloner.clone(procedure)..isExternal = false;
@@ -1716,4 +1724,97 @@
       }
     }
   }
+
+  /// Returns a map which maps the type variables of [superclass] to their
+  /// respective values as defined by the superclass clause of this class (and
+  /// its superclasses).
+  ///
+  /// It's assumed that [superclass] is a superclass of this class.
+  ///
+  /// For example, given:
+  ///
+  ///     class Box<T> {}
+  ///     class BeatBox extends Box<Beat> {}
+  ///     class Beat {}
+  ///
+  /// We have:
+  ///
+  ///     [[BeatBox]].getSubstitutionMap([[Box]]) -> {[[Box::T]]: Beat]]}.
+  ///
+  /// This method returns null if the map is empty, and it's an error if
+  /// [superclass] isn't a superclass.
+  Map<TypeParameter, DartType> getSubstitutionMap(ClassBuilder superclass,
+      Uri fileUri, int charOffset, TypeBuilder dynamicType) {
+    TypeBuilder supertype = this.supertype;
+    Map<TypeVariableBuilder, TypeBuilder> substitutionMap;
+    List arguments;
+    List variables;
+    Declaration declaration;
+
+    /// If [application] is mixing in [superclass] directly or via other named
+    /// mixin applications, return it.
+    NamedTypeBuilder findSuperclass(MixinApplicationBuilder application) {
+      for (TypeBuilder t in application.mixins) {
+        if (t is NamedTypeBuilder) {
+          if (t.declaration == superclass) return t;
+        } else if (t is MixinApplicationBuilder) {
+          NamedTypeBuilder s = findSuperclass(t);
+          if (s != null) return s;
+        }
+      }
+      return null;
+    }
+
+    void handleNamedTypeBuilder(NamedTypeBuilder t) {
+      declaration = t.declaration;
+      arguments = t.arguments ?? const [];
+      if (declaration is ClassBuilder) {
+        ClassBuilder cls = declaration;
+        variables = cls.typeVariables;
+        supertype = cls.supertype;
+      }
+    }
+
+    while (declaration != superclass) {
+      variables = null;
+      if (supertype is NamedTypeBuilder) {
+        handleNamedTypeBuilder(supertype);
+      } else if (supertype is MixinApplicationBuilder) {
+        MixinApplicationBuilder t = supertype;
+        NamedTypeBuilder s = findSuperclass(t);
+        if (s != null) {
+          handleNamedTypeBuilder(s);
+        }
+        supertype = t.supertype;
+      } else {
+        internalProblem(
+            templateInternalProblemSuperclassNotFound
+                .withArguments(superclass.fullNameForErrors),
+            charOffset,
+            fileUri);
+      }
+      if (variables != null) {
+        Map<TypeVariableBuilder, TypeBuilder> directSubstitutionMap =
+            <TypeVariableBuilder, TypeBuilder>{};
+        for (int i = 0; i < variables.length; i++) {
+          TypeBuilder argument =
+              i < arguments.length ? arguments[i] : dynamicType;
+          if (substitutionMap != null) {
+            argument = argument.subst(substitutionMap);
+          }
+          directSubstitutionMap[variables[i]] = argument;
+        }
+        substitutionMap = directSubstitutionMap;
+      }
+    }
+
+    if (substitutionMap == null) return const <TypeParameter, DartType>{};
+
+    Map<TypeParameter, DartType> result = <TypeParameter, DartType>{};
+    substitutionMap
+        .forEach((TypeVariableBuilder variable, TypeBuilder argument) {
+      result[variable.target] = argument.build(library);
+    });
+    return result;
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index c5f59d2..fd807fc 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -91,8 +91,7 @@
         LibraryBuilder,
         NamedTypeBuilder,
         TypeBuilder,
-        TypeDeclarationBuilder,
-        TypeVariableBuilder;
+        TypeDeclarationBuilder;
 
 import 'metadata_collector.dart' show MetadataCollector;
 
@@ -482,10 +481,8 @@
         builder.addSyntheticConstructor(makeDefaultConstructor(builder.target));
       } else {
         Map<TypeParameter, DartType> substitutionMap =
-            computeKernelSubstitutionMap(
-                builder.getSubstitutionMap(supertype, builder.fileUri,
-                    builder.charOffset, dynamicType),
-                builder.parent);
+            builder.getSubstitutionMap(
+                supertype, builder.fileUri, builder.charOffset, dynamicType);
         for (Constructor constructor in supertype.cls.constructors) {
           builder.addSyntheticConstructor(makeMixinApplicationConstructor(
               builder.target, builder.cls.mixin, constructor, substitutionMap));
@@ -499,18 +496,6 @@
     }
   }
 
-  Map<TypeParameter, DartType> computeKernelSubstitutionMap(
-      Map<TypeVariableBuilder, TypeBuilder> substitutionMap,
-      LibraryBuilder library) {
-    if (substitutionMap == null) return const <TypeParameter, DartType>{};
-    Map<TypeParameter, DartType> result = <TypeParameter, DartType>{};
-    substitutionMap
-        .forEach((TypeVariableBuilder variable, TypeBuilder argument) {
-      result[variable.target] = argument.build(library);
-    });
-    return result;
-  }
-
   Constructor makeMixinApplicationConstructor(Class cls, Class mixin,
       Constructor constructor, Map<TypeParameter, DartType> substitutionMap) {
     VariableDeclaration copyFormal(VariableDeclaration formal) {