// Copyright (c) 2018, 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.

// @dart = 2.9

library fasta.class_hierarchy_builder;

import 'package:kernel/ast.dart';

import 'package:kernel/class_hierarchy.dart'
    show ClassHierarchy, ClassHierarchyBase;

import 'package:kernel/core_types.dart' show CoreTypes;

import 'package:kernel/type_algebra.dart' show Substitution, uniteNullabilities;
import 'package:kernel/type_environment.dart';

import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/src/nnbd_top_merge.dart';
import 'package:kernel/src/norm.dart';
import 'package:kernel/src/standard_bounds.dart';
import 'package:kernel/src/types.dart' show Types;

import '../../base/common.dart';
import '../../testing/id_testing_utils.dart' show typeToText;

import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/field_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/procedure_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';

import '../loader.dart' show Loader;

import '../messages.dart'
    show
        LocatedMessage,
        Message,
        messageDeclaredMemberConflictsWithInheritedMember,
        messageDeclaredMemberConflictsWithInheritedMemberCause,
        messageDeclaredMemberConflictsWithOverriddenMembersCause,
        messageInheritedMembersConflict,
        messageInheritedMembersConflictCause1,
        messageInheritedMembersConflictCause2,
        messageStaticAndInstanceConflict,
        messageStaticAndInstanceConflictCause,
        templateCantInferTypesDueToNoCombinedSignature,
        templateCantInferReturnTypeDueToNoCombinedSignature,
        templateCantInferTypeDueToNoCombinedSignature,
        templateCombinedMemberSignatureFailed,
        templateDuplicatedDeclaration,
        templateDuplicatedDeclarationCause,
        templateDuplicatedDeclarationUse,
        templateMissingImplementationCause,
        templateMissingImplementationNotAbstract;

import '../names.dart' show noSuchMethodName;

import '../scope.dart' show Scope;

import '../source/source_class_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;

import '../source/source_loader.dart' show SourceLoader;

import '../type_inference/standard_bounds.dart' show TypeSchemaStandardBounds;

import '../type_inference/type_constraint_gatherer.dart'
    show TypeConstraintGatherer;

import '../type_inference/type_inferrer.dart' show MixinInferrer;

import '../type_inference/type_schema.dart' show UnknownType;

import '../type_inference/type_schema_environment.dart' show TypeConstraint;

import 'combined_member_signature.dart';

import 'member_covariance.dart';

import 'forwarding_node.dart' show ForwardingNode;

const DebugLogger debug =
    const bool.fromEnvironment("debug.hierarchy") ? const DebugLogger() : null;

class DebugLogger {
  const DebugLogger();
  void log(Object message) => print(message);
}

int compareDeclarations(ClassMember a, ClassMember b) {
  if (a == b) return 0;
  return ClassHierarchy.compareNames(a.name, b.name);
}

int compareClassMembers(ClassMember a, ClassMember b) {
  if (a.forSetter == b.forSetter) {
    return compareDeclarations(a, b);
  } else if (a.forSetter) {
    return 1;
  } else {
    return -1;
  }
}

bool isNameVisibleIn(Name name, LibraryBuilder libraryBuilder) {
  return !name.isPrivate || name.library == libraryBuilder.library;
}

class Tuple {
  final Name name;
  ClassMember _declaredMember;
  ClassMember _declaredSetter;
  ClassMember _mixedInMember;
  ClassMember _mixedInSetter;
  ClassMember _extendedMember;
  ClassMember _extendedSetter;
  List<ClassMember> _implementedMembers;
  List<ClassMember> _implementedSetters;

  Tuple.declareMember(this._declaredMember)
      : assert(!_declaredMember.forSetter),
        this.name = _declaredMember.name;

  Tuple.mixInMember(this._mixedInMember)
      : assert(!_mixedInMember.forSetter),
        this.name = _mixedInMember.name;

  Tuple.extendMember(this._extendedMember)
      : assert(!_extendedMember.forSetter),
        this.name = _extendedMember.name;

  Tuple.implementMember(ClassMember implementedMember)
      : assert(!implementedMember.forSetter),
        this.name = implementedMember.name,
        _implementedMembers = <ClassMember>[implementedMember];

  Tuple.declareSetter(this._declaredSetter)
      : assert(_declaredSetter.forSetter),
        this.name = _declaredSetter.name;

  Tuple.mixInSetter(this._mixedInSetter)
      : assert(_mixedInSetter.forSetter),
        this.name = _mixedInSetter.name;

  Tuple.extendSetter(this._extendedSetter)
      : assert(_extendedSetter.forSetter),
        this.name = _extendedSetter.name;

  Tuple.implementSetter(ClassMember implementedSetter)
      : assert(implementedSetter.forSetter),
        this.name = implementedSetter.name,
        _implementedSetters = <ClassMember>[implementedSetter];

  ClassMember get declaredMember => _declaredMember;

  void set declaredMember(ClassMember value) {
    assert(!value.forSetter);
    assert(
        _declaredMember == null,
        "Declared member already set to $_declaredMember, "
        "trying to set it to $value.");
    _declaredMember = value;
  }

  ClassMember get declaredSetter => _declaredSetter;

  void set declaredSetter(ClassMember value) {
    assert(value.forSetter);
    assert(
        _declaredSetter == null,
        "Declared setter already set to $_declaredSetter, "
        "trying to set it to $value.");
    _declaredSetter = value;
  }

  ClassMember get extendedMember => _extendedMember;

  void set extendedMember(ClassMember value) {
    assert(!value.forSetter);
    assert(
        _extendedMember == null,
        "Extended member already set to $_extendedMember, "
        "trying to set it to $value.");
    _extendedMember = value;
  }

  ClassMember get extendedSetter => _extendedSetter;

  void set extendedSetter(ClassMember value) {
    assert(value.forSetter);
    assert(
        _extendedSetter == null,
        "Extended setter already set to $_extendedSetter, "
        "trying to set it to $value.");
    _extendedSetter = value;
  }

  ClassMember get mixedInMember => _mixedInMember;

  void set mixedInMember(ClassMember value) {
    assert(!value.forSetter);
    assert(
        _mixedInMember == null,
        "Mixed in member already set to $_mixedInMember, "
        "trying to set it to $value.");
    _mixedInMember = value;
  }

  ClassMember get mixedInSetter => _mixedInSetter;

  void set mixedInSetter(ClassMember value) {
    assert(value.forSetter);
    assert(
        _mixedInSetter == null,
        "Mixed in setter already set to $_mixedInSetter, "
        "trying to set it to $value.");
    _mixedInSetter = value;
  }

  List<ClassMember> get implementedMembers => _implementedMembers;

  void addImplementedMember(ClassMember value) {
    assert(!value.forSetter);
    _implementedMembers ??= <ClassMember>[];
    _implementedMembers.add(value);
  }

  List<ClassMember> get implementedSetters => _implementedSetters;

  void addImplementedSetter(ClassMember value) {
    assert(value.forSetter);
    _implementedSetters ??= <ClassMember>[];
    _implementedSetters.add(value);
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    String comma = '';
    sb.write('Tuple(');
    if (_declaredMember != null) {
      sb.write(comma);
      sb.write('declaredMember=');
      sb.write(_declaredMember);
      comma = ',';
    }
    if (_declaredSetter != null) {
      sb.write(comma);
      sb.write('declaredSetter=');
      sb.write(_declaredSetter);
      comma = ',';
    }
    if (_mixedInMember != null) {
      sb.write(comma);
      sb.write('mixedInMember=');
      sb.write(_mixedInMember);
      comma = ',';
    }
    if (_mixedInSetter != null) {
      sb.write(comma);
      sb.write('mixedInSetter=');
      sb.write(_mixedInSetter);
      comma = ',';
    }
    if (_extendedMember != null) {
      sb.write(comma);
      sb.write('extendedMember=');
      sb.write(_extendedMember);
      comma = ',';
    }
    if (_extendedSetter != null) {
      sb.write(comma);
      sb.write('extendedSetter=');
      sb.write(_extendedSetter);
      comma = ',';
    }
    if (_implementedMembers != null) {
      sb.write(comma);
      sb.write('implementedMembers=');
      sb.write(_implementedMembers);
      comma = ',';
    }
    if (_implementedSetters != null) {
      sb.write(comma);
      sb.write('implementedSetters=');
      sb.write(_implementedSetters);
      comma = ',';
    }
    sb.write(')');
    return sb.toString();
  }
}

abstract class ClassMember {
  Name get name;
  bool get isStatic;
  bool get isField;
  bool get isAssignable;
  bool get isSetter;
  bool get isGetter;
  bool get isFinal;
  bool get isConst;
  bool get forSetter;

  /// Returns `true` if this member corresponds to a declaration in the source
  /// code.
  bool get isSourceDeclaration;

  /// Returns `true` if this member is a field, getter or setter.
  bool get isProperty;

  /// Computes the [Member] node resulting from this class member.
  Member getMember(ClassHierarchyBuilder hierarchy);

  /// Returns the member [Covariance] for this class member.
  Covariance getCovariance(ClassHierarchyBuilder hierarchy);

  bool get isDuplicate;
  String get fullName;
  String get fullNameForErrors;
  ClassBuilder get classBuilder;

  /// Returns `true` if this class member is declared in Object from dart:core.
  bool isObjectMember(ClassBuilder objectClass);
  Uri get fileUri;
  int get charOffset;

  /// Returns `true` if this class member is an interface member.
  bool get isAbstract;

  /// Returns `true` if this member doesn't corresponds to a declaration in the
  /// source code.
  bool get isSynthesized;

  // If `true` this member is not part of the interface but only part of the
  // class members.
  //
  // This is `true` for instance for synthesized fields added for the late
  // lowering.
  bool get isInternalImplementation;

  /// Returns `true` if this member is composed from a list of class members
  /// accessible through [declarations].
  bool get hasDeclarations;

  /// If [hasDeclaration] is `true`, this returns the list of class members
  /// from which this class member is composed.
  ///
  /// This is used in [unfoldDeclarations] to retrieve all underlying member
  /// source declarations, and in [toSet] to retrieve all members used for
  /// this class member wrt. certain level of the hierarchy.
  /// TODO(johnniwinther): Can the use of [toSet] be replaced with a direct
  /// use of [declarations]?
  List<ClassMember> get declarations;

  /// The interface member corresponding to this member.
  ///
  /// If this member is declared on the source, the interface member is
  /// the member itself. For instance
  ///
  ///     abstract class Class {
  ///        void concreteMethod() {}
  ///        void abstractMethod();
  ///     }
  ///
  /// the interface members for `concreteMethod` and `abstractMethod` are the
  /// members themselves.
  ///
  /// If this member is a synthesized interface member, the
  /// interface member is the member itself. For instance
  ///
  ///     abstract class Interface1 {
  ///        void method() {}
  ///     }
  ///     abstract class Interface2 {
  ///        void method() {}
  ///     }
  ///     abstract class Class implements Interface1, Interface2 {}
  ///
  /// the interface member for `method` in `Class` is the synthesized interface
  /// member created for the implemented members `Interface1.method` and
  /// `Interface2.method`.
  ///
  /// If this member is a concrete member that implements an interface member,
  /// the interface member is the implemented interface member. For instance
  ///
  ///     class Super {
  ///        void method() {}
  ///     }
  ///     class Interface {
  ///        void method() {}
  ///     }
  ///     class Class extends Super implements Interface {}
  ///
  /// the interface member for `Super.method` implementing `method` in `Class`
  /// is the synthesized interface member created for the implemented members
  /// `Super.method` and `Interface.method`.
  ClassMember get interfaceMember;

  void inferType(ClassHierarchyBuilder hierarchy);
  void registerOverrideDependency(Set<ClassMember> overriddenMembers);

  /// Returns `true` if this has the same underlying declaration as [other].
  ///
  /// This is used for avoiding unnecessary checks and can this trivially
  /// return `false`.
  bool isSameDeclaration(ClassMember other);
}

bool hasSameSignature(FunctionNode a, FunctionNode b) {
  List<TypeParameter> aTypeParameters = a.typeParameters;
  List<TypeParameter> bTypeParameters = b.typeParameters;
  int typeParameterCount = aTypeParameters.length;
  if (typeParameterCount != bTypeParameters.length) return false;
  Substitution substitution;
  if (typeParameterCount != 0) {
    List<DartType> types = new List<DartType>.filled(typeParameterCount, null);
    for (int i = 0; i < typeParameterCount; i++) {
      types[i] = new TypeParameterType.forAlphaRenaming(
          bTypeParameters[i], aTypeParameters[i]);
    }
    substitution = Substitution.fromPairs(bTypeParameters, types);
    for (int i = 0; i < typeParameterCount; i++) {
      DartType aBound = aTypeParameters[i].bound;
      DartType bBound = substitution.substituteType(bTypeParameters[i].bound);
      if (aBound != bBound) return false;
    }
  }

  if (a.requiredParameterCount != b.requiredParameterCount) return false;
  List<VariableDeclaration> aPositionalParameters = a.positionalParameters;
  List<VariableDeclaration> bPositionalParameters = b.positionalParameters;
  if (aPositionalParameters.length != bPositionalParameters.length) {
    return false;
  }
  for (int i = 0; i < aPositionalParameters.length; i++) {
    VariableDeclaration aParameter = aPositionalParameters[i];
    VariableDeclaration bParameter = bPositionalParameters[i];
    if (aParameter.isCovariant != bParameter.isCovariant) return false;
    DartType aType = aParameter.type;
    DartType bType = bParameter.type;
    if (substitution != null) {
      bType = substitution.substituteType(bType);
    }
    if (aType != bType) return false;
  }

  List<VariableDeclaration> aNamedParameters = a.namedParameters;
  List<VariableDeclaration> bNamedParameters = b.namedParameters;
  if (aNamedParameters.length != bNamedParameters.length) return false;
  for (int i = 0; i < aNamedParameters.length; i++) {
    VariableDeclaration aParameter = aNamedParameters[i];
    VariableDeclaration bParameter = bNamedParameters[i];
    if (aParameter.isCovariant != bParameter.isCovariant) return false;
    if (aParameter.name != bParameter.name) return false;
    DartType aType = aParameter.type;
    DartType bType = bParameter.type;
    if (substitution != null) {
      bType = substitution.substituteType(bType);
    }
    if (aType != bType) return false;
  }

  DartType aReturnType = a.returnType;
  DartType bReturnType = b.returnType;
  if (substitution != null) {
    bReturnType = substitution.substituteType(bReturnType);
  }

  return aReturnType == bReturnType;
}

class ClassHierarchyBuilder implements ClassHierarchyBase {
  final Map<Class, ClassHierarchyNode> nodes = <Class, ClassHierarchyNode>{};

  final Map<ClassBuilder, Map<Class, Substitution>> substitutions =
      <ClassBuilder, Map<Class, Substitution>>{};

  final ClassBuilder objectClassBuilder;

  final Loader loader;

  final Class objectClass;

  final Class futureClass;

  final Class functionClass;

  final List<DelayedTypeComputation> _delayedTypeComputations =
      <DelayedTypeComputation>[];

  final List<DelayedCheck> _delayedChecks = <DelayedCheck>[];

  final List<ClassMember> _delayedMemberComputations = <ClassMember>[];

  final CoreTypes coreTypes;

  Types types;

  ClassHierarchyBuilder(this.objectClassBuilder, this.loader, this.coreTypes)
      : objectClass = objectClassBuilder.cls,
        futureClass = coreTypes.futureClass,
        functionClass = coreTypes.functionClass {
    types = new Types(this);
  }

  void clear() {
    nodes.clear();
    substitutions.clear();
    _delayedChecks.clear();
    _delayedTypeComputations.clear();
    _delayedMemberComputations.clear();
  }

  void registerDelayedTypeComputation(DelayedTypeComputation computation) {
    _delayedTypeComputations.add(computation);
  }

  void registerOverrideCheck(SourceClassBuilder classBuilder,
      ClassMember declaredMember, Set<ClassMember> overriddenMembers) {
    _delayedChecks.add(new DelayedOverrideCheck(
        classBuilder, declaredMember, overriddenMembers));
  }

  void registerGetterSetterCheck(
      SourceClassBuilder classBuilder, ClassMember getter, ClassMember setter) {
    _delayedChecks
        .add(new DelayedGetterSetterCheck(classBuilder, getter, setter));
  }

  void registerMemberComputation(ClassMember member) {
    _delayedMemberComputations.add(member);
  }

  List<DelayedTypeComputation> takeDelayedTypeComputations() {
    List<DelayedTypeComputation> list = _delayedTypeComputations.toList();
    _delayedTypeComputations.clear();
    return list;
  }

  List<DelayedCheck> takeDelayedChecks() {
    List<DelayedCheck> list = _delayedChecks.toList();
    _delayedChecks.clear();
    return list;
  }

  List<ClassMember> takeDelayedMemberComputations() {
    List<ClassMember> list = _delayedMemberComputations.toList();
    _delayedMemberComputations.clear();
    return list;
  }

  void inferFieldType(SourceFieldBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    ClassHierarchyNodeBuilder.inferFieldType(
        this,
        declaredMember.classBuilder,
        substitutions[declaredMember.classBuilder],
        declaredMember,
        overriddenMembers);
  }

  void inferGetterType(SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    ClassHierarchyNodeBuilder.inferGetterType(
        this,
        declaredMember.classBuilder,
        substitutions[declaredMember.classBuilder],
        declaredMember,
        overriddenMembers);
  }

  void inferSetterType(SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    ClassHierarchyNodeBuilder.inferSetterType(
        this,
        declaredMember.classBuilder,
        substitutions[declaredMember.classBuilder],
        declaredMember,
        overriddenMembers);
  }

