[cfe] Create constructors through fragments

Change-Id: If2a7095c09dcf2d73d326b6ba6d796acfa882c55
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/408780
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
index 68aa737..0719373 100644
--- a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
@@ -225,7 +225,7 @@
 
   void finalizeInitializingFormal(
       DeclarationBuilder declarationBuilder,
-      ConstructorDeclaration constructorDeclaration,
+      ConstructorDeclarationBuilder constructorDeclaration,
       ClassHierarchyBase hierarchy) {
     String fieldName = isWildcardLoweredFormalParameter(name) ? '_' : name;
     Builder? fieldBuilder = declarationBuilder.lookupLocalMember(fieldName);
diff --git a/pkg/front_end/lib/src/fragment/constructor.dart b/pkg/front_end/lib/src/fragment/constructor.dart
index 55ce76f..d35939c 100644
--- a/pkg/front_end/lib/src/fragment/constructor.dart
+++ b/pkg/front_end/lib/src/fragment/constructor.dart
@@ -22,7 +22,7 @@
   final bool forAbstractClassOrMixin;
   Token? _beginInitializers;
 
-  AbstractSourceConstructorBuilder? _builder;
+  SourceConstructorBuilderImpl? _builder;
 
   ConstructorFragment(
       {required this.constructorName,
@@ -55,12 +55,12 @@
   }
 
   @override
-  AbstractSourceConstructorBuilder get builder {
+  SourceConstructorBuilderImpl get builder {
     assert(_builder != null, "Builder has not been computed for $this.");
     return _builder!;
   }
 
-  void set builder(AbstractSourceConstructorBuilder value) {
+  void set builder(SourceConstructorBuilderImpl value) {
     assert(_builder == null, "Builder has already been computed for $this.");
     _builder = value;
   }
@@ -91,8 +91,7 @@
       //  constructor body. An error is reported by the parser but we skip
       //  the body here to avoid overwriting the already lowering const
       //  constructor.
-      !(_fragment.builder is SourceExtensionTypeConstructorBuilder &&
-          _fragment.modifiers.isConst);
+      !(_fragment.builder.isExtensionTypeMember && _fragment.modifiers.isConst);
 
   @override
   LocalScope computeFormalParameterScope(LookupScope typeParameterScope) {
diff --git a/pkg/front_end/lib/src/fragment/constructor/declaration.dart b/pkg/front_end/lib/src/fragment/constructor/declaration.dart
new file mode 100644
index 0000000..f0e51ea
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/constructor/declaration.dart
@@ -0,0 +1,677 @@
+// Copyright (c) 2025, 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:kernel/ast.dart';
+import 'package:kernel/type_algebra.dart';
+
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/metadata_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/internal_ast.dart';
+import '../../kernel/kernel_helper.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_constructor_builder.dart';
+import '../../source/source_extension_type_declaration_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_member_builder.dart';
+import '../fragment.dart';
+import 'encoding.dart';
+
+abstract class ConstructorDeclaration {
+  List<MetadataBuilder>? get metadata;
+
+  OmittedTypeBuilder get returnType;
+
+  List<NominalParameterBuilder>? get typeParameters;
+
+  List<FormalParameterBuilder>? get formals;
+
+  Member get constructor;
+
+  Procedure? get tearOff;
+
+  FunctionNode get function;
+
+  Member get readTarget;
+
+  Reference get readTargetReference;
+
+  Member get invokeTarget;
+
+  Reference get invokeTargetReference;
+
+  void registerFunctionBody(Statement value);
+
+  void registerNoBodyConstructor();
+
+  VariableDeclaration? get thisVariable;
+
+  List<TypeParameter>? get thisTypeParameters;
+
+  List<Initializer> get initializers;
+
+  void createNode(
+      {required String name,
+      required SourceLibraryBuilder libraryBuilder,
+      required NameScheme nameScheme,
+      required Reference? constructorReference,
+      required Reference? tearOffReference});
+
+  void buildOutlineNodes(
+    BuildNodesCallback f, {
+    required SourceConstructorBuilder constructorBuilder,
+    required SourceLibraryBuilder libraryBuilder,
+    required Member declarationConstructor,
+    required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+  });
+
+  void prepareInitializers();
+
+  void prependInitializer(Initializer initializer);
+
+  void becomeNative();
+
+  VariableDeclaration? getTearOffParameter(int index);
+
+  void finishAugmentation(SourceConstructorBuilder origin);
+
+  Substitution computeFieldTypeSubstitution(
+      DeclarationBuilder declarationBuilder);
+
+  void buildBody();
+
+  bool get isRedirecting;
+
+  bool get hasSuperInitializingFormals;
+
+  void addSuperParameterDefaultValueCloners(
+      {required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+      required Member superTarget,
+      required List<int?>? positionalSuperParameters,
+      required List<String>? namedSuperParameters,
+      required SourceLibraryBuilder libraryBuilder});
+}
+
+mixin RegularConstructorDeclarationMixin implements ConstructorDeclaration {
+  RegularConstructorEncoding get _encoding;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Member get constructor => _encoding.constructor;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Procedure? get tearOff => _encoding.constructorTearOff;
+
+  @override
+  FunctionNode get function => _encoding.function;
+
+  @override
+  Member get readTarget => _encoding.readTarget;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Reference get readTargetReference => _encoding.readTargetReference;
+
+  @override
+  Member get invokeTarget => _encoding.invokeTarget;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Reference get invokeTargetReference => _encoding.invokeTargetReference;
+
+  @override
+  void registerFunctionBody(Statement value) {
+    _encoding.registerFunctionBody(value);
+  }
+
+  @override
+  void registerNoBodyConstructor() {
+    _encoding.registerNoBodyConstructor();
+  }
+
+  @override
+  VariableDeclaration? get thisVariable => null;
+
+  @override
+  List<TypeParameter>? get thisTypeParameters => null;
+
+  @override
+  List<Initializer> get initializers => _encoding.initializers;
+
+  @override
+  void prepareInitializers() {
+    _encoding.prepareInitializers();
+  }
+
+  @override
+  void prependInitializer(Initializer initializer) {
+    _encoding.prependInitializer(initializer);
+  }
+
+  @override
+  void becomeNative() {
+    _encoding.becomeNative();
+  }
+
+  @override
+  VariableDeclaration? getTearOffParameter(int index) {
+    return _encoding.getTearOffParameter(index);
+  }
+
+  @override
+  void finishAugmentation(SourceConstructorBuilder origin) {
+    _encoding.finishAugmentation(origin);
+  }
+
+  @override
+  Substitution computeFieldTypeSubstitution(
+      DeclarationBuilder declarationBuilder) {
+    // Nothing to substitute. Regular generative constructors don't have their
+    // own type parameters.
+    return Substitution.empty;
+  }
+
+  @override
+  void buildBody() {}
+
+  @override
+  bool get isRedirecting {
+    for (Initializer initializer in initializers) {
+      if (initializer is RedirectingInitializer) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  late final bool hasSuperInitializingFormals =
+      formals?.any((formal) => formal.isSuperInitializingFormal) ?? false;
+
+  @override
+  void addSuperParameterDefaultValueCloners(
+      {required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+      required Member superTarget,
+      required List<int?>? positionalSuperParameters,
+      required List<String>? namedSuperParameters,
+      required SourceLibraryBuilder libraryBuilder}) {
+    _encoding.addSuperParameterDefaultValueCloners(
+        delayedDefaultValueCloners: delayedDefaultValueCloners,
+        superTarget: superTarget,
+        positionalSuperParameters: positionalSuperParameters,
+        namedSuperParameters: namedSuperParameters,
+        libraryBuilder: libraryBuilder);
+  }
+}
+
+class RegularConstructorDeclaration
+    with RegularConstructorDeclarationMixin
+    implements ConstructorDeclaration {
+  final ConstructorFragment _fragment;
+  final List<FormalParameterBuilder>? _syntheticFormals;
+
+  @override
+  final RegularConstructorEncoding _encoding;
+
+  @override
+  final List<NominalParameterBuilder>? typeParameters;
+
+  RegularConstructorDeclaration(this._fragment,
+      {required List<FormalParameterBuilder>? syntheticFormals,
+      required this.typeParameters})
+      : _syntheticFormals = syntheticFormals,
+        _encoding = new RegularConstructorEncoding(
+            isExternal: _fragment.modifiers.isExternal);
+
+  @override
+  List<MetadataBuilder>? get metadata => _fragment.metadata;
+
+  @override
+  OmittedTypeBuilder get returnType => _fragment.returnType;
+
+  @override
+  late final List<FormalParameterBuilder>? formals = _syntheticFormals != null
+      ? [..._syntheticFormals, ...?_fragment.formals]
+      : _fragment.formals;
+
+  @override
+  void createNode(
+      {required String name,
+      required SourceLibraryBuilder libraryBuilder,
+      required NameScheme nameScheme,
+      required Reference? constructorReference,
+      required Reference? tearOffReference}) {
+    _encoding.createNode(
+        name: name,
+        libraryBuilder: libraryBuilder,
+        nameScheme: nameScheme,
+        constructorReference: constructorReference,
+        tearOffReference: tearOffReference,
+        fileUri: _fragment.fileUri,
+        startOffset: _fragment.startOffset,
+        fileOffset: _fragment.fullNameOffset,
+        endOffset: _fragment.endOffset,
+        isSynthetic: false,
+        forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
+  }
+
+  @override
+  void buildOutlineNodes(BuildNodesCallback f,
+      {required SourceConstructorBuilder constructorBuilder,
+      required SourceLibraryBuilder libraryBuilder,
+      required Member declarationConstructor,
+      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+    _encoding.buildOutlineNodes(f,
+        constructorBuilder: constructorBuilder,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder:
+            constructorBuilder.declarationBuilder as SourceClassBuilder,
+        declarationConstructor: declarationConstructor,
+        formalsOffset: _fragment.formalsOffset,
+        isConst: _fragment.modifiers.isConst,
+        returnType: returnType,
+        typeParameters: typeParameters,
+        formals: formals,
+        delayedDefaultValueCloners: delayedDefaultValueCloners);
+  }
+}
+
+// Coverage-ignore(suite): Not run.
+class PrimaryConstructorDeclaration
+    with RegularConstructorDeclarationMixin
+    implements ConstructorDeclaration {
+  final PrimaryConstructorFragment _fragment;
+
+  @override
+  final RegularConstructorEncoding _encoding;
+
+  PrimaryConstructorDeclaration(this._fragment)
+      : _encoding = new RegularConstructorEncoding(
+            isExternal: _fragment.modifiers.isExternal);
+
+  @override
+  OmittedTypeBuilder get returnType => _fragment.returnType;
+
+  @override
+  List<MetadataBuilder>? get metadata => null;
+
+  @override
+  List<FormalParameterBuilder>? get formals => _fragment.formals;
+
+  @override
+  List<NominalParameterBuilder>? get typeParameters => null;
+
+  @override
+  void createNode(
+      {required String name,
+      required SourceLibraryBuilder libraryBuilder,
+      required NameScheme nameScheme,
+      required Reference? constructorReference,
+      required Reference? tearOffReference}) {
+    _encoding.createNode(
+        name: name,
+        libraryBuilder: libraryBuilder,
+        nameScheme: nameScheme,
+        constructorReference: constructorReference,
+        tearOffReference: tearOffReference,
+        fileUri: _fragment.fileUri,
+        startOffset: _fragment.startOffset,
+        fileOffset: _fragment.fileOffset,
+        // TODO(johnniwinther): Provide `endOffset`.
+        endOffset: _fragment.formalsOffset,
+        isSynthetic: false,
+        forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
+  }
+
+  @override
+  void buildOutlineNodes(BuildNodesCallback f,
+      {required SourceConstructorBuilder constructorBuilder,
+      required SourceLibraryBuilder libraryBuilder,
+      required Member declarationConstructor,
+      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+    _encoding.buildOutlineNodes(f,
+        constructorBuilder: constructorBuilder,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder:
+            constructorBuilder.declarationBuilder as SourceClassBuilder,
+        declarationConstructor: declarationConstructor,
+        formalsOffset: _fragment.formalsOffset,
+        isConst: _fragment.modifiers.isConst,
+        returnType: returnType,
+        typeParameters: typeParameters,
+        formals: formals,
+        delayedDefaultValueCloners: delayedDefaultValueCloners);
+  }
+}
+
+class DefaultEnumConstructorDeclaration
+    with RegularConstructorDeclarationMixin
+    implements ConstructorDeclaration {
+  final Uri _fileUri;
+  final int _fileOffset;
+
+  @override
+  final OmittedTypeBuilder returnType;
+
+  @override
+  final List<FormalParameterBuilder> formals;
+
+  @override
+  final RegularConstructorEncoding _encoding =
+      new RegularConstructorEncoding(isExternal: false);
+
+  DefaultEnumConstructorDeclaration(
+      {required this.returnType,
+      required this.formals,
+      required Uri fileUri,
+      required int fileOffset})
+      : _fileUri = fileUri,
+        _fileOffset = fileOffset;
+
+  @override
+  List<MetadataBuilder>? get metadata => null;
+
+  @override
+  List<NominalParameterBuilder>? get typeParameters => null;
+
+  @override
+  void createNode(
+      {required String name,
+      required SourceLibraryBuilder libraryBuilder,
+      required NameScheme nameScheme,
+      required Reference? constructorReference,
+      required Reference? tearOffReference}) {
+    _encoding.createNode(
+        name: name,
+        libraryBuilder: libraryBuilder,
+        nameScheme: nameScheme,
+        constructorReference: constructorReference,
+        tearOffReference: tearOffReference,
+        fileUri: _fileUri,
+        startOffset: _fileOffset,
+        fileOffset: _fileOffset,
+        endOffset: _fileOffset,
+        isSynthetic: true,
+        forAbstractClassOrEnumOrMixin: true);
+  }
+
+  @override
+  void buildOutlineNodes(BuildNodesCallback f,
+      {required SourceConstructorBuilder constructorBuilder,
+      required SourceLibraryBuilder libraryBuilder,
+      required Member declarationConstructor,
+      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+    _encoding.buildOutlineNodes(f,
+        constructorBuilder: constructorBuilder,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder:
+            constructorBuilder.declarationBuilder as SourceClassBuilder,
+        declarationConstructor: declarationConstructor,
+        formalsOffset: _fileOffset,
+        isConst: true,
+        returnType: returnType,
+        typeParameters: typeParameters,
+        formals: formals,
+        delayedDefaultValueCloners: delayedDefaultValueCloners);
+  }
+}
+
+mixin ExtensionTypeConstructorDeclarationMixin
+    implements ConstructorDeclaration {
+  ExtensionTypeConstructorEncoding get _encoding;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Member get constructor => _encoding.constructor;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Procedure? get tearOff => _encoding.constructorTearOff;
+
+  @override
+  FunctionNode get function => _encoding.function;
+
+  @override
+  Member get readTarget => _encoding.readTarget;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Reference get readTargetReference => _encoding.readTargetReference;
+
+  @override
+  Member get invokeTarget => _encoding.invokeTarget;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Reference get invokeTargetReference => _encoding.invokeTargetReference;
+
+  @override
+  void registerFunctionBody(Statement value) {
+    _encoding.registerFunctionBody(value);
+  }
+
+  @override
+  void registerNoBodyConstructor() {
+    _encoding.registerNoBodyConstructor();
+  }
+
+  @override
+  VariableDeclaration? get thisVariable => _encoding.thisVariable;
+
+  @override
+  List<TypeParameter>? get thisTypeParameters => _encoding.thisTypeParameters;
+
+  @override
+  List<Initializer> get initializers => _encoding.initializers;
+
+  @override
+  void prepareInitializers() {
+    _encoding.prepareInitializers();
+  }
+
+  @override
+  void prependInitializer(Initializer initializer) {
+    _encoding.prependInitializer(initializer);
+  }
+
+  @override
+  void becomeNative() {
+    throw new UnsupportedError("$runtimeType.becomeNative()");
+  }
+
+  @override
+  VariableDeclaration? getTearOffParameter(int index) {
+    return _encoding.getTearOffParameter(index);
+  }
+
+  @override
+  void finishAugmentation(SourceConstructorBuilder origin) {
+    throw new UnsupportedError('$runtimeType.finishAugmentation');
+  }
+
+  @override
+  Substitution computeFieldTypeSubstitution(
+      DeclarationBuilder declarationBuilder) {
+    if (typeParameters != null) {
+      assert(
+          declarationBuilder.typeParameters!.length == typeParameters?.length);
+      return Substitution.fromPairs(
+          (declarationBuilder as SourceExtensionTypeDeclarationBuilder)
+              .extensionTypeDeclaration
+              .typeParameters,
+          new List<DartType>.generate(
+              declarationBuilder.typeParameters!.length,
+              (int index) => new TypeParameterType.withDefaultNullability(
+                  function.typeParameters[index])));
+    } else {
+      return Substitution.empty;
+    }
+  }
+
+  @override
+  void buildBody() {
+    _encoding.buildBody();
+  }
+
+  @override
+  bool get isRedirecting {
+    for (Initializer initializer in initializers) {
+      if (initializer is ExtensionTypeRedirectingInitializer) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  late final bool hasSuperInitializingFormals =
+      formals?.any((formal) => formal.isSuperInitializingFormal) ?? false;
+
+  @override
+  void addSuperParameterDefaultValueCloners(
+      {required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+      required Member superTarget,
+      required List<int?>? positionalSuperParameters,
+      required List<String>? namedSuperParameters,
+      required SourceLibraryBuilder libraryBuilder}) {
+    throw new UnsupportedError(
+        '$runtimeType.addSuperParameterDefaultValueCloners');
+  }
+}
+
+class ExtensionTypeConstructorDeclaration
+    with ExtensionTypeConstructorDeclarationMixin
+    implements ConstructorDeclaration {
+  final ConstructorFragment _fragment;
+
+  @override
+  final List<NominalParameterBuilder>? typeParameters;
+
+  @override
+  final ExtensionTypeConstructorEncoding _encoding;
+
+  ExtensionTypeConstructorDeclaration(this._fragment,
+      {required this.typeParameters})
+      : _encoding = new ExtensionTypeConstructorEncoding(
+            isExternal: _fragment.modifiers.isExternal);
+
+  @override
+  List<MetadataBuilder>? get metadata => _fragment.metadata;
+
+  @override
+  OmittedTypeBuilder get returnType => _fragment.returnType;
+
+  @override
+  List<FormalParameterBuilder>? get formals => _fragment.formals;
+
+  @override
+  void createNode(
+      {required String name,
+      required SourceLibraryBuilder libraryBuilder,
+      required NameScheme nameScheme,
+      required Reference? constructorReference,
+      required Reference? tearOffReference}) {
+    _encoding.createNode(
+        name: name,
+        libraryBuilder: libraryBuilder,
+        nameScheme: nameScheme,
+        constructorReference: constructorReference,
+        tearOffReference: tearOffReference,
+        fileUri: _fragment.fileUri,
+        fileOffset: _fragment.fullNameOffset,
+        endOffset: _fragment.endOffset,
+        forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
+  }
+
+  @override
+  void buildOutlineNodes(BuildNodesCallback f,
+      {required SourceConstructorBuilder constructorBuilder,
+      required SourceLibraryBuilder libraryBuilder,
+      required Member declarationConstructor,
+      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+    _encoding.buildOutlineNodes(f,
+        constructorBuilder: constructorBuilder,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder: constructorBuilder.declarationBuilder
+            as SourceExtensionTypeDeclarationBuilder,
+        declarationConstructor: declarationConstructor,
+        fileOffset: _fragment.fullNameOffset,
+        formalsOffset: _fragment.formalsOffset,
+        isConst: _fragment.modifiers.isConst,
+        returnType: returnType,
+        typeParameters: typeParameters,
+        formals: formals,
+        delayedDefaultValueCloners: delayedDefaultValueCloners);
+  }
+}
+
+class ExtensionTypePrimaryConstructorDeclaration
+    with ExtensionTypeConstructorDeclarationMixin
+    implements ConstructorDeclaration {
+  final PrimaryConstructorFragment _fragment;
+
+  @override
+  final List<NominalParameterBuilder>? typeParameters;
+
+  @override
+  final ExtensionTypeConstructorEncoding _encoding;
+
+  ExtensionTypePrimaryConstructorDeclaration(this._fragment,
+      {required this.typeParameters})
+      : _encoding = new ExtensionTypeConstructorEncoding(
+            isExternal: _fragment.modifiers.isExternal);
+
+  @override
+  List<MetadataBuilder>? get metadata => null;
+
+  @override
+  OmittedTypeBuilder get returnType => _fragment.returnType;
+
+  @override
+  List<FormalParameterBuilder>? get formals => _fragment.formals;
+
+  @override
+  void createNode(
+      {required String name,
+      required SourceLibraryBuilder libraryBuilder,
+      required NameScheme nameScheme,
+      required Reference? constructorReference,
+      required Reference? tearOffReference}) {
+    _encoding.createNode(
+        name: name,
+        libraryBuilder: libraryBuilder,
+        nameScheme: nameScheme,
+        constructorReference: constructorReference,
+        tearOffReference: tearOffReference,
+        fileUri: _fragment.fileUri,
+        fileOffset: _fragment.fileOffset,
+        // TODO(johnniwinther): Provide `endOffset`.
+        endOffset: _fragment.formalsOffset,
+        forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
+  }
+
+  @override
+  void buildOutlineNodes(BuildNodesCallback f,
+      {required SourceConstructorBuilder constructorBuilder,
+      required SourceLibraryBuilder libraryBuilder,
+      required Member declarationConstructor,
+      required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
+    _encoding.buildOutlineNodes(f,
+        constructorBuilder: constructorBuilder,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder: constructorBuilder.declarationBuilder
+            as SourceExtensionTypeDeclarationBuilder,
+        declarationConstructor: declarationConstructor,
+        fileOffset: _fragment.fileOffset,
+        formalsOffset: _fragment.formalsOffset,
+        isConst: _fragment.modifiers.isConst,
+        returnType: returnType,
+        typeParameters: typeParameters,
+        formals: formals,
+        delayedDefaultValueCloners: delayedDefaultValueCloners);
+  }
+}
diff --git a/pkg/front_end/lib/src/fragment/constructor/encoding.dart b/pkg/front_end/lib/src/fragment/constructor/encoding.dart
new file mode 100644
index 0000000..2ac19d0
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/constructor/encoding.dart
@@ -0,0 +1,564 @@
+// Copyright (c) 2025, 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:kernel/ast.dart';
+
+import '../../api_prototype/lowering_predicates.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/omitted_type_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/constructor_tearoff_lowering.dart';
+import '../../kernel/internal_ast.dart';
+import '../../kernel/kernel_helper.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_constructor_builder.dart';
+import '../../source/source_extension_type_declaration_builder.dart';
+import '../../source/source_function_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_member_builder.dart';
+import '../../type_inference/type_schema.dart';
+
+class RegularConstructorEncoding {
+  late final Constructor _constructor;
+
+  late final Procedure? _constructorTearOff;
+
+  final bool _isExternal;
+
+  Statement? bodyInternal;
+
+  RegularConstructorEncoding({required bool isExternal})
+      : _isExternal = isExternal;
+
+  Member get readTarget =>
+      _constructorTearOff ??
+      // The case is need to ensure that the upper bound is [Member] and not
+      // [GenericFunction].
+      _constructor as Member;
+
+  // Coverage-ignore(suite): Not run.
+  Reference get readTargetReference =>
+      (_constructorTearOff ?? _constructor).reference;
+
+  Member get invokeTarget => _constructor;
+
+  // Coverage-ignore(suite): Not run.
+  Reference get invokeTargetReference => _constructor.reference;
+
+  void registerFunctionBody(Statement value) {
+    function.body = value..parent = function;
+  }
+
+  void registerNoBodyConstructor() {
+    if (!_isExternal) {
+      registerFunctionBody(new EmptyStatement());
+    }
+  }
+
+  FunctionNode get function => _constructor.function;
+
+  void createNode(
+      {required String name,
+      required SourceLibraryBuilder libraryBuilder,
+      required NameScheme nameScheme,
+      required Reference? constructorReference,
+      required Reference? tearOffReference,
+      required Uri fileUri,
+      required int startOffset,
+      required int fileOffset,
+      required int endOffset,
+      required bool isSynthetic,
+      required bool forAbstractClassOrEnumOrMixin}) {
+    _constructor = new Constructor(
+        new FunctionNode(_isExternal ? null : new EmptyStatement()),
+        name: dummyName,
+        fileUri: fileUri,
+        reference: constructorReference,
+        isSynthetic: isSynthetic)
+      ..startFileOffset = startOffset
+      ..fileOffset = fileOffset
+      ..fileEndOffset = endOffset;
+    nameScheme
+        .getConstructorMemberName(name, isTearOff: false)
+        .attachMember(_constructor);
+    _constructorTearOff = createConstructorTearOffProcedure(
+        nameScheme.getConstructorMemberName(name, isTearOff: true),
+        libraryBuilder,
+        fileUri,
+        fileOffset,
+        tearOffReference,
+        forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin);
+  }
+
+  // Coverage-ignore(suite): Not run.
+  Member get constructor => _constructor;
+
+  // Coverage-ignore(suite): Not run.
+  Procedure? get constructorTearOff => _constructorTearOff;
+
+  List<Initializer> get initializers => _constructor.initializers;
+
+  void buildOutlineNodes(
+    BuildNodesCallback f, {
+    required SourceConstructorBuilder constructorBuilder,
+    required SourceLibraryBuilder libraryBuilder,
+    required SourceClassBuilder declarationBuilder,
+    required Member declarationConstructor,
+    required int formalsOffset,
+    required bool isConst,
+    required TypeBuilder returnType,
+    required List<NominalParameterBuilder>? typeParameters,
+    required List<FormalParameterBuilder>? formals,
+    required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+  }) {
+    _build(
+        constructorBuilder: constructorBuilder,
+        libraryBuilder: libraryBuilder,
+        classBuilder: declarationBuilder,
+        declarationConstructor: declarationConstructor,
+        formalsOffset: formalsOffset,
+        isConst: isConst,
+        returnType: returnType,
+        typeParameters: typeParameters,
+        formals: formals,
+        delayedDefaultValueCloners: delayedDefaultValueCloners);
+    f(
+        member: _constructor,
+        tearOff: _constructorTearOff,
+        kind: BuiltMemberKind.Constructor);
+  }
+
+  bool _hasBeenBuilt = false;
+
+  void _build({
+    required SourceConstructorBuilder constructorBuilder,
+    required SourceLibraryBuilder libraryBuilder,
+    required SourceClassBuilder classBuilder,
+    required Member declarationConstructor,
+    required int formalsOffset,
+    required bool isConst,
+    required TypeBuilder returnType,
+    required List<NominalParameterBuilder>? typeParameters,
+    required List<FormalParameterBuilder>? formals,
+    required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+  }) {
+    if (!_hasBeenBuilt) {
+      // According to the specification §9.3 the return type of a constructor
+      // function is its enclosing class.
+      function.asyncMarker = AsyncMarker.Sync;
+      buildTypeParametersAndFormals(
+          libraryBuilder, function, typeParameters, formals,
+          classTypeParameters: null, supportsTypeParameters: false);
+      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.withDefaultNullability(typeParameter));
+      }
+      InterfaceType type = new InterfaceType(
+          enclosingClass, Nullability.nonNullable, typeParameterTypes);
+      returnType.registerInferredType(type);
+      _constructor.function.fileOffset = formalsOffset;
+      _constructor.function.fileEndOffset = _constructor.fileEndOffset;
+      _constructor.function.typeParameters = const <TypeParameter>[];
+      _constructor.isConst = isConst;
+      _constructor.isExternal = _isExternal;
+
+      if (_constructorTearOff != null) {
+        DelayedDefaultValueCloner delayedDefaultValueCloner =
+            buildConstructorTearOffProcedure(
+                tearOff: _constructorTearOff,
+                declarationConstructor: declarationConstructor,
+                implementationConstructor: _constructor,
+                enclosingDeclarationTypeParameters:
+                    classBuilder.cls.typeParameters,
+                libraryBuilder: libraryBuilder);
+        delayedDefaultValueCloners.add(delayedDefaultValueCloner);
+      }
+
+      _hasBeenBuilt = true;
+    }
+    if (formals != null) {
+      bool needsInference = false;
+      for (FormalParameterBuilder formal in formals) {
+        if (formal.type is InferableTypeBuilder &&
+            (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
+          formal.variable!.type = const UnknownType();
+          needsInference = true;
+        } else if (!formal.hasDeclaredInitializer &&
+            formal.isSuperInitializingFormal) {
+          needsInference = true;
+        }
+      }
+      if (needsInference) {
+        libraryBuilder.loader
+            .registerConstructorToBeInferred(_constructor, constructorBuilder);
+      }
+    }
+  }
+
+  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;
+  }
+
+  void prependInitializer(Initializer initializer) {
+    initializer.parent = _constructor;
+    _constructor.initializers.insert(0, initializer);
+  }
+
+  void becomeNative() {
+    _constructor.isExternal = true;
+  }
+
+  VariableDeclaration? getTearOffParameter(int index) {
+    Procedure? constructorTearOff = _constructorTearOff;
+    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 finishAugmentation(SourceConstructorBuilder origin) {
+    finishConstructorAugmentation(
+        origin.invokeTarget as Constructor, _constructor);
+
+    if (_constructorTearOff != null) {
+      finishProcedureAugmentation(
+          origin.readTarget as Procedure, _constructorTearOff);
+    }
+  }
+
+  bool _hasAddedDefaultValueCloners = false;
+
+  void addSuperParameterDefaultValueCloners(
+      {required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+      required Member superTarget,
+      required List<int?>? positionalSuperParameters,
+      required List<String>? namedSuperParameters,
+      required SourceLibraryBuilder libraryBuilder}) {
+    if (!_hasAddedDefaultValueCloners) {
+      // If this constructor formals are part of a cyclic dependency this
+      // might be called more than once.
+      delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
+          superTarget, invokeTarget,
+          positionalSuperParameters: positionalSuperParameters ?? const <int>[],
+          namedSuperParameters: namedSuperParameters ?? const <String>[],
+          isOutlineNode: true,
+          libraryBuilder: libraryBuilder));
+      if (_constructorTearOff != null) {
+        delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
+            superTarget, _constructorTearOff,
+            positionalSuperParameters:
+                positionalSuperParameters ?? const <int>[],
+            namedSuperParameters: namedSuperParameters ?? const <String>[],
+            isOutlineNode: true,
+            libraryBuilder: libraryBuilder));
+      }
+      _hasAddedDefaultValueCloners = true;
+    }
+  }
+}
+
+class ExtensionTypeConstructorEncoding {
+  late final Procedure _constructor;
+
+  late final Procedure? _constructorTearOff;
+
+  final bool _isExternal;
+
+  Statement? bodyInternal;
+
+  /// If this procedure is an extension instance member or extension type
+  /// instance member, [_thisVariable] holds the synthetically added `this`
+  /// parameter.
+  VariableDeclaration? _thisVariable;
+
+  /// If this procedure is an extension instance member or extension type
+  /// instance member, [_thisTypeParameters] holds the type parameters copied
+  /// from the extension/extension type declaration.
+  List<TypeParameter>? _thisTypeParameters;
+
+  List<Initializer> initializers = [];
+
+  ExtensionTypeConstructorEncoding({required bool isExternal})
+      : _isExternal = isExternal;
+
+  Member get readTarget =>
+      _constructorTearOff ?? // Coverage-ignore(suite): Not run.
+      _constructor;
+
+  // Coverage-ignore(suite): Not run.
+  Reference get readTargetReference =>
+      (_constructorTearOff ?? _constructor).reference;
+
+  Member get invokeTarget => _constructor;
+
+  // Coverage-ignore(suite): Not run.
+  Reference get invokeTargetReference => _constructor.reference;
+
+  void registerFunctionBody(Statement value) {
+    function.body = value..parent = function;
+  }
+
+  void registerNoBodyConstructor() {
+    if (!_hasBuiltBody && !_isExternal) {
+      registerFunctionBody(new EmptyStatement());
+    }
+  }
+
+  FunctionNode get function => _constructor.function;
+
+  void createNode(
+      {required String name,
+      required SourceLibraryBuilder libraryBuilder,
+      required NameScheme nameScheme,
+      required Reference? constructorReference,
+      required Reference? tearOffReference,
+      required Uri fileUri,
+      required int fileOffset,
+      required int endOffset,
+      required bool forAbstractClassOrEnumOrMixin}) {
+    _constructor = new Procedure(dummyName, ProcedureKind.Method,
+        new FunctionNode(_isExternal ? null : new EmptyStatement()),
+        fileUri: fileUri, reference: constructorReference)
+      ..fileOffset = fileOffset
+      ..fileEndOffset = endOffset;
+    nameScheme
+        .getConstructorMemberName(name, isTearOff: false)
+        .attachMember(_constructor);
+    _constructorTearOff = createConstructorTearOffProcedure(
+        nameScheme.getConstructorMemberName(name, isTearOff: true),
+        libraryBuilder,
+        fileUri,
+        fileOffset,
+        tearOffReference,
+        forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin,
+        forceCreateLowering: true)
+      ?..isExtensionTypeMember = true;
+  }
+
+  // Coverage-ignore(suite): Not run.
+  Member get constructor => _constructor;
+
+  // Coverage-ignore(suite): Not run.
+  Procedure? get constructorTearOff => _constructorTearOff;
+
+  void buildOutlineNodes(
+    BuildNodesCallback f, {
+    required SourceConstructorBuilder constructorBuilder,
+    required SourceLibraryBuilder libraryBuilder,
+    required SourceExtensionTypeDeclarationBuilder declarationBuilder,
+    required Member declarationConstructor,
+    required int fileOffset,
+    required int formalsOffset,
+    required bool isConst,
+    required TypeBuilder returnType,
+    required List<NominalParameterBuilder>? typeParameters,
+    required List<FormalParameterBuilder>? formals,
+    required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+  }) {
+    _build(
+        constructorBuilder: constructorBuilder,
+        libraryBuilder: libraryBuilder,
+        declarationBuilder: declarationBuilder,
+        declarationConstructor: declarationConstructor,
+        fileOffset: fileOffset,
+        formalsOffset: formalsOffset,
+        isConst: isConst,
+        returnType: returnType,
+        typeParameters: typeParameters,
+        formals: formals,
+        delayedDefaultValueCloners: delayedDefaultValueCloners);
+    f(
+        member: _constructor,
+        tearOff: _constructorTearOff,
+        kind: BuiltMemberKind.ExtensionTypeConstructor);
+  }
+
+  bool _hasBeenBuilt = false;
+
+  void _build({
+    required SourceConstructorBuilder constructorBuilder,
+    required SourceLibraryBuilder libraryBuilder,
+    required SourceExtensionTypeDeclarationBuilder declarationBuilder,
+    required Member declarationConstructor,
+    required int fileOffset,
+    required int formalsOffset,
+    required bool isConst,
+    required TypeBuilder returnType,
+    required List<NominalParameterBuilder>? typeParameters,
+    required List<FormalParameterBuilder>? formals,
+    required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
+  }) {
+    if (!_hasBeenBuilt) {
+      // According to the specification §9.3 the return type of a constructor
+      // function is its enclosing class.
+      function.asyncMarker = AsyncMarker.Sync;
+      buildTypeParametersAndFormals(
+          libraryBuilder, function, typeParameters, formals,
+          classTypeParameters: null, supportsTypeParameters: true);
+
+      if (declarationBuilder.typeParameters != null) {
+        int count = declarationBuilder.typeParameters!.length;
+        _thisTypeParameters = new List<TypeParameter>.generate(
+            count, (int index) => function.typeParameters[index],
+            growable: false);
+      }
+      List<DartType> typeArguments;
+      if (_thisTypeParameters != null) {
+        typeArguments = [
+          for (TypeParameter parameter in _thisTypeParameters!)
+            new TypeParameterType.withDefaultNullability(parameter)
+        ];
+      } else {
+        typeArguments = [];
+      }
+
+      ExtensionTypeDeclaration extensionTypeDeclaration =
+          declarationBuilder.extensionTypeDeclaration;
+      _thisVariable = new VariableDeclarationImpl(syntheticThisName,
+          isFinal: true,
+          type: new ExtensionType(
+              extensionTypeDeclaration, Nullability.nonNullable, typeArguments))
+        ..fileOffset = fileOffset
+        ..isLowered = true;
+
+      List<DartType> typeParameterTypes = <DartType>[];
+      for (int i = 0; i < function.typeParameters.length; i++) {
+        TypeParameter typeParameter = function.typeParameters[i];
+        typeParameterTypes
+            .add(new TypeParameterType.withDefaultNullability(typeParameter));
+      }
+      ExtensionType type = new ExtensionType(extensionTypeDeclaration,
+          Nullability.nonNullable, typeParameterTypes);
+      returnType.registerInferredType(type);
+      _constructor.function.fileOffset = formalsOffset;
+      _constructor.function.fileEndOffset = _constructor.fileEndOffset;
+      _constructor.isConst = isConst;
+      _constructor.isExternal = _isExternal;
+      _constructor.isStatic = true;
+      _constructor.isExtensionTypeMember = true;
+
+      if (_constructorTearOff != null) {
+        delayedDefaultValueCloners.add(buildConstructorTearOffProcedure(
+            tearOff: _constructorTearOff,
+            declarationConstructor: declarationConstructor,
+            implementationConstructor: _constructor,
+            libraryBuilder: libraryBuilder));
+      }
+
+      _hasBeenBuilt = true;
+    }
+    if (formals != null) {
+      bool needsInference = false;
+      for (FormalParameterBuilder formal in formals) {
+        if (formal.type is InferableTypeBuilder &&
+            (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
+          formal.variable!.type = const UnknownType();
+          needsInference = true;
+        } else if (!formal.hasDeclaredInitializer &&
+            formal.isSuperInitializingFormal) {
+          needsInference = true;
+        }
+      }
+      if (needsInference) {
+        libraryBuilder.loader
+            .registerConstructorToBeInferred(_constructor, constructorBuilder);
+      }
+    }
+  }
+
+  VariableDeclaration? get thisVariable {
+    assert(_thisVariable != null,
+        "ProcedureBuilder.thisVariable has not been set.");
+    return _thisVariable;
+  }
+
+  List<TypeParameter>? get thisTypeParameters {
+    // Use [_thisVariable] as marker for whether this type parameters have
+    // been computed.
+    assert(_thisVariable != null,
+        "ProcedureBuilder.thisTypeParameters has not been set.");
+    return _thisTypeParameters;
+  }
+
+  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.
+    initializers = [];
+    //redirectingInitializer = null;
+    //superInitializer = null;
+  }
+
+  void prependInitializer(Initializer initializer) {
+    initializers.insert(0, initializer);
+  }
+
+  VariableDeclaration? getTearOffParameter(int index) {
+    Procedure? constructorTearOff = _constructorTearOff;
+    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;
+  }
+
+  bool _hasBuiltBody = false;
+
+  void buildBody() {
+    if (_hasBuiltBody) {
+      return;
+    }
+    if (!_isExternal) {
+      VariableDeclaration thisVariable = this.thisVariable!;
+      List<Statement> statements = [thisVariable];
+      ExtensionTypeInitializerToStatementConverter visitor =
+          new ExtensionTypeInitializerToStatementConverter(
+              statements, thisVariable);
+      for (Initializer initializer in initializers) {
+        initializer.accept(visitor);
+      }
+      if (function.body != null && function.body is! EmptyStatement) {
+        statements.add(function.body!);
+      }
+      statements.add(new ReturnStatement(new VariableGet(thisVariable)));
+      registerFunctionBody(new Block(statements));
+    }
+    _hasBuiltBody = true;
+  }
+}
diff --git a/pkg/front_end/lib/src/fragment/getter.dart b/pkg/front_end/lib/src/fragment/getter.dart
index 526b22d..c1e5c65 100644
--- a/pkg/front_end/lib/src/fragment/getter.dart
+++ b/pkg/front_end/lib/src/fragment/getter.dart
@@ -898,7 +898,7 @@
   TypeBuilder get returnType => _fragment.returnType;
 
   @override
-  void setBody(Statement body) {
+  void registerFunctionBody(Statement body) {
     function.body = body..parent = function;
   }
 
diff --git a/pkg/front_end/lib/src/fragment/method.dart b/pkg/front_end/lib/src/fragment/method.dart
index dbe8e64..18525a8 100644
--- a/pkg/front_end/lib/src/fragment/method.dart
+++ b/pkg/front_end/lib/src/fragment/method.dart
@@ -1276,7 +1276,7 @@
   TypeBuilder get returnType => _fragment.returnType;
 
   @override
-  void setBody(Statement body) {
+  void registerFunctionBody(Statement body) {
     function.body = body..parent = function;
   }
 
diff --git a/pkg/front_end/lib/src/fragment/primary_constructor.dart b/pkg/front_end/lib/src/fragment/primary_constructor.dart
index ed22ba3..3f78c8e 100644
--- a/pkg/front_end/lib/src/fragment/primary_constructor.dart
+++ b/pkg/front_end/lib/src/fragment/primary_constructor.dart
@@ -18,7 +18,7 @@
   final bool forAbstractClassOrMixin;
   Token? _beginInitializers;
 
-  AbstractSourceConstructorBuilder? _builder;
+  SourceConstructorBuilderImpl? _builder;
 
   PrimaryConstructorFragment(
       {required this.constructorName,
@@ -47,12 +47,12 @@
   }
 
   @override
-  AbstractSourceConstructorBuilder get builder {
+  SourceConstructorBuilderImpl get builder {
     assert(_builder != null, "Builder has not been computed for $this.");
     return _builder!;
   }
 
-  void set builder(AbstractSourceConstructorBuilder value) {
+  void set builder(SourceConstructorBuilderImpl value) {
     assert(_builder == null, "Builder has already been computed for $this.");
     _builder = value;
   }
diff --git a/pkg/front_end/lib/src/fragment/setter.dart b/pkg/front_end/lib/src/fragment/setter.dart
index 40e0733..38b8b88 100644
--- a/pkg/front_end/lib/src/fragment/setter.dart
+++ b/pkg/front_end/lib/src/fragment/setter.dart
@@ -919,7 +919,7 @@
   TypeBuilder get returnType => _fragment.returnType;
 
   @override
-  void setBody(Statement body) {
+  void registerFunctionBody(Statement body) {
     function.body = body..parent = function;
   }
 
diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart
index 9406f7b..f8ff125 100644
--- a/pkg/front_end/lib/src/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder.dart
@@ -1340,7 +1340,7 @@
         ])
           ..fileOffset = body.fileOffset;
       }
-      _context.setBody(body);
+      _context.registerFunctionBody(body);
     }
 
     performBacklogComputations();
@@ -2114,7 +2114,7 @@
       /// >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.
-      function.body = new EmptyStatement()..parent = function;
+      _context.registerNoBodyConstructor();
     } else if (body != null && _context.isMixinClass && !_context.isFactory) {
       // Report an error if a mixin class has a non-factory constructor with a
       // body.
diff --git a/pkg/front_end/lib/src/kernel/body_builder_context.dart b/pkg/front_end/lib/src/kernel/body_builder_context.dart
index 07216ff..42d0993 100644
--- a/pkg/front_end/lib/src/kernel/body_builder_context.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder_context.dart
@@ -368,8 +368,13 @@
   }
 
   /// Registers [body] as the result of the body building.
-  void setBody(Statement body) {
-    throw new UnsupportedError("${runtimeType}.setBody");
+  void registerFunctionBody(Statement body) {
+    throw new UnsupportedError("${runtimeType}.registerFunctionBody");
+  }
+
+  /// Registers that the constructor has no body.
+  void registerNoBodyConstructor() {
+    throw new UnsupportedError("${runtimeType}.registerNoBodyConstructor");
   }
 
   /// Returns the type of `this` in the body being built.
@@ -793,8 +798,8 @@
   }
 }
 
-mixin _ConstructorBodyBuilderContextMixin<T extends ConstructorDeclaration>
-    implements BodyBuilderContext {
+mixin _ConstructorBodyBuilderContextMixin<
+    T extends ConstructorDeclarationBuilder> implements BodyBuilderContext {
   T get _member;
 
   TreeNode get _initializerParent;
@@ -853,11 +858,11 @@
 
 class ConstructorBodyBuilderContext extends BodyBuilderContext
     with
-        _FunctionBodyBuilderContextMixin<DeclaredSourceConstructorBuilder>,
-        _ConstructorBodyBuilderContextMixin<DeclaredSourceConstructorBuilder>,
-        _MemberBodyBuilderContext<DeclaredSourceConstructorBuilder> {
+        _FunctionBodyBuilderContextMixin<SourceConstructorBuilderImpl>,
+        _ConstructorBodyBuilderContextMixin<SourceConstructorBuilderImpl>,
+        _MemberBodyBuilderContext<SourceConstructorBuilderImpl> {
   @override
-  final DeclaredSourceConstructorBuilder _member;
+  final SourceConstructorBuilderImpl _member;
 
   @override
   final Member _builtMember;
@@ -872,8 +877,13 @@
   }
 
   @override
-  void setBody(Statement body) {
-    _member.body = body;
+  void registerFunctionBody(Statement body) {
+    _member.registerFunctionBody(body);
+  }
+
+  @override
+  void registerNoBodyConstructor() {
+    _member.registerNoBodyConstructor();
   }
 
   @override
@@ -883,7 +893,8 @@
 
   @override
   bool needsImplicitSuperInitializer(CoreTypes coreTypes) {
-    return !_declarationContext.isObjectClass(coreTypes) &&
+    return _member.isClassMember &&
+        !_declarationContext.isObjectClass(coreTypes) &&
         !isExternalConstructor;
   }
 
@@ -891,40 +902,6 @@
   TreeNode get _initializerParent => _member.invokeTarget;
 }
 
-class ExtensionTypeConstructorBodyBuilderContext extends BodyBuilderContext
-    with
-        _FunctionBodyBuilderContextMixin<SourceExtensionTypeConstructorBuilder>,
-        _ConstructorBodyBuilderContextMixin<
-            SourceExtensionTypeConstructorBuilder>,
-        _MemberBodyBuilderContext<SourceExtensionTypeConstructorBuilder> {
-  @override
-  final SourceExtensionTypeConstructorBuilder _member;
-  @override
-  final Member _builtMember;
-
-  ExtensionTypeConstructorBodyBuilderContext(this._member, this._builtMember)
-      : super(_member.libraryBuilder, _member.declarationBuilder,
-            isDeclarationInstanceMember: _member.isDeclarationInstanceMember);
-
-  @override
-  LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
-    return _member.computeFormalParameterInitializerScope(parent);
-  }
-
-  @override
-  void setBody(Statement body) {
-    _member.body = body;
-  }
-
-  @override
-  bool isConstructorCyclic(String name) {
-    return _declarationContext.isConstructorCyclic(_member.name, name);
-  }
-
-  @override
-  TreeNode get _initializerParent => _member.invokeTarget;
-}
-
 class ParameterBodyBuilderContext extends BodyBuilderContext {
   factory ParameterBodyBuilderContext(
       LibraryBuilder libraryBuilder,
diff --git a/pkg/front_end/lib/src/kernel/kernel_target.dart b/pkg/front_end/lib/src/kernel/kernel_target.dart
index 2908382..7df0adb 100644
--- a/pkg/front_end/lib/src/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/kernel/kernel_target.dart
@@ -102,6 +102,14 @@
       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);
@@ -1232,30 +1240,25 @@
         enclosingClass.enclosingLibrary.nonNullable, typeParameterTypes);
   }
 
+  void _bindCoreType(NamedTypeBuilder typeBuilder, {bool isNullClass = false}) {
+    TypeDeclarationBuilder typeDeclarationBuilder = loader.coreLibrary
+            .lookupLocalMember(typeBuilder.typeName.name, required: true)
+        as TypeDeclarationBuilder;
+    typeBuilder.bind(loader.coreLibrary, typeDeclarationBuilder);
+    if (isNullClass) {
+      (typeDeclarationBuilder as ClassBuilder).isNullClass = true;
+    }
+  }
+
   void setupTopAndBottomTypes() {
-    objectType.bind(
-        loader.coreLibrary,
-        loader.coreLibrary.lookupLocalMember("Object", required: true)
-            as TypeDeclarationBuilder);
-    dynamicType.bind(
-        loader.coreLibrary,
-        loader.coreLibrary.lookupLocalMember("dynamic", required: true)
-            as TypeDeclarationBuilder);
-    ClassBuilder nullClassBuilder = loader.coreLibrary
-        .lookupLocalMember("Null", required: true) as ClassBuilder;
-    nullType.bind(loader.coreLibrary, nullClassBuilder..isNullClass = true);
-    bottomType.bind(
-        loader.coreLibrary,
-        loader.coreLibrary.lookupLocalMember("Never", required: true)
-            as TypeDeclarationBuilder);
-    enumType.bind(
-        loader.coreLibrary,
-        loader.coreLibrary.lookupLocalMember("Enum", required: true)
-            as TypeDeclarationBuilder);
-    underscoreEnumType.bind(
-        loader.coreLibrary,
-        loader.coreLibrary.lookupLocalMember("_Enum", required: true)
-            as TypeDeclarationBuilder);
+    _bindCoreType(objectType);
+    _bindCoreType(stringType);
+    _bindCoreType(intType);
+    _bindCoreType(dynamicType);
+    _bindCoreType(nullType, isNullClass: true);
+    _bindCoreType(bottomType);
+    _bindCoreType(enumType);
+    _bindCoreType(underscoreEnumType);
   }
 
   void computeCoreTypes() {
@@ -1421,15 +1424,16 @@
       }
     }
 
-    Map<ConstructorDeclaration, Set<SourcePropertyBuilder>>
+    Map<ConstructorDeclarationBuilder, Set<SourcePropertyBuilder>>
         constructorInitializedFields = new Map.identity();
     Set<SourcePropertyBuilder>? initializedFieldBuilders = null;
     Set<SourcePropertyBuilder>? uninitializedInstanceFields;
 
-    Iterator<ConstructorDeclaration> constructorIterator =
-        classDeclaration.fullConstructorIterator<ConstructorDeclaration>();
+    Iterator<ConstructorDeclarationBuilder> constructorIterator =
+        classDeclaration
+            .fullConstructorIterator<ConstructorDeclarationBuilder>();
     while (constructorIterator.moveNext()) {
-      ConstructorDeclaration constructor = constructorIterator.current;
+      ConstructorDeclarationBuilder constructor = constructorIterator.current;
       if (constructor.isEffectivelyRedirecting) continue;
       if (constructor.isConst && nonFinalFields.isNotEmpty) {
         classDeclaration.addProblem(messageConstConstructorNonFinalField,
@@ -1514,9 +1518,10 @@
 
     // Run through all fields that are initialized by some constructor, and
     // make sure that all other constructors also initialize them.
-    for (MapEntry<ConstructorDeclaration, Set<SourcePropertyBuilder>> entry
+    for (MapEntry<ConstructorDeclarationBuilder,
+            Set<SourcePropertyBuilder>> entry
         in constructorInitializedFields.entries) {
-      ConstructorDeclaration constructorBuilder = entry.key;
+      ConstructorDeclarationBuilder constructorBuilder = entry.key;
       Set<SourcePropertyBuilder> fieldBuilders = entry.value;
       for (SourcePropertyBuilder fieldBuilder
           in initializedFieldBuilders!.difference(fieldBuilders)) {
diff --git a/pkg/front_end/lib/src/source/constructor_declaration.dart b/pkg/front_end/lib/src/source/constructor_declaration.dart
index c679343..47f64e1 100644
--- a/pkg/front_end/lib/src/source/constructor_declaration.dart
+++ b/pkg/front_end/lib/src/source/constructor_declaration.dart
@@ -12,7 +12,7 @@
 /// Common interface for builders for generative constructor declarations in
 /// source code, such as a generative constructor in a regular class or a
 /// generative constructor in an extension type declaration.
-abstract class ConstructorDeclaration implements SourceFunctionBuilder {
+abstract class ConstructorDeclarationBuilder implements SourceFunctionBuilder {
   /// Returns `true` if this constructor, including its augmentations, is
   /// external.
   ///
diff --git a/pkg/front_end/lib/src/source/source_class_builder.dart b/pkg/front_end/lib/src/source/source_class_builder.dart
index 5e50ac4..b356df5 100644
--- a/pkg/front_end/lib/src/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/source/source_class_builder.dart
@@ -940,7 +940,7 @@
         SourceMemberBuilder constructor = constructorIterator.current;
         // Assumes the constructor isn't synthetic since
         // [installSyntheticConstructors] hasn't been called yet.
-        if (constructor is DeclaredSourceConstructorBuilder) {
+        if (constructor is SourceConstructorBuilderImpl) {
           // Report an error if a mixin class has a constructor with parameters,
           // is external, or is a redirecting constructor.
           if (constructor.isRedirecting ||
diff --git a/pkg/front_end/lib/src/source/source_constructor_builder.dart b/pkg/front_end/lib/src/source/source_constructor_builder.dart
index c7356eb..20fd2bc 100644
--- a/pkg/front_end/lib/src/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/source/source_constructor_builder.dart
@@ -8,7 +8,6 @@
 import 'package:kernel/type_algebra.dart';
 import 'package:kernel/type_environment.dart';
 
-import '../api_prototype/lowering_predicates.dart';
 import '../base/constant_context.dart' show ConstantContext;
 import '../base/identifiers.dart';
 import '../base/local_scope.dart';
@@ -33,27 +32,20 @@
 import '../builder/metadata_builder.dart';
 import '../builder/omitted_type_builder.dart';
 import '../builder/type_builder.dart';
+import '../fragment/constructor/declaration.dart';
 import '../kernel/body_builder.dart' show BodyBuilder;
 import '../kernel/body_builder_context.dart';
-import '../kernel/constructor_tearoff_lowering.dart';
 import '../kernel/expression_generator_helper.dart';
 import '../kernel/hierarchy/class_member.dart' show ClassMember;
 import '../kernel/internal_ast.dart';
 import '../kernel/kernel_helper.dart'
-    show
-        DelayedDefaultValueCloner,
-        TypeDependency,
-        finishConstructorAugmentation,
-        finishProcedureAugmentation;
+    show DelayedDefaultValueCloner, TypeDependency;
 import '../kernel/type_algorithms.dart';
 import '../type_inference/inference_results.dart';
-import '../type_inference/type_schema.dart';
 import 'constructor_declaration.dart';
 import 'name_scheme.dart';
-import 'source_builder_mixins.dart';
 import 'source_class_builder.dart';
 import 'source_enum_builder.dart';
-import 'source_extension_type_declaration_builder.dart';
 import 'source_function_builder.dart';
 import 'source_library_builder.dart' show SourceLibraryBuilder;
 import 'source_loader.dart'
@@ -85,56 +77,66 @@
   Uri get fileUri;
 }
 
-abstract class AbstractSourceConstructorBuilder extends SourceMemberBuilderImpl
+class SourceConstructorBuilderImpl extends SourceMemberBuilderImpl
     implements
         SourceConstructorBuilder,
         SourceFunctionBuilder,
         Inferable,
-        ConstructorDeclaration,
+        ConstructorDeclarationBuilder,
         InferredTypeListener {
-  @override
-  final List<MetadataBuilder>? metadata;
-
   final Modifiers modifiers;
 
   @override
   final String name;
 
   @override
-  final List<NominalParameterBuilder>? typeParameters;
+  final SourceLibraryBuilder libraryBuilder;
 
   @override
-  final List<FormalParameterBuilder>? formals;
-
-  /// If this procedure is an extension instance member or extension type
-  /// instance member, [_thisVariable] holds the synthetically added `this`
-  /// parameter.
-  VariableDeclaration? _thisVariable;
-
-  /// If this procedure is an extension instance member or extension type
-  /// instance member, [_thisTypeParameters] holds the type parameters copied
-  /// from the extension/extension type declaration.
-  List<TypeParameter>? _thisTypeParameters;
+  final DeclarationBuilder declarationBuilder;
 
   @override
-  final OmittedTypeBuilder returnType;
+  final int fileOffset;
 
-  final int charOpenParenOffset;
-
-  bool _hasFormalsInferred = false;
+  @override
+  final Uri fileUri;
 
   Token? beginInitializers;
 
-  AbstractSourceConstructorBuilder(
-      this.metadata,
-      this.modifiers,
-      this.returnType,
-      this.name,
-      this.typeParameters,
-      this.formals,
-      this.charOpenParenOffset,
-      this.nativeMethodName,
-      this.beginInitializers) {
+  final ConstructorDeclaration _introductory;
+
+  final MemberName _memberName;
+
+  final List<DelayedDefaultValueCloner> _delayedDefaultValueCloners = [];
+
+  Set<SourcePropertyBuilder>? _initializedFields;
+
+  SourceConstructorBuilderImpl? actualOrigin;
+
+  List<SourceConstructorBuilderImpl>? _augmentations;
+
+  SourceConstructorBuilderImpl({
+    required this.modifiers,
+    required this.name,
+    required this.libraryBuilder,
+    required this.declarationBuilder,
+    required this.fileOffset,
+    required this.fileUri,
+    this.nativeMethodName,
+    required Reference? constructorReference,
+    required Reference? tearOffReference,
+    required NameScheme nameScheme,
+    required this.beginInitializers,
+    required ConstructorDeclaration constructorDeclaration,
+  })  : _introductory = constructorDeclaration,
+        _memberName = nameScheme.getDeclaredName(name) {
+    _introductory.createNode(
+        name: name,
+        libraryBuilder: libraryBuilder,
+        nameScheme: nameScheme,
+        constructorReference: constructorReference,
+        tearOffReference: tearOffReference);
+
     returnType.registerInferredTypeListener(this);
     if (formals != null) {
       for (FormalParameterBuilder formal in formals!) {
@@ -146,6 +148,22 @@
   }
 
   @override
+  Builder get parent => declarationBuilder;
+
+  @override
+  List<MetadataBuilder>? get metadata => _introductory.metadata;
+
+  @override
+  OmittedTypeBuilder get returnType => _introductory.returnType;
+
+  @override
+  List<NominalParameterBuilder>? get typeParameters =>
+      _introductory.typeParameters;
+
+  @override
+  List<FormalParameterBuilder>? get formals => _introductory.formals;
+
+  @override
   // Coverage-ignore(suite): Not run.
   Iterable<MetadataBuilder>? get metadataForTesting => metadata;
 
@@ -171,9 +189,119 @@
   // Coverage-ignore(suite): Not run.
   bool get isAssignable => false;
 
+  @override
+  // Coverage-ignore(suite): Not run.
+  Name get memberName => _memberName.name;
+
   /// Returns `true` if this member is augmented, either by being the origin
   /// of a augmented member or by not being the last among augmentations.
-  bool get isAugmented;
+  bool get isAugmented {
+    if (isAugmenting) {
+      return origin._augmentations!.last != this;
+    } else {
+      return _augmentations != null;
+    }
+  }
+
+  @override
+  SourceConstructorBuilderImpl get origin => actualOrigin ?? this;
+
+  // Coverage-ignore(suite): Not run.
+  List<SourceConstructorBuilder>? get augmentationsForTesting => _augmentations;
+
+  @override
+  void applyAugmentation(Builder augmentation) {
+    if (augmentation is SourceConstructorBuilderImpl) {
+      if (checkAugmentation(
+          augmentationLibraryBuilder: augmentation.libraryBuilder,
+          origin: this,
+          augmentation: augmentation)) {
+        augmentation.actualOrigin = this;
+        (_augmentations ??= []).add(augmentation);
+      }
+    } else {
+      // Coverage-ignore-block(suite): Not run.
+      reportAugmentationMismatch(
+          originLibraryBuilder: libraryBuilder,
+          origin: this,
+          augmentation: augmentation);
+    }
+  }
+
+  @override
+  bool get isRedirecting => _introductory.isRedirecting;
+
+  @override
+  VariableDeclaration? get thisVariable => _introductory.thisVariable;
+
+  @override
+  List<TypeParameter>? get thisTypeParameters =>
+      _introductory.thisTypeParameters;
+
+  @override
+  Member get readTarget => _introductory.readTarget;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Reference get readTargetReference => _introductory.readTargetReference;
+
+  @override
+  Member get invokeTarget =>
+      isAugmenting ? origin.invokeTarget : _introductory.invokeTarget;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Reference get invokeTargetReference => isAugmenting
+      ? origin.invokeTargetReference
+      : _introductory.invokeTargetReference;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Member? get writeTarget => null;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Reference? get writeTargetReference => null;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  Iterable<Reference> get exportedMemberReferences => [invokeTargetReference];
+
+  // TODO(johnniwinther): Add annotations to tear-offs.
+  @override
+  Iterable<Annotatable> get annotatables => [invokeTarget];
+
+  @override
+  FunctionNode get function => _introductory.function;
+
+  @override
+  void becomeNative(SourceLoader loader) {
+    _introductory.becomeNative();
+    for (Annotatable annotatable in annotatables) {
+      loader.addNativeAnnotation(annotatable, nativeMethodName!);
+    }
+  }
+
+  late final Substitution _fieldTypeSubstitution =
+      _introductory.computeFieldTypeSubstitution(declarationBuilder);
+
+  @override
+  DartType substituteFieldType(DartType fieldType) {
+    return _fieldTypeSubstitution.substituteType(fieldType);
+  }
+
+  void registerFunctionBody(Statement value) {
+    _introductory.registerFunctionBody(value);
+  }
+
+  void registerNoBodyConstructor() {
+    _introductory.registerNoBodyConstructor();
+  }
+
+  @override
+  VariableDeclaration? getTearOffParameter(int index) {
+    return _introductory.getTearOffParameter(index);
+  }
 
   LocalScope computeFormalParameterScope(LookupScope parent) {
     if (formals == null) return new FormalParameterScope(parent: parent);
@@ -255,275 +383,38 @@
 
   final String? nativeMethodName;
 
-  Statement? bodyInternal;
-
-  void set body(Statement? newBody) {
-//    if (newBody != null) {
-//      if (isAbstract) {
-//        // TODO(danrubel): Is this check needed?
-//        return internalProblem(messageInternalProblemBodyOnAbstractMethod,
-//            newBody.fileOffset, fileUri);
-//      }
-//    }
-    bodyInternal = newBody;
-    // A forwarding semi-stub is a method that is abstract in the source code,
-    // but which needs to have a forwarding stub body in order to ensure that
-    // covariance checks occur.  We don't want to replace the forwarding stub
-    // body with null.
-    TreeNode? parent = function.parent;
-    if (!(newBody == null &&
-        // Coverage-ignore(suite): Not run.
-        parent is Procedure &&
-        // Coverage-ignore(suite): Not run.
-        parent.isForwardingSemiStub)) {
-      function.body = newBody;
-      newBody?.parent = function;
-    }
-  }
-
   @override
   // Coverage-ignore(suite): Not run.
   bool get isNative => nativeMethodName != null;
 
-  bool get supportsTypeParameters => true;
-
-  void buildFunction() {
-    function.asyncMarker = AsyncMarker.Sync;
-    function.body = body;
-    body?.parent = function;
-    buildTypeParametersAndFormals(
-        libraryBuilder, function, typeParameters, formals,
-        classTypeParameters: null,
-        supportsTypeParameters: supportsTypeParameters);
-    if (!(isExtensionInstanceMember || isExtensionTypeInstanceMember) &&
-        isSetter &&
-        // Coverage-ignore(suite): Not run.
-        (formals?.length != 1 || formals![0].isOptionalPositional)) {
-      // Coverage-ignore-block(suite): Not run.
-      // Replace illegal parameters by single dummy parameter.
-      // Do this after building the parameters, since the diet listener
-      // assumes that parameters are built, even if illegal in number.
-      VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
-      function.positionalParameters.clear();
-      function.positionalParameters.add(parameter);
-      parameter.parent = function;
-      function.namedParameters.clear();
-      function.requiredParameterCount = 1;
-    } else if ((isExtensionInstanceMember || isExtensionTypeInstanceMember) &&
-        isSetter &&
-        // Coverage-ignore(suite): Not run.
-        (formals?.length != 2 || formals![1].isOptionalPositional)) {
-      // Coverage-ignore-block(suite): Not run.
-      // Replace illegal parameters by single dummy parameter (after #this).
-      // Do this after building the parameters, since the diet listener
-      // assumes that parameters are built, even if illegal in number.
-      VariableDeclaration thisParameter = function.positionalParameters[0];
-      VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
-      function.positionalParameters.clear();
-      function.positionalParameters.add(thisParameter);
-      function.positionalParameters.add(parameter);
-      parameter.parent = function;
-      function.namedParameters.clear();
-      function.requiredParameterCount = 2;
-    }
-    if (returnType is! InferableTypeBuilder) {
-      // Coverage-ignore-block(suite): Not run.
-      function.returnType =
-          returnType.build(libraryBuilder, TypeUse.returnType);
-    }
-    if (isExtensionInstanceMember || isExtensionTypeInstanceMember) {
-      SourceDeclarationBuilderMixin declarationBuilder =
-          parent as SourceDeclarationBuilderMixin;
-      if (declarationBuilder.typeParameters != null) {
-        int count = declarationBuilder.typeParameters!.length;
-        _thisTypeParameters = new List<TypeParameter>.generate(
-            count, (int index) => function.typeParameters[index],
-            growable: false);
-      }
-      if (isExtensionTypeInstanceMember && isConstructor) {
-        SourceExtensionTypeDeclarationBuilder extensionTypeDeclarationBuilder =
-            parent as SourceExtensionTypeDeclarationBuilder;
-        List<DartType> typeArguments;
-        if (_thisTypeParameters != null) {
-          typeArguments = [
-            for (TypeParameter parameter in _thisTypeParameters!)
-              new TypeParameterType.withDefaultNullability(parameter)
-          ];
-        } else {
-          typeArguments = [];
-        }
-        _thisVariable = new VariableDeclarationImpl(syntheticThisName,
-            isFinal: true,
-            type: new ExtensionType(
-                extensionTypeDeclarationBuilder.extensionTypeDeclaration,
-                Nullability.nonNullable,
-                typeArguments))
-          ..fileOffset = fileOffset
-          ..isLowered = true;
-      } else {
-        // Coverage-ignore-block(suite): Not run.
-        _thisVariable = function.positionalParameters.first;
-      }
-    }
-  }
-
-  @override
-  VariableDeclaration getFormalParameter(int index) {
-    return formals![index].variable!;
-  }
-
-  @override
-  VariableDeclaration? get thisVariable {
-    assert(
-        _thisVariable != null ||
-            !(isExtensionInstanceMember || isExtensionTypeInstanceMember),
-        "ProcedureBuilder.thisVariable has not been set.");
-    return _thisVariable;
-  }
-
-  @override
-  List<TypeParameter>? get thisTypeParameters {
-    // Use [_thisVariable] as marker for whether this type parameters have
-    // been computed.
-    assert(
-        _thisVariable != null ||
-            !(isExtensionInstanceMember || isExtensionTypeInstanceMember),
-        "ProcedureBuilder.thisTypeParameters has not been set.");
-    return _thisTypeParameters;
-  }
-
   @override
   void onInferredType(DartType type) {
     function.returnType = type;
   }
 
-  bool hasBuiltOutlineExpressions = false;
-
-  @override
-  void buildOutlineExpressions(ClassHierarchy classHierarchy,
-      List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
-    if (!hasBuiltOutlineExpressions) {
-      formals?.infer(classHierarchy);
-
-      DeclarationBuilder? classOrExtensionBuilder =
-          isClassMember || isExtensionMember || isExtensionTypeMember
-              ? parent as DeclarationBuilder
-              : null;
-      LookupScope parentScope =
-          classOrExtensionBuilder?.scope ?? // Coverage-ignore(suite): Not run.
-              libraryBuilder.scope;
-      for (Annotatable annotatable in annotatables) {
-        MetadataBuilder.buildAnnotations(annotatable, metadata,
-            createBodyBuilderContext(), libraryBuilder, fileUri, parentScope,
-            createFileUriExpression: isAugmented);
-      }
-      if (typeParameters != null) {
-        for (int i = 0; i < typeParameters!.length; i++) {
-          typeParameters![i].buildOutlineExpressions(
-              libraryBuilder,
-              createBodyBuilderContext(),
-              classHierarchy,
-              computeTypeParameterScope(parentScope));
-        }
-      }
-
-      if (formals != null) {
-        // For const constructors we need to include default parameter values
-        // into the outline. For all other formals we need to call
-        // buildOutlineExpressions to clear initializerToken to prevent
-        // consuming too much memory.
-        for (FormalParameterBuilder formal in formals!) {
-          formal.buildOutlineExpressions(libraryBuilder, declarationBuilder,
-              buildDefaultValue: FormalParameterBuilder
-                  .needsDefaultValuesBuiltAsOutlineExpressions(this));
-        }
-      }
-      hasBuiltOutlineExpressions = true;
-    }
-  }
-
-  @override
-  void becomeNative(SourceLoader loader) {
-    for (Annotatable annotatable in annotatables) {
-      loader.addNativeAnnotation(annotatable, nativeMethodName!);
-    }
-  }
-
-  BodyBuilderContext createBodyBuilderContext();
-
   @override
   bool get isConstructor => true;
 
-  Statement? get body {
-    if (bodyInternal == null && !isExternal) {
-      bodyInternal = new EmptyStatement();
-    }
-    return bodyInternal;
-  }
+  List<Initializer> get _initializers => _introductory.initializers;
 
-  @override
-  void inferTypes(ClassHierarchyBase hierarchy) {
-    inferFormalTypes(hierarchy);
-  }
-
-  @override
-  void inferFormalTypes(ClassHierarchyBase hierarchy) {
-    if (_hasFormalsInferred) return;
-    if (formals != null) {
-      libraryBuilder.loader.withUriForCrashReporting(fileUri, fileOffset, () {
-        for (FormalParameterBuilder formal in formals!) {
-          if (formal.type is InferableTypeBuilder) {
-            if (formal.isInitializingFormal) {
-              formal.finalizeInitializingFormal(
-                  declarationBuilder, this, hierarchy);
-            }
-          }
-        }
-        _inferSuperInitializingFormals(hierarchy);
-      });
-    }
-    _hasFormalsInferred = true;
-  }
-
-  // Coverage-ignore(suite): Not run.
-  void _inferSuperInitializingFormals(ClassHierarchyBase hierarchy) {}
-
-  void _buildFormals(Member member) {
-    if (formals != null) {
-      bool needsInference = false;
-      for (FormalParameterBuilder formal in formals!) {
-        if (formal.type is InferableTypeBuilder &&
-            (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
-          formal.variable!.type = const UnknownType();
-          needsInference = true;
-        } else if (!formal.hasDeclaredInitializer &&
-            formal.isSuperInitializingFormal) {
-          needsInference = true;
-        }
-      }
-      if (needsInference) {
-        libraryBuilder.loader.registerConstructorToBeInferred(member, this);
-      }
-    }
-  }
-
-  List<Initializer> get initializers;
-
-  void _injectInvalidInitializer(Message message, int charOffset, int length,
-      ExpressionGeneratorHelper helper, TreeNode parent) {
-    Initializer lastInitializer = initializers.removeLast();
-    assert(lastInitializer == superInitializer ||
-        lastInitializer == redirectingInitializer);
-    Initializer error = helper.buildInvalidInitializer(
-        helper.buildProblem(message, charOffset, length));
-    initializers.add(error..parent = parent);
-    initializers.add(lastInitializer);
-  }
+  List<Initializer> get initializers =>
+      isAugmenting ? origin.initializers : _initializers;
 
   SuperInitializer? superInitializer;
 
   RedirectingInitializer? redirectingInitializer;
 
+  void _injectInvalidInitializer(Message message, int charOffset, int length,
+      ExpressionGeneratorHelper helper, TreeNode parent) {
+    Initializer lastInitializer = _introductory.initializers.removeLast();
+    assert(lastInitializer == superInitializer ||
+        lastInitializer == redirectingInitializer);
+    Initializer error = helper.buildInvalidInitializer(
+        helper.buildProblem(message, charOffset, length));
+    _initializers.add(error..parent = parent);
+    _initializers.add(lastInitializer);
+  }
+
   @override
   void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
       {required InitializerInferenceResult? inferenceResult,
@@ -540,7 +431,7 @@
             helper,
             parent);
       } else {
-        inferenceResult?.applyResult(initializers, parent);
+        inferenceResult?.applyResult(_initializers, parent);
         superInitializer = initializer;
 
         LocatedMessage? message = helper.checkArgumentsForFunction(
@@ -548,7 +439,7 @@
             initializer.arguments,
             initializer.arguments.fileOffset, <TypeParameter>[]);
         if (message != null) {
-          initializers.add(helper.buildInvalidInitializer(
+          _initializers.add(helper.buildInvalidInitializer(
               helper.buildUnresolvedError(
                   helper.constructorNameForDiagnostics(
                       initializer.target.name.text),
@@ -559,7 +450,7 @@
                   kind: UnresolvedKind.Constructor))
             ..parent = parent);
         } else {
-          initializers.add(initializer..parent = parent);
+          _initializers.add(initializer..parent = parent);
         }
       }
     } else if (initializer is RedirectingInitializer) {
@@ -578,10 +469,10 @@
             noLength,
             helper,
             parent);
-      } else if (initializers.isNotEmpty) {
+      } else if (_initializers.isNotEmpty) {
         // Error on all previous ones.
-        for (int i = 0; i < initializers.length; i++) {
-          Initializer initializer = initializers[i];
+        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(
@@ -590,13 +481,13 @@
                   initializer.fileOffset,
                   length));
           error.parent = parent;
-          initializers[i] = error;
+          _initializers[i] = error;
         }
-        inferenceResult?.applyResult(initializers, parent);
-        initializers.add(initializer..parent = parent);
+        inferenceResult?.applyResult(_initializers, parent);
+        _initializers.add(initializer..parent = parent);
         redirectingInitializer = initializer;
       } else {
-        inferenceResult?.applyResult(initializers, parent);
+        inferenceResult?.applyResult(_initializers, parent);
         redirectingInitializer = initializer;
 
         LocatedMessage? message = helper.checkArgumentsForFunction(
@@ -604,7 +495,7 @@
             initializer.arguments,
             initializer.arguments.fileOffset, const <TypeParameter>[]);
         if (message != null) {
-          initializers.add(helper.buildInvalidInitializer(
+          _initializers.add(helper.buildInvalidInitializer(
               helper.buildUnresolvedError(
                   helper.constructorNameForDiagnostics(
                       initializer.target.name.text),
@@ -615,7 +506,7 @@
                   kind: UnresolvedKind.Constructor))
             ..parent = parent);
         } else {
-          initializers.add(initializer..parent = parent);
+          _initializers.add(initializer..parent = parent);
         }
       }
     } else if (redirectingInitializer != null) {
@@ -631,8 +522,8 @@
       _injectInvalidInitializer(messageSuperInitializerNotLast,
           initializer.fileOffset, noLength, helper, parent);
     } else {
-      inferenceResult?.applyResult(initializers, parent);
-      initializers.add(initializer..parent = parent);
+      inferenceResult?.applyResult(_initializers, parent);
+      _initializers.add(initializer..parent = parent);
     }
   }
 
@@ -662,24 +553,6 @@
     }
   }
 
-  Procedure? get _constructorTearOff;
-
-  @override
-  VariableDeclaration? getTearOffParameter(int index) {
-    Procedure? constructorTearOff = _constructorTearOff;
-    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;
-  }
-
   @override
   int computeDefaultTypes(ComputeDefaultTypeContext context,
       {required bool inErrorRecovery}) {
@@ -701,6 +574,12 @@
       TypeEnvironment typeEnvironment) {
     library.checkInitializersInFormals(formals, typeEnvironment,
         isAbstract: isAbstract, isExternal: isExternal);
+    List<SourceConstructorBuilderImpl>? augmentations = _augmentations;
+    if (augmentations != null) {
+      for (SourceConstructorBuilderImpl augmentation in augmentations) {
+        augmentation.checkTypes(library, nameSpace, typeEnvironment);
+      }
+    }
   }
 
   @override
@@ -745,27 +624,121 @@
   @override
   // Coverage-ignore(suite): Not run.
   bool get isEnumElement => false;
-}
-
-class DeclaredSourceConstructorBuilder
-    extends AbstractSourceConstructorBuilder {
-  late final Constructor _constructor;
 
   @override
-  late final Procedure? _constructorTearOff;
-
-  Set<SourcePropertyBuilder>? _initializedFields;
-
-  DeclaredSourceConstructorBuilder? actualOrigin;
-
-  List<DeclaredSourceConstructorBuilder>? _augmentations;
-
-  bool _hasDefaultValueCloner = false;
+  void buildOutlineNodes(BuildNodesCallback f) {
+    _introductory.buildOutlineNodes(f,
+        constructorBuilder: this,
+        libraryBuilder: libraryBuilder,
+        declarationConstructor: invokeTarget,
+        delayedDefaultValueCloners: _delayedDefaultValueCloners);
+  }
 
   @override
-  List<FormalParameterBuilder>? formals;
+  int buildBodyNodes(BuildNodesCallback f) {
+    _introductory.buildBody();
+    if (!isAugmenting) return 0;
+    _introductory.finishAugmentation(origin);
+    return 1;
+  }
 
-  final MemberName _memberName;
+  @override
+  void registerInitializedField(SourcePropertyBuilder fieldBuilder) {
+    if (isAugmenting) {
+      origin.registerInitializedField(fieldBuilder);
+    } else {
+      (_initializedFields ??= {}).add(fieldBuilder);
+    }
+  }
+
+  @override
+  Set<SourcePropertyBuilder>? takeInitializedFields() {
+    Set<SourcePropertyBuilder>? result = _initializedFields;
+    _initializedFields = null;
+    return result;
+  }
+
+  @override
+  void prepareInitializers() {
+    _introductory.prepareInitializers();
+    redirectingInitializer = null;
+    superInitializer = null;
+  }
+
+  @override
+  void prependInitializer(Initializer initializer) {
+    if (isAugmentation) {
+      // Coverage-ignore-block(suite): Not run.
+      origin.prependInitializer(initializer);
+    } else {
+      _introductory.prependInitializer(initializer);
+    }
+  }
+
+  bool _hasBuiltOutlines = false;
+  bool hasBuiltOutlineExpressions = false;
+
+  @override
+  void buildOutlineExpressions(ClassHierarchy classHierarchy,
+      List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
+    if (_hasBuiltOutlines) return;
+
+    if (isConst && isAugmenting) {
+      origin.buildOutlineExpressions(
+          classHierarchy, delayedDefaultValueCloners);
+    }
+    if (!hasBuiltOutlineExpressions) {
+      formals?.infer(classHierarchy);
+
+      LookupScope parentScope = declarationBuilder.scope;
+      for (Annotatable annotatable in annotatables) {
+        MetadataBuilder.buildAnnotations(annotatable, metadata,
+            createBodyBuilderContext(), libraryBuilder, fileUri, parentScope,
+            createFileUriExpression: isAugmented);
+      }
+      if (typeParameters != null) {
+        for (int i = 0; i < typeParameters!.length; i++) {
+          typeParameters![i].buildOutlineExpressions(
+              libraryBuilder,
+              createBodyBuilderContext(),
+              classHierarchy,
+              computeTypeParameterScope(parentScope));
+        }
+      }
+
+      if (formals != null) {
+        // For const constructors we need to include default parameter values
+        // into the outline. For all other formals we need to call
+        // buildOutlineExpressions to clear initializerToken to prevent
+        // consuming too much memory.
+        for (FormalParameterBuilder formal in formals!) {
+          formal.buildOutlineExpressions(libraryBuilder, declarationBuilder,
+              buildDefaultValue: FormalParameterBuilder
+                  .needsDefaultValuesBuiltAsOutlineExpressions(this));
+        }
+      }
+      hasBuiltOutlineExpressions = true;
+    }
+    if (isConst || _introductory.hasSuperInitializingFormals) {
+      // For modular compilation purposes we need to include initializers
+      // for const constructors into the outline.
+      LookupScope typeParameterScope =
+          computeTypeParameterScope(declarationBuilder.scope);
+      _buildConstructorForOutline(beginInitializers, typeParameterScope);
+      _introductory.buildBody();
+    }
+
+    addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
+    delayedDefaultValueCloners.addAll(_delayedDefaultValueCloners);
+    _delayedDefaultValueCloners.clear();
+
+    if (isConst && isAugmenting) {
+      _introductory.finishAugmentation(origin);
+    }
+
+    beginInitializers = null;
+    _hasBuiltOutlines = true;
+  }
 
   @override
   String get fullNameForErrors {
@@ -774,121 +747,6 @@
   }
 
   @override
-  final int fileOffset;
-
-  @override
-  final Uri fileUri;
-
-  @override
-  final SourceLibraryBuilder libraryBuilder;
-
-  @override
-  final DeclarationBuilder declarationBuilder;
-
-  DeclaredSourceConstructorBuilder(
-      {required List<MetadataBuilder>? metadata,
-      required Modifiers modifiers,
-      required OmittedTypeBuilder returnType,
-      required String name,
-      required List<NominalParameterBuilder>? typeParameters,
-      required this.formals,
-      required this.libraryBuilder,
-      required this.declarationBuilder,
-      required this.fileUri,
-      required int startOffset,
-      required this.fileOffset,
-      required int formalsOffset,
-      required int endOffset,
-      required Reference? constructorReference,
-      required Reference? tearOffReference,
-      required NameScheme nameScheme,
-      String? nativeMethodName,
-      required bool forAbstractClassOrEnumOrMixin,
-      required Token? beginInitializers,
-      bool isSynthetic = false})
-      : _hasSuperInitializingFormals =
-            formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
-        _memberName = nameScheme.getDeclaredName(name),
-        super(metadata, modifiers, returnType, name, typeParameters, formals,
-            formalsOffset, nativeMethodName, beginInitializers) {
-    _constructor = new Constructor(new FunctionNode(null),
-        name: dummyName,
-        fileUri: fileUri,
-        reference: constructorReference,
-        isSynthetic: isSynthetic)
-      ..startFileOffset = startOffset
-      ..fileOffset = fileOffset
-      ..fileEndOffset = endOffset;
-    nameScheme
-        .getConstructorMemberName(name, isTearOff: false)
-        .attachMember(_constructor);
-    _constructorTearOff = createConstructorTearOffProcedure(
-        nameScheme.getConstructorMemberName(name, isTearOff: true),
-        libraryBuilder,
-        fileUri,
-        fileOffset,
-        tearOffReference,
-        forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin);
-  }
-
-  @override
-  Builder get parent => declarationBuilder;
-
-  @override
-  bool get supportsTypeParameters => false;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Name get memberName => _memberName.name;
-
-  @override
-  SourceClassBuilder get classBuilder =>
-      super.classBuilder as SourceClassBuilder;
-
-  @override
-  Member get readTarget =>
-      _constructorTearOff ??
-      // The case is need to ensure that the upper bound is [Member] and not
-      // [GenericFunction].
-      _constructor as Member;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Reference get readTargetReference =>
-      (_constructorTearOff ?? _constructor).reference;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Member? get writeTarget => null;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Reference? get writeTargetReference => null;
-
-  @override
-  Member get invokeTarget => constructor;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Reference get invokeTargetReference => constructor.reference;
-
-  @override
-  FunctionNode get function => _constructor.function;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Iterable<Reference> get exportedMemberReferences => [constructor.reference];
-
-  @override
-  List<Initializer> get initializers => _constructor.initializers;
-
-  @override
-  DeclaredSourceConstructorBuilder get origin => actualOrigin ?? this;
-
-  // Coverage-ignore(suite): Not run.
-  List<SourceConstructorBuilder>? get augmentationsForTesting => _augmentations;
-
-  @override
   bool get isDeclarationInstanceMember => false;
 
   @override
@@ -910,16 +768,6 @@
   }
 
   @override
-  bool get isRedirecting {
-    for (Initializer initializer in initializers) {
-      if (initializer is RedirectingInitializer) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @override
   bool get isEffectivelyRedirecting {
     bool isRedirecting = this.isRedirecting;
     if (!isRedirecting) {
@@ -934,53 +782,21 @@
   }
 
   @override
-  void buildOutlineNodes(BuildNodesCallback f) {
-    _build();
-    f(
-        member: _constructor,
-        tearOff: _constructorTearOff,
-        kind: BuiltMemberKind.Constructor);
-  }
-
-  bool _hasBeenBuilt = false;
-
-  void _build() {
-    if (!_hasBeenBuilt) {
-      buildFunction();
-      _constructor.function.fileOffset = charOpenParenOffset;
-      _constructor.function.fileEndOffset = _constructor.fileEndOffset;
-      _constructor.function.typeParameters = const <TypeParameter>[];
-      _constructor.isConst = isConst;
-      _constructor.isExternal = isExternal;
-
-      if (_constructorTearOff != null) {
-        DelayedDefaultValueCloner delayedDefaultValueCloners =
-            buildConstructorTearOffProcedure(
-                tearOff: _constructorTearOff,
-                declarationConstructor: constructor,
-                implementationConstructor: _constructor,
-                enclosingDeclarationTypeParameters:
-                    classBuilder.cls.typeParameters,
-                libraryBuilder: libraryBuilder);
-        _delayedDefaultValueCloners.add(delayedDefaultValueCloners);
-      }
-
-      _hasBeenBuilt = true;
-    }
-    _buildFormals(_constructor);
-  }
-
-  @override
   VariableDeclaration getFormalParameter(int index) {
-    if (parent is SourceEnumBuilder) {
+    if (declarationBuilder is SourceEnumBuilder) {
       return formals![index + 2].variable!;
     } else {
-      return super.getFormalParameter(index);
+      return formals![index].variable!;
     }
   }
 
   ConstructorBuilder? _computeSuperTargetBuilder(
       List<Initializer>? initializers) {
+    if (declarationBuilder is! SourceClassBuilder) {
+      return null;
+    }
+    SourceClassBuilder classBuilder = declarationBuilder as SourceClassBuilder;
+
     Member superTarget;
     ClassBuilder superclassBuilder;
 
@@ -1031,14 +847,34 @@
     }
   }
 
-  final bool _hasSuperInitializingFormals;
+  @override
+  void inferTypes(ClassHierarchyBase hierarchy) {
+    inferFormalTypes(hierarchy);
+  }
 
-  final List<DelayedDefaultValueCloner> _delayedDefaultValueCloners =
-      <DelayedDefaultValueCloner>[];
+  bool _hasFormalsInferred = false;
 
   @override
+  void inferFormalTypes(ClassHierarchyBase hierarchy) {
+    if (_hasFormalsInferred) return;
+    if (formals != null) {
+      libraryBuilder.loader.withUriForCrashReporting(fileUri, fileOffset, () {
+        for (FormalParameterBuilder formal in formals!) {
+          if (formal.type is InferableTypeBuilder) {
+            if (formal.isInitializingFormal) {
+              formal.finalizeInitializingFormal(
+                  declarationBuilder, this, hierarchy);
+            }
+          }
+        }
+        _inferSuperInitializingFormals(hierarchy);
+      });
+    }
+    _hasFormalsInferred = true;
+  }
+
   void _inferSuperInitializingFormals(ClassHierarchyBase hierarchy) {
-    if (_hasSuperInitializingFormals) {
+    if (_introductory.hasSuperInitializingFormals) {
       List<Initializer>? initializers;
       if (beginInitializers != null) {
         BodyBuilder bodyBuilder = libraryBuilder.loader
@@ -1050,17 +886,17 @@
         initializers = bodyBuilder.parseInitializers(beginInitializers!,
             doFinishConstructor: false);
       }
-      finalizeSuperInitializingFormals(
+      _finalizeSuperInitializingFormals(
           hierarchy, _delayedDefaultValueCloners, initializers);
     }
   }
 
-  void finalizeSuperInitializingFormals(
+  void _finalizeSuperInitializingFormals(
       ClassHierarchyBase hierarchy,
       List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
       List<Initializer>? initializers) {
     if (formals == null) return;
-    if (!_hasSuperInitializingFormals) return;
+    if (!_introductory.hasSuperInitializingFormals) return;
 
     void performRecoveryForErroneousCase() {
       for (FormalParameterBuilder formal in formals!) {
@@ -1116,7 +952,7 @@
     List<String>? namedSuperParameters;
 
     Supertype? supertype = hierarchy.getClassAsInstanceOf(
-        classBuilder.cls, superTarget.enclosingClass!);
+        classBuilder!.cls, superTarget.enclosingClass!);
     assert(supertype != null);
     Map<TypeParameter, DartType> substitution =
         new Map<TypeParameter, DartType>.fromIterables(
@@ -1186,68 +1022,24 @@
     }
 
     if (positionalSuperParameters != null || namedSuperParameters != null) {
-      if (!_hasDefaultValueCloner) {
-        // If this constructor formals are part of a cyclic dependency this
-        // might be called more than once.
-        delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
-            superTarget, constructor,
-            positionalSuperParameters:
-                positionalSuperParameters ?? const <int>[],
-            namedSuperParameters: namedSuperParameters ?? const <String>[],
-            isOutlineNode: true,
-            libraryBuilder: libraryBuilder));
-        if (_constructorTearOff != null) {
-          delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
-              superTarget, _constructorTearOff,
-              positionalSuperParameters:
-                  positionalSuperParameters ?? const <int>[],
-              namedSuperParameters: namedSuperParameters ?? const <String>[],
-              isOutlineNode: true,
-              libraryBuilder: libraryBuilder));
-        }
-        _hasDefaultValueCloner = true;
-      }
+      _introductory.addSuperParameterDefaultValueCloners(
+          libraryBuilder: libraryBuilder,
+          delayedDefaultValueCloners: delayedDefaultValueCloners,
+          superTarget: superTarget,
+          positionalSuperParameters: positionalSuperParameters,
+          namedSuperParameters: namedSuperParameters);
     }
   }
 
-  bool _hasBuiltOutlines = false;
-
-  @override
-  void buildOutlineExpressions(ClassHierarchy classHierarchy,
-      List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
-    if (_hasBuiltOutlines) return;
-
-    formals?.infer(classHierarchy);
-
-    if (isConst && isAugmenting) {
-      origin.buildOutlineExpressions(
-          classHierarchy, delayedDefaultValueCloners);
-    }
-    super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
-
-    // 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) {
-      _buildConstructorForOutline(beginInitializers, classBuilder.scope);
-    }
-    addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
-    if (isConst && isAugmenting) {
-      _finishAugmentation();
-    }
-    beginInitializers = null;
-    _hasBuiltOutlines = true;
-  }
-
   @override
   void addSuperParameterDefaultValueCloners(
       List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
-    if (beginInitializers != null && constructor.initializers.isNotEmpty) {
+    if (beginInitializers != null && initializers.isNotEmpty) {
       // If the initializers aren't built yet, we can't compute the super
       // target. The synthetic initializers should be excluded, since they can
       // be built separately from formal field initializers.
       bool allInitializersAreSynthetic = true;
-      for (Initializer initializer in constructor.initializers) {
+      for (Initializer initializer in initializers) {
         if (!initializer.isSynthetic) {
           allInitializersAreSynthetic = false;
           break;
@@ -1255,160 +1047,17 @@
       }
       if (!allInitializersAreSynthetic) {
         ConstructorBuilder? superTargetBuilder =
-            _computeSuperTargetBuilder(constructor.initializers);
+            _computeSuperTargetBuilder(initializers);
         if (superTargetBuilder is SourceConstructorBuilder) {
           superTargetBuilder
               .addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
         }
       }
     }
-
-    delayedDefaultValueCloners.addAll(_delayedDefaultValueCloners);
-    _delayedDefaultValueCloners.clear();
   }
 
-  @override
-  void buildFunction() {
-    // According to the specification §9.3 the return type of a constructor
-    // function is its enclosing class.
-    super.buildFunction();
-    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.withDefaultNullability(typeParameter));
-    }
-    InterfaceType type = new InterfaceType(
-        enclosingClass, Nullability.nonNullable, typeParameterTypes);
-    returnType.registerInferredType(type);
-  }
-
-  Constructor get constructor =>
-      isAugmenting ? origin.constructor : _constructor;
-
-  void _finishAugmentation() {
-    finishConstructorAugmentation(origin.constructor, _constructor);
-
-    if (_constructorTearOff != null) {
-      finishProcedureAugmentation(
-          origin._constructorTearOff!, _constructorTearOff);
-    }
-  }
-
-  @override
-  int buildBodyNodes(BuildNodesCallback f) {
-    if (!isAugmenting) return 0;
-    _finishAugmentation();
-    return 1;
-  }
-
-  @override
-  void becomeNative(SourceLoader loader) {
-    _constructor.isExternal = true;
-    super.becomeNative(loader);
-  }
-
-  @override
-  void applyAugmentation(Builder augmentation) {
-    if (augmentation is DeclaredSourceConstructorBuilder) {
-      if (checkAugmentation(
-          augmentationLibraryBuilder: augmentation.libraryBuilder,
-          origin: this,
-          augmentation: augmentation)) {
-        augmentation.actualOrigin = this;
-        (_augmentations ??= []).add(augmentation);
-      }
-    } else {
-      // Coverage-ignore-block(suite): Not run.
-      reportAugmentationMismatch(
-          originLibraryBuilder: libraryBuilder,
-          origin: this,
-          augmentation: augmentation);
-    }
-  }
-
-  @override
-  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;
-  }
-
-  @override
-  void prependInitializer(Initializer initializer) {
-    initializer.parent = constructor;
-    constructor.initializers.insert(0, initializer);
-  }
-
-  @override
-  void registerInitializedField(SourcePropertyBuilder fieldBuilder) {
-    if (isAugmenting) {
-      origin.registerInitializedField(fieldBuilder);
-    } else {
-      (_initializedFields ??= {}).add(fieldBuilder);
-    }
-  }
-
-  @override
-  Set<SourcePropertyBuilder>? takeInitializedFields() {
-    Set<SourcePropertyBuilder>? result = _initializedFields;
-    _initializedFields = null;
-    return result;
-  }
-
-  void ensureGrowableFormals() {
-    if (formals != null) {
-      formals = new List<FormalParameterBuilder>.of(formals!, growable: true);
-    } else {
-      formals = <FormalParameterBuilder>[];
-    }
-  }
-
-  @override
-  void checkTypes(SourceLibraryBuilder library, NameSpace nameSpace,
-      TypeEnvironment typeEnvironment) {
-    super.checkTypes(library, nameSpace, typeEnvironment);
-    List<DeclaredSourceConstructorBuilder>? augmentations = _augmentations;
-    if (augmentations != null) {
-      for (DeclaredSourceConstructorBuilder augmentation in augmentations) {
-        augmentation.checkTypes(library, nameSpace, typeEnvironment);
-      }
-    }
-  }
-
-  @override
-  DartType substituteFieldType(DartType fieldType) {
-    // Nothing to do. Regular generative constructors don't have their own
-    // type parameters.
-    return fieldType;
-  }
-
-  @override
   BodyBuilderContext createBodyBuilderContext() {
-    return new ConstructorBodyBuilderContext(this, constructor);
-  }
-
-  // TODO(johnniwinther): Add annotations to tear-offs.
-  @override
-  Iterable<Annotatable> get annotatables => [constructor];
-
-  @override
-  bool get isAugmented {
-    if (isAugmenting) {
-      return origin._augmentations!.last != this;
-    } else {
-      return _augmentations != null;
-    }
+    return new ConstructorBodyBuilderContext(this, invokeTarget);
   }
 }
 
@@ -1652,322 +1301,6 @@
       TypeEnvironment typeEnvironment) {}
 }
 
-class SourceExtensionTypeConstructorBuilder
-    extends AbstractSourceConstructorBuilder {
-  @override
-  final SourceLibraryBuilder libraryBuilder;
-
-  @override
-  final SourceExtensionTypeDeclarationBuilder declarationBuilder;
-
-  late final Procedure _constructor;
-
-  @override
-  late final Procedure? _constructorTearOff;
-
-  Set<SourcePropertyBuilder>? _initializedFields;
-
-  @override
-  List<Initializer> initializers = [];
-
-  final MemberName _memberName;
-
-  DelayedDefaultValueCloner? _delayedDefaultValueCloner;
-
-  @override
-  final int fileOffset;
-
-  @override
-  final Uri fileUri;
-
-  SourceExtensionTypeConstructorBuilder(
-      {required List<MetadataBuilder>? metadata,
-      required Modifiers modifiers,
-      required OmittedTypeBuilder returnType,
-      required String name,
-      required List<NominalParameterBuilder>? typeParameters,
-      required List<FormalParameterBuilder>? formals,
-      required this.libraryBuilder,
-      required this.declarationBuilder,
-      required this.fileUri,
-      required int startOffset,
-      required this.fileOffset,
-      required int formalsOffset,
-      required int endOffset,
-      required Reference? constructorReference,
-      required Reference? tearOffReference,
-      required NameScheme nameScheme,
-      String? nativeMethodName,
-      required bool forAbstractClassOrEnumOrMixin,
-      required Token? beginInitializers})
-      : _memberName = nameScheme.getDeclaredName(name),
-        super(metadata, modifiers, returnType, name, typeParameters, formals,
-            formalsOffset, nativeMethodName, beginInitializers) {
-    _constructor = new Procedure(
-        dummyName, ProcedureKind.Method, new FunctionNode(null),
-        fileUri: fileUri, reference: constructorReference)
-      ..fileOffset = fileOffset
-      ..fileEndOffset = endOffset;
-    nameScheme
-        .getConstructorMemberName(name, isTearOff: false)
-        .attachMember(_constructor);
-    _constructorTearOff = createConstructorTearOffProcedure(
-        nameScheme.getConstructorMemberName(name, isTearOff: true),
-        libraryBuilder,
-        fileUri,
-        fileOffset,
-        tearOffReference,
-        forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin,
-        forceCreateLowering: true)
-      ?..isExtensionTypeMember = true;
-  }
-
-  @override
-  Builder get parent => declarationBuilder;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Name get memberName => _memberName.name;
-
-  @override
-  Member get readTarget =>
-      _constructorTearOff ?? // Coverage-ignore(suite): Not run.
-      _constructor;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Reference get readTargetReference =>
-      (_constructorTearOff ?? _constructor).reference;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Member? get writeTarget => null;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Reference? get writeTargetReference => null;
-
-  @override
-  Member get invokeTarget => _constructor;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Reference get invokeTargetReference => _constructor.reference;
-
-  @override
-  FunctionNode get function => _constructor.function;
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  Iterable<Reference> get exportedMemberReferences => [_constructor.reference];
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  void addSuperParameterDefaultValueCloners(
-      List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {}
-
-  @override
-  void _inferSuperInitializingFormals(ClassHierarchyBase hierarchy) {
-    if (formals != null) {
-      for (FormalParameterBuilder formal in formals!) {
-        if (formal.isSuperInitializingFormal) {
-          TypeBuilder formalTypeBuilder = formal.type;
-          if (formalTypeBuilder is InferableTypeBuilder) {
-            formalTypeBuilder.registerType(const InvalidType());
-          }
-        }
-      }
-    }
-  }
-
-  @override
-  void buildOutlineExpressions(ClassHierarchy classHierarchy,
-      List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
-    super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
-
-    if (isConst) {
-      // For modular compilation purposes we need to include initializers
-      // for const constructors into the outline.
-      LookupScope typeParameterScope =
-          computeTypeParameterScope(declarationBuilder.scope);
-      _buildConstructorForOutline(beginInitializers, typeParameterScope);
-      _buildBody();
-    }
-    beginInitializers = null;
-
-    if (_delayedDefaultValueCloner != null) {
-      delayedDefaultValueCloners.add(_delayedDefaultValueCloner!);
-    }
-  }
-
-  bool _hasBuiltBody = false;
-
-  void _buildBody() {
-    if (_hasBuiltBody) {
-      return;
-    }
-    if (!isExternal) {
-      VariableDeclaration thisVariable = this.thisVariable!;
-      List<Statement> statements = [thisVariable];
-      ExtensionTypeInitializerToStatementConverter visitor =
-          new ExtensionTypeInitializerToStatementConverter(
-              statements, thisVariable);
-      for (Initializer initializer in initializers) {
-        initializer.accept(visitor);
-      }
-      if (body != null && body is! EmptyStatement) {
-        statements.add(body!);
-      }
-      statements.add(new ReturnStatement(new VariableGet(thisVariable)));
-      body = new Block(statements);
-    }
-    _hasBuiltBody = true;
-  }
-
-  @override
-  int buildBodyNodes(BuildNodesCallback f) {
-    _buildBody();
-    // TODO(johnniwinther): Support augmentation.
-    return 0;
-  }
-
-  @override
-  void buildOutlineNodes(BuildNodesCallback f) {
-    _build();
-    f(
-        member: _constructor,
-        tearOff: _constructorTearOff,
-        kind: BuiltMemberKind.ExtensionTypeConstructor);
-  }
-
-  bool _hasBeenBuilt = false;
-
-  @override
-  void buildFunction() {
-    // According to the specification §9.3 the return type of a constructor
-    // function is its enclosing class.
-    super.buildFunction();
-    ExtensionTypeDeclaration extensionTypeDeclaration =
-        declarationBuilder.extensionTypeDeclaration;
-    List<DartType> typeParameterTypes = <DartType>[];
-    for (int i = 0; i < function.typeParameters.length; i++) {
-      TypeParameter typeParameter = function.typeParameters[i];
-      typeParameterTypes
-          .add(new TypeParameterType.withDefaultNullability(typeParameter));
-    }
-    ExtensionType type = new ExtensionType(
-        extensionTypeDeclaration, Nullability.nonNullable, typeParameterTypes);
-    returnType.registerInferredType(type);
-  }
-
-  void _build() {
-    if (!_hasBeenBuilt) {
-      buildFunction();
-      _constructor.function.fileOffset = charOpenParenOffset;
-      _constructor.function.fileEndOffset = _constructor.fileEndOffset;
-      _constructor.isConst = isConst;
-      _constructor.isExternal = isExternal;
-      _constructor.isStatic = true;
-      _constructor.isExtensionTypeMember = true;
-
-      if (_constructorTearOff != null) {
-        _delayedDefaultValueCloner = buildConstructorTearOffProcedure(
-            tearOff: _constructorTearOff,
-            declarationConstructor: _constructor,
-            implementationConstructor: _constructor,
-            libraryBuilder: libraryBuilder);
-      }
-
-      _hasBeenBuilt = true;
-    }
-    _buildFormals(_constructor);
-  }
-
-  @override
-  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.
-    initializers = [];
-    redirectingInitializer = null;
-    superInitializer = null;
-  }
-
-  @override
-  void prependInitializer(Initializer initializer) {
-    initializers.insert(0, initializer);
-  }
-
-  @override
-  void registerInitializedField(SourcePropertyBuilder fieldBuilder) {
-    (_initializedFields ??= {}).add(fieldBuilder);
-  }
-
-  @override
-  Set<SourcePropertyBuilder>? takeInitializedFields() {
-    Set<SourcePropertyBuilder>? result = _initializedFields;
-    _initializedFields = null;
-    return result;
-  }
-
-  @override
-  bool get isEffectivelyExternal => isExternal;
-
-  @override
-  bool get isRedirecting {
-    for (Initializer initializer in initializers) {
-      if (initializer is ExtensionTypeRedirectingInitializer) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @override
-  bool get isEffectivelyRedirecting => isRedirecting;
-
-  Substitution? _substitutionCache;
-
-  Substitution get _substitution {
-    if (typeParameters != null) {
-      assert(
-          declarationBuilder.typeParameters!.length == typeParameters?.length);
-      _substitutionCache = Substitution.fromPairs(
-          declarationBuilder.extensionTypeDeclaration.typeParameters,
-          new List<DartType>.generate(
-              declarationBuilder.typeParameters!.length,
-              (int index) => new TypeParameterType.withDefaultNullability(
-                  function.typeParameters[index])));
-    } else {
-      _substitutionCache = Substitution.empty;
-    }
-    return _substitutionCache!;
-  }
-
-  @override
-  DartType substituteFieldType(DartType fieldType) {
-    return _substitution.substituteType(fieldType);
-  }
-
-  @override
-  BodyBuilderContext createBodyBuilderContext() {
-    return new ExtensionTypeConstructorBodyBuilderContext(this, _constructor);
-  }
-
-  // TODO(johnniwinther): Add annotations to tear-offs.
-  @override
-  Iterable<Annotatable> get annotatables => [_constructor];
-
-  @override
-  bool get isAugmented => false;
-}
-
 class ExtensionTypeInitializerToStatementConverter
     implements InitializerVisitor<void> {
   VariableDeclaration thisVariable;
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart
index daf4e30..ed2fe0e 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -33,6 +33,7 @@
         messageNoUnnamedConstructorInObject,
         noLength,
         templateEnumContainsRestrictedInstanceDeclaration;
+import '../fragment/constructor/declaration.dart';
 import '../fragment/fragment.dart';
 import '../kernel/body_builder_context.dart';
 import '../kernel/constructor_tearoff_lowering.dart';
@@ -58,17 +59,13 @@
 
   final TypeBuilder _underscoreEnumTypeBuilder;
 
-  late final NamedTypeBuilder intType;
-
-  late final NamedTypeBuilder stringType;
-
   late final NamedTypeBuilder objectType;
 
   late final NamedTypeBuilder listType;
 
   late final NamedTypeBuilder selfType;
 
-  DeclaredSourceConstructorBuilder? synthesizedDefaultConstructorBuilder;
+  SourceConstructorBuilderImpl? synthesizedDefaultConstructorBuilder;
 
   late final _EnumValuesFieldDeclaration _enumValuesFieldDeclaration;
 
@@ -141,30 +138,6 @@
     super.buildScopes(coreLibrary);
     _createSynthesizedMembers(coreLibrary);
 
-    // Include duplicates to install the formals on all constructors to avoid a
-    // crash later.
-    Iterator<MemberBuilder> iterator =
-        nameSpace.filteredConstructorNameIterator(
-            includeDuplicates: true, includeAugmentations: true);
-    while (iterator.moveNext()) {
-      MemberBuilder member = iterator.current;
-      if (member is DeclaredSourceConstructorBuilder) {
-        member.ensureGrowableFormals();
-
-        FormalParameterBuilder nameFormalParameterBuilder =
-            new FormalParameterBuilder(FormalParameterKind.requiredPositional,
-                Modifiers.empty, stringType, "#name", fileOffset,
-                fileUri: fileUri, hasImmediatelyDeclaredInitializer: false);
-        member.formals!.insert(0, nameFormalParameterBuilder);
-
-        FormalParameterBuilder indexFormalParameterBuilder =
-            new FormalParameterBuilder(FormalParameterKind.requiredPositional,
-                Modifiers.empty, intType, "#index", fileOffset,
-                fileUri: fileUri, hasImmediatelyDeclaredInitializer: false);
-        member.formals!.insert(0, indexFormalParameterBuilder);
-      }
-    }
-
     Iterator<MemberBuilder> constructorIterator =
         nameSpace.filteredConstructorIterator(
             includeDuplicates: false, includeAugmentations: true);
@@ -180,23 +153,6 @@
   void _createSynthesizedMembers(LibraryBuilder coreLibrary) {
     // TODO(ahe): These types shouldn't be looked up in scope, they come
     // directly from dart:core.
-    intType = new NamedTypeBuilderImpl(
-        const PredefinedTypeName("int"), const NullabilityBuilder.omitted(),
-        instanceTypeParameterAccess:
-            // If "int" resolves to an instance type parameter then that we
-            // would allowed (the types that we are adding are in instance
-            // context after all) but it would be unexpected and we would like
-            // an assertion failure, since "int" was meant to be `int` from
-            // `dart:core`.
-            // TODO(johnniwinther): Add a more robust way of creating named
-            // typed builders for dart:core types. This might be needed for the
-            // enhanced enums feature where enums can actually declare type
-            // variables.
-            InstanceTypeParameterAccessState.Unexpected);
-    stringType = new NamedTypeBuilderImpl(
-        const PredefinedTypeName("String"), const NullabilityBuilder.omitted(),
-        instanceTypeParameterAccess:
-            InstanceTypeParameterAccessState.Unexpected);
     objectType = new NamedTypeBuilderImpl(
         const PredefinedTypeName("Object"), const NullabilityBuilder.omitted(),
         instanceTypeParameterAccess:
@@ -326,35 +282,55 @@
       }
     }
     if (needsSynthesizedDefaultConstructor) {
-      synthesizedDefaultConstructorBuilder =
-          new DeclaredSourceConstructorBuilder(
-              metadata: null,
-              modifiers: Modifiers.Const,
+      FormalParameterBuilder nameFormalParameterBuilder =
+          new FormalParameterBuilder(
+              FormalParameterKind.requiredPositional,
+              Modifiers.empty,
+              libraryBuilder.loader.target.stringType,
+              "#name",
+              fileOffset,
+              fileUri: fileUri,
+              hasImmediatelyDeclaredInitializer: false);
+
+      FormalParameterBuilder indexFormalParameterBuilder =
+          new FormalParameterBuilder(
+              FormalParameterKind.requiredPositional,
+              Modifiers.empty,
+              libraryBuilder.loader.target.intType,
+              "#index",
+              fileOffset,
+              fileUri: fileUri,
+              hasImmediatelyDeclaredInitializer: false);
+
+      ConstructorDeclaration constructorDeclaration =
+          new DefaultEnumConstructorDeclaration(
               returnType:
                   libraryBuilder.loader.inferableTypes.addInferableType(),
-              name: "",
-              typeParameters: null,
-              formals: [],
-              libraryBuilder: libraryBuilder,
-              declarationBuilder: this,
+              formals: [
+                indexFormalParameterBuilder,
+                nameFormalParameterBuilder
+              ],
               fileUri: fileUri,
-              startOffset: fileOffset,
-              fileOffset: fileOffset,
-              formalsOffset: fileOffset,
-              endOffset: endOffset,
-              constructorReference: constructorReference,
-              tearOffReference: tearOffReference,
-              nameScheme: new NameScheme(
-                  isInstanceMember: false,
-                  containerName: new ClassName(name),
-                  containerType: ContainerType.Class,
-                  libraryName: libraryName),
-              forAbstractClassOrEnumOrMixin: true,
-              isSynthetic: true,
-              // Trick the constructor to be built during the outline phase.
-              // TODO(johnniwinther): Avoid relying on [beginInitializers] to
-              // ensure building constructors creation during the outline phase.
-              beginInitializers: new Token.eof(-1));
+              fileOffset: fileOffset);
+      synthesizedDefaultConstructorBuilder = new SourceConstructorBuilderImpl(
+          modifiers: Modifiers.Const,
+          name: "",
+          libraryBuilder: libraryBuilder,
+          declarationBuilder: this,
+          fileUri: fileUri,
+          fileOffset: fileOffset,
+          constructorReference: constructorReference,
+          tearOffReference: tearOffReference,
+          nameScheme: new NameScheme(
+              isInstanceMember: false,
+              containerName: new ClassName(name),
+              containerType: ContainerType.Class,
+              libraryName: libraryName),
+          // Trick the constructor to be built during the outline phase.
+          // TODO(johnniwinther): Avoid relying on [beginInitializers] to
+          // ensure building constructors creation during the outline phase.
+          beginInitializers: new Token.eof(-1),
+          constructorDeclaration: constructorDeclaration);
       synthesizedDefaultConstructorBuilder!
           .registerInitializedField(valuesBuilder);
       nameSpace.addConstructor("", synthesizedDefaultConstructorBuilder!);
@@ -379,7 +355,9 @@
         isAbstract: false,
         reference: toStringReference,
         creator: new _EnumToStringCreator(
-            this, stringType, _underscoreEnumTypeBuilder));
+            this,
+            libraryBuilder.loader.target.stringType,
+            _underscoreEnumTypeBuilder));
     nameSpace.addLocalMember(toStringBuilder.name, toStringBuilder,
         setter: false);
     nameSpaceBuilder.checkTypeParameterConflict(libraryBuilder,
@@ -410,9 +388,6 @@
       }
     }
 
-    intType.resolveIn(coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
-    stringType.resolveIn(
-        coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
     objectType.resolveIn(
         coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
     listType.resolveIn(coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
@@ -429,7 +404,7 @@
     if (identical(this.supertypeBuilder, _underscoreEnumTypeBuilder)) {
       if (synthesizedDefaultConstructorBuilder != null) {
         Constructor constructor =
-            synthesizedDefaultConstructorBuilder!.constructor;
+            synthesizedDefaultConstructorBuilder!.invokeTarget as Constructor;
         ClassBuilder objectClass = objectType.declaration as ClassBuilder;
         ClassBuilder enumClass =
             _underscoreEnumTypeBuilder.declaration as ClassBuilder;
diff --git a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
index fedd303..830bc84 100644
--- a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
@@ -860,14 +860,14 @@
 
   /// Looks up the constructor by [name] on the class built by this class
   /// builder.
-  SourceExtensionTypeConstructorBuilder? lookupConstructor(Name name) {
+  SourceConstructorBuilderImpl? lookupConstructor(Name name) {
     if (name.text == "new") {
       // Coverage-ignore-block(suite): Not run.
       name = new Name("", name.library);
     }
 
     Builder? builder = nameSpace.lookupConstructor(name.text);
-    if (builder is SourceExtensionTypeConstructorBuilder) {
+    if (builder is SourceConstructorBuilderImpl) {
       return builder;
     }
     return null;
diff --git a/pkg/front_end/lib/src/source/source_factory_builder.dart b/pkg/front_end/lib/src/source/source_factory_builder.dart
index b516aac..cd560ec 100644
--- a/pkg/front_end/lib/src/source/source_factory_builder.dart
+++ b/pkg/front_end/lib/src/source/source_factory_builder.dart
@@ -515,7 +515,7 @@
   }
 
   @override
-  void setBody(Statement body) {
+  void registerFunctionBody(Statement body) {
     _member.setBody(body);
   }
 
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index ff69493..941edfc 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -2,6 +2,7 @@
 // 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/parser/formal_parameter_kind.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/reference_from_index.dart';
 
@@ -12,12 +13,14 @@
 import '../base/scope.dart';
 import '../builder/builder.dart';
 import '../builder/declaration_builders.dart';
+import '../builder/formal_parameter_builder.dart';
 import '../builder/function_builder.dart';
 import '../builder/member_builder.dart';
 import '../builder/named_type_builder.dart';
 import '../builder/nullability_builder.dart';
 import '../builder/prefix_builder.dart';
 import '../builder/type_builder.dart';
+import '../fragment/constructor/declaration.dart';
 import '../fragment/fragment.dart';
 import 'builder_factory.dart';
 import 'name_scheme.dart';
@@ -1583,11 +1586,32 @@
               methodBuilder;
         }
       case ConstructorFragment():
-        List<NominalParameterBuilder>? typeParameters =
-            fragment.typeParameters?.builders;
+        String name = fragment.name;
+        NameScheme nameScheme = new NameScheme(
+            isInstanceMember: false,
+            containerName: containerName,
+            containerType: containerType,
+            libraryName: indexedLibrary != null
+                ? new LibraryName(indexedLibrary.library.reference)
+                : enclosingLibraryBuilder.libraryName);
+
+        Reference? constructorReference;
+        Reference? tearOffReference;
+
+        if (indexedContainer != null) {
+          constructorReference = indexedContainer!.lookupConstructorReference(
+              nameScheme.getConstructorMemberName(name, isTearOff: false).name);
+          tearOffReference = indexedContainer!.lookupGetterReference(
+              nameScheme.getConstructorMemberName(name, isTearOff: true).name);
+        }
+
+        SourceConstructorBuilderImpl constructorBuilder;
         switch (declarationBuilder!) {
-          case ExtensionBuilder():
           case ExtensionTypeDeclarationBuilder():
+            List<NominalParameterBuilder>? typeParameters = fragment
+                .typeParameters
+                // Coverage-ignore(suite): Not run.
+                ?.builders;
             NominalParameterCopy? nominalVariableCopy =
                 NominalParameterCopy.copyTypeParameters(
                     unboundNominalParameters, declarationBuilder.typeParameters,
@@ -1603,74 +1627,109 @@
                 typeParameters = nominalVariableCopy.newParameterBuilders;
               }
             }
+            fragment.typeParameterNameSpace.addTypeParameters(
+                problemReporting, typeParameters,
+                ownerName: fragment.name, allowNameConflict: true);
+            ConstructorDeclaration constructorDeclaration =
+                new ExtensionTypeConstructorDeclaration(fragment,
+                    typeParameters: typeParameters);
+            constructorBuilder = new SourceConstructorBuilderImpl(
+                modifiers: fragment.modifiers,
+                name: name,
+                libraryBuilder: enclosingLibraryBuilder,
+                declarationBuilder:
+                    declarationBuilder as SourceExtensionTypeDeclarationBuilder,
+                fileUri: fragment.fileUri,
+                fileOffset: fragment.fullNameOffset,
+                constructorReference: constructorReference,
+                tearOffReference: tearOffReference,
+                nameScheme: nameScheme,
+                nativeMethodName: fragment.nativeMethodName,
+                beginInitializers: fragment.beginInitializers,
+                constructorDeclaration: constructorDeclaration);
           case ClassBuilder():
-        }
-        fragment.typeParameterNameSpace.addTypeParameters(
-            problemReporting, typeParameters,
-            ownerName: fragment.name, allowNameConflict: true);
-
-        String name = fragment.name;
-        NameScheme nameScheme = new NameScheme(
-            isInstanceMember: false,
-            containerName: containerName,
-            containerType: containerType,
-            libraryName: indexedLibrary != null
-                ? new LibraryName(indexedLibrary.library.reference)
-                : enclosingLibraryBuilder.libraryName);
-
-        Reference? constructorReference;
-        Reference? tearOffReference;
-
-        if (indexedContainer != null) {
-          constructorReference = indexedContainer!.lookupConstructorReference(
-              nameScheme.getConstructorMemberName(name, isTearOff: false).name);
-          tearOffReference = indexedContainer!.lookupGetterReference(
-              nameScheme.getConstructorMemberName(name, isTearOff: true).name);
-        }
-
-        AbstractSourceConstructorBuilder constructorBuilder;
-        if (declarationBuilder is SourceExtensionTypeDeclarationBuilder) {
-          constructorBuilder = new SourceExtensionTypeConstructorBuilder(
-              metadata: fragment.metadata,
-              modifiers: fragment.modifiers,
-              returnType: fragment.returnType,
-              name: name,
-              typeParameters: typeParameters,
-              formals: fragment.formals,
-              libraryBuilder: enclosingLibraryBuilder,
-              declarationBuilder: declarationBuilder,
-              fileUri: fragment.fileUri,
-              startOffset: fragment.startOffset,
-              fileOffset: fragment.fullNameOffset,
-              formalsOffset: fragment.formalsOffset,
-              endOffset: fragment.endOffset,
-              constructorReference: constructorReference,
-              tearOffReference: tearOffReference,
-              nameScheme: nameScheme,
-              nativeMethodName: fragment.nativeMethodName,
-              forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
-              beginInitializers: fragment.beginInitializers);
-        } else {
-          constructorBuilder = new DeclaredSourceConstructorBuilder(
-              metadata: fragment.metadata,
-              modifiers: fragment.modifiers,
-              returnType: fragment.returnType,
-              name: fragment.name,
-              typeParameters: typeParameters,
-              formals: fragment.formals,
-              libraryBuilder: enclosingLibraryBuilder,
-              declarationBuilder: declarationBuilder,
-              fileUri: fragment.fileUri,
-              startOffset: fragment.startOffset,
-              fileOffset: fragment.fullNameOffset,
-              formalsOffset: fragment.formalsOffset,
-              endOffset: fragment.endOffset,
-              constructorReference: constructorReference,
-              tearOffReference: tearOffReference,
-              nameScheme: nameScheme,
-              nativeMethodName: fragment.nativeMethodName,
-              forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
-              beginInitializers: fragment.beginInitializers);
+            List<FormalParameterBuilder>? syntheticFormals;
+            if (declarationBuilder.isEnum) {
+              syntheticFormals = [
+                new FormalParameterBuilder(
+                    FormalParameterKind.requiredPositional,
+                    Modifiers.empty,
+                    loader.target.intType,
+                    "#index",
+                    fragment.fullNameOffset,
+                    fileUri: fragment.fileUri,
+                    hasImmediatelyDeclaredInitializer: false),
+                new FormalParameterBuilder(
+                    FormalParameterKind.requiredPositional,
+                    Modifiers.empty,
+                    loader.target.stringType,
+                    "#name",
+                    fragment.fullNameOffset,
+                    fileUri: fragment.fileUri,
+                    hasImmediatelyDeclaredInitializer: false),
+              ];
+            }
+            List<NominalParameterBuilder>? typeParameters =
+                fragment.typeParameters?.builders;
+            fragment.typeParameterNameSpace.addTypeParameters(
+                problemReporting, typeParameters,
+                ownerName: fragment.name, allowNameConflict: true);
+            ConstructorDeclaration constructorDeclaration =
+                new RegularConstructorDeclaration(fragment,
+                    typeParameters: typeParameters,
+                    syntheticFormals: syntheticFormals);
+            constructorBuilder = new SourceConstructorBuilderImpl(
+                modifiers: fragment.modifiers,
+                name: fragment.name,
+                libraryBuilder: enclosingLibraryBuilder,
+                declarationBuilder: declarationBuilder,
+                fileUri: fragment.fileUri,
+                fileOffset: fragment.fullNameOffset,
+                constructorReference: constructorReference,
+                tearOffReference: tearOffReference,
+                nameScheme: nameScheme,
+                nativeMethodName: fragment.nativeMethodName,
+                beginInitializers: fragment.beginInitializers,
+                constructorDeclaration: constructorDeclaration);
+          case ExtensionBuilder():
+            List<NominalParameterBuilder>? typeParameters = fragment
+                .typeParameters
+                // Coverage-ignore(suite): Not run.
+                ?.builders;
+            NominalParameterCopy? nominalVariableCopy =
+                NominalParameterCopy.copyTypeParameters(
+                    unboundNominalParameters, declarationBuilder.typeParameters,
+                    kind: TypeParameterKind.extensionSynthesized,
+                    instanceTypeParameterAccess:
+                        InstanceTypeParameterAccessState.Allowed);
+            if (nominalVariableCopy != null) {
+              if (typeParameters != null) {
+                // Coverage-ignore-block(suite): Not run.
+                typeParameters = nominalVariableCopy.newParameterBuilders
+                  ..addAll(typeParameters);
+              } else {
+                typeParameters = nominalVariableCopy.newParameterBuilders;
+              }
+            }
+            fragment.typeParameterNameSpace.addTypeParameters(
+                problemReporting, typeParameters,
+                ownerName: fragment.name, allowNameConflict: true);
+            ConstructorDeclaration constructorDeclaration =
+                new RegularConstructorDeclaration(fragment,
+                    typeParameters: typeParameters, syntheticFormals: null);
+            constructorBuilder = new SourceConstructorBuilderImpl(
+                modifiers: fragment.modifiers,
+                name: fragment.name,
+                libraryBuilder: enclosingLibraryBuilder,
+                declarationBuilder: declarationBuilder,
+                fileUri: fragment.fileUri,
+                fileOffset: fragment.fullNameOffset,
+                constructorReference: constructorReference,
+                tearOffReference: tearOffReference,
+                nameScheme: nameScheme,
+                nativeMethodName: fragment.nativeMethodName,
+                beginInitializers: fragment.beginInitializers,
+                constructorDeclaration: constructorDeclaration);
         }
         fragment.builder = constructorBuilder;
         builders.add(new _AddBuilder(fragment.name, constructorBuilder,
@@ -1685,19 +1744,6 @@
       case PrimaryConstructorFragment():
         String name = fragment.name;
 
-        NominalParameterCopy? nominalVariableCopy =
-            NominalParameterCopy.copyTypeParameters(
-                unboundNominalParameters, declarationBuilder!.typeParameters,
-                kind: TypeParameterKind.extensionSynthesized,
-                instanceTypeParameterAccess:
-                    InstanceTypeParameterAccessState.Allowed);
-
-        List<NominalParameterBuilder>? typeParameters =
-            nominalVariableCopy?.newParameterBuilders;
-        fragment.typeParameterNameSpace.addTypeParameters(
-            problemReporting, typeParameters,
-            ownerName: fragment.name, allowNameConflict: true);
-
         NameScheme nameScheme = new NameScheme(
             isInstanceMember: false,
             containerName: containerName,
@@ -1716,50 +1762,57 @@
               nameScheme.getConstructorMemberName(name, isTearOff: true).name);
         }
 
-        AbstractSourceConstructorBuilder constructorBuilder;
-        if (declarationBuilder is SourceExtensionTypeDeclarationBuilder) {
-          constructorBuilder = new SourceExtensionTypeConstructorBuilder(
-              metadata: null,
-              modifiers: fragment.modifiers,
-              returnType: fragment.returnType,
-              name: name,
-              typeParameters: typeParameters,
-              formals: fragment.formals,
-              libraryBuilder: enclosingLibraryBuilder,
-              declarationBuilder: declarationBuilder,
-              fileUri: fragment.fileUri,
-              startOffset: fragment.startOffset,
-              fileOffset: fragment.fileOffset,
-              formalsOffset: fragment.formalsOffset,
-              // TODO(johnniwinther): Provide `endOffset`.
-              endOffset: fragment.formalsOffset,
-              constructorReference: constructorReference,
-              tearOffReference: tearOffReference,
-              nameScheme: nameScheme,
-              forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
-              beginInitializers: fragment.beginInitializers);
-        } else {
-          // Coverage-ignore-block(suite): Not run.
-          constructorBuilder = new DeclaredSourceConstructorBuilder(
-              metadata: null,
-              modifiers: fragment.modifiers,
-              returnType: fragment.returnType,
-              name: fragment.name,
-              typeParameters: typeParameters,
-              formals: fragment.formals,
-              libraryBuilder: enclosingLibraryBuilder,
-              declarationBuilder: declarationBuilder,
-              fileUri: fragment.fileUri,
-              startOffset: fragment.startOffset,
-              fileOffset: fragment.fileOffset,
-              formalsOffset: fragment.formalsOffset,
-              // TODO(johnniwinther): Provide `endOffset`.
-              endOffset: fragment.formalsOffset,
-              constructorReference: constructorReference,
-              tearOffReference: tearOffReference,
-              nameScheme: nameScheme,
-              forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
-              beginInitializers: fragment.beginInitializers);
+        SourceConstructorBuilderImpl constructorBuilder;
+        switch (declarationBuilder!) {
+          case ExtensionTypeDeclarationBuilder():
+            NominalParameterCopy? nominalVariableCopy =
+                NominalParameterCopy.copyTypeParameters(
+                    unboundNominalParameters, declarationBuilder.typeParameters,
+                    kind: TypeParameterKind.extensionSynthesized,
+                    instanceTypeParameterAccess:
+                        InstanceTypeParameterAccessState.Allowed);
+
+            List<NominalParameterBuilder>? typeParameters =
+                nominalVariableCopy?.newParameterBuilders;
+            fragment.typeParameterNameSpace.addTypeParameters(
+                problemReporting, typeParameters,
+                ownerName: fragment.name, allowNameConflict: true);
+            ConstructorDeclaration constructorDeclaration =
+                new ExtensionTypePrimaryConstructorDeclaration(fragment,
+                    typeParameters: typeParameters);
+            constructorBuilder = new SourceConstructorBuilderImpl(
+                modifiers: fragment.modifiers,
+                name: name,
+                libraryBuilder: enclosingLibraryBuilder,
+                declarationBuilder:
+                    declarationBuilder as SourceExtensionTypeDeclarationBuilder,
+                fileUri: fragment.fileUri,
+                fileOffset: fragment.fileOffset,
+                constructorReference: constructorReference,
+                tearOffReference: tearOffReference,
+                nameScheme: nameScheme,
+                beginInitializers: fragment.beginInitializers,
+                constructorDeclaration: constructorDeclaration);
+          // Coverage-ignore(suite): Not run.
+          case ClassBuilder():
+            ConstructorDeclaration constructorDeclaration =
+                new PrimaryConstructorDeclaration(fragment);
+            constructorBuilder = new SourceConstructorBuilderImpl(
+                modifiers: fragment.modifiers,
+                name: fragment.name,
+                libraryBuilder: enclosingLibraryBuilder,
+                declarationBuilder: declarationBuilder,
+                fileUri: fragment.fileUri,
+                fileOffset: fragment.fileOffset,
+                constructorReference: constructorReference,
+                tearOffReference: tearOffReference,
+                nameScheme: nameScheme,
+                beginInitializers: fragment.beginInitializers,
+                constructorDeclaration: constructorDeclaration);
+          // Coverage-ignore(suite): Not run.
+          case ExtensionBuilder():
+            throw new UnsupportedError(
+                'Unexpected extension primary constructor $fragment');
         }
         fragment.builder = constructorBuilder;
         builders.add(new _AddBuilder(fragment.name, constructorBuilder,
diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/type_inference/inference_visitor.dart
index 8dfb41e..cd32bfa 100644
--- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart
+++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart
@@ -151,7 +151,7 @@
   @override
   final TypeAnalyzerOptions options;
 
-  final ConstructorDeclaration? constructorDeclaration;
+  final ConstructorDeclarationBuilder? constructorDeclaration;
 
   @override
   late final SharedTypeAnalyzerErrors errors = new SharedTypeAnalyzerErrors(
diff --git a/pkg/front_end/lib/src/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/type_inference/type_inferrer.dart
index 426df7b..8730c11 100644
--- a/pkg/front_end/lib/src/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/type_inference/type_inferrer.dart
@@ -52,8 +52,10 @@
       DartType returnType, AsyncMarker asyncMarker, Statement body);
 
   /// Performs type inference on the given constructor initializer.
-  InitializerInferenceResult inferInitializer(InferenceHelper helper,
-      ConstructorDeclaration constructorDeclaration, Initializer initializer);
+  InitializerInferenceResult inferInitializer(
+      InferenceHelper helper,
+      ConstructorDeclarationBuilder constructorDeclaration,
+      Initializer initializer);
 
   /// Performs type inference on the given metadata annotations.
   void inferMetadata(
@@ -141,7 +143,7 @@
             typeCacheLegacy: engine.typeCacheLegacy);
 
   InferenceVisitorBase _createInferenceVisitor(InferenceHelper helper,
-      [ConstructorDeclaration? constructorDeclaration]) {
+      [ConstructorDeclarationBuilder? constructorDeclaration]) {
     // For full (non-top level) inference, we need access to the
     // InferenceHelper so that we can perform error reporting.
     return new InferenceVisitorImpl(
@@ -246,8 +248,10 @@
   }
 
   @override
-  InitializerInferenceResult inferInitializer(InferenceHelper helper,
-      ConstructorDeclaration constructorDeclaration, Initializer initializer) {
+  InitializerInferenceResult inferInitializer(
+      InferenceHelper helper,
+      ConstructorDeclarationBuilder constructorDeclaration,
+      Initializer initializer) {
     // Use polymorphic dispatch on [KernelInitializer] to perform whatever
     // kind of type inference is correct for this kind of initializer.
     // TODO(paulberry): experiment to see if dynamic dispatch would be better,
@@ -349,8 +353,10 @@
   }
 
   @override
-  InitializerInferenceResult inferInitializer(InferenceHelper helper,
-      ConstructorDeclaration constructorDeclaration, Initializer initializer) {
+  InitializerInferenceResult inferInitializer(
+      InferenceHelper helper,
+      ConstructorDeclarationBuilder constructorDeclaration,
+      Initializer initializer) {
     benchmarker.beginSubdivide(BenchmarkSubdivides.inferInitializer);
     InitializerInferenceResult result =
         impl.inferInitializer(helper, constructorDeclaration, initializer);
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index 438e04e..89d9b71 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -479,6 +479,16 @@
     missCount: 0,
   ),
   // 100.0%.
+  "package:front_end/src/fragment/constructor/declaration.dart": (
+    hitCount: 248,
+    missCount: 0,
+  ),
+  // 100.0%.
+  "package:front_end/src/fragment/constructor/encoding.dart": (
+    hitCount: 318,
+    missCount: 0,
+  ),
+  // 100.0%.
   "package:front_end/src/fragment/enum.dart": (
     hitCount: 13,
     missCount: 0,
@@ -580,12 +590,12 @@
   ),
   // 100.0%.
   "package:front_end/src/kernel/body_builder.dart": (
-    hitCount: 7181,
+    hitCount: 7180,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/kernel/body_builder_context.dart": (
-    hitCount: 303,
+    hitCount: 289,
     missCount: 0,
   ),
   // 100.0%.
@@ -730,7 +740,7 @@
   ),
   // 100.0%.
   "package:front_end/src/kernel/kernel_target.dart": (
-    hitCount: 1068,
+    hitCount: 1051,
     missCount: 0,
   ),
   // 100.0%.
@@ -860,12 +870,12 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_constructor_builder.dart": (
-    hitCount: 1084,
+    hitCount: 722,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/source/source_enum_builder.dart": (
-    hitCount: 420,
+    hitCount: 403,
     missCount: 0,
   ),
   // 100.0%.
@@ -931,7 +941,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/type_parameter_scope_builder.dart": (
-    hitCount: 1395,
+    hitCount: 1408,
     missCount: 0,
   ),
   // 100.0%.
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index 4409fb2..0271767 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_test.dart
@@ -169,7 +169,7 @@
     if (memberBuilder is SourcePropertyBuilder) {
       patchMembers = memberBuilder.augmentationsForTesting;
     }
-    if (memberBuilder is DeclaredSourceConstructorBuilder) {
+    if (memberBuilder is SourceConstructorBuilderImpl) {
       patchMembers = memberBuilder.augmentationsForTesting;
     }
     if (memberBuilder is SourceFactoryBuilder) {
diff --git a/pkg/front_end/testcases/extension_types/issue53212.dart.strong.outline.expect b/pkg/front_end/testcases/extension_types/issue53212.dart.strong.outline.expect
index 75dd9c6..85d6418 100644
--- a/pkg/front_end/testcases/extension_types/issue53212.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/extension_types/issue53212.dart.strong.outline.expect
@@ -55,27 +55,35 @@
   ;
 static extension-type-member method E1|constructor#_#new#tearOff(core::int foo) → self::E1% /* erasure=core::int, declared=! */
   return self::E1|constructor#(foo);
-static extension-type-member method E1|constructor#named(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */
-  ;
+static extension-type-member method E1|constructor#named(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */ {
+  lowered final self::E1% /* erasure=core::int, declared=! */ #this = foo;
+  return #this;
+}
 static extension-type-member method E1|constructor#_#named#tearOff(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */
   return self::E1|constructor#named(foo, bar);
 static extension-type-member method E2|constructor#(core::int foo) → self::E2% /* erasure=core::int, declared=! */
   ;
 static extension-type-member method E2|constructor#_#new#tearOff(core::int foo) → self::E2% /* erasure=core::int, declared=! */
   return self::E2|constructor#(foo);
-static extension-type-member method E2|constructor#named(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */
-  ;
+static extension-type-member method E2|constructor#named(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */ {
+  lowered final self::E2% /* erasure=core::int, declared=! */ #this = foo;
+  return #this;
+}
 static extension-type-member method E2|constructor#_#named#tearOff(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */
   return self::E2|constructor#named(foo, bar: bar);
 static extension-type-member method E3|constructor#(core::int foo) → self::E3% /* erasure=core::int, declared=! */
   ;
 static extension-type-member method E3|constructor#_#new#tearOff(core::int foo) → self::E3% /* erasure=core::int, declared=! */
   return self::E3|constructor#(foo);
-static extension-type-member method E3|constructor#named(core::int foo, [has-declared-initializer invalid-type bar = null]) → self::E3% /* erasure=core::int, declared=! */
-  ;
+static extension-type-member method E3|constructor#named(core::int foo, [has-declared-initializer invalid-type bar = null]) → self::E3% /* erasure=core::int, declared=! */ {
+  lowered final self::E3% /* erasure=core::int, declared=! */ #this = foo;
+  return #this;
+}
 static extension-type-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3% /* erasure=core::int, declared=! */
   return self::E3|constructor#named(foo, bar);
-static extension-type-member method E4|constructor#(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */
-  ;
+static extension-type-member method E4|constructor#(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */ {
+  lowered final self::E4% /* erasure=invalid-type, declared=! */ #this = foo;
+  return #this;
+}
 static extension-type-member method E4|constructor#_#new#tearOff(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */
   return self::E4|constructor#(foo);
diff --git a/pkg/front_end/testcases/extension_types/issue53625.dart.strong.outline.expect b/pkg/front_end/testcases/extension_types/issue53625.dart.strong.outline.expect
index f44f65e..6e001c1 100644
--- a/pkg/front_end/testcases/extension_types/issue53625.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/extension_types/issue53625.dart.strong.outline.expect
@@ -38,8 +38,10 @@
   ;
 static extension-type-member method E07|constructor#_#new#tearOff(core::int x) → self::E07% /* erasure=core::int, declared=! */
   return self::E07|constructor#(x);
-static extension-type-member method E08|constructor#(core::int x) → self::E08% /* erasure=core::int, declared=! */
-  ;
+static extension-type-member method E08|constructor#(core::int x) → self::E08% /* erasure=core::int, declared=! */ {
+  lowered final self::E08% /* erasure=core::int, declared=! */ #this = x;
+  return #this;
+}
 static extension-type-member method E08|constructor#_#new#tearOff(core::int x) → self::E08% /* erasure=core::int, declared=! */
   return self::E08|constructor#(x);
 static extension-type-member method E11|constructor#(() → core::int x) → self::E11% /* erasure=() → core::int, declared=! */