// 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.

import 'dart:typed_data';

import 'package:_fe_analyzer_shared/src/messages/severity.dart'
    show CfeSeverity;
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart';
import 'package:kernel/reference_from_index.dart'
    show IndexedContainer, IndexedClass;
import 'package:kernel/target/changed_structure_notifier.dart'
    show ChangedStructureNotifier;
import 'package:kernel/target/targets.dart' show DiagnosticReporter, Target;
import 'package:kernel/type_algebra.dart' show Substitution;
import 'package:kernel/type_environment.dart' show TypeEnvironment;
import 'package:kernel/verifier.dart' show VerificationStage;
import 'package:package_config/package_config.dart' hide LanguageVersion;

import '../api_prototype/experimental_flags.dart'
    show ExperimentalFlag, GlobalFeatures;
import '../api_prototype/file_system.dart' show FileSystem;
import '../base/compiler_context.dart' show CompilerContext;
import '../base/crash.dart' show withCrashReporting;
import '../base/loader.dart' show Loader;
import '../base/messages.dart'
    show
        FormattedMessage,
        LocatedMessage,
        Message,
        codeConstConstructorLateFinalFieldCause,
        codeConstConstructorLateFinalFieldError,
        codeConstConstructorNonFinalField,
        codeConstConstructorNonFinalFieldCause,
        codeConstConstructorRedirectionToNonConst,
        noLength,
        codeFieldNonNullableNotInitializedByConstructorError,
        codeFieldNonNullableWithoutInitializerError,
        codeFinalFieldNotInitialized,
        codeFinalFieldNotInitializedByConstructor,
        codeMissingImplementationCause,
        codeSuperclassHasNoDefaultConstructor;
import '../base/processed_options.dart' show ProcessedOptions;
import '../base/ticker.dart' show Ticker;
import '../base/uri_offset.dart';
import '../base/uri_translator.dart' show UriTranslator;
import '../builder/builder.dart';
import '../builder/compilation_unit.dart';
import '../builder/declaration_builders.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/method_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/property_builder.dart';
import '../builder/type_builder.dart';
import '../dill/dill_target.dart' show DillTarget;
import '../fragment/constructor/declaration.dart';
import '../source/name_scheme.dart';
import '../source/source_class_builder.dart' show SourceClassBuilder;
import '../source/source_constructor_builder.dart';
import '../source/source_declaration_builder.dart';
import '../source/source_extension_type_declaration_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
import '../source/source_loader.dart'
    show CompilationPhaseForProblemReporting, SourceLoader;
import '../source/source_property_builder.dart';
import '../type_inference/type_schema.dart';
import 'benchmarker.dart' show BenchmarkPhases, Benchmarker;
import 'cfe_verifier.dart' show verifyComponent, verifyGetStaticType;
import 'constant_evaluator.dart'
    as constants
    show
        transformLibraries,
        transformProcedure,
        ConstantCoverage,
        ConstantEvaluationData;
import 'constructor_tearoff_lowering.dart';
import 'dynamic_module_validator.dart' as dynamic_module_validator;
import 'kernel_constants.dart' show KernelConstantErrorReporter;
import 'kernel_helper.dart';
import 'utils.dart';

class KernelTarget {
  final Ticker ticker;

  /// The [FileSystem] which should be used to access files.
  final FileSystem fileSystem;

  /// Whether comments should be scanned and parsed.
  final bool includeComments;

  final DillTarget dillTarget;

  late final SourceLoader loader;

  Component? component;

  // 'dynamic' is always nullable.
  // TODO(johnniwinther): Why isn't this using a FixedTypeBuilder?
  final NamedTypeBuilder dynamicType = new NamedTypeBuilderImpl(
    const PredefinedTypeName("dynamic"),
    const NullabilityBuilder.inherent(),
    instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected,
  );

  final NamedTypeBuilder intType = new NamedTypeBuilderImpl(
    const PredefinedTypeName("int"),
    const NullabilityBuilder.omitted(),
    instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected,
  );

  final NamedTypeBuilder stringType = new NamedTypeBuilderImpl(
    const PredefinedTypeName("String"),
    const NullabilityBuilder.omitted(),
    instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected,
  );

  final NamedTypeBuilder objectType = new NamedTypeBuilderImpl(
    const PredefinedTypeName("Object"),
    const NullabilityBuilder.omitted(),
    instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected,
  );

  // Null is always nullable.
  // TODO(johnniwinther): This could (maybe) use a FixedTypeBuilder when we
  //  have NullType?
  final NamedTypeBuilder nullType = new NamedTypeBuilderImpl(
    const PredefinedTypeName("Null"),
    const NullabilityBuilder.inherent(),
    instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected,
  );

  // TODO(johnniwinther): Why isn't this using a FixedTypeBuilder?
  final NamedTypeBuilder bottomType = new NamedTypeBuilderImpl(
    const PredefinedTypeName("Never"),
    const NullabilityBuilder.omitted(),
    instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected,
  );

  final NamedTypeBuilder enumType = new NamedTypeBuilderImpl(
    const PredefinedTypeName("Enum"),
    const NullabilityBuilder.omitted(),
    instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected,
  );

  final NamedTypeBuilder underscoreEnumType = new NamedTypeBuilderImpl(
    const PredefinedTypeName("_Enum"),
    const NullabilityBuilder.omitted(),
    instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected,
  );

  bool get excludeSource => !context.options.embedSourceText;

  Map<String, String>? get environmentDefines =>
      context.options.environmentDefines;

  bool get errorOnUnevaluatedConstant =>
      context.options.errorOnUnevaluatedConstant;

  final Map<Member, DelayedDefaultValueCloner> _delayedDefaultValueCloners = {};

  final UriTranslator uriTranslator;

  final Target backendTarget;

  final CompilerContext context;

  /// Shared with [CompilerContext].
  Map<Uri, Source> get uriToSource => context.uriToSource;

  MemberBuilder? _cachedDuplicatedFieldInitializerError;
  MemberBuilder? _cachedNativeAnnotation;

  final ProcessedOptions _options;

  final Benchmarker? benchmarker;

  KernelTarget(
    this.context,
    this.fileSystem,
    this.includeComments,
    DillTarget dillTarget,
    this.uriTranslator,
  ) : dillTarget = dillTarget,
      backendTarget = dillTarget.backendTarget,
      _options = context.options,
      ticker = dillTarget.ticker,
      benchmarker = dillTarget.benchmarker {
    assert(_options.haveBeenValidated, "Options have not been validated");
    loader = createLoader();
  }

  GlobalFeatures get globalFeatures => _options.globalFeatures;

  bool isExperimentEnabledInLibraryByVersion(
    ExperimentalFlag flag,
    Uri importUri,
    Version version,
  ) {
    return _options.isExperimentEnabledInLibraryByVersion(
      flag,
      importUri,
      version,
    );
  }

  Uri? translateUri(Uri uri) => uriTranslator.translate(uri);

  /// Returns a reference to the constructor used for creating a runtime error
  /// when a final field is initialized twice. The constructor is expected to
  /// accept a single argument which is the name of the field.
  MemberBuilder getDuplicatedFieldInitializerError(Loader loader) {
    return _cachedDuplicatedFieldInitializerError ??= loader.coreLibrary
        .getConstructor(
          "_DuplicatedFieldInitializerError",
          bypassLibraryPrivacy: true,
        );
  }