  void inferMethodType(SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    ClassHierarchyNodeBuilder.inferMethodType(
        this,
        declaredMember.classBuilder,
        substitutions[declaredMember.classBuilder],
        declaredMember,
        overriddenMembers);
  }

  ClassHierarchyNode getNodeFromClassBuilder(ClassBuilder classBuilder) {
    return nodes[classBuilder.cls] ??= new ClassHierarchyNodeBuilder(
            this, classBuilder, substitutions[classBuilder] ??= {})
        .build();
  }

  ClassHierarchyNode getNodeFromTypeBuilder(TypeBuilder type) {
    ClassBuilder cls = getClass(type);
    return cls == null ? null : getNodeFromClassBuilder(cls);
  }

  ClassHierarchyNode getNodeFromClass(Class cls) {
    return nodes[cls] ??
        getNodeFromClassBuilder(loader.computeClassBuilderFromTargetClass(cls));
  }

  Supertype asSupertypeOf(InterfaceType subtype, Class supertype) {
    if (subtype.classNode == supertype) {
      return new Supertype(supertype, subtype.typeArguments);
    }
    ClassHierarchyNode clsNode = getNodeFromClass(subtype.classNode);
    ClassHierarchyNode supertypeNode = getNodeFromClass(supertype);
    List<Supertype> superclasses = clsNode.superclasses;
    int depth = supertypeNode.depth;
    if (depth < superclasses.length) {
      Supertype superclass = superclasses[depth];
      if (superclass.classNode == supertype) {
        return Substitution.fromInterfaceType(subtype)
            .substituteSupertype(superclass);
      }
    }
    List<Supertype> superinterfaces = clsNode.interfaces;
    for (int i = 0; i < superinterfaces.length; i++) {
      Supertype superinterface = superinterfaces[i];
      if (superinterface.classNode == supertype) {
        return Substitution.fromInterfaceType(subtype)
            .substituteSupertype(superinterface);
      }
    }
    return null;
  }

  InterfaceType getTypeAsInstanceOf(
      InterfaceType type, Class superclass, Library clientLibrary) {
    if (type.classNode == superclass) return type;
    return asSupertypeOf(type, superclass)
        .asInterfaceType
        .withDeclaredNullability(type.nullability);
  }

  List<DartType> getTypeArgumentsAsInstanceOf(
      InterfaceType type, Class superclass) {
    if (type.classNode == superclass) return type.typeArguments;
    return asSupertypeOf(type, superclass)?.typeArguments;
  }

  @override
  InterfaceType getLegacyLeastUpperBound(
      InterfaceType type1, InterfaceType type2, Library clientLibrary) {
    if (type1 == type2) return type1;

    // LLUB(Null, List<dynamic>*) works differently for opt-in and opt-out
    // libraries.  In opt-out libraries the legacy behavior is preserved, so
    // LLUB(Null, List<dynamic>*) = List<dynamic>*.  In opt-out libraries the
    // rules imply that LLUB(Null, List<dynamic>*) = List<dynamic>?.
    if (!clientLibrary.isNonNullableByDefault) {
      if (type1 is NullType) {
        return type2;
      }
      if (type2 is NullType) {
        return type1;
      }
    }

    ClassHierarchyNode node1 = getNodeFromClass(type1.classNode);
    ClassHierarchyNode node2 = getNodeFromClass(type2.classNode);
    Set<ClassHierarchyNode> nodes1 = node1.computeAllSuperNodes(this).toSet();
    List<ClassHierarchyNode> nodes2 = node2.computeAllSuperNodes(this);
    List<ClassHierarchyNode> common = <ClassHierarchyNode>[];

    for (int i = 0; i < nodes2.length; i++) {
      ClassHierarchyNode node = nodes2[i];
      if (node == null) continue;
      if (node.classBuilder.cls.isAnonymousMixin) {
        // Never find unnamed mixin application in least upper bound.
        continue;
      }
      if (nodes1.contains(node)) {
        DartType candidate1 =
            getTypeAsInstanceOf(type1, node.classBuilder.cls, clientLibrary);
        DartType candidate2 =
            getTypeAsInstanceOf(type2, node.classBuilder.cls, clientLibrary);
        if (candidate1 == candidate2) {
          common.add(node);
        }
      }
    }

    if (common.length == 1) {
      return coreTypes.objectRawType(
          uniteNullabilities(type1.nullability, type2.nullability));
    }
    common.sort(ClassHierarchyNode.compareMaxInheritancePath);

    for (int i = 0; i < common.length - 1; i++) {
      ClassHierarchyNode node = common[i];
      if (node.maxInheritancePath != common[i + 1].maxInheritancePath) {
        return getTypeAsInstanceOf(type1, node.classBuilder.cls, clientLibrary)
            .withDeclaredNullability(
                uniteNullabilities(type1.nullability, type2.nullability));
      } else {
        do {
          i++;
        } while (node.maxInheritancePath == common[i + 1].maxInheritancePath);
      }
    }
    return coreTypes.objectRawType(
        uniteNullabilities(type1.nullability, type2.nullability));
  }

  Member getInterfaceMember(Class cls, Name name, {bool setter: false}) {
    return getNodeFromClass(cls)
        .getInterfaceMember(name, setter)
        ?.getMember(this);
  }

  Member getDispatchTargetKernel(Class cls, Name name, bool isSetter) {
    ClassMember classMember =
        getNodeFromClass(cls).getDispatchTarget(name, isSetter);
    Member member = classMember?.getMember(this);
    if (member != null && member.isAbstract) {
      if (cls.superclass != null) {
        return getDispatchTargetKernel(cls.superclass, name, isSetter);
      } else {
        return null;
      }
    }
    return member;
  }

  Member getCombinedMemberSignatureKernel(Class cls, Name name, bool isSetter,
      int charOffset, SourceLibraryBuilder library) {
    ClassMember declaration =
        getNodeFromClass(cls).getInterfaceMember(name, isSetter);
    if (declaration?.isStatic ?? true) return null;
    if (declaration.isDuplicate) {
      library?.addProblem(
          templateDuplicatedDeclarationUse.withArguments(name.text),
          charOffset,
          name.text.length,
          library.fileUri);
      return null;
    }
    return declaration.getMember(this);
  }

  static ClassHierarchyBuilder build(ClassBuilder objectClass,
      List<ClassBuilder> classes, SourceLoader loader, CoreTypes coreTypes) {
    ClassHierarchyBuilder hierarchy =
        new ClassHierarchyBuilder(objectClass, loader, coreTypes);
    for (int i = 0; i < classes.length; i++) {
      ClassBuilder classBuilder = classes[i];
      if (!classBuilder.isPatch) {
        hierarchy.nodes[classBuilder.cls] = new ClassHierarchyNodeBuilder(
                hierarchy,
                classBuilder,
                hierarchy.substitutions[classBuilder] ??= {})
            .build();
      } else {
        // TODO(ahe): Merge the injected members of patch into the hierarchy
        // node of `cls.origin`.
      }
    }
    return hierarchy;
  }

  void computeTypes() {
    List<DelayedTypeComputation> typeComputations =
        takeDelayedTypeComputations();
    for (int i = 0; i < typeComputations.length; i++) {
      typeComputations[i].compute(this);
    }
  }
}

class ClassHierarchyNodeBuilder {
  final ClassHierarchyBuilder hierarchy;

  final ClassBuilder classBuilder;

  bool hasNoSuchMethod = false;

  final Map<Class, Substitution> substitutions;

  ClassHierarchyNodeBuilder(
      this.hierarchy, this.classBuilder, this.substitutions);

  ClassBuilder get objectClass => hierarchy.objectClassBuilder;

  bool get shouldModifyKernel =>
      classBuilder.library.loader == hierarchy.loader;

  ClassMember checkInheritanceConflict(ClassMember a, ClassMember b) {
    if (a.isStatic || a.isProperty != b.isProperty) {
      reportInheritanceConflict(a, b);
      return a;
    }
    return null;
  }

  static void inferMethodType(
      ClassHierarchyBuilder hierarchy,
      ClassBuilder classBuilder,
      Map<Class, Substitution> substitutions,
      SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    assert(!declaredMember.isGetter && !declaredMember.isSetter);
    if (declaredMember.classBuilder == classBuilder &&
        (declaredMember.returnType == null ||
            declaredMember.formals != null &&
                declaredMember.formals
                    .any((parameter) => parameter.type == null))) {
      Procedure declaredProcedure = declaredMember.member;
      FunctionNode declaredFunction = declaredProcedure.function;
      List<TypeParameter> declaredTypeParameters =
          declaredFunction.typeParameters;
      List<VariableDeclaration> declaredPositional =
          declaredFunction.positionalParameters;
      List<VariableDeclaration> declaredNamed =
          declaredFunction.namedParameters;
      declaredNamed = declaredNamed.toList()..sort(compareNamedParameters);

      DartType inferredReturnType;
      Map<FormalParameterBuilder, DartType> inferredParameterTypes = {};

      Set<ClassMember> overriddenMemberSet =
          toSet(declaredMember.classBuilder, overriddenMembers);
      CombinedClassMemberSignature combinedMemberSignature =
          new CombinedClassMemberSignature(
              hierarchy, classBuilder, overriddenMemberSet.toList(),
              forSetter: false);
      FunctionType combinedMemberSignatureType = combinedMemberSignature
          .getCombinedSignatureTypeInContext(declaredTypeParameters);

      bool cantInferReturnType = false;
      List<FormalParameterBuilder> cantInferParameterTypes;

      if (declaredMember.returnType == null) {
        if (combinedMemberSignatureType == null) {
          inferredReturnType = const InvalidType();
          cantInferReturnType = true;
        } else {
          inferredReturnType = combinedMemberSignatureType.returnType;
        }
      }
      if (declaredMember.formals != null) {
        for (int i = 0; i < declaredPositional.length; i++) {
          FormalParameterBuilder declaredParameter = declaredMember.formals[i];
          if (declaredParameter.type != null) {
            continue;
          }

          DartType inferredParameterType;
          if (combinedMemberSignatureType == null) {
            inferredParameterType = const InvalidType();
            cantInferParameterTypes ??= [];
            cantInferParameterTypes.add(declaredParameter);
          } else if (i <
              combinedMemberSignatureType.positionalParameters.length) {
            inferredParameterType =
                combinedMemberSignatureType.positionalParameters[i];
          }
          inferredParameterTypes[declaredParameter] = inferredParameterType;
        }

        Map<String, DartType> namedParameterTypes;
        for (int i = declaredPositional.length;
            i < declaredMember.formals.length;
            i++) {
          FormalParameterBuilder declaredParameter = declaredMember.formals[i];
          if (declaredParameter.type != null) {
            continue;
          }

          DartType inferredParameterType;
          if (combinedMemberSignatureType == null) {
            inferredParameterType = const InvalidType();
            cantInferParameterTypes ??= [];
            cantInferParameterTypes.add(declaredParameter);
          } else {
            if (namedParameterTypes == null) {
              namedParameterTypes = {};
              for (NamedType namedType
                  in combinedMemberSignatureType.namedParameters) {
                namedParameterTypes[namedType.name] = namedType.type;
              }
            }
            inferredParameterType = namedParameterTypes[declaredParameter.name];
          }
          inferredParameterTypes[declaredParameter] = inferredParameterType;
        }
      }

      if ((cantInferReturnType && cantInferParameterTypes != null) ||
          (cantInferParameterTypes != null &&
              cantInferParameterTypes.length > 1)) {
        reportCantInferTypes(
            classBuilder, declaredMember, hierarchy, overriddenMembers);
      } else if (cantInferReturnType) {
        reportCantInferReturnType(
            classBuilder, declaredMember, hierarchy, overriddenMembers);
      } else if (cantInferParameterTypes != null) {
        reportCantInferParameterType(classBuilder,
            cantInferParameterTypes.single, hierarchy, overriddenMembers);
      }

      if (declaredMember.returnType == null) {
        inferredReturnType ??= const DynamicType();
        declaredFunction.returnType = inferredReturnType;
      }
      if (declaredMember.formals != null) {
        for (FormalParameterBuilder declaredParameter
            in declaredMember.formals) {
          if (declaredParameter.type == null) {
            DartType inferredParameterType =
                inferredParameterTypes[declaredParameter] ??
                    const DynamicType();
            declaredParameter.variable.type = inferredParameterType;
          }
        }
      }
    }
  }

  void inferMethodSignature(ClassHierarchyBuilder hierarchy,
      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
    assert(!declaredMember.isGetter && !declaredMember.isSetter);
    // Trigger computation of method type.
    Procedure declaredProcedure = declaredMember.getMember(hierarchy);
    for (ClassMember overriddenMember
        in toSet(declaredMember.classBuilder, overriddenMembers)) {
      Covariance covariance = overriddenMember.getCovariance(hierarchy);
      covariance.applyCovariance(declaredProcedure);
    }
  }

  void inferGetterSignature(ClassHierarchyBuilder hierarchy,
      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
    assert(declaredMember.isGetter);
    // Trigger computation of the getter type.
    declaredMember.getMember(hierarchy);
    // Otherwise nothing to do. Getters have no variance.
  }

  void inferSetterSignature(ClassHierarchyBuilder hierarchy,
      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
    assert(declaredMember.isSetter);
    // Trigger computation of the getter type.
    Procedure declaredSetter = declaredMember.getMember(hierarchy);
    for (ClassMember overriddenMember
        in toSet(declaredMember.classBuilder, overriddenMembers)) {
      Covariance covariance = overriddenMember.getCovariance(hierarchy);
      covariance.applyCovariance(declaredSetter);
    }
  }

