// Copyright (c) 2019, 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 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/type_algebra.dart';

import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/constructor_builder.dart';
import '../builder/field_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';
import '../builder/type_variable_builder.dart';
import '../constant_context.dart' show ConstantContext;
import '../dill/dill_member_builder.dart';
import '../kernel/body_builder.dart' show BodyBuilder;
import '../kernel/constructor_tearoff_lowering.dart';
import '../kernel/expression_generator_helper.dart'
    show ExpressionGeneratorHelper;
import '../kernel/hierarchy/class_member.dart' show ClassMember;
import '../kernel/kernel_helper.dart' show SynthesizedFunctionNode;
import '../kernel/utils.dart'
    show isRedirectingGenerativeConstructorImplementation;
import '../messages.dart'
    show
        Message,
        messageMoreThanOneSuperInitializer,
        messageRedirectingConstructorWithAnotherInitializer,
        messageRedirectingConstructorWithMultipleRedirectInitializers,
        messageRedirectingConstructorWithSuperInitializer,
        messageSuperInitializerNotLast,
        noLength;
import '../source/source_class_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
import '../source/source_loader.dart' show SourceLoader;
import '../source/source_member_builder.dart';
import '../type_inference/type_inferrer.dart';
import '../type_inference/type_schema.dart';
import '../util/helpers.dart' show DelayedActionPerformer;
import 'source_function_builder.dart';