  /// Returns a reference to the constructor used for creating `native`
  /// annotations. The constructor is expected to accept a single argument of
  /// type String, which is the name of the native method.
  MemberBuilder getNativeAnnotation(SourceLoader loader) {
    if (_cachedNativeAnnotation != null) return _cachedNativeAnnotation!;
    LibraryBuilder internal = loader.lookupLoadedLibraryBuilder(
      Uri.parse("dart:_internal"),
    )!;
    return _cachedNativeAnnotation = internal.getConstructor("ExternalName");
  }

  void loadExtraRequiredLibraries(SourceLoader loader) {
    for (String uri in backendTarget.extraRequiredLibraries) {
      loader.read(
        Uri.parse(uri),
        0,
        accessor: loader.coreLibraryCompilationUnit,
      );
    }
    if (context.compilingPlatform) {
      // Coverage-ignore-block(suite): Not run.
      for (String uri in backendTarget.extraRequiredLibrariesPlatform) {
        loader.read(
          Uri.parse(uri),
          0,
          accessor: loader.coreLibraryCompilationUnit,
        );
      }
    }
  }

  FormattedMessage createFormattedMessage(
    Message message,
    int charOffset,
    int length,
    Uri? fileUri,
    List<LocatedMessage>? messageContext,
    CfeSeverity severity, {
    List<Uri>? involvedFiles,
  }) {
    ProcessedOptions processedOptions = context.options;
    return processedOptions.format(
      context,
      fileUri != null
          ? message.withLocation(fileUri, charOffset, length)
          :
            // Coverage-ignore(suite): Not run.
            message.withoutLocation(),
      severity,
      messageContext,
      involvedFiles: involvedFiles,
    );
  }

  String get currentSdkVersionString {
    return context.options.currentSdkVersion;
  }

  Version get leastSupportedVersion => const Version(2, 12);

  Version? _currentSdkVersion;

  Version get currentSdkVersion {
    if (_currentSdkVersion == null) {
      _parseCurrentSdkVersion();
    }
    return _currentSdkVersion!;
  }

  void _parseCurrentSdkVersion() {
    bool good = false;
    List<String> dotSeparatedParts = currentSdkVersionString.split(".");
    if (dotSeparatedParts.length >= 2) {
      _currentSdkVersion = new Version(
        int.tryParse(dotSeparatedParts[0])!,
        int.tryParse(dotSeparatedParts[1])!,
      );
      good = true;
    }
    if (!good) {
      throw new StateError(
        "Unparsable sdk version given: $currentSdkVersionString",
      );
    }
  }

  SourceLoader createLoader() =>
      new SourceLoader(fileSystem, includeComments, this);

  bool _hasAddedSources = false;

  void addSourceInformation(
    Uri importUri,
    Uri fileUri,
    List<int> lineStarts,
    Uint8List sourceCode,
  ) {
    Source source = new Source(lineStarts, sourceCode, importUri, fileUri);
    uriToSource[fileUri] = source;
    if (_hasAddedSources) {
      // Coverage-ignore-block(suite): Not run.
      // The sources have already been added to the component in [link] so we
      // have to add source directly here to create a consistent component.
      component?.uriToSource[fileUri] = excludeSource
          ? new Source.emptySource(
              source.lineStarts,
              source.importUri,
              source.fileUri,
            )
          : source;
    }
  }

  // Coverage-ignore(suite): Not run.
  void removeSourceInformation(Uri fileUri) {
    uriToSource.remove(fileUri);
    if (_hasAddedSources) {
      // The sources have already been added to the component in [link] so we
      // have to remove source directly here to create a consistent component.
      component?.uriToSource.remove(fileUri);
    }
  }

  /// Return list of same size as input with possibly translated uris.
  List<Uri> setEntryPoints(List<Uri> entryPoints) {
    List<Uri> result = <Uri>[];
    for (Uri entryPoint in entryPoints) {
      Uri translatedEntryPoint = getEntryPointUri(entryPoint);
      result.add(translatedEntryPoint);
      loader.readAsEntryPoint(
        translatedEntryPoint,
        fileUri: translatedEntryPoint != entryPoint ? entryPoint : null,
      );
    }
    return result;
  }

  /// Return list of same size as input with possibly translated uris.
  Uri getEntryPointUri(Uri entryPoint) {
    String scheme = entryPoint.scheme;
    switch (scheme) {
      case "package":
      case "dart":
      case "data":
        break;
      default:
        // Attempt to reverse-lookup [entryPoint] in package config.
        String asString = "$entryPoint";
        Package? package = uriTranslator.packages.packageOf(entryPoint);
        if (package != null) {
          String packageName = package.name;
          Uri packageUri = package.packageUriRoot;
          if (packageUri.hasFragment == true) {
            // Coverage-ignore-block(suite): Not run.
            packageUri = packageUri.removeFragment();
          }
          String prefix = "${packageUri}";
          if (asString.startsWith(prefix)) {
            // Coverage-ignore-block(suite): Not run.
            Uri reversed = Uri.parse(
              "package:$packageName/${asString.substring(prefix.length)}",
            );
            if (entryPoint == uriTranslator.translate(reversed)) {
              entryPoint = reversed;
              break;
            }
          }
        }
    }
    return entryPoint;
  }

  bool _hasComputedNeededPrecompilations = false;