  static void inferGetterType(
      ClassHierarchyBuilder hierarchy,
      ClassBuilder classBuilder,
      Map<Class, Substitution> substitutions,
      SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    assert(declaredMember.isGetter);
    if (declaredMember.classBuilder == classBuilder &&
        declaredMember.returnType == null) {
      DartType inferredType;
      overriddenMembers = toSet(classBuilder, overriddenMembers);

      List<ClassMember> overriddenGetters = [];
      List<ClassMember> overriddenSetters = [];
      for (ClassMember overriddenMember in overriddenMembers) {
        if (overriddenMember.forSetter) {
          overriddenSetters.add(overriddenMember);
        } else {
          overriddenGetters.add(overriddenMember);
        }
      }

      void inferFrom(List<ClassMember> members, {bool forSetter}) {
        assert(forSetter != null);
        CombinedClassMemberSignature combinedMemberSignature =
            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
                forSetter: forSetter);
        DartType combinedMemberSignatureType =
            combinedMemberSignature.combinedMemberSignatureType;
        if (combinedMemberSignatureType == null) {
          inferredType = const InvalidType();
          reportCantInferReturnType(
              classBuilder, declaredMember, hierarchy, members);
        } else {
          inferredType = combinedMemberSignatureType;
        }
      }

      if (overriddenGetters.isNotEmpty) {
        // 1) The return type of a getter, parameter type of a setter or type
        // of a field which overrides/implements only one or more getters is
        // inferred to be the return type of the combined member signature of
        // said getter in the direct superinterfaces.

        // 2) The return type of a getter which overrides/implements both a
        // setter and a getter is inferred to be the return type of the
        // combined member signature of said getter in the direct
        // superinterfaces.
        inferFrom(overriddenGetters, forSetter: false);
      } else {
        // The return type of a getter, parameter type of a setter or type of
        // a field which overrides/implements only one or more setters is
        // inferred to be the parameter type of the combined member signature
        // of said setter in the direct superinterfaces.
        inferFrom(overriddenSetters, forSetter: true);
      }

      inferredType ??= const DynamicType();
      declaredMember.procedure.function.returnType = inferredType;
    }
  }

  static void inferSetterType(
      ClassHierarchyBuilder hierarchy,
      ClassBuilder classBuilder,
      Map<Class, Substitution> substitutions,
      SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    assert(declaredMember.isSetter);
    FormalParameterBuilder parameter = declaredMember.formals.first;
    if (declaredMember.classBuilder == classBuilder && parameter.type == null) {
      DartType inferredType;

      overriddenMembers = toSet(classBuilder, overriddenMembers);

      List<ClassMember> overriddenGetters = [];
      List<ClassMember> overriddenSetters = [];
      for (ClassMember overriddenMember in overriddenMembers) {
        if (overriddenMember.forSetter) {
          overriddenSetters.add(overriddenMember);
        } else {
          overriddenGetters.add(overriddenMember);
        }
      }

      void inferFrom(List<ClassMember> members, {bool forSetter}) {
        assert(forSetter != null);
        CombinedClassMemberSignature combinedMemberSignature =
            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
                forSetter: forSetter);
        DartType combinedMemberSignatureType =
            combinedMemberSignature.combinedMemberSignatureType;
        if (combinedMemberSignatureType == null) {
          inferredType = const InvalidType();
          reportCantInferReturnType(
              classBuilder, declaredMember, hierarchy, members);
        } else {
          inferredType = combinedMemberSignatureType;
        }
      }

      if (overriddenSetters.isNotEmpty) {
        // 1) The return type of a getter, parameter type of a setter or type
        // of a field which overrides/implements only one or more setters is
        // inferred to be the parameter type of the combined member signature
        // of said setter in the direct superinterfaces.
        //
        // 2) The parameter type of a setter which overrides/implements both a
        // setter and a getter is inferred to be the parameter type of the
        // combined member signature of said setter in the direct
        // superinterfaces.
        inferFrom(overriddenSetters, forSetter: true);
      } else {
        // The return type of a getter, parameter type of a setter or type of
        // a field which overrides/implements only one or more getters is
        // inferred to be the return type of the combined member signature of
        // said getter in the direct superinterfaces.
        inferFrom(overriddenGetters, forSetter: false);
      }

      inferredType ??= const DynamicType();
      parameter.variable.type = inferredType;
    }
  }

  /// Merge the [inheritedType] with the currently [inferredType] using
  /// nnbd-top-merge or legacy-top-merge depending on whether [classBuilder] is
  /// defined in an opt-in or opt-out library. If the types could not be merged
  /// `null` is returned and an error should be reported by the caller.
  static DartType mergeTypeInLibrary(
      ClassHierarchyBuilder hierarchy,
      ClassBuilder classBuilder,
      DartType inferredType,
      DartType inheritedType) {
    if (classBuilder.library.isNonNullableByDefault) {
      if (inferredType == null) {
        return inheritedType;
      } else {
        return nnbdTopMerge(
            hierarchy.coreTypes,
            norm(hierarchy.coreTypes, inferredType),
            norm(hierarchy.coreTypes, inheritedType));
      }
    } else {
      inheritedType = legacyErasure(inheritedType);
      if (inferredType == null) {
        return inheritedType;
      } else {
        if (inferredType is DynamicType &&
            inheritedType == hierarchy.coreTypes.objectLegacyRawType) {
          return inferredType;
        } else if (inheritedType is DynamicType &&
            inferredType == hierarchy.coreTypes.objectLegacyRawType) {
          return inheritedType;
        }
        if (inferredType != inheritedType) {
          return null;
        }
        return inferredType;
      }
    }
  }

  /// Infers the field type of [fieldBuilder] based on [overriddenMembers].
  static void inferFieldType(
      ClassHierarchyBuilder hierarchy,
      ClassBuilder classBuilder,
      Map<Class, Substitution> substitutions,
      SourceFieldBuilder fieldBuilder,
      Iterable<ClassMember> overriddenMembers) {
    if (fieldBuilder.classBuilder == classBuilder &&
        fieldBuilder.type == null) {
      DartType inferredType;

      overriddenMembers = toSet(classBuilder, overriddenMembers);
      List<ClassMember> overriddenGetters = [];
      List<ClassMember> overriddenSetters = [];
      for (ClassMember overriddenMember in overriddenMembers) {
        if (overriddenMember.forSetter) {
          overriddenSetters.add(overriddenMember);
        } else {
          overriddenGetters.add(overriddenMember);
        }
      }

      DartType inferFrom(List<ClassMember> members, {bool forSetter}) {
        assert(forSetter != null);
        CombinedClassMemberSignature combinedMemberSignature =
            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
                forSetter: forSetter);
        return combinedMemberSignature.combinedMemberSignatureType;
      }

      DartType combinedMemberSignatureType;
      if (fieldBuilder.isAssignable &&
          overriddenGetters.isNotEmpty &&
          overriddenSetters.isNotEmpty) {
        // The type of a non-final field which overrides/implements both a
        // setter and a getter is inferred to be the parameter type of the
        // combined member signature of said setter in the direct
        // superinterfaces, if this type is the same as the return type of the
        // combined member signature of said getter in the direct
        // superinterfaces. If the types are not the same then inference fails
        // with an error.
        DartType getterType = inferFrom(overriddenGetters, forSetter: false);
        DartType setterType = inferFrom(overriddenSetters, forSetter: true);
        if (getterType == setterType) {
          combinedMemberSignatureType = getterType;
        }
      } else if (overriddenGetters.isNotEmpty) {
        // 1) The return type of a getter, parameter type of a setter or type
        // of a field which overrides/implements only one or more getters is
        // inferred to be the return type of the combined member signature of
        // said getter in the direct superinterfaces.
        //
        // 2) The type of a final field which overrides/implements both a
        // setter and a getter is inferred to be the return type of the
        // combined member signature of said getter in the direct
        // superinterfaces.
        combinedMemberSignatureType =
            inferFrom(overriddenGetters, forSetter: false);
      } else {
        // The return type of a getter, parameter type of a setter or type of
        // a field which overrides/implements only one or more setters is
        // inferred to be the parameter type of the combined member signature
        // of said setter in the direct superinterfaces.
        combinedMemberSignatureType =
            inferFrom(overriddenSetters, forSetter: true);
      }

      if (combinedMemberSignatureType == null) {
        inferredType = const InvalidType();
        reportCantInferFieldType(classBuilder, fieldBuilder, overriddenMembers);
      } else {
        inferredType = combinedMemberSignatureType;
      }

      inferredType ??= const DynamicType();
      fieldBuilder.fieldType = inferredType;
    }
  }

  /// Infers the field signature of [declaredMember] based on
  /// [overriddenMembers].
  void inferFieldSignature(ClassHierarchyBuilder hierarchy,
      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
    Field declaredField = declaredMember.getMember(hierarchy);
    for (ClassMember overriddenMember
        in toSet(declaredMember.classBuilder, overriddenMembers)) {
      Covariance covariance = overriddenMember.getCovariance(hierarchy);
      covariance.applyCovariance(declaredField);
    }
  }

  void reportInheritanceConflict(ClassMember a, ClassMember b) {
    String name = a.fullNameForErrors;
    if (a.classBuilder != b.classBuilder) {
      if (a.classBuilder == classBuilder) {
        classBuilder.addProblem(
            messageDeclaredMemberConflictsWithInheritedMember,
            a.charOffset,
            name.length,
            context: <LocatedMessage>[
              messageDeclaredMemberConflictsWithInheritedMemberCause
                  .withLocation(b.fileUri, b.charOffset, name.length)
            ]);
      } else if (b.classBuilder == classBuilder) {
        classBuilder.addProblem(
            messageDeclaredMemberConflictsWithInheritedMember,
            b.charOffset,
            name.length,
            context: <LocatedMessage>[
              messageDeclaredMemberConflictsWithInheritedMemberCause
                  .withLocation(a.fileUri, a.charOffset, name.length)
            ]);
      } else {
        classBuilder.addProblem(messageInheritedMembersConflict,
            classBuilder.charOffset, classBuilder.fullNameForErrors.length,
            context: _inheritedConflictContext(a, b));
      }
    } else if (a.isStatic != b.isStatic) {
      ClassMember staticMember;
      ClassMember instanceMember;
      if (a.isStatic) {
        staticMember = a;
        instanceMember = b;
      } else {
        staticMember = b;
        instanceMember = a;
      }
      classBuilder.library.addProblem(messageStaticAndInstanceConflict,
          staticMember.charOffset, name.length, staticMember.fileUri,
          context: <LocatedMessage>[
            messageStaticAndInstanceConflictCause.withLocation(
                instanceMember.fileUri, instanceMember.charOffset, name.length)
          ]);
    } else {
      // This message can be reported twice (when merging localMembers with
      // classSetters, or localSetters with classMembers). By ensuring that
      // we always report the one with higher charOffset as the duplicate,
      // the message duplication logic ensures that we only report this
      // problem once.
      ClassMember existing;
      ClassMember duplicate;
      assert(a.fileUri == b.fileUri);
      if (a.charOffset < b.charOffset) {
        existing = a;
        duplicate = b;
      } else {
        existing = b;
        duplicate = a;
      }
      classBuilder.library.addProblem(
          templateDuplicatedDeclaration.withArguments(name),
          duplicate.charOffset,
          name.length,
          duplicate.fileUri,
          context: <LocatedMessage>[
            templateDuplicatedDeclarationCause.withArguments(name).withLocation(
                existing.fileUri, existing.charOffset, name.length)
          ]);
    }
  }

  ClassHierarchyNode build() {
    assert(!classBuilder.isPatch);
    ClassHierarchyNode supernode;
    if (objectClass != classBuilder.origin) {
      supernode =
          hierarchy.getNodeFromTypeBuilder(classBuilder.supertypeBuilder);
      if (supernode == null) {
        supernode = hierarchy.getNodeFromClassBuilder(objectClass);
      }
      assert(supernode != null);
    }

    /// Set to `true` if the class needs interfaces, that is, if it has any
    /// members where the interface member is different from its corresponding
    /// class members.
    ///
    /// This is an optimization to avoid unnecessary computation of interface
    /// members.
    bool hasInterfaces = false;

    Map<Name, Tuple> memberMap = {};

    Scope scope = classBuilder.scope;

    for (MemberBuilder memberBuilder in scope.localMembers) {
      for (ClassMember classMember in memberBuilder.localMembers) {
        if (classMember.isAbstract) {
          hasInterfaces = true;
        }
        Tuple tuple = memberMap[classMember.name];
        if (tuple == null) {
          memberMap[classMember.name] = new Tuple.declareMember(classMember);
        } else {
          tuple.declaredMember = classMember;
        }
      }
      for (ClassMember classMember in memberBuilder.localSetters) {
        if (classMember.isAbstract) {
          hasInterfaces = true;
        }
        Tuple tuple = memberMap[classMember.name];
        if (tuple == null) {
          memberMap[classMember.name] = new Tuple.declareSetter(classMember);
        } else {
          tuple.declaredSetter = classMember;
        }
      }
    }

    for (MemberBuilder memberBuilder in scope.localSetters) {
      for (ClassMember classMember in memberBuilder.localMembers) {
        if (classMember.isAbstract) {
          hasInterfaces = true;
        }
        Tuple tuple = memberMap[classMember.name];
        if (tuple == null) {
          memberMap[classMember.name] = new Tuple.declareMember(classMember);
        } else {
          tuple.declaredMember = classMember;
        }
      }
      for (ClassMember classMember in memberBuilder.localSetters) {
        if (classMember.isAbstract) {
          hasInterfaces = true;
        }
        Tuple tuple = memberMap[classMember.name];
        if (tuple == null) {
          memberMap[classMember.name] = new Tuple.declareSetter(classMember);
        } else {
          tuple.declaredSetter = classMember;
        }
      }
    }

    if (classBuilder.isMixinApplication) {
      TypeBuilder mixedInTypeBuilder = classBuilder.mixedInTypeBuilder;
      TypeDeclarationBuilder mixin = mixedInTypeBuilder.declaration;
      inferMixinApplication();
      while (mixin.isNamedMixinApplication) {
        ClassBuilder named = mixin;
        mixedInTypeBuilder = named.mixedInTypeBuilder;
        mixin = mixedInTypeBuilder.declaration;
      }
      if (mixin is TypeAliasBuilder) {
        TypeAliasBuilder aliasBuilder = mixin;
        NamedTypeBuilder namedBuilder = mixedInTypeBuilder;
        mixin = aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
      }
      if (mixin is ClassBuilder) {
        scope = mixin.scope.computeMixinScope();

        for (MemberBuilder memberBuilder in scope.localMembers) {
          for (ClassMember classMember in memberBuilder.localMembers) {
            if (classMember.isAbstract) {
              hasInterfaces = true;
            }
            Tuple tuple = memberMap[classMember.name];
            if (tuple == null) {
              memberMap[classMember.name] = new Tuple.mixInMember(classMember);
            } else {
              tuple.mixedInMember = classMember;
            }
          }
          for (ClassMember classMember in memberBuilder.localSetters) {
            if (classMember.isAbstract) {
              hasInterfaces = true;
            }
            Tuple tuple = memberMap[classMember.name];
            if (tuple == null) {
              memberMap[classMember.name] = new Tuple.mixInSetter(classMember);
            } else {
              tuple.mixedInSetter = classMember;
            }
          }
        }

        for (MemberBuilder memberBuilder in scope.localSetters) {
          for (ClassMember classMember in memberBuilder.localMembers) {
            if (classMember.isAbstract) {
              hasInterfaces = true;
            }
            Tuple tuple = memberMap[classMember.name];
            if (tuple == null) {
              memberMap[classMember.name] = new Tuple.mixInMember(classMember);
            } else {
              tuple.mixedInMember = classMember;
            }
          }
          for (ClassMember classMember in memberBuilder.localSetters) {
            if (classMember.isAbstract) {
              hasInterfaces = true;
            }
            Tuple tuple = memberMap[classMember.name];
            if (tuple == null) {
              memberMap[classMember.name] = new Tuple.mixInSetter(classMember);
            } else {
              tuple.mixedInSetter = classMember;
            }
          }
        }
      }
    }

    List<Supertype> superclasses;

    List<Supertype> interfaces;

    int maxInheritancePath;

    void extend(Map<Name, ClassMember> superClassMembers) {
      if (superClassMembers == null) return;
      for (Name name in superClassMembers.keys) {
        ClassMember superClassMember = superClassMembers[name];
        Tuple tuple = memberMap[name];
        if (tuple != null) {
          if (superClassMember.forSetter) {
            tuple.extendedSetter = superClassMember;
          } else {
            tuple.extendedMember = superClassMember;
          }
        } else {
          if (superClassMember.forSetter) {
            memberMap[name] = new Tuple.extendSetter(superClassMember);
          } else {
            memberMap[name] = new Tuple.extendMember(superClassMember);
          }
        }
      }
    }

    void implement(Map<Name, ClassMember> superInterfaceMembers) {
      if (superInterfaceMembers == null) return;
      for (Name name in superInterfaceMembers.keys) {
        ClassMember superInterfaceMember = superInterfaceMembers[name];
        Tuple tuple = memberMap[name];
        if (tuple != null) {
          if (superInterfaceMember.forSetter) {
            tuple.addImplementedSetter(superInterfaceMember);
          } else {
            tuple.addImplementedMember(superInterfaceMember);
          }
        } else {
          if (superInterfaceMember.forSetter) {
            memberMap[superInterfaceMember.name] =
                new Tuple.implementSetter(superInterfaceMember);
          } else {
            memberMap[superInterfaceMember.name] =
                new Tuple.implementMember(superInterfaceMember);
          }
        }
      }
    }

    if (supernode == null) {
      // This should be Object.
      superclasses = new List<Supertype>.filled(0, null);
      interfaces = new List<Supertype>.filled(0, null);
      maxInheritancePath = 0;
    } else {
      maxInheritancePath = supernode.maxInheritancePath + 1;

      superclasses =
          new List<Supertype>.filled(supernode.superclasses.length + 1, null);
      Supertype supertype = classBuilder.supertypeBuilder.buildSupertype(
          classBuilder.library, classBuilder.charOffset, classBuilder.fileUri);
      if (supertype == null) {
        // If the superclass is not an interface type we use Object instead.
        // A similar normalization is performed on [supernode] above.
        supertype =
            new Supertype(hierarchy.coreTypes.objectClass, const <DartType>[]);
      }
      superclasses.setRange(0, superclasses.length - 1,
          substSupertypes(supertype, supernode.superclasses));
      superclasses[superclasses.length - 1] = supertype;
      if (!classBuilder.library.isNonNullableByDefault &&
          supernode.classBuilder.library.isNonNullableByDefault) {
        for (int i = 0; i < superclasses.length; i++) {
          superclasses[i] = legacyErasureSupertype(superclasses[i]);
        }
      }

      List<TypeBuilder> directInterfaceBuilders =
          ignoreFunction(classBuilder.interfaceBuilders);
      if (classBuilder.isMixinApplication) {
        if (directInterfaceBuilders == null) {
          directInterfaceBuilders = <TypeBuilder>[
            classBuilder.mixedInTypeBuilder
          ];
        } else {
          directInterfaceBuilders = <TypeBuilder>[
            classBuilder.mixedInTypeBuilder
          ]..addAll(directInterfaceBuilders);
        }
      }

      List<Supertype> superclassInterfaces = supernode.interfaces;
      if (superclassInterfaces != null) {
        superclassInterfaces = substSupertypes(supertype, superclassInterfaces);
      }

      extend(supernode.classMemberMap);
      extend(supernode.classSetterMap);

      if (supernode.interfaceMemberMap != null ||
          supernode.interfaceSetterMap != null) {
        hasInterfaces = true;
      }

      if (hasInterfaces) {
        implement(supernode.interfaceMemberMap ?? supernode.classMemberMap);
        implement(supernode.interfaceSetterMap ?? supernode.classSetterMap);
      }

      if (directInterfaceBuilders != null) {
        for (int i = 0; i < directInterfaceBuilders.length; i++) {
          ClassHierarchyNode interfaceNode =
              hierarchy.getNodeFromTypeBuilder(directInterfaceBuilders[i]);
          if (interfaceNode != null) {
            hasInterfaces = true;

            implement(interfaceNode.interfaceMemberMap ??
                interfaceNode.classMemberMap);
            implement(interfaceNode.interfaceSetterMap ??
                interfaceNode.classSetterMap);
          }
        }

        interfaces = <Supertype>[];
        if (superclassInterfaces != null) {
          for (int i = 0; i < superclassInterfaces.length; i++) {
            addInterface(interfaces, superclasses, superclassInterfaces[i]);
          }
        }

        for (int i = 0; i < directInterfaceBuilders.length; i++) {
          Supertype directInterface = directInterfaceBuilders[i].buildSupertype(
              classBuilder.library,
              classBuilder.charOffset,
              classBuilder.fileUri);
          if (directInterface != null) {
            addInterface(interfaces, superclasses, directInterface);
            ClassHierarchyNode interfaceNode =
                hierarchy.getNodeFromClass(directInterface.classNode);
            if (interfaceNode != null) {
              if (maxInheritancePath < interfaceNode.maxInheritancePath + 1) {
                maxInheritancePath = interfaceNode.maxInheritancePath + 1;
              }

              List<Supertype> types =
                  substSupertypes(directInterface, interfaceNode.superclasses);
              for (int i = 0; i < types.length; i++) {
                addInterface(interfaces, superclasses, types[i]);
              }
              if (interfaceNode.interfaces != null) {
                List<Supertype> types =
                    substSupertypes(directInterface, interfaceNode.interfaces);
                for (int i = 0; i < types.length; i++) {
                  addInterface(interfaces, superclasses, types[i]);
                }
              }
            }
          }
        }
      } else if (superclassInterfaces != null &&
          !classBuilder.library.isNonNullableByDefault &&
          supernode.classBuilder.library.isNonNullableByDefault) {
        interfaces = <Supertype>[];
        for (int i = 0; i < superclassInterfaces.length; i++) {
          addInterface(interfaces, superclasses, superclassInterfaces[i]);
        }
      } else {
        interfaces = superclassInterfaces;
      }
    }

    for (Supertype superclass in superclasses) {
      recordSupertype(superclass);
    }
    if (interfaces != null) {
      for (Supertype superinterface in interfaces) {
        recordSupertype(superinterface);
      }
    }

    /// Members (excluding setters) declared in [cls] or its superclasses. This
    /// includes static methods of [cls], but not its superclasses.
    Map<Name, ClassMember> classMemberMap = {};

    /// Setters declared in [cls] or its superclasses. This includes static
    /// setters of [cls], but not its superclasses.
    Map<Name, ClassMember> classSetterMap = {};

    /// Members (excluding setters) inherited from interfaces. This contains no
    /// static members. If no interfaces are implemented by this class or its
    /// superclasses this is identical to [classMemberMap] and we do not store
    /// it in the [ClassHierarchyNode].
    Map<Name, ClassMember> interfaceMemberMap = {};

    /// Setters inherited from interfaces. This contains no static setters. If
    /// no interfaces are implemented by this class or its superclasses this is
    /// identical to [classSetterMap] and we do not store it in the
    /// [ClassHierarchyNode].
    Map<Name, ClassMember> interfaceSetterMap = {};

    /// Map for members declared in this class to the members that they
    /// override. This is used for checking valid overrides and to ensure that
    /// override inference correctly propagates inferred types through the
    /// class hierarchy.
    Map<ClassMember, Set<ClassMember>> declaredOverridesMap = {};

    /// In case this class is a mixin application, this maps members declared in
    /// the mixin to the members that they override. This is used for checking
    /// valid overrides but _not_ as for [declaredOverridesMap] for override
    /// inference.
    Map<ClassMember, Set<ClassMember>> mixinApplicationOverridesMap = {};

    /// In case this class is concrete, this maps concrete members that are
    /// inherited into this class to the members they should override to validly
    /// implement the interface of this class.
    Map<ClassMember, Set<ClassMember>> inheritedImplementsMap = {};

    /// In case this class is concrete, this holds the interface members
    /// without a corresponding class member. These are either reported as
    /// missing implementations or trigger insertion of noSuchMethod forwarders.
    List<ClassMember> abstractMembers = [];

    ClassHierarchyNodeDataForTesting dataForTesting;
    if (retainDataForTesting) {
      dataForTesting = new ClassHierarchyNodeDataForTesting(
          abstractMembers,
          declaredOverridesMap,
          mixinApplicationOverridesMap,
          inheritedImplementsMap);
    }

    /// Registers that the current class has an interface member without a
    /// corresponding class member.
    ///
    /// This is used to report missing implementation or, in the case the class
    /// has a user defined concrete noSuchMethod, to insert noSuchMethod
    /// forwarders. (Currently, insertion of forwarders is handled elsewhere.)
    ///
    /// For instance:
    ///
    ///    abstract class Interface {
    ///      method();
    ///    }
    ///    class Class1 implements Interface {
    ///      // Missing implementation for `Interface.method`.
    ///    }
    ///    class Class2 implements Interface {
    ///      noSuchMethod(_) {}
    ///      // A noSuchMethod forwarder is added for `Interface.method`.
    ///    }
    ///
    void registerAbstractMember(ClassMember abstractMember) {
      if (!abstractMember.isInternalImplementation) {
        /// If `isInternalImplementation` is `true`, the member is synthesized
        /// implementation that does not require implementation in other
        /// classes.
        ///
        /// This is for instance used for late lowering where
        ///
        ///    class Interface {
        ///      late int? field;
        ///    }
        ///    class Class implements Interface {
        ///      int? field;
        ///    }
        ///
        /// is encoded as
        ///
        ///    class Interface {
        ///      bool _#field#isSet = false;
        ///      int? _#field = null;
        ///      int? get field => _#field#isSet ? _#field : throw ...;
        ///      void set field(int? value) { ... }
        ///    }
        ///    class Class implements Interface {
        ///      int? field;
        ///    }
        ///
        /// and `Class` should not be required to implement
        /// `Interface._#field#isSet` and `Interface._#field`.
        abstractMembers.add(abstractMember);
      }
    }

    /// Registers that [inheritedMember] should be checked to validly override
    /// [overrides].
    ///
    /// This is needed in the case where a concrete member is inherited into
    /// a concrete subclass. For instance:
    ///
    ///    class Super {
    ///      void method() {}
    ///    }
    ///    abstract class Interface {
    ///      void method();
    ///    }
    ///    class Class extends Super implements Interface {}
    ///
    /// Here `Super.method` must be checked to be a valid implementation for
    /// `Interface.method` by being a valid override of it.
    void registerInheritedImplements(
        ClassMember inheritedMember, Set<ClassMember> overrides,
        {ClassMember aliasForTesting}) {
      if (classBuilder is SourceClassBuilder) {
        assert(
            inheritedMember.classBuilder != classBuilder,
            "Only inherited members can implement by inheritance: "
            "${inheritedMember}");
        inheritedImplementsMap[inheritedMember] = overrides;
        if (dataForTesting != null && aliasForTesting != null) {
          dataForTesting.aliasMap[aliasForTesting] = inheritedMember;
        }
      }
    }

    /// Returns `true` if the current class is from an opt-out library and
    /// [classMember] is from an opt-in library.
    ///
    /// In this case a member signature needs to be inserted to show the
    /// legacy erased type of the interface member. For instance:
    ///
    ///    // Opt-in library:
    ///    class Super {
    ///      int? method(int i) {}
    ///    }
    ///    // Opt-out library:
    ///    class Class extends Super {
    ///      // A member signature is inserted:
    ///      // int* method(int* i);
    ///    }
    ///
    bool needsMemberSignatureFor(ClassMember classMember) {
      return !classBuilder.library.isNonNullableByDefault &&
          classMember.classBuilder.library.isNonNullableByDefault;
    }

    memberMap.forEach((Name name, Tuple tuple) {
      /// The computation starts by sanitizing the members. Conflicts between
      /// methods and properties (getters/setters) or between static and
      /// instance members are reported. Conflicting members and members
      /// overridden by duplicates are removed.
      ///
      /// For this [definingGetable] and [definingSetable] hold the first member
      /// of its kind found among declared, mixed in, extended and implemented
      /// members.
      ///
      /// Conflicts between [definingGetable] and [definingSetable] are reported
      /// afterwards.

      ClassMember definingGetable;
      ClassMember definingSetable;

      ClassMember declaredGetable = tuple.declaredMember;
      if (declaredGetable != null) {
        /// class Class {
        ///   method() {}
        /// }
        definingGetable = declaredGetable;
      }
      ClassMember declaredSetable = tuple.declaredSetter;
      if (declaredSetable != null) {
        /// class Class {
        ///   set setter(value) {}
        /// }
        definingSetable = declaredSetable;
      }

      ClassMember mixedInGetable;
      if (tuple.mixedInMember != null &&
          !tuple.mixedInMember.isStatic &&
          !tuple.mixedInMember.isDuplicate &&
          !tuple.mixedInMember.isSynthesized) {
        /// We treat
        ///
        ///   opt-in:
        ///   class Interface {
        ///     method3() {}
        ///   }
        ///   opt-out:
        ///   class Mixin implements Interface {
        ///     static method1() {}
        ///     method2() {}
        ///     method2() {}
        ///     /*member-signature*/ method3() {}
        ///   }
        ///   class Class with Mixin {}
        ///
        /// as
        ///
        ///   class Mixin {}
        ///   class Class with Mixin {}
        ///
        /// Note that skipped synthetic getable 'method3' is still included
        /// in the implemented getables, but its type will not define the type
        /// when mixed in. For instance
        ///
        ///   opt-in:
        ///   abstract class Interface {
        ///     num get getter;
        ///   }
        ///   opt-out:
        ///   abstract class Super {
        ///     int get getter;
        ///   }
        ///   abstract class Mixin implements Interface {
        ///     /*member-signature*/ num get getter;
        ///   }
        ///   abstract class Class extends Super with Mixin {}
        ///
        /// Here the type of `Class.getter` should not be defined from the
        /// synthetic member signature `Mixin.getter` but as a combined member
        /// signature of `Super.getter` and `Mixin.getter`, resulting in type
        /// `int` instead of `num`.
        if (definingGetable == null) {
          /// class Mixin {
          ///   method() {}
          /// }
          /// class Class with Mixin {}
          definingGetable = mixedInGetable = tuple.mixedInMember;
        } else if (!definingGetable.isDuplicate) {
          // This case is currently unreachable from source code since classes
          // cannot both declare and mix in members. From dill, this can occur
          // but should not conflicting members.
          //
          // The case is handled for consistency.
          if (definingGetable.isStatic ||
              definingGetable.isProperty != tuple.mixedInMember.isProperty) {
            reportInheritanceConflict(definingGetable, tuple.mixedInMember);
          } else {
            mixedInGetable = tuple.mixedInMember;
          }
        }
      }
      ClassMember mixedInSetable;
      if (tuple.mixedInSetter != null &&
          !tuple.mixedInSetter.isStatic &&
          !tuple.mixedInSetter.isDuplicate &&
          !tuple.mixedInSetter.isSynthesized) {
        /// We treat
        ///
        ///   class Mixin {
        ///     static set setter1(value) {}
        ///     set setter2(value) {}
        ///     set setter2(value) {}
        ///     /*member-signature*/ setter3() {}
        ///   }
        ///   class Class with Mixin {}
        ///
        /// as
        ///
        ///   class Mixin {}
        ///   class Class with Mixin {}
        ///
        /// Note that skipped synthetic setable 'setter3' is still included
        /// in the implemented setables, but its type will not define the type
        /// when mixed in. For instance
        ///
        ///   opt-in:
        ///   abstract class Interface {
        ///     void set setter(int value);
        ///   }
        ///   opt-out:
        ///   abstract class Super {
        ///     void set setter(num value);
        ///   }
        ///   abstract class Mixin implements Interface {
        ///     /*member-signature*/ num get getter;
        ///   }
        ///   abstract class Class extends Super with Mixin {}
        ///
        /// Here the type of `Class.setter` should not be defined from the
        /// synthetic member signature `Mixin.setter` but as a combined member
        /// signature of `Super.setter` and `Mixin.setter`, resulting in type
        /// `num` instead of `int`.
        if (definingSetable == null) {
          /// class Mixin {
          ///   set setter(value) {}
          /// }
          /// class Class with Mixin {}
          definingSetable = mixedInSetable = tuple.mixedInSetter;
        } else if (!definingSetable.isDuplicate) {
          if (definingSetable.isStatic ||
              definingSetable.isProperty != tuple.mixedInSetter.isProperty) {
            reportInheritanceConflict(definingGetable, tuple.mixedInSetter);
          } else {
            mixedInSetable = tuple.mixedInSetter;
          }
        }
      }

      ClassMember extendedGetable;
      if (tuple.extendedMember != null &&
          !tuple.extendedMember.isStatic &&
          !tuple.extendedMember.isDuplicate) {
        /// We treat
        ///
        ///   class Super {
        ///     static method1() {}
        ///     method2() {}
        ///     method2() {}
        ///   }
        ///   class Class extends Super {}
        ///
        /// as
        ///
        ///   class Super {}
        ///   class Class extends Super {}
        ///
        if (definingGetable == null) {
          /// class Super {
          ///   method() {}
          /// }
          /// class Class extends Super {}
          definingGetable = extendedGetable = tuple.extendedMember;
        } else if (!definingGetable.isDuplicate) {
          if (definingGetable.isStatic ||
              definingGetable.isProperty != tuple.extendedMember.isProperty) {
            ///   class Super {
            ///     method() {}
            ///   }
            ///   class Class extends Super {
            ///     static method() {}
            ///   }
            ///
            /// or
            ///
            ///   class Super {
            ///     method() {}
            ///   }
            ///   class Class extends Super {
            ///     get getter => 0;
            ///   }
            reportInheritanceConflict(definingGetable, tuple.extendedMember);
          } else {
            extendedGetable = tuple.extendedMember;
          }
        }
      }
      ClassMember extendedSetable;
      if (tuple.extendedSetter != null &&
          !tuple.extendedSetter.isStatic &&
          !tuple.extendedSetter.isDuplicate) {
        /// We treat
        ///
        ///   class Super {
        ///     static set setter1(value) {}
        ///     set setter2(value) {}
        ///     set setter2(value) {}
        ///   }
        ///   class Class extends Super {}
        ///
        /// as
        ///
        ///   class Super {}
        ///   class Class extends Super {}
        ///
        if (definingSetable == null) {
          /// class Super {
          ///   set setter(value) {}
          /// }
          /// class Class extends Super {}
          definingSetable = extendedSetable = tuple.extendedSetter;
        } else if (!definingSetable.isDuplicate) {
          if (definingSetable.isStatic ||
              definingSetable.isProperty != tuple.extendedSetter.isProperty) {
            reportInheritanceConflict(definingSetable, tuple.extendedSetter);
          } else {
            extendedSetable = tuple.extendedSetter;
          }
        }
      }

      // TODO(johnniwinther): Remove extended and mixed in members/setters
      // from implemented members/setters. Mixin applications always implement
      // the mixin class leading to unnecessary interface members.
      List<ClassMember> implementedGetables;
      if (tuple.implementedMembers != null &&
          // Skip implemented members if we already have a duplicate.
          !(definingGetable != null && definingGetable.isDuplicate)) {
        for (int i = 0; i < tuple.implementedMembers.length; i++) {
          ClassMember implementedGetable = tuple.implementedMembers[i];
          if (implementedGetable.isStatic || implementedGetable.isDuplicate) {
            /// We treat
            ///
            ///   class Interface {
            ///     static method1() {}
            ///     method2() {}
            ///     method2() {}
            ///   }
            ///   class Class implements Interface {}
            ///
            /// as
            ///
            ///   class Interface {}
            ///   class Class implements Interface {}
            ///
            implementedGetable = null;
          } else {
            if (definingGetable == null) {
              /// class Interface {
              ///   method() {}
              /// }
              /// class Class implements Interface {}
              definingGetable = implementedGetable;
            } else if (definingGetable.isStatic ||
                definingGetable.isProperty != implementedGetable.isProperty) {
              ///   class Interface {
              ///     method() {}
              ///   }
              ///   class Class implements Interface {
              ///     static method() {}
              ///   }
              ///
              /// or
              ///
              ///   class Interface {
              ///     method() {}
              ///   }
              ///   class Class implements Interface {
              ///     get getter => 0;
              ///   }
              reportInheritanceConflict(definingGetable, implementedGetable);
              implementedGetable = null;
            }
          }
          if (implementedGetable == null) {
            // On the first skipped member we add all previous.
            implementedGetables ??= tuple.implementedMembers.take(i).toList();
          } else if (implementedGetables != null) {
            // If already skipping members we add [implementedGetable]
            // explicitly.
            implementedGetables.add(implementedGetable);
          }
        }
        if (implementedGetables == null) {
          // No members were skipped so we use the full list.
          implementedGetables = tuple.implementedMembers;
        } else if (implementedGetables.isEmpty) {
          // No members were included.
          implementedGetables = null;
        }
      }

      List<ClassMember> implementedSetables;
      if (tuple.implementedSetters != null &&
          // Skip implemented setters if we already have a duplicate.
          !(definingSetable != null && definingSetable.isDuplicate)) {
        for (int i = 0; i < tuple.implementedSetters.length; i++) {
          ClassMember implementedSetable = tuple.implementedSetters[i];
          if (implementedSetable.isStatic || implementedSetable.isDuplicate) {
            /// We treat
            ///
            ///   class Interface {
            ///     static set setter1(value) {}
            ///     set setter2(value) {}
            ///     set setter2(value) {}
            ///   }
            ///   class Class implements Interface {}
            ///
            /// as
            ///
            ///   class Interface {}
            ///   class Class implements Interface {}
            ///
            implementedSetable = null;
          } else {
            if (definingSetable == null) {
              /// class Interface {
              ///   set setter(value) {}
              /// }
              /// class Class implements Interface {}
              definingSetable = implementedSetable;
            } else if (definingSetable.isStatic ||
                definingSetable.isProperty != implementedSetable.isProperty) {
              /// class Interface {
              ///   set setter(value) {}
              /// }
              /// class Class implements Interface {
              ///   static set setter(value) {}
              /// }
              reportInheritanceConflict(definingSetable, implementedSetable);
              implementedSetable = null;
            }
          }
          if (implementedSetable == null) {
            // On the first skipped setter we add all previous.
            implementedSetables ??= tuple.implementedSetters.take(i).toList();
          } else if (implementedSetables != null) {
            // If already skipping setters we add [implementedSetable]
            // explicitly.
            implementedSetables.add(implementedSetable);
          }
        }
        if (implementedSetables == null) {
          // No setters were skipped so we use the full list.
          implementedSetables = tuple.implementedSetters;
        } else if (implementedSetables.isEmpty) {
          // No setters were included.
          implementedSetables = null;
        }
      }

      if (definingGetable != null && definingSetable != null) {
        if (definingGetable.isStatic != definingSetable.isStatic ||
            definingGetable.isProperty != definingSetable.isProperty) {
          reportInheritanceConflict(definingGetable, definingSetable);
          // TODO(johnniwinther): Should we remove [definingSetable]? If we
          // leave it in this conflict will also be reported in subclasses. If
          // we remove it, any write to the setable will be unresolved.
        }
      }

      // TODO(johnniwinther): Handle declared members together with mixed in
      // members. This should only occur from .dill, though.
      if (mixedInGetable != null) {
        declaredGetable = null;
      }
      if (mixedInSetable != null) {
        declaredSetable = null;
      }

      /// Set to `true` if declared members have been registered in
      /// [registerDeclaredOverride] or [registerMixedInOverride].
      bool hasDeclaredMembers = false;

      /// Declared methods, getters and setters registered in
      /// [registerDeclaredOverride].
      ClassMember declaredMethod;
      List<ClassMember> declaredProperties;

      /// Declared methods, getters and setters registered in
      /// [registerDeclaredOverride].
      ClassMember mixedInMethod;
      List<ClassMember> mixedInProperties;

      /// Registers that [declaredMember] overrides extended and implemented
      /// members.
      ///
      /// Getters and setters share overridden members so the registration
      /// of override relations is performed after the interface members have
      /// been computed.
      ///
      /// Declared members must be checked for valid override of the overridden
      /// members _and_ must register an override dependency with the overridden
      /// members so that override inference can propagate inferred types
      /// correctly. For instance:
      ///
      ///    class Super {
      ///      int get property => 42;
      ///    }
      ///    class Class extends Super {
      ///      void set property(value) {}
      ///    }
      ///
      /// Here the parameter type of the setter `Class.property` must be
      /// inferred from the type of the getter `Super.property`.
      void registerDeclaredOverride(ClassMember declaredMember,
          {ClassMember aliasForTesting}) {
        if (classBuilder is SourceClassBuilder && !declaredMember.isStatic) {
          assert(
              declaredMember.isSourceDeclaration &&
                  declaredMember.classBuilder == classBuilder,
              "Only declared members can override: ${declaredMember}");
          hasDeclaredMembers = true;
          if (declaredMember.isProperty) {
            declaredProperties ??= [];
            declaredProperties.add(declaredMember);
          } else {
            assert(
                declaredMethod == null,
                "Multiple methods unexpectedly declared: "
                "${declaredMethod} and ${declaredMember}.");
            declaredMethod = declaredMember;
          }
          if (dataForTesting != null && aliasForTesting != null) {
            dataForTesting.aliasMap[aliasForTesting] = declaredMember;
          }
        }
      }

      /// Registers that [mixedMember] overrides extended and implemented
      /// members through application.
      ///
      /// Getters and setters share overridden members so the registration
      /// of override relations in performed after the interface members have
      /// been computed.
      ///
      /// Declared mixed in members must be checked for valid override of the
      /// overridden members but _not_ register an override dependency with the
      /// overridden members. This is in contrast to declared members. For
      /// instance:
      ///
      ///    class Super {
      ///      int get property => 42;
      ///    }
      ///    class Mixin {
      ///      void set property(value) {}
      ///    }
      ///    class Class = Super with Mixin;
      ///
      /// Here the parameter type of the setter `Mixin.property` must _not_ be
      /// inferred from the type of the getter `Super.property`, but should
      /// instead default to `dynamic`.
      void registerMixedInOverride(ClassMember mixedInMember,
          {ClassMember aliasForTesting}) {
        assert(mixedInMember.classBuilder != classBuilder,
            "Only mixin members can override by application: ${mixedInMember}");
        if (classBuilder is SourceClassBuilder) {
          hasDeclaredMembers = true;
          if (mixedInMember.isProperty) {
            mixedInProperties ??= [];
            mixedInProperties.add(mixedInMember);
          } else {
            assert(
                mixedInMethod == null,
                "Multiple methods unexpectedly declared in mixin: "
                "${mixedInMethod} and ${mixedInMember}.");
            mixedInMethod = mixedInMember;
          }
          if (dataForTesting != null && aliasForTesting != null) {
            dataForTesting.aliasMap[aliasForTesting] = mixedInMember;
          }
        }
      }

      /// Computes the class and interface members for a method, getter, or
      /// setter in the current [tuple].
      ///
      /// [definingMember] is the member which defines whether the computation
      /// is for a method, a getter or a setter.
      /// [declaredMember] is the member declared in the current class, if any.
      /// [mixedInMember] is the member declared in a mixin that is mixed into
      /// the current current class, if any.
      /// [extendedMember] is the member inherited from the super class.
      /// [implementedMembers] are the members inherited from the super
      /// interfaces, if none this is `null`.
      ///
      /// The computed class and interface members are added to [classMemberMap]
      /// and [interfaceMemberMap], respectively.
      ClassMember computeMembers(
          {ClassMember definingMember,
          ClassMember declaredMember,
          ClassMember mixedInMember,
          ClassMember extendedMember,
          List<ClassMember> implementedMembers,
          Map<Name, ClassMember> classMemberMap,
          Map<Name, ClassMember> interfaceMemberMap}) {
        ClassMember classMember;
        ClassMember interfaceMember;

        if (mixedInMember != null) {
          if (mixedInMember.isAbstract) {
            ///    class Mixin {
            ///      method();
            ///    }
            ///    class Class = Object with Mixin;

            /// Interface members from the extended, mixed in, and implemented
            /// members define the combined member signature.
            Set<ClassMember> interfaceMembers = {};

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method();
              ///    }
              ///    class Class = Super with Mixin;
              interfaceMembers.add(extendedMember.interfaceMember);
            }

            interfaceMembers.add(mixedInMember);

            if (implementedMembers != null) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method();
              ///    }
              ///    class Class = Object with Mixin implements Interface;
              interfaceMembers.addAll(implementedMembers);
            }

            /// We always create a synthesized interface member, even in the
            /// case of [interfaceMembers] being a singleton, to insert the
            /// abstract mixin stub.
            interfaceMember = new SynthesizedInterfaceMember(
                classBuilder, name, interfaceMembers.toList(),
                superClassMember: extendedMember,
                // [definingMember] and [mixedInMember] are always the same
                // here. Use the latter here and the former below to show the
                // the member is canonical _because_ its the mixed in member and
                // it defines the isProperty/forSetter properties _because_ it
                // is the defining member.
                canonicalMember: mixedInMember,
                mixedInMember: mixedInMember,
                isProperty: definingMember.isProperty,
                forSetter: definingMember.forSetter,
                shouldModifyKernel: shouldModifyKernel);
            hierarchy.registerMemberComputation(interfaceMember);

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method();
              ///    }
              ///    class Class = Super with Mixin;
              ///
              /// The concrete extended member is the class member but might
              /// be overwritten by a concrete forwarding stub:
              ///
              ///    class Super {
              ///      method(int i) {}
              ///    }
              ///    class Interface {
              ///      method(covariant int i) {}
              ///    }
              ///    class Mixin {
              ///      method(int i);
              ///    }
              ///    // A concrete forwarding stub
              ///    //   method(covariant int i) => super.method(i);
              ///    // will be inserted.
              ///    class Class = Super with Mixin implements Interface;
              ///
              classMember = new InheritedClassMemberImplementsInterface(
                  classBuilder, name,
                  inheritedClassMember: extendedMember,
                  implementedInterfaceMember: interfaceMember,
                  forSetter: definingMember.forSetter,
                  isProperty: definingMember.isProperty);
              hierarchy.registerMemberComputation(classMember);
              if (!classBuilder.isAbstract) {
                registerInheritedImplements(extendedMember, {interfaceMember},
                    aliasForTesting: classMember);
              }
            } else if (!classBuilder.isAbstract) {
              ///    class Mixin {
              ///      method(); // Missing implementation.
              ///    }
              ///    class Class = Object with Mixin;
              registerAbstractMember(interfaceMember);
            }

            assert(!mixedInMember.isSynthesized);
            if (!mixedInMember.isSynthesized) {
              /// Members declared in the mixin must override extended and
              /// implemented members.
              ///
              /// When loading from .dill the mixed in member might be
              /// synthesized, for instance a member signature or forwarding
              /// stub, and this should not be checked to override the extended
              /// and implemented members:
              ///
              ///    // Opt-out library, from source:
              ///    class Mixin {}
              ///    // Opt-out library, from .dill:
              ///    class Mixin {
              ///      ...
              ///      String* toString(); // member signature
              ///    }
              ///    // Opt-out library, from source:
              ///    class Class = Object with Mixin;
              ///    // Mixin.toString should not be checked to override
              ///    // Object.toString.
              ///
              registerMixedInOverride(mixedInMember,
                  aliasForTesting: interfaceMember);
            }
          } else {
            assert(!mixedInMember.isAbstract);

            ///    class Mixin {
            ///      method() {}
            ///    }
            ///    class Class = Object with Mixin;
            ///

            /// Interface members from the extended, mixed in, and implemented
            /// members define the combined member signature.
            Set<ClassMember> interfaceMembers = {};

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method() {}
              ///    }
              ///    class Class = Super with Mixin;
              interfaceMembers.add(extendedMember.interfaceMember);
            }

            interfaceMembers.add(mixedInMember);

            if (implementedMembers != null) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method() {}
              ///    }
              ///    class Class = Object with Mixin implements Interface;
              interfaceMembers.addAll(implementedMembers);
            }

            /// We always create a synthesized interface member, even in the
            /// case of [interfaceMembers] being a singleton, to insert the
            /// concrete mixin stub.
            interfaceMember = new SynthesizedInterfaceMember(
                classBuilder, name, interfaceMembers.toList(),
                superClassMember: mixedInMember,
                // [definingMember] and [mixedInMember] are always the same
                // here. Use the latter here and the former below to show the
                // the member is canonical _because_ its the mixed in member and
                // it defines the isProperty/forSetter properties _because_ it
                // is the defining member.
                canonicalMember: mixedInMember,
                mixedInMember: mixedInMember,
                isProperty: definingMember.isProperty,
                forSetter: definingMember.forSetter,
                shouldModifyKernel: shouldModifyKernel);
            hierarchy.registerMemberComputation(interfaceMember);

            /// The concrete mixed in member is the class member but will
            /// be overwritten by a concrete mixin stub:
            ///
            ///    class Mixin {
            ///       method() {}
            ///    }
            ///    // A concrete mixin stub
            ///    //   method() => super.method();
            ///    // will be inserted.
            ///    class Class = Object with Mixin;
            ///
            classMember = new InheritedClassMemberImplementsInterface(
                classBuilder, name,
                inheritedClassMember: mixedInMember,
                implementedInterfaceMember: interfaceMember,
                forSetter: definingMember.forSetter,
                isProperty: definingMember.isProperty);
            hierarchy.registerMemberComputation(classMember);

            if (!classBuilder.isAbstract) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method() {}
              ///    }
              ///    class Class = Object with Mixin;
              ///
              /// [mixinMember] must implemented interface member.
              registerInheritedImplements(mixedInMember, {interfaceMember},
                  aliasForTesting: classMember);
            }
            assert(!mixedInMember.isSynthesized);
            if (!mixedInMember.isSynthesized) {
              /// Members declared in the mixin must override extended and
              /// implemented members.
              ///
              /// When loading from .dill the mixed in member might be
              /// synthesized, for instance a member signature or forwarding
              /// stub, and this should not be checked to override the extended
              /// and implemented members.
              ///
              /// These synthesized mixed in members should always be abstract
              /// and therefore not be handled here, but we handled them here
              /// for consistency.
              registerMixedInOverride(mixedInMember);
            }
          }
        } else if (declaredMember != null) {
          if (declaredMember.isAbstract) {
            ///    class Class {
            ///      method();
            ///    }
            interfaceMember = declaredMember;

            /// Interface members from the declared, extended, and implemented
            /// members define the combined member signature.
            Set<ClassMember> interfaceMembers = {};

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Class extends Super {
              ///      method();
              ///    }
              interfaceMembers.add(extendedMember);
            }

            interfaceMembers.add(declaredMember);

            if (implementedMembers != null) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class implements Interface {
              ///      method();
              ///    }
              interfaceMembers.addAll(implementedMembers);
            }

            /// If only one member defines the interface member there is no
            /// need for a synthesized interface member, since its result will
            /// simply be that one member.
            if (interfaceMembers.length > 1) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class extends Super implements Interface {
              ///      method();
              ///    }
              interfaceMember = new SynthesizedInterfaceMember(
                  classBuilder, name, interfaceMembers.toList(),
                  superClassMember: extendedMember,
                  // [definingMember] and [declaredMember] are always the same
                  // here. Use the latter here and the former below to show the
                  // the member is canonical _because_ its the declared member
                  // and it defines the isProperty/forSetter properties
                  // _because_ it is the defining member.
                  canonicalMember: declaredMember,
                  isProperty: definingMember.isProperty,
                  forSetter: definingMember.forSetter,
                  shouldModifyKernel: shouldModifyKernel);
              hierarchy.registerMemberComputation(interfaceMember);
            }

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Class extends Super {
              ///      method();
              ///    }
              ///
              /// The concrete extended member is the class member but might
              /// be overwritten by a concrete forwarding stub:
              ///
              ///    class Super {
              ///      method(int i) {}
              ///    }
              ///    class Interface {
              ///      method(covariant int i) {}
              ///    }
              ///    class Class extends Super implements Interface {
              ///      // This will be turned into the concrete forwarding stub
              ///      //    method(covariant int i) => super.method(i);
              ///      method(int i);
              ///    }
              ///
              classMember = new InheritedClassMemberImplementsInterface(
                  classBuilder, name,
                  inheritedClassMember: extendedMember,
                  implementedInterfaceMember: interfaceMember,
                  forSetter: definingMember.forSetter,
                  isProperty: definingMember.isProperty);
              hierarchy.registerMemberComputation(classMember);

              if (!classBuilder.isAbstract) {
                ///    class Super {
                ///      method() {}
                ///    }
                ///    class Class extends Super {
                ///      method();
                ///    }
                ///
                /// [extendedMember] must implemented interface member.
                registerInheritedImplements(extendedMember, {interfaceMember},
                    aliasForTesting: classMember);
              }
            } else if (!classBuilder.isAbstract) {
              ///    class Class {
              ///      method(); // Missing implementation.
              ///    }
              registerAbstractMember(declaredMember);
            }

            /// The declared member must override extended and implemented
            /// members.
            registerDeclaredOverride(declaredMember,
                aliasForTesting: interfaceMember);
          } else {
            assert(!declaredMember.isAbstract);

            ///    class Class {
            ///      method() {}
            ///    }
            classMember = declaredMember;

            /// The declared member must override extended and implemented
            /// members.
            registerDeclaredOverride(declaredMember);
          }
        } else if (extendedMember != null) {
          ///    class Super {
          ///      method() {}
          ///    }
          ///    class Class extends Super {}
          assert(!extendedMember.isAbstract,
              "Abstract extended member: ${extendedMember}");

          classMember = extendedMember;

          if (implementedMembers != null) {
            ///    class Super {
            ///      method() {}
            ///    }
            ///    class Interface {
            ///      method() {}
            ///    }
            ///    class Class extends Super implements Interface {}
            ClassMember extendedInterfaceMember =
                extendedMember.interfaceMember;

            /// Interface members from the extended and implemented
            /// members define the combined member signature.
            Set<ClassMember> interfaceMembers = {extendedInterfaceMember};

            // TODO(johnniwinther): The extended member might be included in
            // a synthesized implemented member. For instance:
            //
            //    class Super {
            //      void method() {}
            //    }
            //    class Interface {
            //      void method() {}
            //    }
            //    abstract class Class extends Super implements Interface {
            //      // Synthesized interface member of
            //      //   {Super.method, Interface.method}
            //    }
            //    class Sub extends Class {
            //      // Super.method implements Class.method =
            //      //   {Super.method, Interface.method}
            //      // Synthesized interface member of
            //      //   {Super.method, Class.method}
            //    }
            //
            // Maybe we should recognized this.
            interfaceMembers.addAll(implementedMembers);

            /// Normally, if only one member defines the interface member there
            /// is no need for a synthesized interface member, since its result
            /// will simply be that one member, but if the extended member is
            /// from an opt-in library and the current class is from an opt-out
            /// library we need to create a member signature:
            ///
            ///    // Opt-in:
            ///    class Super {
            ///      int? method() => null;
            ///    }
            ///    class Interface implements Super {}
            ///    // Opt-out:
            ///    class Class extends Super implements Interface {
            ///      // Member signature added:
            ///      int* method();
            ///    }
            ///
            if (interfaceMembers.length == 1 &&
                !needsMemberSignatureFor(extendedInterfaceMember)) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface implements Super {}
              ///    class Class extends Super implements Interface {}
              interfaceMember = interfaceMembers.first;
            } else {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class extends Super implements Interface {}
              interfaceMember = new SynthesizedInterfaceMember(
                  classBuilder, name, interfaceMembers.toList(),
                  superClassMember: extendedMember,
                  isProperty: definingMember.isProperty,
                  forSetter: definingMember.forSetter,
                  shouldModifyKernel: shouldModifyKernel);
              hierarchy.registerMemberComputation(interfaceMember);
            }
            if (interfaceMember == classMember) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface implements Super {}
              ///    class Class extends Super implements Interface {}
              ///
              /// We keep track of whether a class needs interfaces, that is,
              /// whether is has any members that have an interface member
              /// different from its corresponding class member, so we set
              /// [interfaceMember] to `null` so show that the interface member
              /// is not needed.
              interfaceMember = null;
            } else {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class extends Super implements Interface {}
              ///
              /// The concrete extended member is the class member but might
              /// be overwritten by a concrete forwarding stub:
              ///
              ///    class Super {
              ///      method(int i) {}
              ///    }
              ///    class Interface {
              ///      method(covariant int i) {}
              ///    }
              ///    class Class extends Super implements Interface {
              ///      // A concrete forwarding stub will be created:
              ///      //    method(covariant int i) => super.method(i);
              ///    }
              ///
              classMember = new InheritedClassMemberImplementsInterface(
                  classBuilder, name,
                  inheritedClassMember: extendedMember,
                  implementedInterfaceMember: interfaceMember,
                  isProperty: definingMember.isProperty,
                  forSetter: definingMember.forSetter);
              hierarchy.registerMemberComputation(classMember);
              if (!classBuilder.isAbstract) {
                ///    class Super {
                ///      method() {}
                ///    }
                ///    class Interface {
                ///      method() {}
                ///    }
                ///    class Class extends Super implements Interface {}
                registerInheritedImplements(extendedMember, {interfaceMember},
                    aliasForTesting: classMember);
              }
            }
          } else if (needsMemberSignatureFor(extendedMember)) {
            ///    // Opt-in library:
            ///    class Super {
            ///      method() {}
            ///    }
            ///    // opt-out library:
            ///    class Class extends Super {}
            interfaceMember = new SynthesizedInterfaceMember(
                classBuilder, name, [extendedMember],
                superClassMember: extendedMember,
                isProperty: definingMember.isProperty,
                forSetter: definingMember.forSetter,
                shouldModifyKernel: shouldModifyKernel);
            hierarchy.registerMemberComputation(interfaceMember);

            /// The concrete extended member is the class member and should
            /// be able to be overwritten by a synthesized concrete member here,
            /// but we handle the case for consistency.
            classMember = new InheritedClassMemberImplementsInterface(
                classBuilder, name,
                inheritedClassMember: extendedMember,
                implementedInterfaceMember: interfaceMember,
                isProperty: definingMember.isProperty,
                forSetter: definingMember.forSetter);
            hierarchy.registerMemberComputation(classMember);
          }
        } else if (implementedMembers != null) {
          ///    class Interface {
          ///      method() {}
          ///    }
          ///    class Class implements Interface {}
          Set<ClassMember> interfaceMembers = implementedMembers.toSet();
          if (interfaceMembers.isNotEmpty) {
            /// Normally, if only one member defines the interface member there
            /// is no need for a synthesized interface member, since its result
            /// will simply be that one member, but if the implemented member is
            /// from an opt-in library and the current class is from an opt-out
            /// library we need to create a member signature:
            ///
            ///    // Opt-in:
            ///    class Interface {
            ///      int? method() => null;
            ///    }
            ///    // Opt-out:
            ///    class Class implements Interface {
            ///      // Member signature added:
            ///      int* method();
            ///    }
            ///
            if (interfaceMembers.length == 1 &&
                !needsMemberSignatureFor(interfaceMembers.first)) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class implements Interface {}
              interfaceMember = interfaceMembers.first;
            } else {
              ///    class Interface1 {
              ///      method() {}
              ///    }
              ///    class Interface2 {
              ///      method() {}
              ///    }
              ///    class Class implements Interface1, Interface2 {}
              interfaceMember = new SynthesizedInterfaceMember(
                  classBuilder, name, interfaceMembers.toList(),
                  isProperty: definingMember.isProperty,
                  forSetter: definingMember.forSetter,
                  shouldModifyKernel: shouldModifyKernel);
              hierarchy.registerMemberComputation(interfaceMember);
            }
            if (!classBuilder.isAbstract) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class implements Interface {}
              for (ClassMember abstractMember in interfaceMembers) {
                registerAbstractMember(abstractMember);
              }
            }
          }
        }

        if (interfaceMember != null) {
          // We have an explicit interface.
          hasInterfaces = true;
        }
        if (classMember != null) {
          if (name == noSuchMethodName &&
              !classMember.isObjectMember(objectClass)) {
            hasNoSuchMethod = true;
          }
          classMemberMap[name] = classMember;
          interfaceMember ??= classMember.interfaceMember;
        }
        if (interfaceMember != null) {
          interfaceMemberMap[name] = interfaceMember;
        }
        return interfaceMember;
      }

      ClassMember interfaceGetable;
      if (definingGetable != null) {
        interfaceGetable = computeMembers(
            definingMember: definingGetable,
            declaredMember: declaredGetable,
            mixedInMember: mixedInGetable,
            extendedMember: extendedGetable,
            implementedMembers: implementedGetables,
            classMemberMap: classMemberMap,
            interfaceMemberMap: interfaceMemberMap);
      }
      ClassMember interfaceSetable;
      if (definingSetable != null) {
        interfaceSetable = computeMembers(
            definingMember: definingSetable,
            declaredMember: declaredSetable,
            mixedInMember: mixedInSetable,
            extendedMember: extendedSetable,
            implementedMembers: implementedSetables,
            classMemberMap: classSetterMap,
            interfaceMemberMap: interfaceSetterMap);
      }
      if (classBuilder is SourceClassBuilder) {
        if (interfaceGetable != null &&
            interfaceSetable != null &&
            interfaceGetable.isProperty &&
            interfaceSetable.isProperty &&
            interfaceGetable.isStatic == interfaceSetable.isStatic &&
            !interfaceGetable.isSameDeclaration(interfaceSetable)) {
          /// We need to check that the getter type is a subtype of the setter
          /// type. For instance
          ///
          ///    class Super {
          ///       int get property1 => null;
          ///       num get property2 => null;
          ///    }
          ///    class Mixin {
          ///       void set property1(num value) {}
          ///       void set property2(int value) {}
          ///    }
          ///    class Class = Super with Mixin;
          ///
          /// Here `Super.property1` and `Mixin.property1` form a valid getter/
          /// setter pair in `Class` because the type of the getter
          /// `Super.property1` is a subtype of the setter `Mixin.property1`.
          ///
          /// In contrast the pair `Super.property2` and `Mixin.property2` is
          /// not a valid getter/setter in `Class` because the type of the getter
          /// `Super.property2` is _not_ a subtype of the setter
          /// `Mixin.property1`.
          hierarchy.registerGetterSetterCheck(
              classBuilder, interfaceGetable, interfaceSetable);
        }
      }
      if (hasDeclaredMembers) {
        Set<ClassMember> getableOverrides = {};
        Set<ClassMember> setableOverrides = {};
        if (extendedGetable != null) {
          ///    (abstract) class Super {
          ///      method() {}
          ///      int get property => 0;
          ///    }
          ///    (abstract) class Class extends Super {
          ///      method() {}
          ///      set property(int value) {}
          ///    }
          getableOverrides.add(extendedGetable.interfaceMember);
        }
        if (extendedSetable != null) {
          ///    (abstract) class Super {
          ///      set setter(int value) {}
          ///      set property(int value) {}
          ///    }
          ///    (abstract) class Class extends Super {
          ///      set setter(int value) {}
          ///      int get property => 0;
          ///    }
          setableOverrides.add(extendedSetable.interfaceMember);
        }
        if (implementedGetables != null) {
          ///    (abstract) class Interface {
          ///      method() {}
          ///      int get property => 0;
          ///    }
          ///    (abstract) class Class implements Interface {
          ///      method() {}
          ///      set property(int value) {}
          ///    }
          getableOverrides.addAll(implementedGetables);
        }
        if (implementedSetables != null) {
          ///    (abstract) class Interface {
          ///      set setter(int value) {}
          ///      set property(int value) {}
          ///    }
          ///    (abstract) class Class implements Interface {
          ///      set setter(int value) {}
          ///      int get property => 0;
          ///    }
          setableOverrides.addAll(implementedSetables);
        }
        if (getableOverrides.isNotEmpty || setableOverrides.isNotEmpty) {
          if (declaredMethod != null && getableOverrides.isNotEmpty) {
            ///    class Super {
            ///      method() {}
            ///    }
            ///    class Class extends Super {
            ///      method() {}
            ///    }
            declaredOverridesMap[declaredMethod] = getableOverrides;
          }
          if (declaredProperties != null) {
            Set<ClassMember> overrides;
            if (declaredMethod != null) {
              ///    class Super {
              ///      set setter() {}
              ///    }
              ///    class Class extends Super {
              ///      method() {}
              ///    }
              overrides = setableOverrides;
            } else {
              ///    class Super {
              ///      get property => null
              ///      void set property(value) {}
              ///    }
              ///    class Class extends Super {
              ///      get property => null
              ///      void set property(value) {}
              ///    }
              overrides = {...getableOverrides, ...setableOverrides};
            }
            if (overrides.isNotEmpty) {
              for (ClassMember declaredMember in declaredProperties) {
                declaredOverridesMap[declaredMember] = overrides;
              }
            }
          }
          if (mixedInMethod != null && getableOverrides.isNotEmpty) {
            ///    class Super {
            ///      method() {}
            ///    }
            ///    class Mixin {
            ///      method() {}
            ///    }
            ///    class Class = Super with Mixin;
            mixinApplicationOverridesMap[mixedInMethod] = getableOverrides;
          }
          if (mixedInProperties != null) {
            Set<ClassMember> overrides;
            if (mixedInMethod != null) {
              ///    class Super {
              ///      set setter() {}
              ///    }
              ///    class Mixin {
              ///      method() {}
              ///    }
              ///    class Class = Super with Mixin;
              overrides = setableOverrides;
            } else {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Mixin extends Super {
              ///      method() {}
              ///    }
              overrides = {...getableOverrides, ...setableOverrides};
            }
            if (overrides.isNotEmpty) {
              for (ClassMember mixedInMember in mixedInProperties) {
                mixinApplicationOverridesMap[mixedInMember] = overrides;
              }
            }
          }
        }
      }
    });

    if (classBuilder is SourceClassBuilder) {
      // TODO(johnniwinther): Avoid duplicate override check computations
      //  between [declaredOverridesMap], [mixinApplicationOverridesMap] and
      //  [inheritedImplementsMap].

      // TODO(johnniwinther): Ensure that a class member is only checked to
      // validly override another member once. Currently it can happen multiple
      // times as an inherited implementation.

      declaredOverridesMap.forEach(
          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
        /// A declared member can inherit its type from the overridden members.
        ///
        /// We register this with the class member itself so the it can force
        /// computation of type on the overridden members before determining its
        /// own type.
        ///
        /// Member types can be queried at arbitrary points during top level
        /// inference so we need to ensure that types are computed in dependency
        /// order.
        classMember.registerOverrideDependency(overriddenMembers);

        /// Not all member type are queried during top level inference so we
        /// register delayed computation to ensure that all types have been
        /// computed before override checks are performed.
        DelayedTypeComputation computation =
            new DelayedTypeComputation(this, classMember, overriddenMembers);
        hierarchy.registerDelayedTypeComputation(computation);

        /// Declared members must be checked to validly override the the
        /// overridden members.
        hierarchy.registerOverrideCheck(
            classBuilder, classMember, overriddenMembers);
      });

      mixinApplicationOverridesMap.forEach(
          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
        /// Declared mixed in members must be checked to validly override the
        /// overridden members.
        hierarchy.registerOverrideCheck(
            classBuilder, classMember, overriddenMembers);
      });

      inheritedImplementsMap.forEach(
          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
        /// Concrete members must be checked to validly override the overridden
        /// members in concrete classes.
        hierarchy.registerOverrideCheck(
            classBuilder, classMember, overriddenMembers);
      });
    }

    if (!hasInterfaces) {
      /// All interface members also class members to we don't need to store
      /// the interface members separately.
      assert(
          classMemberMap.length == interfaceMemberMap.length,
          "Class/interface member mismatch. Class members: "
          "$classMemberMap, interface members: $interfaceMemberMap.");
      assert(
          classSetterMap.length == interfaceSetterMap.length,
          "Class/interface setter mismatch. Class setters: "
          "$classSetterMap, interface setters: $interfaceSetterMap.");
      assert(
          classMemberMap.keys.every((Name name) =>
              identical(classMemberMap[name], interfaceMemberMap[name])),
          "Class/interface member mismatch. Class members: "
          "$classMemberMap, interface members: $interfaceMemberMap.");
      assert(
          classSetterMap.keys.every((Name name) =>
              identical(classSetterMap[name], interfaceSetterMap[name])),
          "Class/interface setter mismatch. Class setters: "
          "$classSetterMap, interface setters: $interfaceSetterMap.");
      interfaceMemberMap = null;
      interfaceSetterMap = null;
    }

    if (abstractMembers != null && !classBuilder.isAbstract) {
      if (!hasNoSuchMethod) {
        reportMissingMembers(abstractMembers);
      } else {
        installNsmHandlers();
      }
    }

    return new ClassHierarchyNode(
        classBuilder,
        classMemberMap,
        classSetterMap,
        interfaceMemberMap,
        interfaceSetterMap,
        superclasses,
        interfaces,
        maxInheritancePath,
        hasNoSuchMethod,
        dataForTesting);
  }

  Supertype recordSupertype(Supertype supertype) {
    debug?.log("In ${this.classBuilder.fullNameForErrors} "
        "recordSupertype(${supertype})");
    Class cls = supertype.classNode;
    List<TypeParameter> supertypeTypeParameters = cls.typeParameters;
    if (supertypeTypeParameters.isEmpty) {
      substitutions[cls] = Substitution.empty;
    } else {
      List<DartType> arguments = supertype.typeArguments;
      List<DartType> typeArguments =
          new List<DartType>.filled(arguments.length, null);
      List<TypeParameter> typeParameters =
          new List<TypeParameter>.filled(arguments.length, null);
      for (int i = 0; i < arguments.length; i++) {
        typeParameters[i] = supertypeTypeParameters[i];
        typeArguments[i] = arguments[i];
      }
      substitutions[cls] =
          Substitution.fromPairs(typeParameters, typeArguments);
    }
    return supertype;
  }

  List<Supertype> substSupertypes(
      Supertype supertype, List<Supertype> supertypes) {
    List<TypeParameter> typeVariables = supertype.classNode.typeParameters;
    if (typeVariables.isEmpty) {
      debug?.log("In ${this.classBuilder.fullNameForErrors} "
          "$supertypes aren't substed");
      return supertypes;
    }
    Map<TypeParameter, DartType> map = <TypeParameter, DartType>{};
    List<DartType> arguments = supertype.typeArguments;
    for (int i = 0; i < typeVariables.length; i++) {
      map[typeVariables[i]] = arguments[i];
    }
    Substitution substitution = Substitution.fromMap(map);
    List<Supertype> result;
    for (int i = 0; i < supertypes.length; i++) {
      Supertype supertype = supertypes[i];
      Supertype substituted = substitution.substituteSupertype(supertype);
      if (supertype != substituted) {
        debug?.log("In ${this.classBuilder.fullNameForErrors} $supertype"
            " -> $substituted");
        result ??= supertypes.toList();
        result[i] = substituted;
      } else {
        debug?.log("In ${this.classBuilder.fullNameForErrors} "
            "$supertype isn't substed");
      }
    }
    return result ?? supertypes;
  }

  void addInterface(List<Supertype> interfaces, List<Supertype> superclasses,
      Supertype type) {
    if (type == null) return null;
    if (!classBuilder.library.isNonNullableByDefault) {
      type = legacyErasureSupertype(type);
    }
    ClassHierarchyNode node = hierarchy.getNodeFromClass(type.classNode);
    if (node == null) return null;
    int depth = node.depth;
    int myDepth = superclasses.length;
    Supertype superclass = depth < myDepth ? superclasses[depth] : null;
    if (superclass != null && superclass.classNode == type.classNode) {
      // This is a potential conflict.
      if (classBuilder.library.isNonNullableByDefault) {
        superclass = nnbdTopMergeSupertype(
            hierarchy.coreTypes,
            normSupertype(hierarchy.coreTypes, superclass),
            normSupertype(hierarchy.coreTypes, type));
        if (superclass == null) {
          // This is a conflict.
          // TODO(johnniwinther): Report errors here instead of through
          // the computation of the [ClassHierarchy].
          superclass = superclasses[depth];
        } else {
          superclasses[depth] = superclass;
        }
      }
      return;
    } else {
      for (int i = 0; i < interfaces.length; i++) {
        // This is a quadratic algorithm, but normally, the number of
        // interfaces is really small.
        Supertype interface = interfaces[i];
        if (interface.classNode == type.classNode) {
          // This is a potential conflict.
          if (classBuilder.library.isNonNullableByDefault) {
            interface = nnbdTopMergeSupertype(
                hierarchy.coreTypes,
                normSupertype(hierarchy.coreTypes, interface),
                normSupertype(hierarchy.coreTypes, type));
            if (interface == null) {
              // This is a conflict.
              // TODO(johnniwinther): Report errors here instead of through
              // the computation of the [ClassHierarchy].
              interface = interfaces[i];
            } else {
              interfaces[i] = interface;
            }
          }
          return;
        }
      }
    }
    interfaces.add(type);
  }

  void reportMissingMembers(List<ClassMember> abstractMembers) {
    Map<String, LocatedMessage> contextMap = <String, LocatedMessage>{};
    for (ClassMember declaration in unfoldDeclarations(abstractMembers)) {
      if (isNameVisibleIn(declaration.name, classBuilder.library)) {
        String name = declaration.fullNameForErrors;
        String className = declaration.classBuilder?.fullNameForErrors;
        String displayName =
            declaration.isSetter ? "$className.$name=" : "$className.$name";
        contextMap[displayName] = templateMissingImplementationCause
            .withArguments(displayName)
            .withLocation(
                declaration.fileUri, declaration.charOffset, name.length);
      }
    }
    if (contextMap.isEmpty) return;
    List<String> names = new List<String>.from(contextMap.keys)..sort();
    List<LocatedMessage> context = <LocatedMessage>[];
    for (int i = 0; i < names.length; i++) {
      context.add(contextMap[names[i]]);
    }
    classBuilder.addProblem(
        templateMissingImplementationNotAbstract.withArguments(
            classBuilder.fullNameForErrors, names),
        classBuilder.charOffset,
        classBuilder.fullNameForErrors.length,
        context: context);
  }

  void installNsmHandlers() {
    // TODO(ahe): Implement this.
  }

  void inferMixinApplication() {
    Class cls = classBuilder.cls;
    Supertype mixedInType = cls.mixedInType;
    if (mixedInType == null) return;
    List<DartType> typeArguments = mixedInType.typeArguments;
    if (typeArguments.isEmpty || typeArguments.first is! UnknownType) return;
    new BuilderMixinInferrer(
            classBuilder,
            hierarchy.coreTypes,
            new TypeBuilderConstraintGatherer(hierarchy,
                mixedInType.classNode.typeParameters, cls.enclosingLibrary))
        .infer(cls);
    List<TypeBuilder> inferredArguments =
        new List<TypeBuilder>.filled(typeArguments.length, null);
    for (int i = 0; i < typeArguments.length; i++) {
      inferredArguments[i] =
          hierarchy.loader.computeTypeBuilder(typeArguments[i]);
    }
    NamedTypeBuilder mixedInTypeBuilder = classBuilder.mixedInTypeBuilder;
    mixedInTypeBuilder.arguments = inferredArguments;
  }

  /// The class Function from dart:core is supposed to be ignored when used as
  /// an interface.
  List<TypeBuilder> ignoreFunction(List<TypeBuilder> interfaces) {
    if (interfaces == null) return null;
    for (int i = 0; i < interfaces.length; i++) {
      ClassBuilder classBuilder = getClass(interfaces[i]);
      if (classBuilder != null && classBuilder.cls == hierarchy.functionClass) {
        if (interfaces.length == 1) {
          return null;
        } else {
          interfaces = interfaces.toList();
          interfaces.removeAt(i);
          return ignoreFunction(interfaces);
        }
      }
    }
    return interfaces;
  }
}