class SourceConstructorBuilder extends FunctionBuilderImpl
    implements ConstructorBuilder {
  final Constructor _constructor;
  final Procedure? _constructorTearOff;

  Set<FieldBuilder>? _initializedFields;

  final int charOpenParenOffset;

  bool hasMovedSuperInitializer = false;

  SuperInitializer? superInitializer;

  RedirectingInitializer? redirectingInitializer;

  Token? beginInitializers;

  SourceConstructorBuilder? actualOrigin;

  Constructor get actualConstructor => _constructor;

  bool _hasFormalsInferred = false;

  final bool _hasSuperInitializingFormals;

  final List<SynthesizedFunctionNode> _superParameterDefaultValueCloners =
      <SynthesizedFunctionNode>[];

  SourceConstructorBuilder(
      List<MetadataBuilder>? metadata,
      int modifiers,
      TypeBuilder? returnType,
      String name,
      List<TypeVariableBuilder>? typeVariables,
      List<FormalParameterBuilder>? formals,
      SourceLibraryBuilder compilationUnit,
      int startCharOffset,
      int charOffset,
      this.charOpenParenOffset,
      int charEndOffset,
      Reference? constructorReference,
      Reference? tearOffReference,
      {String? nativeMethodName,
      required bool forAbstractClassOrEnum})
      : _constructor = new Constructor(new FunctionNode(null),
            name: new Name(name, compilationUnit.library),
            fileUri: compilationUnit.fileUri,
            reference: constructorReference)
          ..startFileOffset = startCharOffset
          ..fileOffset = charOffset
          ..fileEndOffset = charEndOffset
          ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
        _constructorTearOff = createConstructorTearOffProcedure(
            name,
            compilationUnit,
            compilationUnit.fileUri,
            charOffset,
            tearOffReference,
            forAbstractClassOrEnum: forAbstractClassOrEnum),
        _hasSuperInitializingFormals =
            formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
        super(metadata, modifiers, returnType, name, typeVariables, formals,
            compilationUnit, charOffset, nativeMethodName);

  @override
  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;

  @override
  SourceClassBuilder get classBuilder =>
      super.classBuilder as SourceClassBuilder;

  @override
  Member? get readTarget => _constructorTearOff ?? _constructor;

  @override
  Member? get writeTarget => null;

  @override
  Member get invokeTarget => constructor;

  @override
  FunctionNode get function => _constructor.function;

  @override
  Iterable<Member> get exportedMembers => [constructor];

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

  ConstructorBuilder? get patchForTesting =>
      dataForTesting?.patchForTesting as ConstructorBuilder?;

  @override
  bool get isDeclarationInstanceMember => false;

  @override
  bool get isClassInstanceMember => false;

  @override
  bool get isConstructor => true;

  @override
  AsyncMarker get asyncModifier => AsyncMarker.Sync;

  @override
  ProcedureKind? get kind => null;

  @override
  bool get isRedirectingGenerativeConstructor {
    return isRedirectingGenerativeConstructorImplementation(_constructor);
  }

  @override
  void buildMembers(
      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
    Member member = build(library);
    f(member, BuiltMemberKind.Constructor);
    if (_constructorTearOff != null) {
      f(_constructorTearOff!, BuiltMemberKind.Method);
    }
  }

  bool _hasBeenBuilt = false;

  @override
  Constructor build(SourceLibraryBuilder libraryBuilder) {
    if (!_hasBeenBuilt) {
      buildFunction(libraryBuilder);
      _constructor.function.fileOffset = charOpenParenOffset;
      _constructor.function.fileEndOffset = _constructor.fileEndOffset;
      _constructor.function.typeParameters = const <TypeParameter>[];
      _constructor.isConst = isConst;
      _constructor.isExternal = isExternal;
      updatePrivateMemberName(_constructor, libraryBuilder);

      if (_constructorTearOff != null) {
        buildConstructorTearOffProcedure(_constructorTearOff!, _constructor,
            classBuilder.cls, libraryBuilder);
      }

      _hasBeenBuilt = true;
    }
    if (formals != null) {
      bool needsInference = false;
      for (FormalParameterBuilder formal in formals!) {
        if (formal.type == null &&
            (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
          formal.variable!.type = const UnknownType();
          needsInference = true;
        }
      }
      if (needsInference) {
        assert(
            library == libraryBuilder,
            "Unexpected library builder ${libraryBuilder} for"
            " constructor $this in ${library}.");
        libraryBuilder.loader
            .registerConstructorToBeInferred(_constructor, this);
      }
    }
    return _constructor;
  }

  /// Infers the types of any untyped initializing formals.
  void inferFormalTypes(ClassHierarchy classHierarchy) {
    if (_hasFormalsInferred) return;
    if (formals != null) {
      for (FormalParameterBuilder formal in formals!) {
        if (formal.type == null) {
          if (formal.isInitializingFormal) {
            formal.finalizeInitializingFormal(classBuilder);
          }
        }
      }

      if (_hasSuperInitializingFormals) {
        if (beginInitializers != null) {
          BodyBuilder bodyBuilder = library.loader
              .createBodyBuilderForOutlineExpression(
                  library, classBuilder, this, classBuilder.scope, fileUri);
          bodyBuilder.constantContext = ConstantContext.required;
          bodyBuilder.parseInitializers(beginInitializers!,
              doFinishConstructor: false);
        }
        finalizeSuperInitializingFormals(
            classHierarchy, _superParameterDefaultValueCloners);
      }
    }
    _hasFormalsInferred = true;
  }

  /* ConstructorBuilder | DillConstructorBuilder */
  Object? _computeSuperTargetBuilder() {
    Constructor superTarget;
    ClassBuilder superclassBuilder;

    TypeBuilder? supertype = classBuilder.supertypeBuilder;
    if (supertype is NamedTypeBuilder) {
      TypeDeclarationBuilder? declaration = supertype.declaration;
      if (declaration is ClassBuilder) {
        superclassBuilder = declaration;
      } else if (declaration is TypeAliasBuilder) {
        declaration = declaration.unaliasDeclaration(supertype.arguments);
        if (declaration is ClassBuilder) {
          superclassBuilder = declaration;
        } else {
          // The error in this case should be reported elsewhere.
          return null;
        }
      } else {
        // The error in this case should be reported elsewhere.
        return null;
      }
    } else {
      // The error in this case should be reported elsewhere.
      return null;
    }

    if (constructor.initializers.isNotEmpty &&
        constructor.initializers.last is SuperInitializer) {
      superTarget = (constructor.initializers.last as SuperInitializer).target;
    } else {
      MemberBuilder? memberBuilder = superclassBuilder.constructors
          .lookup("", charOffset, library.fileUri);
      if (memberBuilder is ConstructorBuilder) {
        superTarget = memberBuilder.constructor;
      } else if (memberBuilder is DillConstructorBuilder) {
        superTarget = memberBuilder.constructor;
      } else {
        // The error in this case should be reported elsewhere.
        return null;
      }
    }

    MemberBuilder? constructorBuilder =
        superclassBuilder.findConstructorOrFactory(
            superTarget.name.text, charOffset, library.fileUri, library);
    return constructorBuilder is ConstructorBuilder ||
            constructorBuilder is DillConstructorBuilder
        ? constructorBuilder
        : null;
  }

  void finalizeSuperInitializingFormals(ClassHierarchy classHierarchy,
      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
    if (formals == null) return;
    if (!_hasSuperInitializingFormals) return;

    void performRecoveryForErroneousCase() {
      for (FormalParameterBuilder formal in formals!) {
        if (formal.isSuperInitializingFormal) {
          formal.variable!.type = const DynamicType();
        }
      }
    }

    Object? superTargetBuilder = _computeSuperTargetBuilder();
    Constructor superTarget;
    List<FormalParameterBuilder>? superFormals;
    if (superTargetBuilder is SourceConstructorBuilder) {
      superTarget = superTargetBuilder.constructor;
      superFormals = superTargetBuilder.formals!;
    } else if (superTargetBuilder is DillConstructorBuilder) {
      superTarget = superTargetBuilder.constructor;
      if (superTargetBuilder is SyntheticConstructorBuilder) {
        superFormals = superTargetBuilder.formals;
      } else {
        // The error in this case should be reported elsewhere. Here we perform
        // a simple recovery.
        return performRecoveryForErroneousCase();
      }
    } else {
      // The error in this case should be reported elsewhere. Here we perform a
      // simple recovery.
      return performRecoveryForErroneousCase();
    }

    if (superFormals == null) {
      // The error in this case should be reported elsewhere. Here we perform a
      // simple recovery.
      return performRecoveryForErroneousCase();
    }

    if (superTargetBuilder is SourceConstructorBuilder) {
      superTargetBuilder.inferFormalTypes(classHierarchy);
    } else if (superTargetBuilder is SyntheticConstructorBuilder) {
      MemberBuilder? superTargetOriginBuilder = superTargetBuilder.actualOrigin;
      if (superTargetOriginBuilder is SourceConstructorBuilder) {
        superTargetOriginBuilder.inferFormalTypes(classHierarchy);
      }
    }

    int superInitializingFormalIndex = -1;
    List<int>? positionalSuperParameters;
    List<String>? namedSuperParameters;

    Supertype? supertype = classHierarchy.getClassAsInstanceOf(
        classBuilder.cls, superTarget.enclosingClass);
    assert(supertype != null);
    Map<TypeParameter, DartType> substitution =
        new Map<TypeParameter, DartType>.fromIterables(
            supertype!.classNode.typeParameters, supertype.typeArguments);

    for (int formalIndex = 0; formalIndex < formals!.length; formalIndex++) {
      FormalParameterBuilder formal = formals![formalIndex];
      if (formal.isSuperInitializingFormal) {
        superInitializingFormalIndex++;
        bool hasImmediatelyDeclaredInitializer = formal.hasDeclaredInitializer;
        if (formal.type == null) {
          DartType? type;

          if (formal.isPositional) {
            if (superInitializingFormalIndex < superFormals.length) {
              FormalParameterBuilder correspondingSuperFormal =
                  superFormals[superInitializingFormalIndex];
              formal.hasDeclaredInitializer =
                  hasImmediatelyDeclaredInitializer ||
                      correspondingSuperFormal.hasDeclaredInitializer;
              if (!hasImmediatelyDeclaredInitializer) {
                (positionalSuperParameters ??= <int>[]).add(formalIndex);
              }
              type = correspondingSuperFormal.variable!.type;
            } else {
              // TODO(cstefantsova): Report an error.
            }
          } else {
            FormalParameterBuilder? correspondingSuperFormal;
            for (FormalParameterBuilder superFormal in superFormals) {
              if (superFormal.isNamed && superFormal.name == formal.name) {
                correspondingSuperFormal = superFormal;
                break;
              }
            }

            if (correspondingSuperFormal != null) {
              formal.hasDeclaredInitializer =
                  hasImmediatelyDeclaredInitializer ||
                      correspondingSuperFormal.hasDeclaredInitializer;
              if (!hasImmediatelyDeclaredInitializer) {
                (namedSuperParameters ??= <String>[]).add(formal.name);
              }
              type = correspondingSuperFormal.variable!.type;
            } else {
              // TODO(cstefantsova): Report an error.
            }
          }

          if (substitution.isNotEmpty && type != null) {
            type = substitute(type, substitution);
          }
          formal.variable!.type = type ?? const DynamicType();
        } else {
          formal.variable!.type = const DynamicType();
        }
      }
    }

    if (positionalSuperParameters != null || namedSuperParameters != null) {
      synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
          substitution, superTarget.function, constructor.function,
          positionalSuperParameters: positionalSuperParameters ?? const <int>[],
          namedSuperParameters: namedSuperParameters ?? const <String>[],
          isOutlineNode: true));
    }
  }

  bool _hasBuiltOutlines = false;

  @override
  void buildOutlineExpressions(
      SourceLibraryBuilder library,
      ClassHierarchy classHierarchy,
      List<DelayedActionPerformer> delayedActionPerformers,
      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
    if (_hasBuiltOutlines) return;
    if (isConst && isPatch) {
      origin.buildOutlineExpressions(library, classHierarchy,
          delayedActionPerformers, synthesizedFunctionNodes);
    }
    super.buildOutlineExpressions(library, classHierarchy,
        delayedActionPerformers, synthesizedFunctionNodes);

    // For modular compilation purposes we need to include initializers
    // for const constructors into the outline. We also need to parse
    // initializers to infer types of the super-initializing parameters.
    if ((isConst || _hasSuperInitializingFormals) &&
        beginInitializers != null) {
      BodyBuilder bodyBuilder = library.loader
          .createBodyBuilderForOutlineExpression(
              library, classBuilder, this, classBuilder.scope, fileUri);
      bodyBuilder.constantContext = ConstantContext.required;
      bodyBuilder.parseInitializers(beginInitializers!,
          doFinishConstructor: isConst);
      bodyBuilder.performBacklogComputations(delayedActionPerformers);
    }
    beginInitializers = null;
    addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
    if (isConst && isPatch) {
      _finishPatch();
    }
    _hasBuiltOutlines = true;
  }

  void addSuperParameterDefaultValueCloners(
      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
    Object? superTargetBuilder = _computeSuperTargetBuilder();
    if (superTargetBuilder is SourceConstructorBuilder) {
      superTargetBuilder
          .addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
    } else if (superTargetBuilder is SyntheticConstructorBuilder) {
      superTargetBuilder
          .addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
    }
    synthesizedFunctionNodes.addAll(_superParameterDefaultValueCloners);
    _superParameterDefaultValueCloners.clear();
  }

  @override
  void buildFunction(SourceLibraryBuilder library) {
    // According to the specification §9.3 the return type of a constructor
    // function is its enclosing class.
    super.buildFunction(library);
    Class enclosingClass = classBuilder.cls;
    List<DartType> typeParameterTypes = <DartType>[];
    for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
      TypeParameter typeParameter = enclosingClass.typeParameters[i];
      typeParameterTypes.add(
          new TypeParameterType.withDefaultNullabilityForLibrary(
              typeParameter, library.library));
    }
    function.returnType = new InterfaceType(
        enclosingClass, library.nonNullable, typeParameterTypes);
  }

  @override
  Constructor get constructor => isPatch ? origin.constructor : _constructor;

  @override
  Member get member => constructor;

  void injectInvalidInitializer(Message message, int charOffset, int length,
      ExpressionGeneratorHelper helper) {
    List<Initializer> initializers = _constructor.initializers;
    Initializer lastInitializer = initializers.removeLast();
    assert(lastInitializer == superInitializer ||
        lastInitializer == redirectingInitializer);
    Initializer error = helper.buildInvalidInitializer(
        helper.buildProblem(message, charOffset, length));
    initializers.add(error..parent = _constructor);
    initializers.add(lastInitializer);
  }

  void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
      {required InitializerInferenceResult? inferenceResult}) {
    List<Initializer> initializers = _constructor.initializers;
    if (initializer is SuperInitializer) {
      if (superInitializer != null) {
        injectInvalidInitializer(messageMoreThanOneSuperInitializer,
            initializer.fileOffset, "super".length, helper);
      } else if (redirectingInitializer != null) {
        injectInvalidInitializer(
            messageRedirectingConstructorWithSuperInitializer,
            initializer.fileOffset,
            "super".length,
            helper);
      } else {
        inferenceResult?.applyResult(initializers, _constructor);
        initializers.add(initializer..parent = _constructor);
        superInitializer = initializer;
      }
    } else if (initializer is RedirectingInitializer) {
      if (superInitializer != null) {
        // Point to the existing super initializer.
        injectInvalidInitializer(
            messageRedirectingConstructorWithSuperInitializer,
            superInitializer!.fileOffset,
            "super".length,
            helper);
      } else if (redirectingInitializer != null) {
        injectInvalidInitializer(
            messageRedirectingConstructorWithMultipleRedirectInitializers,
            initializer.fileOffset,
            noLength,
            helper);
      } else if (initializers.isNotEmpty) {
        // Error on all previous ones.
        for (int i = 0; i < initializers.length; i++) {
          Initializer initializer = initializers[i];
          int length = noLength;
          if (initializer is AssertInitializer) length = "assert".length;
          Initializer error = helper.buildInvalidInitializer(
              helper.buildProblem(
                  messageRedirectingConstructorWithAnotherInitializer,
                  initializer.fileOffset,
                  length));
          error.parent = _constructor;
          initializers[i] = error;
        }
        inferenceResult?.applyResult(initializers, _constructor);
        initializers.add(initializer..parent = _constructor);
        redirectingInitializer = initializer;
      } else {
        inferenceResult?.applyResult(initializers, _constructor);
        initializers.add(initializer..parent = _constructor);
        redirectingInitializer = initializer;
      }
    } else if (redirectingInitializer != null) {
      int length = noLength;
      if (initializer is AssertInitializer) length = "assert".length;
      injectInvalidInitializer(
          messageRedirectingConstructorWithAnotherInitializer,
          initializer.fileOffset,
          length,
          helper);
    } else if (superInitializer != null) {
      injectInvalidInitializer(messageSuperInitializerNotLast,
          initializer.fileOffset, noLength, helper);
    } else {
      inferenceResult?.applyResult(initializers, _constructor);
      initializers.add(initializer..parent = _constructor);
    }
  }

  @override
  VariableDeclaration? getTearOffParameter(int index) {
    if (_constructorTearOff != null) {
      if (index < _constructorTearOff!.function.positionalParameters.length) {
        return _constructorTearOff!.function.positionalParameters[index];
      } else {
        index -= _constructorTearOff!.function.positionalParameters.length;
        if (index < _constructorTearOff!.function.namedParameters.length) {
          return _constructorTearOff!.function.namedParameters[index];
        }
      }
    }
    return null;
  }

  void _finishPatch() {
    // TODO(ahe): restore file-offset once we track both origin and patch file
    // URIs. See https://github.com/dart-lang/sdk/issues/31579
    origin.constructor.fileUri = fileUri;
    origin.constructor.startFileOffset = _constructor.startFileOffset;
    origin.constructor.fileOffset = _constructor.fileOffset;
    origin.constructor.fileEndOffset = _constructor.fileEndOffset;
    origin.constructor.annotations
        .forEach((m) => m.fileOffset = _constructor.fileOffset);

    origin.constructor.isExternal = _constructor.isExternal;
    origin.constructor.function = _constructor.function;
    origin.constructor.function.parent = origin.constructor;
    origin.constructor.initializers = _constructor.initializers;
    setParents(origin.constructor.initializers, origin.constructor);
  }

  @override
  int finishPatch() {
    if (!isPatch) return 0;
    _finishPatch();
    return 1;
  }

  @override
  void becomeNative(SourceLoader loader) {
    _constructor.isExternal = true;
    super.becomeNative(loader);
  }

  @override
  void applyPatch(Builder patch) {
    if (patch is SourceConstructorBuilder) {
      if (checkPatch(patch)) {
        patch.actualOrigin = this;
        dataForTesting?.patchForTesting = patch;
      }
    } else {
      reportPatchMismatch(patch);
    }
  }

  void prepareInitializers() {
    // For const constructors we parse initializers already at the outlining
    // stage, there is no easy way to make body building stage skip initializer
    // parsing, so we simply clear parsed initializers and rebuild them
    // again.
    // For when doing an experimental incremental compilation they are also
    // potentially done more than once (because it rebuilds the bodies of an old
    // compile), and so we also clear them.
    // Note: this method clears both initializers from the target Kernel node
    // and internal state associated with parsing initializers.
    _constructor.initializers = [];
    redirectingInitializer = null;
    superInitializer = null;
    hasMovedSuperInitializer = false;
  }

  @override
  List<ClassMember> get localMembers =>
      throw new UnsupportedError('${runtimeType}.localMembers');

  @override
  List<ClassMember> get localSetters =>
      throw new UnsupportedError('${runtimeType}.localSetters');

  /// Registers field as being initialized by this constructor.
  ///
  /// The field can be initialized either via an initializing formal or via an
  /// entry in the constructor initializer list.
  void registerInitializedField(FieldBuilder fieldBuilder) {
    (_initializedFields ??= {}).add(fieldBuilder);
  }

  /// Returns the fields registered as initialized by this constructor.
  ///
  /// Returns the set of fields previously registered via
  /// [registerInitializedField] and passes on the ownership of the collection
  /// to the caller.
  Set<FieldBuilder>? takeInitializedFields() {
    Set<FieldBuilder>? result = _initializedFields;
    _initializedFields = null;
    return result;
  }
}