  // TODO(johnniwinther): Remove this.
  Future<void> computeNeededPrecompilations() async {
    assert(
      !_hasComputedNeededPrecompilations,
      "Needed precompilations have already been computed.",
    );
    _hasComputedNeededPrecompilations = true;
    if (loader.roots.isEmpty) return null;
    return await withCrashReporting<void>(() async {
      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.outline_kernelBuildOutlines);
      await loader.buildOutlines();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.outline_resolveParts);
      loader.resolveParts();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.outline_buildNameSpaces);
      loader.buildNameSpaces(loader.sourceLibraryBuilders);

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.outline_becomeCoreLibrary);
      loader.coreLibrary.becomeCoreLibrary();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.outline_buildScopes);
      loader.buildScopes(loader.sourceLibraryBuilders);

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.unknownComputeNeededPrecompilations);
    }, () => loader.currentUriForCrashReporting);
  }

  // Coverage-ignore(suite): Not run.
  /// Builds [libraryBuilders] to the state expected after
  /// [SourceLoader.buildScopes].
  void buildSyntheticLibrariesUntilBuildScopes(
    Iterable<SourceLibraryBuilder> libraryBuilders,
  ) {
    loader.buildNameSpaces(libraryBuilders);
    loader.buildScopes(libraryBuilders);
  }

  // Coverage-ignore(suite): Not run.
  /// Builds [libraryBuilders] to the state expected after default types have
  /// been computed.
  ///
  /// This assumes that [libraryBuilders] are in the state after
  /// [SourceLoader.buildScopes].
  void buildSyntheticLibrariesUntilComputeDefaultTypes(
    Iterable<SourceLibraryBuilder> libraryBuilders,
  ) {
    loader.computeLibraryScopes(libraryBuilders);
    loader.resolveTypes(libraryBuilders);
    loader.computeSupertypes(libraryBuilders);
    loader.computeDefaultTypes(
      libraryBuilders,
      dynamicType,
      nullType,
      bottomType,
      objectClassBuilder,
    );
  }

  Future<BuildResult> buildOutlines({CanonicalName? nameRoot}) async {
    if (loader.roots.isEmpty) {
      // Coverage-ignore-block(suite): Not run.
      return new BuildResult();
    }
    return await withCrashReporting<BuildResult>(
      () async {
        if (!_hasComputedNeededPrecompilations) {
          // Coverage-ignore-block(suite): Not run.
          await computeNeededPrecompilations();
        }

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeLibraryScopes);
        loader.computeLibraryScopes(loader.loadedLibraryBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_setupTopAndBottomTypes);
        setupTopAndBottomTypes();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_resolveTypes);
        loader.resolveTypes(loader.sourceLibraryBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeSupertypes);
        loader.computeSupertypes(loader.sourceLibraryBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeMacroApplications);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeVariances);
        loader.computeVariances(loader.sourceLibraryBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeDefaultTypes);
        loader.computeDefaultTypes(
          loader.sourceLibraryBuilders,
          dynamicType,
          nullType,
          bottomType,
          objectClassBuilder,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_checkSemantics);
        List<SourceClassBuilder>? sortedSourceClassBuilders;
        List<SourceExtensionTypeDeclarationBuilder>?
        sortedSourceExtensionTypeBuilders;
        (sortedSourceClassBuilders, sortedSourceExtensionTypeBuilders) = loader
            .checkClassCycles(objectClassBuilder);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_finishTypeParameters);
        loader.finishTypeParameters(
          loader.sourceLibraryBuilders,
          objectClassBuilder,
          dynamicType,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_createTypeInferenceEngine);
        loader.createTypeInferenceEngine();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_buildComponent);
        loader.buildOutlineNodes();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_installDefaultSupertypes);
        installDefaultSupertypes();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_link);
        component = link(
          new List<Library>.of(loader.libraries),
          nameRoot: nameRoot,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeCoreTypes);
        computeCoreTypes();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_buildClassHierarchy);
        loader.buildClassHierarchy(
          sortedSourceClassBuilders,
          sortedSourceExtensionTypeBuilders,
          objectClassBuilder,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_checkSupertypes);
        loader.checkSupertypes(
          sortedSourceClassBuilders,
          sortedSourceExtensionTypeBuilders,
          objectClass,
          enumClass,
          underscoreEnumClass,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_installSyntheticConstructors);
        installSyntheticConstructors(sortedSourceClassBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_resolveConstructors);
        loader.resolveConstructors(loader.sourceLibraryBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_buildClassHierarchyMembers);
        loader.buildClassHierarchyMembers(
          sortedSourceClassBuilders,
          sortedSourceExtensionTypeBuilders,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeHierarchy);
        loader.computeHierarchy();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_installTypedefTearOffs);
        List<DelayedDefaultValueCloner>?
        typedefTearOffsDelayedDefaultValueCloners = loader
            .installTypedefTearOffs();
        typedefTearOffsDelayedDefaultValueCloners?.forEach(
          registerDelayedDefaultValueCloner,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeFieldPromotability);
        loader.computeFieldPromotability();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_prepareTopLevelInference);
        loader.prepareTopLevelInference();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(
          BenchmarkPhases.outline_performRedirectingFactoryInference,
        );
        // TODO(johnniwinther): Add an interface for registering delayed
        // actions.
        List<DelayedDefaultValueCloner> delayedDefaultValueCloners = [];
        loader.inferRedirectingFactories(delayedDefaultValueCloners);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_computeMemberTypes);
        loader.computeMemberTypes();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_performTopLevelInference);
        loader.performTopLevelInference(sortedSourceClassBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_checkOverrides);
        loader.checkOverrides(sortedSourceClassBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_checkAbstractMembers);
        loader.checkAbstractMembers(sortedSourceClassBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_checkMixins);
        loader.checkMixins(sortedSourceClassBuilders);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_buildOutlineExpressions);
        loader.buildOutlineExpressions(
          loader.hierarchy,
          delayedDefaultValueCloners,
        );
        delayedDefaultValueCloners.forEach(registerDelayedDefaultValueCloner);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_checkTypes);
        loader.checkTypes();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_checkRedirectingFactories);
        loader.checkRedirectingFactories(
          sortedSourceClassBuilders,
          sortedSourceExtensionTypeBuilders,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_finishSynthesizedParameters);
        finishSynthesizedParameters(forOutline: true);

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_checkMainMethods);
        loader.checkMainMethods();

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.outline_installAllComponentProblems);
        loader.installAllProblemsIntoComponent(
          component!,
          currentPhase: CompilationPhaseForProblemReporting.outline,
        );

        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.unknownBuildOutlines);

        // For whatever reason sourceClassBuilders is kept alive for some amount
        // of time, meaning that all source library builders will be kept alive
        // (for whatever amount of time) even though we convert them to dill
        // library builders. To avoid it we null it out here.
        sortedSourceClassBuilders = null;

        return new BuildResult(component: component);
      }, // Coverage-ignore(suite): Not run.
      () => loader.currentUriForCrashReporting,
    );
  }

  /// Build the kernel representation of the component loaded by this
  /// target. The component will contain full bodies for the code loaded from
  /// sources, and only references to the code loaded by the [DillTarget],
  /// which may or may not include method bodies (depending on what was loaded
  /// into that target, an outline or a full kernel component).
  ///
  /// If [verify], run the default kernel verification on the resulting
  /// component.
  Future<BuildResult> buildComponent({
    bool verify = false,
    bool allowVerificationErrorForTesting = false,
  }) async {
    if (loader.roots.isEmpty) {
      // Coverage-ignore-block(suite): Not run.
      return new BuildResult();
    }
    return await withCrashReporting<BuildResult>(() async {
      ticker.logMs("Building component");

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_buildBodies);
      await loader.buildBodies(loader.sourceLibraryBuilders);

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_checkMixinSuperAccesses);
      loader.checkMixinSuperAccesses();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_finishSynthesizedParameters);
      finishSynthesizedParameters();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_finishDeferredLoadTearoffs);
      loader.finishDeferredLoadTearoffs();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_finishNoSuchMethodForwarders);
      loader.finishNoSuchMethodForwarders();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_collectSourceClasses);
      List<SourceClassBuilder>? sourceClasses = [];
      List<SourceExtensionTypeDeclarationBuilder>? extensionTypeDeclarations =
          [];
      loader.collectSourceClasses(sourceClasses, extensionTypeDeclarations);

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_finishNativeMethods);
      loader.finishNativeMethods();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_finishAugmentationMethods);
      loader.buildBodyNodes();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_finishAllConstructors);
      finishAllConstructors(sourceClasses, extensionTypeDeclarations);

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_validateDynamicModule);
      await validateDynamicModule();

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_runBuildTransformations);
      runBuildTransformations();

      if (verify) {
        benchmarker
        // Coverage-ignore(suite): Not run.
        ?.enterPhase(BenchmarkPhases.body_verify);
        _verify(
          allowVerificationErrorForTesting: allowVerificationErrorForTesting,
        );
      }

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.body_installAllComponentProblems);
      loader.installAllProblemsIntoComponent(
        component!,
        currentPhase: CompilationPhaseForProblemReporting.bodyBuilding,
      );

      benchmarker
      // Coverage-ignore(suite): Not run.
      ?.enterPhase(BenchmarkPhases.unknownBuildComponent);

      // For whatever reason sourceClasses is kept alive for some amount
      // of time, meaning that all source library builders will be kept alive
      // (for whatever amount of time) even though we convert them to dill
      // library builders. To avoid it we null it out here.
      sourceClasses = null;
      extensionTypeDeclarations = null;

      context.options.hooksForTesting
      // Coverage-ignore(suite): Not run.
      ?.onBuildComponentComplete(component!);

      return new BuildResult(component: component);
    }, () => loader.currentUriForCrashReporting);
  }

  /// Creates a component by combining [libraries] with the libraries of
  /// `dillTarget.loader.component`.
  Component link(List<Library> libraries, {CanonicalName? nameRoot}) {
    libraries.addAll(dillTarget.loader.libraries);

    // Copy source data from the map in [CompilerContext] into a new map that is
    // put on the component.

    Map<Uri, Source> uriToSource = new Map<Uri, Source>();
    void copySource(Uri uri, Source source) {
      uriToSource[uri] = excludeSource
          ?
            // Coverage-ignore(suite): Not run.
            new Source.emptySource(
              source.lineStarts,
              source.importUri,
              source.fileUri,
            )
          : source;
    }

    this.uriToSource.forEach(copySource);
    _hasAddedSources = true;

    Component component = backendTarget.configureComponent(
      new Component(
        nameRoot: nameRoot,
        libraries: libraries,
        uriToSource: uriToSource,
      ),
    );

    Reference? mainReference;

    LibraryBuilder? firstRoot = loader.rootLibrary;
    if (firstRoot != null) {
      // TODO(sigmund): do only for full program
      Builder? declaration = firstRoot.exportNameSpace.lookup("main")?.getable;
      if (declaration is MethodBuilder) {
        mainReference = declaration.invokeTargetReference;
      }
    }
    component.setMainMethodAndMode(mainReference, true);

    ticker.logMs("Linked component");
    return component;
  }

  void installDefaultSupertypes() {
    Class objectClass = this.objectClass;
    for (SourceLibraryBuilder library in loader.sourceLibraryBuilders) {
      library.installDefaultSupertypes(objectClassBuilder, objectClass);
    }
    ticker.logMs("Installed Object as implicit superclass");
  }

  void installSyntheticConstructors(List<SourceClassBuilder> builders) {
    Class objectClass = this.objectClass;
    for (SourceClassBuilder builder in builders) {
      if (builder.cls != objectClass) {
        if (builder.isMixinDeclaration) {
          continue;
        }
        if (builder.isMixinApplication) {
          installForwardingConstructors(builder);
        } else {
          installDefaultConstructor(builder);
        }
      }
    }
    ticker.logMs("Installed synthetic constructors");
  }

  ClassBuilder get objectClassBuilder => objectType.declaration as ClassBuilder;

  Class get objectClass => objectClassBuilder.cls;

  ClassBuilder get enumClassBuilder => enumType.declaration as ClassBuilder;

  Class get enumClass => enumClassBuilder.cls;

  ClassBuilder get underscoreEnumBuilder =>
      underscoreEnumType.declaration as ClassBuilder;

  Class get underscoreEnumClass => underscoreEnumBuilder.cls;

  /// If [builder] doesn't have a constructors, install the defaults.
  void installDefaultConstructor(SourceClassBuilder builder) {
    assert(!builder.isMixinApplication);
    // TODO(askesc): Make this check light-weight in the absence of
    //  augmentations.
    if (builder.cls.constructors.isNotEmpty) return;
    for (Procedure proc in builder.cls.procedures) {
      if (proc.isFactory) return;
    }

    IndexedContainer? indexedClass = builder.indexedClass;
    Reference? constructorReference;
    Reference? tearOffReference;
    if (indexedClass != null) {
      constructorReference = indexedClass.lookupConstructorReference(
        new Name(""),
      );
      tearOffReference = indexedClass.lookupGetterReference(
        new Name(constructorTearOffName(""), indexedClass.library),
      );
    }

    /// From [Dart Programming Language Specification, 4th Edition](
    /// https://ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf):
    /// >Iff no constructor is specified for a class C, it implicitly has a
    /// >default constructor C() : super() {}, unless C is class Object.
    // The superinitializer is installed below in [finishConstructors].
    builder.addSyntheticConstructor(
      _makeDefaultConstructor(builder, constructorReference, tearOffReference),
    );
  }

  void installForwardingConstructors(SourceClassBuilder builder) {
    assert(builder.isMixinApplication);
    if (builder.libraryBuilder.loader != loader) return;
    if (builder.cls.constructors.isNotEmpty) {
      // These were installed by a subclass in the recursive call below.
      return;
    }

    /// From [Dart Programming Language Specification, 4th Edition](
    /// https://ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf):
    /// >A mixin application of the form S with M; defines a class C with
    /// >superclass S.
    /// >...

    /// >Let LM be the library in which M is declared. For each generative
    /// >constructor named qi(Ti1 ai1, . . . , Tiki aiki), i in 1..n of S
    /// >that is accessible to LM , C has an implicitly declared constructor
    /// >named q'i = [C/S]qi of the form q'i(ai1,...,aiki) :
    /// >super(ai1,...,aiki);.
    TypeBuilder? type = builder.supertypeBuilder;
    TypeDeclarationBuilder? supertype = type?.computeUnaliasedDeclaration(
      isUsedAsClass: true,
    );
    if (supertype is SourceClassBuilder && supertype.isMixinApplication) {
      installForwardingConstructors(supertype);
    }

    IndexedContainer? indexedClass = builder.indexedClass;
    Reference? constructorReference;
    Reference? tearOffReference;
    if (indexedClass != null) {
      constructorReference = indexedClass.lookupConstructorReference(
        new Name(""),
      );
      tearOffReference = indexedClass.lookupGetterReference(
        new Name(constructorTearOffName(""), indexedClass.library),
      );
    }

    switch (supertype) {
      case ClassBuilder():
        ClassBuilder superclassBuilder = supertype;
        bool isConstructorAdded = false;
        Map<TypeParameter, DartType>? substitutionMap;

        Iterator<MemberBuilder> iterator = superclassBuilder
            .filteredConstructorsIterator(includeDuplicates: false);
        while (iterator.moveNext()) {
          MemberBuilder memberBuilder = iterator.current;
          String name = memberBuilder.name;
          if (memberBuilder.invokeTarget is Constructor) {
            substitutionMap ??= builder.getSubstitutionMap(
              superclassBuilder.cls,
            );
            if (indexedClass != null) {
              constructorReference = indexedClass.lookupConstructorReference(
                memberBuilder.invokeTarget!.name,
              );
              tearOffReference = indexedClass.lookupGetterReference(
                new Name(constructorTearOffName(name), indexedClass.library),
              );
            }
            builder.addSyntheticConstructor(
              _makeMixinApplicationConstructor(
                builder,
                builder.cls.mixin,
                memberBuilder,
                substitutionMap,
              ),
            );
            isConstructorAdded = true;
          }
        }

        if (!isConstructorAdded) {
          builder.addSyntheticConstructor(
            _makeDefaultConstructor(
              builder,
              constructorReference,
              tearOffReference,
            ),
          );
        }
      case TypeAliasBuilder():
      case NominalParameterBuilder():
      case StructuralParameterBuilder():
      case ExtensionBuilder():
      case ExtensionTypeDeclarationBuilder():
      case InvalidBuilder():
      case BuiltinTypeDeclarationBuilder():
      case null:
        builder.addSyntheticConstructor(
          _makeDefaultConstructor(
            builder,
            constructorReference,
            tearOffReference,
          ),
        );
    }
  }

  SourceConstructorBuilder _makeMixinApplicationConstructor(
    SourceClassBuilder classBuilder,
    Class mixin,
    MemberBuilder superConstructorBuilder,
    Map<TypeParameter, DartType> substitutionMap,
  ) {
    SourceLibraryBuilder libraryBuilder = classBuilder.libraryBuilder;
    Constructor superConstructor =
        superConstructorBuilder.invokeTarget as Constructor;
    Name name = superConstructor.name;

    IndexedClass? indexedClass = classBuilder.indexedClass;

    // If the name of the super constructor is private, we use the library name
    // of its enclosing library to ensure that both constructor and tear-off
    // are private wrt to the original library. Otherwise we use the library
    // name of the [libraryBuilder], since only the tear-off should be private.
    //
    // For instance:
    //
    //     // lib1:
    //     class Super { Super._() }
    //     class Subclass extends Class {
    //       Subclass() : super._();
    //     }
    //     // lib2:
    //     class Mixin {}
    //     class Class = Super with Mixin;
    //
    // Here `super._()` in `Subclass` targets the forwarding stub
    // added to `Class` whose name is `_` private to `lib1`.
    LibraryName libraryName = name.isPrivate
        ? superConstructorBuilder.libraryBuilder.libraryName
        : libraryBuilder.libraryName;

    NameScheme nameScheme = new NameScheme(
      isInstanceMember: false,
      containerName: new ClassName(classBuilder.name),
      containerType: ContainerType.Class,
      libraryName: libraryName,
    );

    ConstructorReferences constructorReferences = new ConstructorReferences(
      name: superConstructorBuilder.name,
      nameScheme: nameScheme,
      indexedContainer: indexedClass,
      loader: loader,
      declarationBuilder: classBuilder,
    );

    bool hasTypeDependency = false;
    Substitution substitution = Substitution.fromMap(substitutionMap);

    VariableDeclaration copyFormal(VariableDeclaration formal) {
      VariableDeclaration copy = new VariableDeclaration(
        formal.name,
        isFinal: formal.isFinal,
        isConst: formal.isConst,
        isRequired: formal.isRequired,
        hasDeclaredInitializer: formal.hasDeclaredInitializer,
        type: const UnknownType(),
      );
      if (!hasTypeDependency && formal.type is! UnknownType) {
        copy.type = substitution.substituteType(formal.type);
      } else {
        hasTypeDependency = true;
      }
      return copy;
    }

    Class cls = classBuilder.cls;
    bool isConst = superConstructor.isConst;
    if (isConst && mixin.fields.isNotEmpty) {
      for (Field field in mixin.fields) {
        if (!field.isStatic) {
          isConst = false;
          break;
        }
      }
    }
    List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
    List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
    List<Expression> positional = <Expression>[];
    List<NamedExpression> named = <NamedExpression>[];

    for (VariableDeclaration formal
        in superConstructor.function.positionalParameters) {
      positionalParameters.add(copyFormal(formal));
      positional.add(new VariableGet(positionalParameters.last));
    }
    for (VariableDeclaration formal
        in superConstructor.function.namedParameters) {
      VariableDeclaration clone = copyFormal(formal);
      namedParameters.add(clone);
      named.add(
        new NamedExpression(
          formal.name!,
          new VariableGet(namedParameters.last),
        ),
      );
    }
    FunctionNode function = new FunctionNode(
      new EmptyStatement(),
      positionalParameters: positionalParameters,
      namedParameters: namedParameters,
      requiredParameterCount: superConstructor.function.requiredParameterCount,
      returnType: makeConstructorReturnType(cls),
    );
    SuperInitializer initializer = new SuperInitializer(
      superConstructor,
      new Arguments(positional, named: named),
    );
    Constructor constructor = new Constructor(
      function,
      name: name,
      initializers: <Initializer>[initializer],
      isSynthetic: true,
      isConst: isConst,
      reference: constructorReferences.constructorReference,
      fileUri: cls.fileUri,
    )..fileOffset = cls.fileOffset
    // TODO(johnniwinther): Should we add file end offset to synthesized
    //  constructors?
    //..fileEndOffset = cls.fileOffset
    ;
    DelayedDefaultValueCloner delayedDefaultValueCloner =
        new DelayedDefaultValueCloner(
          superConstructor,
          constructor,
          libraryBuilder: libraryBuilder,
        );

    TypeDependency? typeDependency;
    if (hasTypeDependency) {
      typeDependency = new TypeDependency(
        constructor,
        superConstructor,
        substitution,
        copyReturnType: false,
      );
    }

    Procedure? constructorTearOff = createConstructorTearOffProcedure(
      new MemberName(libraryName, constructorTearOffName(name.text)),
      libraryBuilder,
      cls.fileUri,
      cls.fileOffset,
      constructorReferences.tearOffReference,
      forAbstractClassOrEnumOrMixin: classBuilder.isAbstract,
    );

    if (constructorTearOff != null) {
      DelayedDefaultValueCloner delayedDefaultValueCloner =
          buildConstructorTearOffProcedure(
            tearOff: constructorTearOff,
            declarationConstructor: constructor,
            implementationConstructor: constructor,
            enclosingDeclarationTypeParameters: classBuilder.cls.typeParameters,
            libraryBuilder: libraryBuilder,
          );
      registerDelayedDefaultValueCloner(delayedDefaultValueCloner);
    }
    ConstructorDeclaration declaration = new ForwardingConstructorDeclaration(
      constructor: constructor,
      constructorTearOff: constructorTearOff,
      // We pass on the original constructor and the cloned function nodes
      // to ensure that the default values are computed and cloned for the
      // outline. It is needed to make the default values a part of the
      // outline for const constructors, and additionally it is required
      // for a potential subclass using super initializing parameters that
      // will required the cloning of the default values.
      definingConstructor: superConstructorBuilder,
      delayedDefaultValueCloner: delayedDefaultValueCloner,
      typeDependency: typeDependency,
    );

    SourceConstructorBuilder constructorBuilder = new SourceConstructorBuilder(
      name: superConstructorBuilder.name,
      libraryBuilder: libraryBuilder,
      declarationBuilder: classBuilder,
      fileOffset: classBuilder.fileOffset,
      fileUri: classBuilder.fileUri,
      constructorReferences: constructorReferences,
      nameScheme: nameScheme,
      introductory: declaration,
      isConst: isConst,
    );

    loader.registerConstructorToBeInferred(
      new InferableConstructor(constructor, constructorBuilder),
    );
    return constructorBuilder;
  }

  void registerDelayedDefaultValueCloner(DelayedDefaultValueCloner cloner) {
    // TODO(cstefantsova): Investigate the reason for the assumption breakage
    // and uncomment the following line.
    // assert(!_delayedDefaultValueCloners.containsKey(cloner.synthesized));
    _delayedDefaultValueCloners[cloner.synthesized] ??= cloner;
  }

  void finishSynthesizedParameters({bool forOutline = false}) {
    void cloneDefaultValues(
      DelayedDefaultValueCloner delayedDefaultValueCloner,
    ) {
      DelayedDefaultValueCloner? originalCloner =
          _delayedDefaultValueCloners[delayedDefaultValueCloner.original];
      if (originalCloner != null) {
        cloneDefaultValues(originalCloner);
      }
      delayedDefaultValueCloner.cloneDefaultValues(loader.typeEnvironment);
    }

    for (DelayedDefaultValueCloner delayedDefaultValueCloner
        in _delayedDefaultValueCloners.values) {
      if (!forOutline || delayedDefaultValueCloner.isOutlineNode) {
        cloneDefaultValues(delayedDefaultValueCloner);
      }
    }
    if (!forOutline) {
      _delayedDefaultValueCloners.clear();
    }
    ticker.logMs("Cloned default values of formals");
  }

  SourceConstructorBuilder _makeDefaultConstructor(
    SourceClassBuilder classBuilder,
    Reference? constructorReference,
    Reference? tearOffReference,
  ) {
    SourceLibraryBuilder libraryBuilder = classBuilder.libraryBuilder;

    IndexedClass? indexedClass = classBuilder.indexedClass;
    LibraryName libraryName = indexedClass != null
        ? new LibraryName(indexedClass.library.reference)
        : libraryBuilder.libraryName;

    Name name = new Name('');

    NameScheme nameScheme = new NameScheme(
      isInstanceMember: false,
      containerName: new ClassName(classBuilder.name),
      containerType: ContainerType.Class,
      libraryName: libraryName,
    );

    ConstructorReferences constructorReferences = new ConstructorReferences(
      name: name.text,
      nameScheme: nameScheme,
      indexedContainer: indexedClass,
      loader: loader,
      declarationBuilder: classBuilder,
    );

    Class enclosingClass = classBuilder.cls;
    Constructor constructor = new Constructor(
      new FunctionNode(
        new EmptyStatement(),
        returnType: makeConstructorReturnType(enclosingClass),
      ),
      name: name,
      isSynthetic: true,
      reference: constructorReferences.constructorReference,
      fileUri: enclosingClass.fileUri,
    )..fileOffset = enclosingClass.fileOffset
    // TODO(johnniwinther): Should we add file end offsets to synthesized
    //  constructors?
    //..fileEndOffset = enclosingClass.fileOffset
    ;
    Procedure? constructorTearOff = createConstructorTearOffProcedure(
      new MemberName(libraryBuilder.libraryName, constructorTearOffName('')),
      libraryBuilder,
      enclosingClass.fileUri,
      enclosingClass.fileOffset,
      constructorReferences.tearOffReference,
      forAbstractClassOrEnumOrMixin:
          enclosingClass.isAbstract || enclosingClass.isEnum,
    );
    if (constructorTearOff != null) {
      DelayedDefaultValueCloner delayedDefaultValueCloner =
          buildConstructorTearOffProcedure(
            tearOff: constructorTearOff,
            declarationConstructor: constructor,
            implementationConstructor: constructor,
            enclosingDeclarationTypeParameters: classBuilder.cls.typeParameters,
            libraryBuilder: libraryBuilder,
          );
      registerDelayedDefaultValueCloner(delayedDefaultValueCloner);
    }
    ConstructorDeclaration declaration = new DefaultConstructorDeclaration(
      constructor: constructor,
      constructorTearOff: constructorTearOff,
    );

    return new SourceConstructorBuilder(
      name: '',
      libraryBuilder: libraryBuilder,
      declarationBuilder: classBuilder,
      fileOffset: classBuilder.fileOffset,
      fileUri: classBuilder.fileUri,
      constructorReferences: constructorReferences,
      nameScheme: nameScheme,
      introductory: declaration,
      isConst: false,
    );
  }

  DartType makeConstructorReturnType(Class enclosingClass) {
    List<DartType> typeParameterTypes = <DartType>[];
    for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
      TypeParameter typeParameter = enclosingClass.typeParameters[i];
      typeParameterTypes.add(
        new TypeParameterType.withDefaultNullability(typeParameter),
      );
    }
    return new InterfaceType(
      enclosingClass,
      enclosingClass.enclosingLibrary.nonNullable,
      typeParameterTypes,
    );
  }

  void setupTopAndBottomTypes() {
    LibraryBuilder coreLibrary = loader.coreLibrary;
    bindCoreType(coreLibrary, objectType);
    bindCoreType(coreLibrary, stringType);
    bindCoreType(coreLibrary, intType);
    bindCoreType(coreLibrary, dynamicType);
    bindCoreType(coreLibrary, nullType, isNullClass: true);
    bindCoreType(coreLibrary, bottomType);
    bindCoreType(coreLibrary, enumType);
    bindCoreType(coreLibrary, underscoreEnumType);
  }

  void computeCoreTypes() {
    List<Library> libraries = <Library>[];
    for (String platformLibrary in [
      "dart:_internal",
      "dart:async",
      "dart:core",
      "dart:mirrors",
      ...backendTarget.extraIndexedLibraries,
    ]) {
      Uri uri = Uri.parse(platformLibrary);
      LibraryBuilder? libraryBuilder = loader.lookupLoadedLibraryBuilder(uri);
      if (libraryBuilder == null) {
        // TODO(ahe): This is working around a bug in kernel_driver_test or
        // kernel_driver.
        bool found = false;
        for (Library target in dillTarget.loader.libraries) {
          if (target.importUri == uri) {
            libraries.add(target);
            found = true;
            break;
          }
        }
        if (!found && uri.path != "mirrors") {
          // Coverage-ignore-block(suite): Not run.
          // dart:mirrors is optional.
          throw "Can't find $uri";
        }
      } else {
        libraries.add(libraryBuilder.library);
      }
    }
    Component platformLibraries = backendTarget.configureComponent(
      new Component(),
    );
    // Add libraries directly to prevent that their parents are changed.
    platformLibraries.libraries.addAll(libraries);
    loader.computeCoreTypes(platformLibraries);
  }

  void finishAllConstructors(
    List<SourceClassBuilder> sourceClassBuilders,
    List<SourceExtensionTypeDeclarationBuilder>
    sourceExtensionTypeDeclarationBuilders,
  ) {
    Class objectClass = this.objectClass;
    for (SourceClassBuilder builder in sourceClassBuilders) {
      Class cls = builder.cls;
      if (cls != objectClass) {
        finishConstructors(builder);
      }
    }
    for (SourceExtensionTypeDeclarationBuilder builder
        in sourceExtensionTypeDeclarationBuilders) {
      finishExtensionTypeConstructors(builder);
    }

    ticker.logMs("Finished constructors");
  }

  /// Ensure constructors of [classBuilder] have the correct initializers and
  /// other requirements.
  void finishConstructors(SourceClassBuilder classBuilder) {
    Class cls = classBuilder.cls;

    Constructor? superTarget;
    for (Constructor constructor in cls.constructors) {
      if (constructor.isExternal) {
        continue;
      }
      bool isRedirecting = false;
      for (Initializer initializer in constructor.initializers) {
        if (initializer is RedirectingInitializer) {
          if (constructor.isConst && !initializer.target.isConst) {
            classBuilder.libraryBuilder.addProblem(
              codeConstConstructorRedirectionToNonConst,
              initializer.fileOffset,
              initializer.target.name.text.length,
              constructor.fileUri,
            );
          }
          isRedirecting = true;
          break;
        }
      }
      if (!isRedirecting) {
        /// >If no superinitializer is provided, an implicit superinitializer
        /// >of the form super() is added at the end of k’s initializer list,
        /// >unless the enclosing class is class Object.
        if (constructor.initializers.isEmpty) {
          superTarget ??= defaultSuperConstructor(cls);
          Initializer initializer;
          if (superTarget == null) {
            int offset = constructor.fileOffset;
            Uri fileUri = constructor.fileUri;
            if (offset == -1 &&
                // Coverage-ignore(suite): Not run.
                constructor.isSynthetic) {
              // Coverage-ignore-block(suite): Not run.
              offset = cls.fileOffset;
              fileUri = cls.fileUri;
            }
            classBuilder.libraryBuilder.addProblem(
              codeSuperclassHasNoDefaultConstructor.withArgumentsOld(
                cls.superclass!.name,
              ),
              offset,
              noLength,
              fileUri,
            );
            initializer = new InvalidInitializer();
          } else {
            initializer = new SuperInitializer(
              superTarget,
              new Arguments.empty(),
            )..isSynthetic = true;
          }
          constructor.initializers.add(initializer);
          initializer.parent = constructor;
        }
        if (constructor.function.body == null) {
          // Coverage-ignore-block(suite): Not run.
          /// >If a generative constructor c is not a redirecting constructor
          /// >and no body is provided, then c implicitly has an empty body {}.
          /// We use an empty statement instead.
          constructor.function.body = new EmptyStatement()
            ..parent = constructor.function;
        }
      }
    }

    _finishConstructors(classBuilder);
  }

  void finishExtensionTypeConstructors(
    SourceExtensionTypeDeclarationBuilder extensionTypeDeclaration,
  ) {
    _finishConstructors(extensionTypeDeclaration);
  }

  void _finishConstructors(SourceDeclarationBuilder classDeclaration) {
    SourceLibraryBuilder libraryBuilder = classDeclaration.libraryBuilder;

    /// Quotes below are from [Dart Programming Language Specification, 4th
    /// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf):
    List<SourcePropertyBuilder> uninitializedFields = [];
    List<SourcePropertyBuilder> nonFinalFields = [];
    List<SourcePropertyBuilder> lateFinalFields = [];

    Iterator<SourcePropertyBuilder> fieldIterator = classDeclaration
        .filteredMembersIterator(includeDuplicates: false);
    while (fieldIterator.moveNext()) {
      SourcePropertyBuilder fieldBuilder = fieldIterator.current;
      if (!fieldBuilder.hasConcreteField) {
        // Skip abstract and external fields. These are abstract/external
        // getters/setters and have no initialization.
        continue;
      }
      if (fieldBuilder.isDeclarationInstanceMember && !fieldBuilder.isFinal) {
        nonFinalFields.add(fieldBuilder);
      }
      if (fieldBuilder.isDeclarationInstanceMember &&
          fieldBuilder.isLate &&
          fieldBuilder.isFinal) {
        lateFinalFields.add(fieldBuilder);
      }
      if (!fieldBuilder.hasInitializer) {
        uninitializedFields.add(fieldBuilder);
      }
    }

    Map<SourceConstructorBuilder, Set<SourcePropertyBuilder>>
    constructorInitializedFields = new Map.identity();
    Set<SourcePropertyBuilder>? initializedFieldBuilders = null;
    Set<SourcePropertyBuilder>? uninitializedInstanceFields;

    Iterator<SourceConstructorBuilder> constructorIterator = classDeclaration
        .filteredConstructorsIterator(includeDuplicates: false);
    while (constructorIterator.moveNext()) {
      SourceConstructorBuilder constructor = constructorIterator.current;
      if (constructor.isEffectivelyRedirecting) continue;
      if (constructor.isConst && nonFinalFields.isNotEmpty) {
        classDeclaration.libraryBuilder.addProblem(
          codeConstConstructorNonFinalField,
          constructor.fileOffset,
          noLength,
          constructor.fileUri,
          context: nonFinalFields
              .map(
                (field) => codeConstConstructorNonFinalFieldCause.withLocation(
                  field.fileUri,
                  field.fileOffset,
                  noLength,
                ),
              )
              .toList(),
        );
        nonFinalFields.clear();
      }
      if (constructor.isConst && lateFinalFields.isNotEmpty) {
        for (SourcePropertyBuilder field in lateFinalFields) {
          classDeclaration.libraryBuilder.addProblem2(
            codeConstConstructorLateFinalFieldError,
            field.fieldUriOffset!,
            context: [
              codeConstConstructorLateFinalFieldCause.withLocation(
                constructor.fileUri,
                constructor.fileOffset,
                noLength,
              ),
            ],
          );
        }
        lateFinalFields.clear();
      }
      if (constructor.isEffectivelyExternal) {
        // Assume that an external constructor initializes all uninitialized
        // instance fields.
        uninitializedInstanceFields ??= uninitializedFields
            .where(
              (SourcePropertyBuilder fieldBuilder) => !fieldBuilder.isStatic,
            )
            .toSet();
        constructorInitializedFields[constructor] = uninitializedInstanceFields;
        (initializedFieldBuilders ??= new Set<SourcePropertyBuilder>.identity())
            .addAll(uninitializedInstanceFields);
      } else {
        Set<SourcePropertyBuilder> fields =
            constructor.takeInitializedFields() ?? const {};
        constructorInitializedFields[constructor] = fields;
        (initializedFieldBuilders ??= new Set<SourcePropertyBuilder>.identity())
            .addAll(fields);
      }
    }

    // Run through all fields that aren't initialized by any constructor, and
    // set their initializer to `null`.
    for (SourcePropertyBuilder fieldBuilder in uninitializedFields) {
      if (fieldBuilder.isExtensionTypeDeclaredInstanceField) continue;
      if (initializedFieldBuilders == null ||
          !initializedFieldBuilders.contains(fieldBuilder)) {
        if (!fieldBuilder.isLate) {
          if (fieldBuilder.isFinal) {
            String uri = '${libraryBuilder.importUri}';
            String file = fieldBuilder.fileUri.pathSegments.last;
            if (uri == 'dart:html' ||
                uri == 'dart:svg' ||
                uri == 'dart:_native_typed_data' ||
                uri == 'dart:_interceptors' &&
                    // Coverage-ignore(suite): Not run.
                    file == 'js_string.dart') {
              // TODO(johnniwinther): Use external getters instead of final
              // fields. See https://github.com/dart-lang/sdk/issues/33762
            } else {
              libraryBuilder.addProblem(
                codeFinalFieldNotInitialized.withArgumentsOld(
                  fieldBuilder.name,
                ),
                fieldBuilder.fileOffset,
                fieldBuilder.name.length,
                fieldBuilder.fileUri,
              );
            }
          } else if (fieldBuilder.fieldType is! InvalidType &&
              fieldBuilder.fieldType.isPotentiallyNonNullable) {
            libraryBuilder.addProblem(
              codeFieldNonNullableWithoutInitializerError.withArgumentsOld(
                fieldBuilder.name,
                fieldBuilder.fieldType,
              ),
              fieldBuilder.fileOffset,
              fieldBuilder.name.length,
              fieldBuilder.fileUri,
            );
          }
          fieldBuilder.buildImplicitDefaultValue();
        }
      }
    }

    // Run through all fields that are initialized by some constructor, and
    // make sure that all other constructors also initialize them.
    for (MapEntry<SourceConstructorBuilder, Set<SourcePropertyBuilder>> entry
        in constructorInitializedFields.entries) {
      SourceConstructorBuilder constructorBuilder = entry.key;
      Set<SourcePropertyBuilder> fieldBuilders = entry.value;
      bool hasReportedErrors = false;
      for (SourcePropertyBuilder fieldBuilder
          in initializedFieldBuilders!.difference(fieldBuilders)) {
        if (fieldBuilder.isExtensionTypeDeclaredInstanceField) continue;
        if (!fieldBuilder.hasInitializer && !fieldBuilder.isLate) {
          Initializer initializer = fieldBuilder.buildImplicitInitializer();
          constructorBuilder.prependInitializer(initializer);
          if (fieldBuilder.isFinal) {
            // Avoid cascading error if the constructor is known to be
            // erroneous: such constructors don't initialize the final fields
            // properly.
            if (!constructorBuilder.invokeTarget.isErroneous) {
              libraryBuilder.addProblem(
                codeFinalFieldNotInitializedByConstructor.withArgumentsOld(
                  fieldBuilder.name,
                ),
                constructorBuilder.fileOffset,
                constructorBuilder.name.length,
                constructorBuilder.fileUri,
                context: [
                  codeMissingImplementationCause
                      .withArgumentsOld(fieldBuilder.name)
                      .withLocation(
                        fieldBuilder.fileUri,
                        fieldBuilder.fileOffset,
                        fieldBuilder.name.length,
                      ),
                ],
              );
              hasReportedErrors = true;
            }
          } else if (fieldBuilder.fieldType is! InvalidType &&
              !fieldBuilder.isLate &&
              fieldBuilder.fieldType.isPotentiallyNonNullable) {
            libraryBuilder.addProblem(
              codeFieldNonNullableNotInitializedByConstructorError
                  .withArgumentsOld(fieldBuilder.name, fieldBuilder.fieldType),
              constructorBuilder.fileOffset,
              noLength,
              constructorBuilder.fileUri,
              context: [
                codeMissingImplementationCause
                    .withArgumentsOld(fieldBuilder.name)
                    .withLocation(
                      fieldBuilder.fileUri,
                      fieldBuilder.fileOffset,
                      fieldBuilder.name.length,
                    ),
              ],
            );
            hasReportedErrors = true;
          }
        }
      }

      if (hasReportedErrors) {
        constructorBuilder.markAsErroneous();
      }
    }
  }

  Future<void> validateDynamicModule() async {
    final Uri? dynamicInterfaceSpecificationUri =
        _options.dynamicInterfaceSpecificationUri;
    if (dynamicInterfaceSpecificationUri != null) {
      final String? dynamicInterfaceSpecification = await _options
          .loadDynamicInterfaceSpecification();
      if (dynamicInterfaceSpecification != null) {
        dynamic_module_validator.validateDynamicModule(
          dynamicInterfaceSpecification,
          dynamicInterfaceSpecificationUri,
          component!,
          loader.coreTypes,
          loader.hierarchy,
          loader.libraries,
          loader,
        );
      }
    }
  }

  /// Run all transformations that are needed when building a bundle of
  /// libraries for the first time.
  void runBuildTransformations() {
    backendTarget.performPreConstantEvaluationTransformations(
      component!,
      loader.coreTypes,
      loader.libraries,
      new KernelDiagnosticReporter(loader),
      logger:
          // Coverage-ignore(suite): Not run.
          (String msg) => ticker.logMs(msg),
      changedStructureNotifier: changedStructureNotifier,
    );

    TypeEnvironment environment = new TypeEnvironment(
      loader.coreTypes,
      loader.hierarchy,
    );

    constants.ConstantEvaluationData constantEvaluationData = constants
        .transformLibraries(
          component!,
          loader.libraries,
          backendTarget,
          environmentDefines,
          environment,
          new KernelConstantErrorReporter(loader),
          evaluateAnnotations: true,
          enableTripleShift: globalFeatures.tripleShift.isEnabled,
          enableConstFunctions: globalFeatures.constFunctions.isEnabled,
          enableConstructorTearOff:
              globalFeatures.constructorTearoffs.isEnabled,
          errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
          exhaustivenessDataForTesting: loader
              .dataForTesting
              // Coverage-ignore(suite): Not run.
              ?.exhaustivenessData,
        );
    ticker.logMs("Evaluated constants");

    markLibrariesUsed(constantEvaluationData.visitedLibraries);

    constants.ConstantCoverage coverage = constantEvaluationData.coverage;
    coverage.constructorCoverage.forEach((Uri fileUri, Set<Reference> value) {
      Source? source = uriToSource[fileUri];
      if (source != null) {
        source.constantCoverageConstructors ??= new Set<Reference>();
        source.constantCoverageConstructors!.addAll(value);
      }
    });
    ticker.logMs("Added constant coverage");

    backendTarget.performModularTransformationsOnLibraries(
      component!,
      loader.coreTypes,
      loader.hierarchy,
      loader.libraries,
      environmentDefines,
      new KernelDiagnosticReporter(loader),
      loader.referenceFromIndex,
      logger: (String msg) => ticker.logMs(msg),
      changedStructureNotifier: changedStructureNotifier,
    );
  }

  ChangedStructureNotifier? get changedStructureNotifier => null;

  // Coverage-ignore(suite): Not run.
  void runProcedureTransformations(Procedure procedure) {
    TypeEnvironment environment = new TypeEnvironment(
      loader.coreTypes,
      loader.hierarchy,
    );
    constants.transformProcedure(
      procedure,
      backendTarget,
      component!,
      environmentDefines,
      environment,
      new KernelConstantErrorReporter(loader),
      evaluateAnnotations: true,
      enableTripleShift: globalFeatures.tripleShift.isEnabled,
      enableConstFunctions: globalFeatures.constFunctions.isEnabled,
      enableConstructorTearOff: globalFeatures.constructorTearoffs.isEnabled,
      errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
    );
    ticker.logMs("Evaluated constants");

    backendTarget.performTransformationsOnProcedure(
      loader.coreTypes,
      loader.hierarchy,
      procedure,
      environmentDefines,
      logger: (String msg) => ticker.logMs(msg),
    );
  }

  void _verify({required bool allowVerificationErrorForTesting}) {
    // TODO(ahe): How to handle errors.
    List<LocatedMessage> errors = verifyComponent(
      context,
      VerificationStage.afterModularTransformations,
      component!,
      skipPlatform: context.options.skipPlatformVerification,
    );
    assert(
      allowVerificationErrorForTesting ||
          // Coverage-ignore(suite): Not run.
          errors.isEmpty,
      "Verification errors found: $errors",
    );
    ClassHierarchy hierarchy = new ClassHierarchy(
      component!,
      new CoreTypes(component!),
      onAmbiguousSupertypes: (Class cls, Supertype a, Supertype b) {
        // An error has already been reported.
      },
    );
    verifyGetStaticType(
      new TypeEnvironment(loader.coreTypes, hierarchy),
      component!,
      skipPlatform: context.options.skipPlatformVerification,
    );
    ticker.logMs("Verified component");
  }

  // Coverage-ignore(suite): Not run.
  /// Return `true` if the given [library] was built by this [KernelTarget]
  /// from sources, and not loaded from a [DillTarget].
  /// Note that this is meant for debugging etc and that it is slow, each
  /// call takes O(# libraries).
  bool isSourceLibraryForDebugging(Library library) {
    return loader.libraries.contains(library);
  }

  void readPatchFiles(
    SourceCompilationUnit compilationUnit,
    Uri originImportUri,
  ) {
    assert(
      originImportUri.isScheme("dart"),
      "Unexpected origin import uri: $originImportUri",
    );
    List<Uri>? patches = uriTranslator.getDartPatches(originImportUri.path);
    if (patches != null) {
      for (Uri patch in patches) {
        compilationUnit.registerAugmentation(
          loader.read(
            patch,
            -1,
            fileUri: patch,
            originImportUri: originImportUri,
            origin: compilationUnit,
            accessor: compilationUnit,
            isPatch: true,
          ),
        );
      }
    }
  }

  void releaseAncillaryResources() {
    component = null;
  }

  void markLibrariesUsed(Set<Library> visitedLibraries) {
    // Default implementation does nothing.
  }
}

/// Looks for a constructor call that matches `super()` from a constructor in
/// [cls]. Such a constructor may have optional arguments, but no required
/// arguments.
Constructor? defaultSuperConstructor(Class cls) {
  Class? superclass = cls.superclass;
  if (superclass != null) {
    for (Constructor constructor in superclass.constructors) {
      if (constructor.name.text.isEmpty) {
        return constructor.function.requiredParameterCount == 0
            ? constructor
            : null;
      }
    }
  }
  return null;
}

class KernelDiagnosticReporter
    extends DiagnosticReporter<Message, LocatedMessage> {
  final SourceLoader loader;

  KernelDiagnosticReporter(this.loader);

  @override
  void report(
    Message message,
    int charOffset,
    int length,
    Uri? fileUri, {
    List<LocatedMessage>? context,
  }) {
    loader.addProblem(message, charOffset, noLength, fileUri, context: context);
  }
}

class BuildResult {
  final Component? component;

  BuildResult({this.component});
}