class ClassHierarchyNode {
  /// The class corresponding to this hierarchy node.
  final ClassBuilder classBuilder;

  /// All the members of this class including [classMembers] of its
  /// superclasses. The members are sorted by [compareDeclarations].
  final Map<Name, ClassMember> classMemberMap;

  /// Similar to [classMembers] but for setters.
  final Map<Name, ClassMember> classSetterMap;

  /// All the interface members of this class including [interfaceMembers] of
  /// its supertypes. The members are sorted by [compareDeclarations].
  ///
  /// In addition to the members of [classMembers] this also contains members
  /// from interfaces.
  ///
  /// This may be null, in which case [classMembers] is the interface members.
  final Map<Name, ClassMember> interfaceMemberMap;

  /// Similar to [interfaceMembers] but for setters.
  ///
  /// This may be null, in which case [classSetters] is the interface setters.
  final Map<Name, ClassMember> interfaceSetterMap;

  /// All superclasses of [classBuilder] excluding itself. The classes are
  /// sorted by depth from the root (Object) in ascending order.
  final List<Supertype> superclasses;

  /// The list of all classes implemented by [classBuilder] and its supertypes
  /// excluding any classes from [superclasses].
  final List<Supertype> interfaces;

  /// The longest inheritance path from [classBuilder] to `Object`.
  final int maxInheritancePath;

