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

library fasta.kernel_library_builder;

import 'dart:convert' show JSON;

import 'package:kernel/ast.dart';

import '../../scanner/token.dart' show Token;

import '../export.dart' show Export;

import '../fasta_codes.dart'
    show
        Message,
        messageConflictsWithTypeVariableCause,
        messageTypeVariableDuplicatedName,
        messageTypeVariableSameNameAsEnclosing,
        templateConflictsWithTypeVariable,
        templateDuplicatedExport,
        templateDuplicatedExportInType,
        templateDuplicatedImport,
        templateDuplicatedImportInType,
        templateExportHidesExport,
        templateImportHidesImport,
        templateLoadLibraryHidesMember,
        templateLocalDefinitionHidesExport,
        templateLocalDefinitionHidesImport,
        templatePatchInjectionFailed,
        templateTypeVariableDuplicatedNameCause;

import '../import.dart' show Import;

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

import '../modifier.dart'
    show abstractMask, namedMixinApplicationMask, staticMask;

import '../parser.dart' show noLength;

import '../problems.dart' show unhandled;

import '../source/source_class_builder.dart' show SourceClassBuilder;

import '../source/source_library_builder.dart'
    show DeclarationBuilder, SourceLibraryBuilder;

import 'kernel_builder.dart'
    show
        AccessErrorBuilder,
        Builder,
        BuiltinTypeBuilder,
        ClassBuilder,
        ConstructorReferenceBuilder,
        FormalParameterBuilder,
        InvalidTypeBuilder,
        KernelClassBuilder,
        KernelConstructorBuilder,
        KernelEnumBuilder,
        KernelFieldBuilder,
        KernelFormalParameterBuilder,
        KernelFunctionBuilder,
        KernelFunctionTypeAliasBuilder,
        KernelFunctionTypeBuilder,
        KernelInvalidTypeBuilder,
        KernelMixinApplicationBuilder,
        KernelNamedTypeBuilder,
        KernelProcedureBuilder,
        KernelRedirectingFactoryBuilder,
        KernelTypeBuilder,
        KernelTypeVariableBuilder,
        LibraryBuilder,
        LoadLibraryBuilder,
        MemberBuilder,
        MetadataBuilder,
        NamedTypeBuilder,
        PrefixBuilder,
        ProcedureBuilder,
        Scope,
        TypeBuilder,
        TypeVariableBuilder,
        UnresolvedType,
        VoidTypeBuilder,
        compareProcedures,
        toKernelCombinators;

import 'metadata_collector.dart';

import 'type_algorithms.dart' show calculateBounds;