class SyntheticConstructorBuilder extends DillConstructorBuilder
    with SourceMemberBuilderMixin {
  // TODO(johnniwinther,cstefantsova): Rename [_origin] to avoid the confusion
  // with patches.
  // TODO(johnniwinther): Change the type of [_origin] to SourceMemberBuilder
  // when it's the supertype for both old SourceMemberBuilder and
  // SyntheticConstructorBuilder.
  MemberBuilder? _origin;
  SynthesizedFunctionNode? _synthesizedFunctionNode;

  SyntheticConstructorBuilder(SourceClassBuilder parent,
      Constructor constructor, Procedure? constructorTearOff,
      {MemberBuilder? origin, SynthesizedFunctionNode? synthesizedFunctionNode})
      : _origin = origin,
        _synthesizedFunctionNode = synthesizedFunctionNode,
        super(constructor, constructorTearOff, parent);

  // TODO(johnniwinther,cstefantsova): Rename [actualOrigin] to avoid the
  //  confusion with patches.
  MemberBuilder? get actualOrigin {
    MemberBuilder? origin = _origin;
    while (origin is SyntheticConstructorBuilder) {
      origin = origin._origin;
    }
    return origin;
  }

  List<FormalParameterBuilder>? get formals {
    MemberBuilder? origin = actualOrigin;
    return origin is SourceConstructorBuilder ? origin.formals : null;
  }

  @override
  void buildOutlineExpressions(
      SourceLibraryBuilder libraryBuilder,
      ClassHierarchy classHierarchy,
      List<DelayedActionPerformer> delayedActionPerformers,
      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
    if (_origin != null) {
      // Ensure that default value expressions have been created for [_origin].
      LibraryBuilder originLibraryBuilder = _origin!.library;
      if (originLibraryBuilder is SourceLibraryBuilder) {
        // If [_origin] is from a source library, we need to build the default
        // values and initializers first.
        MemberBuilder origin = _origin!;
        if (origin is SourceConstructorBuilder) {
          origin.buildOutlineExpressions(originLibraryBuilder, classHierarchy,
              delayedActionPerformers, synthesizedFunctionNodes);
        } else if (origin is SyntheticConstructorBuilder) {
          origin.buildOutlineExpressions(originLibraryBuilder, classHierarchy,
              delayedActionPerformers, synthesizedFunctionNodes);
        }
      }
      addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
      _origin = null;
    }
  }

  void addSuperParameterDefaultValueCloners(
      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
    MemberBuilder? origin = _origin;
    if (origin is SourceConstructorBuilder) {
      origin.addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
    } else if (origin is SyntheticConstructorBuilder) {
      origin.addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
    }
    if (_synthesizedFunctionNode != null) {
      synthesizedFunctionNodes
          .add(_synthesizedFunctionNode!..isOutlineNode = true);
      _synthesizedFunctionNode = null;
    }
  }
}