  int get depth => superclasses.length;

  final bool hasNoSuchMethod;

  final ClassHierarchyNodeDataForTesting dataForTesting;

  ClassHierarchyNode(
      this.classBuilder,
      this.classMemberMap,
      this.classSetterMap,
      this.interfaceMemberMap,
      this.interfaceSetterMap,
      this.superclasses,
      this.interfaces,
      this.maxInheritancePath,
      this.hasNoSuchMethod,
      this.dataForTesting);

  /// Returns a list of all supertypes of [classBuilder], including this node.
  List<ClassHierarchyNode> computeAllSuperNodes(
      ClassHierarchyBuilder hierarchy) {
    List<ClassHierarchyNode> result = new List<ClassHierarchyNode>.filled(
        1 + superclasses.length + interfaces.length, null);
    for (int i = 0; i < superclasses.length; i++) {
      Supertype type = superclasses[i];
      result[i] = hierarchy.getNodeFromClass(type.classNode);
    }
    for (int i = 0; i < interfaces.length; i++) {
      Supertype type = interfaces[i];
      result[i + superclasses.length] =
          hierarchy.getNodeFromClass(type.classNode);
    }
    return result..last = this;
  }

  String toString() {
    StringBuffer sb = new StringBuffer();
    sb
      ..write(classBuilder.fullNameForErrors)
      ..writeln(":");
    if (maxInheritancePath != this.depth) {
      sb
        ..write("  Longest path to Object: ")
        ..writeln(maxInheritancePath);
    }
    sb..writeln("  superclasses:");
    int depth = 0;
    for (Supertype superclass in superclasses) {
      sb.write("  " * (depth + 2));
      if (depth != 0) sb.write("-> ");
      sb.write(typeToText(superclass.asInterfaceType));
      sb.writeln();
      depth++;
    }
    if (interfaces != null) {
      sb.write("  interfaces:");
      bool first = true;
      for (Supertype i in interfaces) {
        if (!first) sb.write(",");
        sb.write(" ");
        sb.write(typeToText(i.asInterfaceType));
        first = false;
      }
      sb.writeln();
    }
    printMemberMap(classMemberMap, sb, "classMembers");
    printMemberMap(classSetterMap, sb, "classSetters");
    if (interfaceMemberMap != null) {
      printMemberMap(interfaceMemberMap, sb, "interfaceMembers");
    }
    if (interfaceSetterMap != null) {
      printMemberMap(interfaceSetterMap, sb, "interfaceSetters");
    }
    return "$sb";
  }