class KernelLibraryBuilder
    extends SourceLibraryBuilder<KernelTypeBuilder, Library> {
  final Library library;

  final KernelLibraryBuilder actualOrigin;

  final Map<String, SourceClassBuilder> mixinApplicationClasses =
      <String, SourceClassBuilder>{};

  final List<KernelFunctionBuilder> nativeMethods = <KernelFunctionBuilder>[];

  final List<KernelTypeVariableBuilder> boundlessTypeVariables =
      <KernelTypeVariableBuilder>[];

  /// Exports that can't be serialized.
  ///
  /// The key is the name of the exported member.
  ///
  /// If the name is `dynamic` or `void`, this library reexports the
  /// corresponding type from `dart:core`, and the value is null.
  ///
  /// Otherwise, this represents an error (an ambiguous export). In this case,
  /// the error message is the corresponding value in the map.
  Map<String, String> unserializableExports;

  KernelLibraryBuilder(Uri uri, Uri fileUri, Loader loader, this.actualOrigin)
      : library = actualOrigin?.library ?? new Library(uri, fileUri: fileUri),
        super(loader, fileUri);

  @override
  KernelLibraryBuilder get origin => actualOrigin ?? this;

  @override
  Library get target => library;

  Uri get uri => library.importUri;

  KernelTypeBuilder addNamedType(
      Object name, List<KernelTypeBuilder> arguments, int charOffset) {
    return addType(new KernelNamedTypeBuilder(name, arguments), charOffset);
  }

  KernelTypeBuilder addMixinApplication(KernelTypeBuilder supertype,
      List<KernelTypeBuilder> mixins, int charOffset) {
    return addType(
        new KernelMixinApplicationBuilder(supertype, mixins), charOffset);
  }

  KernelTypeBuilder addVoidType(int charOffset) {
    return addNamedType("void", null, charOffset)
      ..bind(new VoidTypeBuilder(const VoidType(), this, charOffset));
  }

  void addClass(
      String documentationComment,
      List<MetadataBuilder> metadata,
      int modifiers,
      String className,
      List<TypeVariableBuilder> typeVariables,
      KernelTypeBuilder supertype,
      List<KernelTypeBuilder> interfaces,
      int charOffset,
      int charEndOffset,
      int supertypeOffset) {
    // Nested declaration began in `OutlineBuilder.beginClassDeclaration`.
    var declaration = endNestedDeclaration(className)
      ..resolveTypes(typeVariables, this);
    assert(declaration.parent == libraryDeclaration);
    Map<String, MemberBuilder> members = declaration.members;
    Map<String, MemberBuilder> constructors = declaration.constructors;
    Map<String, MemberBuilder> setters = declaration.setters;

    Scope classScope = new Scope(members, setters,
        scope.withTypeVariables(typeVariables), "class $className",
        isModifiable: false);

    // When looking up a constructor, we don't consider type variables or the
    // library scope.
    Scope constructorScope = new Scope(constructors, null, null, "constructors",
        isModifiable: false);
    ClassBuilder cls = new SourceClassBuilder(
        metadata,
        modifiers,
        className,
        typeVariables,
        applyMixins(supertype, supertypeOffset,
            isSyntheticMixinImplementation: true,
            subclassName: className,
            typeVariables: typeVariables),
        interfaces,
        classScope,
        constructorScope,
        this,
        new List<ConstructorReferenceBuilder>.from(constructorReferences),
        charOffset,
        charEndOffset);
    loader.target.metadataCollector
        ?.setDocumentationComment(cls.target, documentationComment);

    constructorReferences.clear();
    Map<String, TypeVariableBuilder> typeVariablesByName =
        checkTypeVariables(typeVariables, cls);
    void setParent(String name, MemberBuilder member) {
      while (member != null) {
        member.parent = cls;
        member = member.next;
      }
    }

    void setParentAndCheckConflicts(String name, MemberBuilder member) {
      if (typeVariablesByName != null) {
        TypeVariableBuilder tv = typeVariablesByName[name];
        if (tv != null) {
          cls.addCompileTimeError(
              templateConflictsWithTypeVariable.withArguments(name),
              member.charOffset,
              name.length,
              context: messageConflictsWithTypeVariableCause.withLocation(
                  tv.fileUri, tv.charOffset, name.length));
        }
      }
      setParent(name, member);
    }

    members.forEach(setParentAndCheckConflicts);
    constructors.forEach(setParentAndCheckConflicts);
    // Formally, a setter has the name `id=`, so it can never conflict with a
    // type variable.
    setters.forEach(setParent);
    addBuilder(className, cls, charOffset);
  }

  Map<String, TypeVariableBuilder> checkTypeVariables(
      List<TypeVariableBuilder> typeVariables, Builder owner) {
    if (typeVariables?.isEmpty ?? true) return null;
    Map<String, TypeVariableBuilder> typeVariablesByName =
        <String, TypeVariableBuilder>{};
    for (TypeVariableBuilder tv in typeVariables) {
      TypeVariableBuilder existing = typeVariablesByName[tv.name];
      if (existing != null) {
        addCompileTimeError(messageTypeVariableDuplicatedName, tv.charOffset,
            tv.name.length, fileUri,
            context: templateTypeVariableDuplicatedNameCause
                .withArguments(tv.name)
                .withLocation(
                    fileUri, existing.charOffset, existing.name.length));
      } else {
        typeVariablesByName[tv.name] = tv;
        if (owner is ClassBuilder) {
          // Only classes and type variables can't have the same name. See
          // [#29555](https://github.com/dart-lang/sdk/issues/29555).
          if (tv.name == owner.name) {
            addCompileTimeError(messageTypeVariableSameNameAsEnclosing,
                tv.charOffset, tv.name.length, fileUri);
          }
        }
      }
    }
    return typeVariablesByName;
  }

  KernelTypeBuilder applyMixin(
      KernelTypeBuilder supertype, KernelTypeBuilder mixin, String signature,
      {String documentationComment,
      List<MetadataBuilder> metadata,
      bool isSyntheticMixinImplementation: false,
      String name,
      List<TypeVariableBuilder> typeVariables,
      int modifiers: abstractMask,
      List<KernelTypeBuilder> interfaces,
      int charOffset: -1}) {
    var constructors = <String, MemberBuilder>{};
    bool isNamed = name != null;
    SourceClassBuilder builder;
    if (isNamed) {
      modifiers |= namedMixinApplicationMask;
    } else {
      name = "${supertype.name}";
      int index = name.indexOf("^");
      if (index != -1) {
        name = name.substring(0, index);
      }
      name = "_$name&${mixin.name}$signature";
      builder = mixinApplicationClasses[name];
    }
    if (builder == null) {
      builder = new SourceClassBuilder(
          metadata,
          modifiers,
          name,
          typeVariables,
          supertype,
          interfaces,
          new Scope(<String, MemberBuilder>{}, <String, MemberBuilder>{},
              scope.withTypeVariables(typeVariables),
              "mixin $name", isModifiable: false),
          new Scope(constructors, null, null, "constructors",
              isModifiable: false),
          this,
          <ConstructorReferenceBuilder>[],
          charOffset,
          TreeNode.noOffset,
          null,
          mixin);
      loader.target.metadataCollector
          ?.setDocumentationComment(builder.target, documentationComment);
      builder.cls.isSyntheticMixinImplementation =
          isSyntheticMixinImplementation;
      addBuilder(name, builder, charOffset);
      if (!isNamed) {
        mixinApplicationClasses[name] = builder;
      }
    }
    return addNamedType(name, <KernelTypeBuilder>[], charOffset)
      ..bind(isNamed ? builder : null);
  }

  KernelTypeBuilder applyMixins(KernelTypeBuilder type, int charOffset,
      {String documentationComment,
      List<MetadataBuilder> metadata,
      bool isSyntheticMixinImplementation: false,
      String name,
      String subclassName,
      List<TypeVariableBuilder> typeVariables,
      int modifiers: abstractMask,
      List<KernelTypeBuilder> interfaces}) {
    if (type is KernelMixinApplicationBuilder) {
      subclassName ??= name;
      List<List<String>> signatureParts = <List<String>>[];
      Map<String, String> unresolved = <String, String>{};
      Map<String, String> unresolvedReversed = <String, String>{};
      int unresolvedCount = 0;
      Map<String, TypeBuilder> freeTypes = <String, TypeBuilder>{};

      if (name == null || type.mixins.length != 1) {
        TypeBuilder last = type.mixins.last;

        /// Compute a signature of the type arguments used by the supertype and
        /// mixins. These types are free variables. At this point we can't
        /// trust that the number of type arguments match the type parameters,
        /// so we also need to be able to detect missing type arguments.  To do
        /// so, we separate each list of type arguments by `^` and type
        /// arguments by `&`. For example, the mixin `C<S> with M<T, U>` would
        /// look like this:
        ///
        ///     ^#U0^#U1&#U2
        ///
        /// Where `#U0`, `#U1`, and `#U2` are the free variables arising from
        /// `S`, `T`, and `U` respectively.
        ///
        /// As we can resolve any type parameters used at this point, those are
        /// named `#T0` and so forth. This reduces the number of free variables
        /// which is crucial for memory usage and the Dart VM's bootstrap
        /// sequence.
        ///
        /// For example, consider this use of mixin applications:
        ///
        ///     class _InternalLinkedHashMap<K, V> extends _HashVMBase
        ///         with
        ///             MapMixin<K, V>,
        ///             _LinkedHashMapMixin<K, V>,
        ///             _HashBase,
        ///             _OperatorEqualsAndHashCode {}
        ///
        /// In this case, only two variables are free, and we produce this
        /// signature: `^^#T0&#T1^#T0&#T1^^`. Assume another class uses the
        /// sames mixins but with missing type arguments for `MapMixin`, its
        /// signature would be: `^^^#T0&#T1^^`.
        ///
        /// Note that we do not need to compute a signature for a named mixin
        /// application with only one mixin as we don't have to invent a name
        /// for any classes in this situation.
        void analyzeArguments(TypeBuilder type) {
          if (name != null && type == last) {
            // The last mixin of a named mixin application doesn't contribute
            // to free variables.
            return;
          }
          if (type is NamedTypeBuilder) {
            List<String> part = <String>[];
            for (int i = 0; i < (type.arguments?.length ?? 0); i++) {
              var argument = type.arguments[i];
              String name;
              if (argument is NamedTypeBuilder) {
                if (argument.builder != null) {
                  int index = typeVariables?.indexOf(argument.builder) ?? -1;
                  if (index != -1) {
                    name = "#T${index}";
                  }
                } else if (argument.arguments == null) {
                  name = unresolved["${argument.name}"] ??=
                      "#U${unresolvedCount++}";
                }
              }
              name ??= "#U${unresolvedCount++}";
              unresolvedReversed[name] = "${argument.name}";
              freeTypes[name] = argument;
              part.add(name);
              type.arguments[i] = new KernelNamedTypeBuilder(name, null);
            }
            signatureParts.add(part);
          }
        }

        analyzeArguments(type.supertype);
        type.mixins.forEach(analyzeArguments);
      }
      KernelTypeBuilder supertype = type.supertype;
      List<List<String>> currentSignatureParts = <List<String>>[];
      int currentSignatureCount = 0;
      String computeSignature() {
        if (freeTypes.isEmpty) return "";
        currentSignatureParts.add(signatureParts[currentSignatureCount++]);
        if (currentSignatureParts.any((l) => l.isNotEmpty)) {
          return "^${currentSignatureParts.map((l) => l.join('&')).join('^')}";
        } else {
          return "";
        }
      }

      Map<String, TypeVariableBuilder> computeTypeVariables() {
        Map<String, TypeVariableBuilder> variables =
            <String, TypeVariableBuilder>{};
        for (List<String> strings in currentSignatureParts) {
          for (String name in strings) {
            variables[name] ??= addTypeVariable(name, null, -1);
          }
        }
        return variables;
      }

      checkArguments(t) {
        for (var argument in t.arguments ?? const []) {
          if (argument.builder == null && argument.name.startsWith("#")) {
            throw "No builder on ${argument.name}";
          }
        }
      }

      computeSignature(); // This combines the supertype with the first mixin.
      for (int i = 0; i < type.mixins.length - 1; i++) {
        Set<String> supertypeArguments = new Set<String>();
        for (var part in currentSignatureParts) {
          supertypeArguments.addAll(part);
        }
        String signature = computeSignature();
        var variables = computeTypeVariables();
        if (supertypeArguments.isNotEmpty) {
          supertype = addNamedType(
              supertype.name,
              supertypeArguments
                  .map((n) => addNamedType(n, null, -1)..bind(variables[n]))
                  .toList(),
              -1);
        }
        KernelNamedTypeBuilder mixin = type.mixins[i];
        for (var type in mixin.arguments ?? const []) {
          type.bind(variables[type.name]);
        }
        checkArguments(supertype);
        checkArguments(mixin);
        supertype = applyMixin(supertype, mixin, signature,
            isSyntheticMixinImplementation: true,
            typeVariables: new List<TypeVariableBuilder>.from(variables.values),
            // TODO(ahe): Eventually, the charOffset should be -1 as these
            // classes are canonicalized and synthetic. For now, for the
            // benefit of dart2js, we add offsets to help the compiler during
            // the migration process. We add i because dart2js uses these
            // numbers to sort the classes by. Adding i isn't precisely what
            // dart2js does, but it should be good enough.
            charOffset: charOffset + i);
      }
      KernelNamedTypeBuilder mixin = type.mixins.last;

      Set<String> supertypeArguments = new Set<String>();
      for (var part in currentSignatureParts) {
        supertypeArguments.addAll(part);
      }
      String signature = name == null ? computeSignature() : "";
      var variables;
      if (name == null) {
        variables = computeTypeVariables();
        typeVariables = new List<TypeVariableBuilder>.from(variables.values);
        if (supertypeArguments.isNotEmpty) {
          supertype = addNamedType(
              supertype.name,
              supertypeArguments
                  .map((n) => addNamedType(n, null, -1)..bind(variables[n]))
                  .toList(),
              -1);
        }
      } else {
        if (supertypeArguments.isNotEmpty) {
          supertype = addNamedType(supertype.name,
              supertypeArguments.map((n) => freeTypes[n]).toList(), -1);
        }
      }

      if (name == null) {
        for (var type in mixin.arguments ?? const []) {
          type.bind(variables[type.name]);
        }
      }
      checkArguments(supertype);
      checkArguments(mixin);

      KernelNamedTypeBuilder t = applyMixin(supertype, mixin, signature,
          documentationComment: documentationComment,
          metadata: metadata,
          name: name,
          isSyntheticMixinImplementation: isSyntheticMixinImplementation,
          typeVariables: typeVariables,
          modifiers: modifiers,
          interfaces: interfaces,
          charOffset: charOffset);
      if (name == null) {
        var builder = t.builder;
        t = addNamedType(
            t.name, freeTypes.keys.map((k) => freeTypes[k]).toList(), -1);
        if (builder != null) {
          t.bind(builder);
        }
      }
      return t;
    } else {
      return type;
    }
  }

  void addNamedMixinApplication(
      String documentationComment,
      List<MetadataBuilder> metadata,
      String name,
      List<TypeVariableBuilder> typeVariables,
      int modifiers,
      KernelTypeBuilder mixinApplication,
      List<KernelTypeBuilder> interfaces,
      int charOffset) {
    // Nested declaration began in `OutlineBuilder.beginNamedMixinApplication`.
    endNestedDeclaration(name).resolveTypes(typeVariables, this);
    KernelNamedTypeBuilder supertype = applyMixins(mixinApplication, charOffset,
        documentationComment: documentationComment,
        metadata: metadata,
        name: name,
        typeVariables: typeVariables,
        modifiers: modifiers,
        interfaces: interfaces);
    checkTypeVariables(typeVariables, supertype.builder);
  }

  @override
  void addField(
      String documentationComment,
      List<MetadataBuilder> metadata,
      int modifiers,
      KernelTypeBuilder type,
      String name,
      int charOffset,
      Token initializerTokenForInference,
      bool hasInitializer) {
    var builder = new KernelFieldBuilder(metadata, type, name, modifiers, this,
        charOffset, initializerTokenForInference, hasInitializer);
    addBuilder(name, builder, charOffset);
    loader.target.metadataCollector
        ?.setDocumentationComment(builder.target, documentationComment);
  }

  void addConstructor(
      String documentationComment,
      List<MetadataBuilder> metadata,
      int modifiers,
      KernelTypeBuilder returnType,
      final Object name,
      String constructorName,
      List<TypeVariableBuilder> typeVariables,
      List<FormalParameterBuilder> formals,
      int charOffset,
      int charOpenParenOffset,
      int charEndOffset,
      String nativeMethodName) {
    MetadataCollector metadataCollector = loader.target.metadataCollector;
    ProcedureBuilder procedure = new KernelConstructorBuilder(
        metadata,
        modifiers & ~abstractMask,
        returnType,
        constructorName,
        typeVariables,
        formals,
        this,
        charOffset,
        charOpenParenOffset,
        charEndOffset,
        nativeMethodName);
    metadataCollector?.setDocumentationComment(
        procedure.target, documentationComment);
    metadataCollector?.setConstructorNameOffset(procedure.target, name);
    checkTypeVariables(typeVariables, procedure);
    addBuilder(constructorName, procedure, charOffset);
    if (nativeMethodName != null) {
      addNativeMethod(procedure);
    }
  }

  void addProcedure(
      String documentationComment,
      List<MetadataBuilder> metadata,
      int modifiers,
      KernelTypeBuilder returnType,
      String name,
      List<TypeVariableBuilder> typeVariables,
      List<FormalParameterBuilder> formals,
      ProcedureKind kind,
      int charOffset,
      int charOpenParenOffset,
      int charEndOffset,
      String nativeMethodName,
      {bool isTopLevel}) {
    MetadataCollector metadataCollector = loader.target.metadataCollector;
    ProcedureBuilder procedure = new KernelProcedureBuilder(
        metadata,
        modifiers,
        returnType,
        name,
        typeVariables,
        formals,
        kind,
        this,
        charOffset,
        charOpenParenOffset,
        charEndOffset,
        nativeMethodName);
    metadataCollector?.setDocumentationComment(
        procedure.target, documentationComment);
    checkTypeVariables(typeVariables, procedure);
    addBuilder(name, procedure, charOffset);
    if (nativeMethodName != null) {
      addNativeMethod(procedure);
    }
  }

  void addFactoryMethod(
      String documentationComment,
      List<MetadataBuilder> metadata,
      int modifiers,
      ConstructorReferenceBuilder constructorNameReference,
      List<FormalParameterBuilder> formals,
      ConstructorReferenceBuilder redirectionTarget,
      int charOffset,
      int charOpenParenOffset,
      int charEndOffset,
      String nativeMethodName) {
    KernelTypeBuilder returnType = addNamedType(
        currentDeclaration.parent.name, <KernelTypeBuilder>[], charOffset);
    // Nested declaration began in `OutlineBuilder.beginFactoryMethod`.
    DeclarationBuilder<KernelTypeBuilder> factoryDeclaration =
        endNestedDeclaration("#factory_method");
    Object name = constructorNameReference.name;

    // Prepare the simple procedure name.
    String procedureName;
    String constructorName =
        computeAndValidateConstructorName(name, charOffset);
    if (constructorName != null) {
      procedureName = constructorName;
    } else {
      procedureName = name;
    }

    assert(constructorNameReference.suffix == null);
    KernelProcedureBuilder procedure;
    if (redirectionTarget != null) {
      procedure = new KernelRedirectingFactoryBuilder(
          metadata,
          staticMask | modifiers,
          returnType,
          procedureName,
          copyTypeVariables(
              currentDeclaration.typeVariables ?? <TypeVariableBuilder>[],
              factoryDeclaration),
          formals,
          this,
          charOffset,
          charOpenParenOffset,
          charEndOffset,
          nativeMethodName,
          redirectionTarget);
    } else {
      procedure = new KernelProcedureBuilder(
          metadata,
          staticMask | modifiers,
          returnType,
          procedureName,
          copyTypeVariables(
              currentDeclaration.typeVariables ?? <TypeVariableBuilder>[],
              factoryDeclaration),
          formals,
          ProcedureKind.Factory,
          this,
          charOffset,
          charOpenParenOffset,
          charEndOffset,
          nativeMethodName);
    }

    var metadataCollector = loader.target.metadataCollector;
    metadataCollector?.setDocumentationComment(
        procedure.target, documentationComment);
    metadataCollector?.setConstructorNameOffset(procedure.target, name);

    DeclarationBuilder<TypeBuilder> savedDeclaration = currentDeclaration;
    currentDeclaration = factoryDeclaration;
    for (TypeVariableBuilder tv in procedure.typeVariables) {
      KernelNamedTypeBuilder t = procedure.returnType;
      t.arguments.add(addNamedType(tv.name, null, procedure.charOffset));
    }
    currentDeclaration = savedDeclaration;

    factoryDeclaration.resolveTypes(procedure.typeVariables, this);
    addBuilder(procedureName, procedure, charOffset);
    if (nativeMethodName != null) {
      addNativeMethod(procedure);
    }
  }

  void addEnum(
      String documentationComment,
      List<MetadataBuilder> metadata,
      String name,
      List<Object> constantNamesAndOffsets,
      int charOffset,
      int charEndOffset) {
    MetadataCollector metadataCollector = loader.target.metadataCollector;
    KernelEnumBuilder builder = new KernelEnumBuilder(
        metadataCollector,
        metadata,
        name,
        constantNamesAndOffsets,
        this,
        charOffset,
        charEndOffset);
    addBuilder(name, builder, charOffset);
    metadataCollector?.setDocumentationComment(
        builder.target, documentationComment);
  }

  void addFunctionTypeAlias(
      String documentationComment,
      List<MetadataBuilder> metadata,
      String name,
      List<TypeVariableBuilder> typeVariables,
      covariant KernelFunctionTypeBuilder type,
      int charOffset) {
    KernelFunctionTypeAliasBuilder typedef = new KernelFunctionTypeAliasBuilder(
        metadata, name, typeVariables, type, this, charOffset);
    loader.target.metadataCollector
        ?.setDocumentationComment(typedef.target, documentationComment);
    checkTypeVariables(typeVariables, typedef);
    // Nested declaration began in `OutlineBuilder.beginFunctionTypeAlias`.
    endNestedDeclaration("#typedef").resolveTypes(typeVariables, this);
    addBuilder(name, typedef, charOffset);
  }

  KernelFunctionTypeBuilder addFunctionType(
      KernelTypeBuilder returnType,
      List<TypeVariableBuilder> typeVariables,
      List<FormalParameterBuilder> formals,
      int charOffset) {
    var builder =
        new KernelFunctionTypeBuilder(returnType, typeVariables, formals);
    checkTypeVariables(typeVariables, null);
    // Nested declaration began in `OutlineBuilder.beginFunctionType` or
    // `OutlineBuilder.beginFunctionTypedFormalParameter`.
    endNestedDeclaration("#function_type").resolveTypes(typeVariables, this);
    return addType(builder, charOffset);
  }

  KernelFormalParameterBuilder addFormalParameter(
      List<MetadataBuilder> metadata,
      int modifiers,
      KernelTypeBuilder type,
      String name,
      bool hasThis,
      int charOffset) {
    return new KernelFormalParameterBuilder(
        metadata, modifiers, type, name, hasThis, this, charOffset);
  }

  KernelTypeVariableBuilder addTypeVariable(
      String name, KernelTypeBuilder bound, int charOffset) {
    var builder = new KernelTypeVariableBuilder(name, this, charOffset, bound);
    boundlessTypeVariables.add(builder);
    return builder;
  }

  @override
  void buildBuilder(Builder builder, LibraryBuilder coreLibrary) {
    Class cls;
    Member member;
    Typedef typedef;
    if (builder is SourceClassBuilder) {
      cls = builder.build(this, coreLibrary);
    } else if (builder is KernelFieldBuilder) {
      member = builder.build(this)..isStatic = true;
    } else if (builder is KernelProcedureBuilder) {
      member = builder.build(this)..isStatic = true;
    } else if (builder is KernelFunctionTypeAliasBuilder) {
      typedef = builder.build(this);
    } else if (builder is KernelEnumBuilder) {
      cls = builder.build(this, coreLibrary);
    } else if (builder is PrefixBuilder) {
      // Ignored. Kernel doesn't represent prefixes.
      return;
    } else if (builder is BuiltinTypeBuilder) {
      // Nothing needed.
      return;
    } else {
      unhandled("${builder.runtimeType}", "buildBuilder", builder.charOffset,
          builder.fileUri);
      return;
    }
    if (builder.isPatch) {
      // The kernel node of a patch is shared with the origin builder. We have
      // two builders: the origin, and the patch, but only one kernel node
      // (which corresponds to the final output). Consequently, the node
      // shouldn't be added to its apparent kernel parent as this would create
      // a duplicate entry in the parent's list of children/members.
      return;
    }
    if (cls != null) {
      library.addClass(cls);
    } else if (member != null) {
      library.addMember(member);
    } else if (typedef != null) {
      library.addTypedef(typedef);
    }
  }

  void addNativeDependency(Uri nativeImportUri) {
    Builder constructor = loader.getNativeAnnotation();
    Arguments arguments =
        new Arguments(<Expression>[new StringLiteral("$nativeImportUri")]);
    Expression annotation;
    if (constructor.isConstructor) {
      annotation = new ConstructorInvocation(constructor.target, arguments)
        ..isConst = true;
    } else {
      annotation = new StaticInvocation(constructor.target, arguments)
        ..isConst = true;
    }
    library.addAnnotation(annotation);
  }

  void addDependencies(Library library, Set<KernelLibraryBuilder> seen) {
    if (!seen.add(this)) {
      return;
    }

    // Merge import and export lists to have the dependencies in source order.
    // This is required for the DietListener to correctly match up metadata.
    int importIndex = 0;
    int exportIndex = 0;
    while (importIndex < imports.length || exportIndex < exports.length) {
      if (exportIndex >= exports.length ||
          (importIndex < imports.length &&
              imports[importIndex].charOffset <
                  exports[exportIndex].charOffset)) {
        // Add import
        Import import = imports[importIndex++];

        // Rather than add a LibraryDependency, we attach an annotation.
        if (import.nativeImportUri != null) {
          addNativeDependency(import.nativeImportUri);
          continue;
        }

        if (import.deferred && import.prefixBuilder?.dependency != null) {
          library.addDependency(import.prefixBuilder.dependency);
        } else {
          library.addDependency(new LibraryDependency.import(
              import.imported.target,
              name: import.prefix,
              combinators: toKernelCombinators(import.combinators))
            ..fileOffset = import.charOffset);
        }
      } else {
        // Add export
        Export export = exports[exportIndex++];
        library.addDependency(new LibraryDependency.export(
            export.exported.target,
            combinators: toKernelCombinators(export.combinators))
          ..fileOffset = export.charOffset);
      }
    }

    for (KernelLibraryBuilder part in parts) {
      library.addPart(new LibraryPart(<Expression>[], part.fileUri));
      part.addDependencies(library, seen);
    }
  }

  @override
  Library build(LibraryBuilder coreLibrary) {
    super.build(coreLibrary);

    addDependencies(library, new Set<KernelLibraryBuilder>());

    loader.target.metadataCollector
        ?.setDocumentationComment(library, documentationComment);
    library.name = name;
    library.procedures.sort(compareProcedures);

    if (unserializableExports != null) {
      library.addMember(new Field(new Name("_exports#", library),
          initializer: new StringLiteral(JSON.encode(unserializableExports)),
          isStatic: true,
          isConst: true));
    }

    return library;
  }

  @override
  Builder buildAmbiguousBuilder(
      String name, Builder builder, Builder other, int charOffset,
      {bool isExport: false, bool isImport: false}) {
    // TODO(ahe): Can I move this to Scope or Prefix?
    if (builder == other) return builder;
    if (builder is InvalidTypeBuilder) return builder;
    if (other is InvalidTypeBuilder) return other;
    if (builder is AccessErrorBuilder) {
      AccessErrorBuilder error = builder;
      builder = error.builder;
    }
    if (other is AccessErrorBuilder) {
      AccessErrorBuilder error = other;
      other = error.builder;
    }
    bool isLocal = false;
    bool isLoadLibrary = false;
    Builder preferred;
    Uri uri;
    Uri otherUri;
    Uri preferredUri;
    Uri hiddenUri;
    if (scope.local[name] == builder) {
      isLocal = true;
      preferred = builder;
      hiddenUri = other.computeLibraryUri();
    } else {
      uri = builder.computeLibraryUri();
      otherUri = other.computeLibraryUri();
      if (builder is LoadLibraryBuilder) {
        isLoadLibrary = true;
        preferred = builder;
        preferredUri = otherUri;
      } else if (other is LoadLibraryBuilder) {
        isLoadLibrary = true;
        preferred = other;
        preferredUri = uri;
      } else if (otherUri?.scheme == "dart" && uri?.scheme != "dart") {
        preferred = builder;
        preferredUri = uri;
        hiddenUri = otherUri;
      } else if (uri?.scheme == "dart" && otherUri?.scheme != "dart") {
        preferred = other;
        preferredUri = otherUri;
        hiddenUri = uri;
      }
    }
    if (preferred != null) {
      if (isLocal) {
        var template = isExport
            ? templateLocalDefinitionHidesExport
            : templateLocalDefinitionHidesImport;
        addProblem(template.withArguments(name, hiddenUri), charOffset,
            noLength, fileUri);
      } else if (isLoadLibrary) {
        addProblem(templateLoadLibraryHidesMember.withArguments(preferredUri),
            charOffset, noLength, fileUri);
      } else {
        var template =
            isExport ? templateExportHidesExport : templateImportHidesImport;
        addProblem(template.withArguments(name, preferredUri, hiddenUri),
            charOffset, noLength, fileUri);
      }
      return preferred;
    }
    if (builder.next == null && other.next == null) {
      if (isImport && builder is PrefixBuilder && other is PrefixBuilder) {
        // Handles the case where the same prefix is used for different
        // imports.
        return builder
          ..exportScope.merge(other.exportScope,
              (String name, Builder existing, Builder member) {
            return buildAmbiguousBuilder(name, existing, member, charOffset,
                isExport: isExport, isImport: isImport);
          });
      }
    }
    var template =
        isExport ? templateDuplicatedExport : templateDuplicatedImport;
    Message message = template.withArguments(name, uri, otherUri);
    addProblem(message, charOffset, noLength, fileUri);
    var builderTemplate = isExport
        ? templateDuplicatedExportInType
        : templateDuplicatedImportInType;
    return new KernelInvalidTypeBuilder(name, charOffset, fileUri,
        builderTemplate.withArguments(name, uri, otherUri));
  }

  int finishDeferredLoadTearoffs() {
    int total = 0;
    for (var import in imports) {
      if (import.deferred) {
        Procedure tearoff = import.prefixBuilder.loadLibraryBuilder.tearoff;
        if (tearoff != null) library.addMember(tearoff);
        total++;
      }
    }
    return total;
  }

  void addNativeMethod(KernelFunctionBuilder method) {
    nativeMethods.add(method);
  }

  int finishNativeMethods() {
    for (KernelFunctionBuilder method in nativeMethods) {
      method.becomeNative(loader);
    }
    return nativeMethods.length;
  }

  List<TypeVariableBuilder> copyTypeVariables(
      List<TypeVariableBuilder> original, DeclarationBuilder declaration) {
    List<TypeBuilder> newTypes = <TypeBuilder>[];
    List<TypeVariableBuilder> copy = <TypeVariableBuilder>[];
    for (KernelTypeVariableBuilder variable in original) {
      var newVariable = new KernelTypeVariableBuilder(variable.name, this,
          variable.charOffset, variable.bound?.clone(newTypes));
      copy.add(newVariable);
      boundlessTypeVariables.add(newVariable);
    }
    for (TypeBuilder newType in newTypes) {
      declaration.addType(new UnresolvedType(newType, -1, null));
    }
    return copy;
  }

  int finishTypeVariables(ClassBuilder object) {
    int count = boundlessTypeVariables.length;
    for (KernelTypeVariableBuilder builder in boundlessTypeVariables) {
      builder.finish(this, object);
    }
    boundlessTypeVariables.clear();
    return count;
  }

  int instantiateToBound(TypeBuilder dynamicType, ClassBuilder objectClass) {
    int count = 0;

    for (var declarationBuilder in libraryDeclaration.members.values) {
      if (declarationBuilder is KernelClassBuilder) {
        if (declarationBuilder.typeVariables != null) {
          declarationBuilder.calculatedBounds = calculateBounds(
              declarationBuilder.typeVariables, dynamicType, objectClass);
          count += declarationBuilder.calculatedBounds.length;
        }
      } else if (declarationBuilder is KernelFunctionTypeAliasBuilder) {
        if (declarationBuilder.typeVariables != null) {
          declarationBuilder.calculatedBounds = calculateBounds(
              declarationBuilder.typeVariables, dynamicType, objectClass);
          count += declarationBuilder.calculatedBounds.length;
        }
      }
    }

    return count;
  }

  @override
  void includePart(covariant KernelLibraryBuilder part) {
    part.mixinApplicationClasses
        .forEach((String name, SourceClassBuilder builder) {
      SourceClassBuilder existing =
          mixinApplicationClasses.putIfAbsent(name, () => builder);
      if (existing != builder) {
        part.scope.local.remove(name);
      }
    });
    super.includePart(part);
    nativeMethods.addAll(part.nativeMethods);
    boundlessTypeVariables.addAll(part.boundlessTypeVariables);
  }

  @override
  void addImportsToScope() {
    super.addImportsToScope();
    exportScope.forEach((String name, Builder member) {
      if (member.parent != this) {
        switch (name) {
          case "dynamic":
          case "void":
            unserializableExports ??= <String, String>{};
            unserializableExports[name] = null;
            break;

          default:
            if (member is InvalidTypeBuilder) {
              unserializableExports ??= <String, String>{};
              unserializableExports[name] = member.message.message;
            } else {
              library.additionalExports.add(member.target.reference);
            }
        }
      }
    });
  }

  @override
  void applyPatches() {
    if (!isPatch) return;
    origin.forEach((String name, Builder member) {
      bool isSetter = member.isSetter;
      Builder patch = isSetter ? scope.setters[name] : scope.local[name];
      if (patch != null) {
        // [patch] has the same name as a [member] in [origin] library, so it
        // must be a patch to [member].
        member.applyPatch(patch);
        // TODO(ahe): Verify that patch has the @patch annotation.
      } else {
        // No member with [name] exists in this library already. So we need to
        // import it into the patch library. This ensures that the origin
        // library is in scope of the patch library.
        if (isSetter) {
          scopeBuilder.addSetter(name, member);
        } else {
          scopeBuilder.addMember(name, member);
        }
      }
    });
    forEach((String name, Builder member) {
      // We need to inject all non-patch members into the origin library. This
      // should only apply to private members.
      if (member.isPatch) {
        // Ignore patches.
      } else if (name.startsWith("_")) {
        origin.injectMemberFromPatch(name, member);
      } else {
        origin.exportMemberFromPatch(name, member);
      }
    });
  }

  int finishPatchMethods() {
    if (!isPatch) return 0;
    int count = 0;
    forEach((String name, Builder member) {
      count += member.finishPatch();
    });
    return count;
  }

  void injectMemberFromPatch(String name, Builder member) {
    if (member.isSetter) {
      assert(scope.setters[name] == null);
      scopeBuilder.addSetter(name, member);
    } else {
      assert(scope.local[name] == null);
      scopeBuilder.addMember(name, member);
    }
  }

  void exportMemberFromPatch(String name, Builder member) {
    if (uri.scheme != "dart" || !uri.path.startsWith("_")) {
      addCompileTimeError(templatePatchInjectionFailed.withArguments(name, uri),
          member.charOffset, noLength, member.fileUri);
    }
    // Platform-private libraries, such as "dart:_internal" have special
    // semantics: public members are injected into the origin library.
    // TODO(ahe): See if we can remove this special case.

    // If this member already exist in the origin library scope, it should
    // have been marked as patch.
    assert((member.isSetter && scope.setters[name] == null) ||
        (!member.isSetter && scope.local[name] == null));
    addToExportScope(name, member);
  }
}