  void printMembers(
      List<ClassMember> members, StringBuffer sb, String heading) {
    sb.write("  ");
    sb.write(heading);
    sb.writeln(":");
    for (ClassMember member in members) {
      sb
        ..write("    ")
        ..write(member.classBuilder.fullNameForErrors)
        ..write(".")
        ..write(member.fullNameForErrors)
        ..writeln();
    }
  }

  void printMemberMap(
      Map<Name, ClassMember> memberMap, StringBuffer sb, String heading) {
    List<ClassMember> members = memberMap.values.toList();
    members.sort(compareDeclarations);
    printMembers(members, sb, heading);
  }

  ClassMember getInterfaceMember(Name name, bool isSetter) {
    return isSetter
        ? (interfaceSetterMap ?? classSetterMap)[name]
        : (interfaceMemberMap ?? classMemberMap)[name];
  }

  ClassMember findMember(Name name, List<ClassMember> declarations) {
    // TODO(ahe): Consider creating a map or scope. The obvious choice would be
    // to use scopes, but they don't handle private names correctly.

    // This is a copy of `ClassHierarchy.findMemberByName`.
    int low = 0, high = declarations.length - 1;
    while (low <= high) {
      int mid = low + ((high - low) >> 1);
      ClassMember pivot = declarations[mid];
      int comparison = ClassHierarchy.compareNames(name, pivot.name);
      if (comparison < 0) {
        high = mid - 1;
      } else if (comparison > 0) {
        low = mid + 1;
      } else if (high != mid) {
        // Ensure we find the first element of the given name.
        high = mid;
      } else {
        return pivot;
      }
    }
    return null;
  }

  ClassMember getDispatchTarget(Name name, bool isSetter) {
    return isSetter ? classSetterMap[name] : classMemberMap[name];
  }

  static int compareMaxInheritancePath(
      ClassHierarchyNode a, ClassHierarchyNode b) {
    return b.maxInheritancePath.compareTo(a.maxInheritancePath);
  }
}

class ClassHierarchyNodeDataForTesting {
  final List<ClassMember> abstractMembers;
  final Map<ClassMember, Set<ClassMember>> declaredOverrides;
  final Map<ClassMember, Set<ClassMember>> mixinApplicationOverrides;
  final Map<ClassMember, Set<ClassMember>> inheritedImplements;
  final Map<ClassMember, ClassMember> aliasMap = {};

  ClassHierarchyNodeDataForTesting(this.abstractMembers, this.declaredOverrides,
      this.mixinApplicationOverrides, this.inheritedImplements);
}

List<LocatedMessage> _inheritedConflictContext(ClassMember a, ClassMember b) {
  int length = a.fullNameForErrors.length;
  // TODO(ahe): Delete this method when it isn't used by [InterfaceResolver].
  int compare = "${a.fileUri}".compareTo("${b.fileUri}");
  if (compare == 0) {
    compare = a.charOffset.compareTo(b.charOffset);
  }
  ClassMember first;
  ClassMember second;
  if (compare < 0) {
    first = a;
    second = b;
  } else {
    first = b;
    second = a;
  }
  return <LocatedMessage>[
    messageInheritedMembersConflictCause1.withLocation(
        first.fileUri, first.charOffset, length),
    messageInheritedMembersConflictCause2.withLocation(
        second.fileUri, second.charOffset, length),
  ];
}

class BuilderMixinInferrer extends MixinInferrer {
  final ClassBuilder cls;

  BuilderMixinInferrer(
      this.cls, CoreTypes coreTypes, TypeBuilderConstraintGatherer gatherer)
      : super(coreTypes, gatherer);

  Supertype asInstantiationOf(Supertype type, Class superclass) {
    List<DartType> arguments =
        gatherer.getTypeArgumentsAsInstanceOf(type.asInterfaceType, superclass);
    if (arguments == null) return null;
    return new Supertype(superclass, arguments);
  }

  void reportProblem(Message message, Class kernelClass) {
    int length = cls.isMixinApplication ? 1 : cls.fullNameForErrors.length;
    cls.addProblem(message, cls.charOffset, length);
  }
}

class TypeBuilderConstraintGatherer extends TypeConstraintGatherer
    with StandardBounds, TypeSchemaStandardBounds {
  final ClassHierarchyBuilder hierarchy;

  TypeBuilderConstraintGatherer(this.hierarchy,
      Iterable<TypeParameter> typeParameters, Library currentLibrary)
      : super.subclassing(typeParameters, currentLibrary);

  @override
  CoreTypes get coreTypes => hierarchy.coreTypes;

  @override
  void addLowerBound(
      TypeConstraint constraint, DartType lower, Library clientLibrary) {
    constraint.lower =
        getStandardUpperBound(constraint.lower, lower, clientLibrary);
  }

  @override
  void addUpperBound(
      TypeConstraint constraint, DartType upper, Library clientLibrary) {
    constraint.upper =
        getStandardLowerBound(constraint.upper, upper, clientLibrary);
  }

  @override
  Member getInterfaceMember(Class class_, Name name, {bool setter: false}) {
    return null;
  }

  @override
  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
      Library clientLibrary, CoreTypes coreTypes) {
    return hierarchy.getTypeAsInstanceOf(type, superclass, clientLibrary);
  }

  @override
  List<DartType> getTypeArgumentsAsInstanceOf(
      InterfaceType type, Class superclass) {
    return hierarchy.getTypeArgumentsAsInstanceOf(type, superclass);
  }

  @override
  InterfaceType futureType(DartType type, Nullability nullability) {
    return new InterfaceType(
        hierarchy.futureClass, nullability, <DartType>[type]);
  }

  @override
  bool isSubtypeOf(
      DartType subtype, DartType supertype, SubtypeCheckMode mode) {
    return hierarchy.types.isSubtypeOf(subtype, supertype, mode);
  }

  @override
  bool areMutualSubtypes(DartType s, DartType t, SubtypeCheckMode mode) {
    return isSubtypeOf(s, t, mode) && isSubtypeOf(t, s, mode);
  }
}

abstract class DelayedCheck {
  void check(ClassHierarchyBuilder hierarchy);
}

class DelayedOverrideCheck implements DelayedCheck {
  final SourceClassBuilder _classBuilder;
  final ClassMember _declaredMember;
  final Set<ClassMember> _overriddenMembers;

  DelayedOverrideCheck(
      this._classBuilder, this._declaredMember, this._overriddenMembers);

  void check(ClassHierarchyBuilder hierarchy) {
    Member declaredMember = _declaredMember.getMember(hierarchy);

    /// If [_declaredMember] is a class member that is declared in an opt-in
    /// library but inherited to [_classBuilder] through an opt-out class then
    /// we need to apply legacy erasure to the declared type to get the
    /// inherited type.
    ///
    /// For interface members this is handled by member signatures but since
    /// these are abstract they will never be the inherited class member.
    ///
    /// For instance:
    ///
    ///    // Opt in:
    ///    class Super {
    ///      int extendedMethod(int i, {required int j}) => i;
    ///    }
    ///    class Mixin {
    ///      int mixedInMethod(int i, {required int j}) => i;
    ///    }
    ///    // Opt out:
    ///    class Legacy extends Super with Mixin {}
    ///    // Opt in:
    ///    class Class extends Legacy {
    ///      // Valid overrides since the type of `Legacy.extendedMethod` is
    ///      // `int* Function(int*, {int* j})`.
    ///      int? extendedMethod(int? i, {int? j}) => i;
    ///      // Valid overrides since the type of `Legacy.mixedInMethod` is
    ///      // `int* Function(int*, {int* j})`.
    ///      int? mixedInMethod(int? i, {int? j}) => i;
    ///    }
    ///
    bool declaredNeedsLegacyErasure =
        needsLegacyErasure(_classBuilder.cls, declaredMember.enclosingClass);
    void callback(Member interfaceMember, bool isSetter) {
      _classBuilder.checkOverride(
          hierarchy.types, declaredMember, interfaceMember, isSetter, callback,
          isInterfaceCheck: !_classBuilder.isMixinApplication,
          declaredNeedsLegacyErasure: declaredNeedsLegacyErasure);
    }

    for (ClassMember overriddenMember in _overriddenMembers) {
      callback(overriddenMember.getMember(hierarchy), _declaredMember.isSetter);
    }
  }
}

class DelayedGetterSetterCheck implements DelayedCheck {
  final SourceClassBuilder classBuilder;
  final ClassMember getter;
  final ClassMember setter;

  const DelayedGetterSetterCheck(this.classBuilder, this.getter, this.setter);

  void check(ClassHierarchyBuilder hierarchy) {
    classBuilder.checkGetterSetter(hierarchy.types, getter.getMember(hierarchy),
        setter.getMember(hierarchy));
  }
}

class DelayedTypeComputation {
  final ClassHierarchyNodeBuilder builder;
  final ClassMember declaredMember;
  final Set<ClassMember> overriddenMembers;
  bool _computed = false;

  DelayedTypeComputation(
      this.builder, this.declaredMember, this.overriddenMembers)
      : assert(declaredMember.isSourceDeclaration);

  void compute(ClassHierarchyBuilder hierarchy) {
    if (_computed) return;
    declaredMember.inferType(hierarchy);
    _computed = true;
    if (declaredMember.isField) {
      builder.inferFieldSignature(hierarchy, declaredMember, overriddenMembers);
    } else if (declaredMember.isGetter) {
      builder.inferGetterSignature(
          hierarchy, declaredMember, overriddenMembers);
    } else if (declaredMember.isSetter) {
      builder.inferSetterSignature(
          hierarchy, declaredMember, overriddenMembers);
    } else {
      builder.inferMethodSignature(
          hierarchy, declaredMember, overriddenMembers);
    }
  }

  @override
  String toString() => 'DelayedTypeComputation('
      '${builder.classBuilder.name},$declaredMember,$overriddenMembers)';
}

int compareNamedParameters(VariableDeclaration a, VariableDeclaration b) {
  return a.name.compareTo(b.name);
}

void reportCantInferParameterType(
    ClassBuilder cls,
    FormalParameterBuilder parameter,
    ClassHierarchyBuilder hierarchy,
    Iterable<ClassMember> overriddenMembers) {
  String name = parameter.name;
  List<LocatedMessage> context = overriddenMembers
      .map((ClassMember overriddenMember) {
        return messageDeclaredMemberConflictsWithOverriddenMembersCause
            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                overriddenMember.fullNameForErrors.length);
      })
      // Call toSet to avoid duplicate context for instance of fields that are
      // overridden both as getters and setters.
      .toSet()
      .toList();
  cls.addProblem(
      templateCantInferTypeDueToNoCombinedSignature.withArguments(name),
      parameter.charOffset,
      name.length,
      wasHandled: true,
      context: context);
}

void reportCantInferTypes(ClassBuilder cls, SourceProcedureBuilder member,
    ClassHierarchyBuilder hierarchy, Iterable<ClassMember> overriddenMembers) {
  String name = member.fullNameForErrors;
  List<LocatedMessage> context = overriddenMembers
      .map((ClassMember overriddenMember) {
        return messageDeclaredMemberConflictsWithOverriddenMembersCause
            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                overriddenMember.fullNameForErrors.length);
      })
      // Call toSet to avoid duplicate context for instance of fields that are
      // overridden both as getters and setters.
      .toSet()
      .toList();
  cls.addProblem(
      templateCantInferTypesDueToNoCombinedSignature.withArguments(name),
      member.charOffset,
      name.length,
      wasHandled: true,
      context: context);
}

void reportCantInferReturnType(ClassBuilder cls, SourceProcedureBuilder member,
    ClassHierarchyBuilder hierarchy, Iterable<ClassMember> overriddenMembers) {
  String name = member.fullNameForErrors;
  List<LocatedMessage> context = overriddenMembers
      .map((ClassMember overriddenMember) {
        return messageDeclaredMemberConflictsWithOverriddenMembersCause
            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                overriddenMember.fullNameForErrors.length);
      })
      // Call toSet to avoid duplicate context for instance of fields that are
      // overridden both as getters and setters.
      .toSet()
      .toList();
  // // TODO(ahe): The following is for debugging, but could be cleaned up and
  // // used to improve this error message in general.
  //
  // context = <LocatedMessage>[];
  // ClassHierarchyNode supernode = hierarchy.getNodeFromType(cls.supertype);
  // // TODO(ahe): Wrong template.
  // Template<Message Function(String)> template =
  //     templateMissingImplementationCause;
  // if (supernode != null) {
  //   Declaration superMember =
  //       supernode.getInterfaceMember(new Name(name), false);
  //   if (superMember != null) {
  //     context.add(template
  //         .withArguments(name)
  //         .withLocation(
  //             superMember.fileUri, superMember.charOffset, name.length));
  //   }
  //   superMember = supernode.getInterfaceMember(new Name(name), true);
  //   if (superMember != null) {
  //     context.add(template
  //         .withArguments(name)
  //         .withLocation(
  //             superMember.fileUri, superMember.charOffset, name.length));
  //   }
  // }
  // List<TypeBuilder> directInterfaces = cls.interfaces;
  // for (int i = 0; i < directInterfaces.length; i++) {
  //   ClassHierarchyNode supernode =
  //       hierarchy.getNodeFromType(directInterfaces[i]);
  //   if (supernode != null) {
  //     Declaration superMember =
  //         supernode.getInterfaceMember(new Name(name), false);
  //     if (superMember != null) {
  //       context.add(template
  //           .withArguments(name)
  //           .withLocation(
  //               superMember.fileUri, superMember.charOffset, name.length));
  //     }
  //     superMember = supernode.getInterfaceMember(new Name(name), true);
  //     if (superMember != null) {
  //       context.add(template
  //           .withArguments(name)
  //           .withLocation(
  //               superMember.fileUri, superMember.charOffset, name.length));
  //     }
  //   }
  // }
  cls.addProblem(
      templateCantInferReturnTypeDueToNoCombinedSignature.withArguments(name),
      member.charOffset,
      name.length,
      wasHandled: true,
      context: context);
}

void reportCantInferFieldType(ClassBuilder cls, SourceFieldBuilder member,
    Iterable<ClassMember> overriddenMembers) {
  List<LocatedMessage> context = overriddenMembers
      .map((ClassMember overriddenMember) {
        return messageDeclaredMemberConflictsWithOverriddenMembersCause
            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                overriddenMember.fullNameForErrors.length);
      })
      // Call toSet to avoid duplicate context for instance of fields that are
      // overridden both as getters and setters.
      .toSet()
      .toList();
  String name = member.fullNameForErrors;
  cls.addProblem(
      templateCantInferTypeDueToNoCombinedSignature.withArguments(name),
      member.charOffset,
      name.length,
      wasHandled: true,
      context: context);
}

ClassBuilder getClass(TypeBuilder type) {
  Builder declaration = type.declaration;
  if (declaration is TypeAliasBuilder) {
    TypeAliasBuilder aliasBuilder = declaration;
    NamedTypeBuilder namedBuilder = type;
    declaration = aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
  }
  return declaration is ClassBuilder ? declaration : null;
}

Set<ClassMember> toSet(
    ClassBuilder classBuilder, Iterable<ClassMember> members) {
  Set<ClassMember> result = <ClassMember>{};
  _toSet(classBuilder, members, result);
  return result;
}

void _toSet(ClassBuilder classBuilder, Iterable<ClassMember> members,
    Set<ClassMember> result) {
  for (ClassMember member in members) {
    if (member.hasDeclarations && classBuilder == member.classBuilder) {
      _toSet(classBuilder, member.declarations, result);
    } else {
      result.add(member);
    }
  }
}

Set<ClassMember> unfoldDeclarations(Iterable<ClassMember> members) {
  Set<ClassMember> result = <ClassMember>{};
  _unfoldDeclarations(members, result);
  return result;
}

void _unfoldDeclarations(
    Iterable<ClassMember> members, Set<ClassMember> result) {
  for (ClassMember member in members) {
    if (member.hasDeclarations) {
      _unfoldDeclarations(member.declarations, result);
    } else {
      result.add(member);
    }
  }
}

abstract class SynthesizedMember extends ClassMember {
  @override
  final ClassBuilder classBuilder;

  @override
  final Name name;

  @override
  final bool forSetter;

  @override
  final bool isProperty;

  SynthesizedMember(this.classBuilder, this.name,
      {this.forSetter, this.isProperty})
      : assert(forSetter != null),
        assert(isProperty != null);

  @override
  List<ClassMember> get declarations => throw new UnimplementedError();

  @override
  void inferType(ClassHierarchyBuilder hierarchy) {}

  @override
  bool get isAssignable => throw new UnimplementedError();

  @override
  bool get isConst => throw new UnimplementedError();

  @override
  bool get isDuplicate => false;

  @override
  bool get isField => throw new UnimplementedError();

  @override
  bool get isFinal => throw new UnimplementedError();

  @override
  bool get isGetter => throw new UnimplementedError();

  @override
  bool get isInternalImplementation => false;

  @override
  bool get isSetter => forSetter;

  @override
  bool get isSourceDeclaration => false;

  @override
  bool get isStatic => false;

  @override
  bool get isSynthesized => true;

  @override
  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {}
}

/// Class member for a set of interface members.
///
/// This is used to compute combined member signature of a set of interface
/// members inherited into the same class, and to insert forwarding stubs,
/// mixin stubs, and member signatures where needed.
class SynthesizedInterfaceMember extends SynthesizedMember {
  @override
  final List<ClassMember> declarations;

  /// The concrete member in the super class overridden by [declarations], if
  /// any.
  ///
  /// This is used to as the target when creating concrete forwarding and mixin
  /// stub. For instance:
  ///
  ///    class Super {
  ///      method(int i) {}
  ///    }
  ///    class Interface {
  ///      method(covariant int i) {}
  ///    }
  ///    class Class extends Super implements Interface {
  ///      // Concrete forwarding stub calling [_superClassMember]:
  ///      method(covariant int i) => super.method(i);
  ///
  final ClassMember _superClassMember;

  /// The canonical member of the combined member signature if it is known by
  /// construction. The canonical member defines the type of combined member
  /// signature.
  ///
  /// This is used when a declared member is part of a set of implemented
  /// members. For instance
  ///
  ///     class Super {
  ///       method(int i) {}
  ///     }
  ///     class Interface {
  ///       method(covariant num i) {}
  ///     }
  ///     class Class implements Interface {
  ///       // This member is updated to be a concrete forwarding stub with an
  ///       // covariant parameter but with its declared parameter type:
  ///       //    method(covariant int i) => super.method(i);
  ///       method(int i);
  ///     }
  final ClassMember _canonicalMember;

  /// The member in [declarations] that is mixed in, if any.
  ///
  /// This is used to create mixin stubs. If the mixed in member is abstract,
  /// an abstract mixin stub is created:
  ///
  ///    class Super {
  ///      void method() {}
  ///    }
  ///    class Mixin {
  ///      void method();
  ///    }
  ///    // Abstract mixin stub with `Mixin.method` as target inserted:
  ///    //   void method();
  ///    class Class = Super with Mixin;
  ///
  /// If the mixed in member is concrete, a concrete mixin member is created:
  ///
  ///    class Super {
  ///      void method() {}
  ///    }
  ///    class Mixin {
  ///      void method() {}
  ///    }
  ///    // Concrete mixin stub with `Mixin.method` as target inserted:
  ///    //   void method() => super.method();
  ///    class Class = Super with Mixin;
  ///
  /// If a forwarding stub is needed, the created stub will be a possibly
  /// concrete forwarding stub:
  ///
  ///    class Super {
  ///      void method(int i) {}
  ///    }
  ///    class Interface {
  ///      void method(covariant num i) {}
  ///    }
  ///    class Mixin {
  ///      void method(int i);
  ///    }
  ///    // Concrete forwarding stub with `Super.method` as target inserted:
  ///    //   void method(covariant int i) => super.method(i);
  ///    class Class = Super with Mixin implements Interface;
  ///
  final ClassMember _mixedInMember;

  /// If `true`, a stub should be inserted, if needed.
  final bool _shouldModifyKernel;

  Member _member;
  Covariance _covariance;

  SynthesizedInterfaceMember(
      ClassBuilder classBuilder, Name name, this.declarations,
      {ClassMember superClassMember,
      ClassMember canonicalMember,
      ClassMember mixedInMember,
      bool isProperty,
      bool forSetter,
      bool shouldModifyKernel})
      : this._superClassMember = superClassMember,
        this._canonicalMember = canonicalMember,
        this._mixedInMember = mixedInMember,
        this._shouldModifyKernel = shouldModifyKernel,
        super(classBuilder, name, isProperty: isProperty, forSetter: forSetter);

  @override
  bool get hasDeclarations => true;

  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
    if (_member != null) {
      return;
    }
    if (classBuilder.library is! SourceLibraryBuilder) {
      if (_canonicalMember != null) {
        _member = _canonicalMember.getMember(hierarchy);
        _covariance = _canonicalMember.getCovariance(hierarchy);
      } else {
        _member = declarations.first.getMember(hierarchy);
        _covariance = declarations.first.getCovariance(hierarchy);
      }
      return;
    }
    CombinedClassMemberSignature combinedMemberSignature;
    if (_canonicalMember != null) {
      combinedMemberSignature = new CombinedClassMemberSignature.internal(
          hierarchy,
          classBuilder,
          declarations.indexOf(_canonicalMember),
          declarations,
          forSetter: isSetter);
    } else {
      combinedMemberSignature = new CombinedClassMemberSignature(
          hierarchy, classBuilder, declarations,
          forSetter: isSetter);

      if (combinedMemberSignature.canonicalMember == null) {
        String name = classBuilder.fullNameForErrors;
        int length = classBuilder.isAnonymousMixinApplication ? 1 : name.length;
        List<LocatedMessage> context = declarations.map((ClassMember d) {
          return messageDeclaredMemberConflictsWithOverriddenMembersCause
              .withLocation(
                  d.fileUri, d.charOffset, d.fullNameForErrors.length);
        }).toList();

        classBuilder.addProblem(
            templateCombinedMemberSignatureFailed.withArguments(
                classBuilder.fullNameForErrors,
                declarations.first.fullNameForErrors),
            classBuilder.charOffset,
            length,
            context: context);
        // TODO(johnniwinther): Maybe we should have an invalid marker to avoid
        // cascading errors.
        _member = declarations.first.getMember(hierarchy);
        _covariance = declarations.first.getCovariance(hierarchy);
        return;
      }
    }

    if (_shouldModifyKernel) {
      ProcedureKind kind = ProcedureKind.Method;
      Member canonicalMember =
          combinedMemberSignature.canonicalMember.getMember(hierarchy);
      if (combinedMemberSignature.canonicalMember.isProperty) {
        kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
      } else if (canonicalMember is Procedure &&
          canonicalMember.kind == ProcedureKind.Operator) {
        kind = ProcedureKind.Operator;
      }

      Procedure stub = new ForwardingNode(
              combinedMemberSignature, kind, _superClassMember, _mixedInMember)
          .finalize();
      if (stub != null) {
        assert(classBuilder.cls == stub.enclosingClass);
        assert(stub != canonicalMember);
        classBuilder.cls.addProcedure(stub);
        SourceLibraryBuilder library = classBuilder.library;
        if (canonicalMember is Procedure) {
          library.forwardersOrigins..add(stub)..add(canonicalMember);
        }
        _member = stub;
        _covariance = combinedMemberSignature.combinedMemberSignatureCovariance;
        assert(
            _covariance ==
                new Covariance.fromMember(_member, forSetter: forSetter),
            "Unexpected covariance for combined members signature "
            "$_member. Found $_covariance, expected "
            "${new Covariance.fromMember(_member, forSetter: forSetter)}.");
        return;
      }
    }

    _member = combinedMemberSignature.canonicalMember.getMember(hierarchy);
    _covariance = combinedMemberSignature.combinedMemberSignatureCovariance;
  }

  @override
  Member getMember(ClassHierarchyBuilder hierarchy) {
    _ensureMemberAndCovariance(hierarchy);
    return _member;
  }

  @override
  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
    _ensureMemberAndCovariance(hierarchy);
    return _covariance;
  }

  @override
  ClassMember get interfaceMember => this;

  @override
  bool isObjectMember(ClassBuilder objectClass) {
    return false;
  }

  @override
  bool isSameDeclaration(ClassMember other) {
    // TODO(johnniwinther): Optimize this.
    return false;
  }

  @override
  int get charOffset => declarations.first.charOffset;

  @override
  Uri get fileUri => declarations.first.fileUri;

  @override
  bool get isAbstract => true;

  @override
  String get fullNameForErrors =>
      declarations.map((ClassMember m) => m.fullName).join("%");

  @override
  String get fullName {
    String suffix = isSetter ? "=" : "";
    return "${fullNameForErrors}$suffix";
  }

  String toString() => 'SynthesizedInterfaceMember($classBuilder,$name,'
      '$declarations,forSetter=$forSetter)';
}

/// Class member for an inherited concrete member that implements an interface
/// member.
///
/// This is used to ensure that both the inherited concrete member and the
/// interface member is taken into account when computing the resulting [Member]
/// node.
///
/// This is needed because an interface member, though initially abstract, can
/// result in a concrete stub that overrides the concrete member. For instance
///
///    class Super {
///      method(int i) {}
///    }
///    class Interface {
///      method(covariant int i) {}
///    }
///    class Class extends Super implements Interface {
///      // A concrete forwarding stub is inserted:
///      method(covariant int i) => super.method(i);
///    }
///    class Sub extends Class implements Interface {
///      // No forwarding stub should be inserted since `Class.method` is
///      // adequate.
///    }
///
///
///  Here the create stub `Class.method` overrides `Super.method` and should
///  be used to determine whether to insert a forwarding stub in subclasses.
class InheritedClassMemberImplementsInterface extends SynthesizedMember {
  final ClassMember inheritedClassMember;
  final ClassMember implementedInterfaceMember;

  Member _member;
  Covariance _covariance;

  InheritedClassMemberImplementsInterface(ClassBuilder classBuilder, Name name,
      {this.inheritedClassMember,
      this.implementedInterfaceMember,
      bool isProperty,
      bool forSetter})
      : assert(inheritedClassMember != null),
        assert(implementedInterfaceMember != null),
        super(classBuilder, name, isProperty: isProperty, forSetter: forSetter);

  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
    if (_member == null) {
      Member classMember = inheritedClassMember.getMember(hierarchy);
      Member interfaceMember = implementedInterfaceMember.getMember(hierarchy);
      if (!interfaceMember.isAbstract &&
          interfaceMember.enclosingClass == classBuilder.cls) {
        /// The interface member resulted in a concrete stub being inserted.
        /// For instance for `method1` but _not_ for `method2` here:
        ///
        ///    class Super {
        ///      method1(int i) {}
        ///      method2(covariant int i) {}
        ///    }
        ///    class Interface {
        ///      method1(covariant int i) {}
        ///      method2(int i) {}
        ///    }
        ///    class Class extends Super implements Interface {
        ///      // A concrete forwarding stub is inserted for `method1` since
        ///      // the parameter on `Super.method1` is _not_ marked as
        ///      // covariant:
        ///      method1(covariant int i) => super.method(i);
        ///      // No concrete forwarding stub is inserted for `method2` since
        ///      // the parameter on `Super.method2` is already marked as
        ///      // covariant.
        ///    }
        ///
        /// The inserted stub should be used as the resulting member.
        _member = interfaceMember;
        _covariance = implementedInterfaceMember.getCovariance(hierarchy);
      } else {
        /// The interface member did not result in an inserted stub or the
        /// inserted stub was abstract. For instance:
        ///
        ///    // Opt-in:
        ///    class Super {
        ///      method(int? i) {}
        ///    }
        ///    // Opt-out:
        ///    class Class extends Super {
        ///      // An abstract member signature stub is inserted:
        ///      method(int* i);
        ///    }
        ///
        /// The inserted stub should _not_ be used as the resulting member
        /// since it is abstract and therefore not a class member.
        _member = classMember;
        _covariance = inheritedClassMember.getCovariance(hierarchy);
      }
    }
  }

  @override
  Member getMember(ClassHierarchyBuilder hierarchy) {
    _ensureMemberAndCovariance(hierarchy);
    return _member;
  }

  @override
  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
    _ensureMemberAndCovariance(hierarchy);
    return _covariance;
  }

  @override
  ClassMember get interfaceMember => implementedInterfaceMember;

  @override
  bool isObjectMember(ClassBuilder objectClass) {
    return inheritedClassMember.isObjectMember(objectClass);
  }

  @override
  bool isSameDeclaration(ClassMember other) {
    // TODO(johnniwinther): Optimize this.
    return false;
  }

  @override
  int get charOffset => inheritedClassMember.charOffset;

  @override
  Uri get fileUri => inheritedClassMember.fileUri;

  @override
  bool get hasDeclarations => false;

  @override
  bool get isAbstract => false;

  @override
  String get fullNameForErrors => inheritedClassMember.fullNameForErrors;

  String get fullName => inheritedClassMember.fullName;

  @override
  String toString() =>
      'InheritedClassMemberImplementsInterface($classBuilder,$name,'
      'inheritedClassMember=$inheritedClassMember,'
      'implementedInterfaceMember=$implementedInterfaceMember,'
      'forSetter=$forSetter)';
}
