[cfe] Use SourceCompilationUnit in SourceLoader.tokenize

This moves a lot of the methods needed for tokenization and
outline parsing from SourceLibraryBuilder to SourceCompilationUnitImpl.

Parts that are still used elsewhere remains in SourceLibraryBuilder
but accessed through SourceCompilationUnitImpl.

Change-Id: I0df431eee4c187e5447850961d2c27be14cb0ba3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/371682
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 92eb566..5ec9469d 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -5,10 +5,17 @@
 library fasta.library_builder;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:kernel/ast.dart' show Class, Library;
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show FormalParameterKind;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+import 'package:kernel/ast.dart'
+    show AsyncMarker, Class, Library, ProcedureKind;
 
+import '../../api_prototype/experimental_flags.dart';
 import '../combinator.dart' show CombinatorBuilder;
+import '../configuration.dart';
 import '../export.dart' show Export;
+import '../identifiers.dart';
 import '../loader.dart' show Loader;
 import '../messages.dart'
     show
@@ -23,15 +30,23 @@
 import '../source/name_scheme.dart';
 import '../source/offset_map.dart';
 import '../source/source_class_builder.dart';
+import '../source/source_enum_builder.dart';
 import '../source/source_function_builder.dart';
 import '../source/source_library_builder.dart';
+import '../source/source_loader.dart';
 import 'builder.dart';
 import 'constructor_reference_builder.dart';
 import 'declaration_builders.dart';
+import 'formal_parameter_builder.dart';
 import 'inferable_type_builder.dart';
 import 'member_builder.dart';
+import 'metadata_builder.dart';
+import 'mixin_application_builder.dart';
 import 'modifier_builder.dart';
 import 'name_iterator.dart';
+import 'named_type_builder.dart';
+import 'nullability_builder.dart';
+import 'omitted_type_builder.dart';
 import 'prefix_builder.dart';
 import 'type_builder.dart';
 
@@ -97,10 +112,50 @@
 abstract class SourceCompilationUnit implements CompilationUnit {
   SourceLibraryBuilder createLibrary();
 
+  @override
+  SourceLoader get loader;
+
   // TODO(johnniwinther): Remove this.
   SourceLibraryBuilder get sourceLibraryBuilder;
 
-  OffsetMap get offsetMap;
+  abstract OffsetMap offsetMap;
+
+  LibraryFeatures get libraryFeatures;
+
+  /// The current declaration that is being built. When we start parsing a
+  /// declaration (class, method, and so on), we don't have enough information
+  /// to create a builder and this object records its members and types until,
+  /// for example, [addClass] is called.
+  TypeParameterScopeBuilder get currentTypeParameterScopeBuilder;
+
+  void beginNestedDeclaration(TypeParameterScopeKind kind, String name,
+      {bool hasMembers = true});
+
+  TypeParameterScopeBuilder endNestedDeclaration(
+      TypeParameterScopeKind kind, String? name);
+
+  /// Call this when entering a class, mixin, enum, or extension type
+  /// declaration.
+  ///
+  /// This is done to set up the current [_indexedContainer] used to lookup
+  /// references of members from a previous incremental compilation.
+  ///
+  /// Called in `OutlineBuilder.beginClassDeclaration`,
+  /// `OutlineBuilder.beginEnum`, `OutlineBuilder.beginMixinDeclaration` and
+  /// `OutlineBuilder.beginExtensionTypeDeclaration`.
+  void beginIndexedContainer(String name,
+      {required bool isExtensionTypeDeclaration});
+
+  /// Call this when leaving a class, mixin, enum, or extension type
+  /// declaration.
+  ///
+  /// Called in `OutlineBuilder.endClassDeclaration`,
+  /// `OutlineBuilder.endEnum`, `OutlineBuilder.endMixinDeclaration` and
+  /// `OutlineBuilder.endExtensionTypeDeclaration`.
+  void endIndexedContainer();
+
+  String? computeAndValidateConstructorName(Identifier identifier,
+      {isFactory = false});
 
   List<ConstructorReferenceBuilder> get constructorReferences;
 
@@ -111,6 +166,8 @@
   // TODO(johnniwinther): Remove this.
   Library get library;
 
+  abstract String? name;
+
   // TODO(johnniwinther): Remove this?
   LibraryName get libraryName;
 
@@ -126,6 +183,8 @@
 
   Scope get scope;
 
+  abstract List<MetadataBuilder>? metadata;
+
   List<NominalVariableBuilder> get unboundNominalVariables;
 
   List<StructuralVariableBuilder> get unboundStructuralVariables;
@@ -138,6 +197,275 @@
   void addDependencies(Library library, Set<SourceLibraryBuilder> seen);
 
   void validatePart(SourceLibraryBuilder? library, Set<Uri>? usedParts);
+
+  void addScriptToken(int charOffset);
+
+  void addPart(OffsetMap offsetMap, Token partKeyword,
+      List<MetadataBuilder>? metadata, String uri, int charOffset);
+
+  void addPartOf(List<MetadataBuilder>? metadata, String? name, String? uri,
+      int uriOffset);
+
+  void addImport(
+      {OffsetMap? offsetMap,
+      Token? importKeyword,
+      required List<MetadataBuilder>? metadata,
+      required bool isAugmentationImport,
+      required String uri,
+      required List<Configuration>? configurations,
+      required String? prefix,
+      required List<CombinatorBuilder>? combinators,
+      required bool deferred,
+      required int charOffset,
+      required int prefixCharOffset,
+      required int uriOffset,
+      required int importIndex});
+
+  void addExport(
+      OffsetMap offsetMap,
+      Token exportKeyword,
+      List<MetadataBuilder>? metadata,
+      String uri,
+      List<Configuration>? configurations,
+      List<CombinatorBuilder>? combinators,
+      int charOffset,
+      int uriOffset);
+
+  void addClass(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      TypeBuilder? supertype,
+      MixinApplicationBuilder? mixins,
+      List<TypeBuilder>? interfaces,
+      int startOffset,
+      int nameOffset,
+      int endOffset,
+      int supertypeOffset,
+      {required bool isMacro,
+      required bool isSealed,
+      required bool isBase,
+      required bool isInterface,
+      required bool isFinal,
+      required bool isAugmentation,
+      required bool isMixinClass});
+
+  void addEnum(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      MixinApplicationBuilder? supertypeBuilder,
+      List<TypeBuilder>? interfaceBuilders,
+      List<EnumConstantInfo?>? enumConstantInfos,
+      int startCharOffset,
+      int charEndOffset);
+
+  void addExtensionDeclaration(
+      OffsetMap offsetMap,
+      Token beginToken,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier? identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      TypeBuilder type,
+      int startOffset,
+      int nameOffset,
+      int endOffset);
+
+  void addExtensionTypeDeclaration(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      List<TypeBuilder>? interfaces,
+      int startOffset,
+      int endOffset);
+
+  void addMixinDeclaration(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      List<TypeBuilder>? supertypeConstraints,
+      List<TypeBuilder>? interfaces,
+      int startOffset,
+      int nameOffset,
+      int endOffset,
+      int supertypeOffset,
+      {required bool isBase,
+      required bool isAugmentation});
+
+  void addNamedMixinApplication(
+      List<MetadataBuilder>? metadata,
+      String name,
+      List<NominalVariableBuilder>? typeVariables,
+      int modifiers,
+      TypeBuilder? supertype,
+      MixinApplicationBuilder mixinApplication,
+      List<TypeBuilder>? interfaces,
+      int startCharOffset,
+      int charOffset,
+      int charEndOffset,
+      {required bool isMacro,
+      required bool isSealed,
+      required bool isBase,
+      required bool isInterface,
+      required bool isFinal,
+      required bool isAugmentation,
+      required bool isMixinClass});
+
+  MixinApplicationBuilder addMixinApplication(
+      List<TypeBuilder> mixins, int charOffset);
+
+  void addFunctionTypeAlias(
+      List<MetadataBuilder>? metadata,
+      String name,
+      List<NominalVariableBuilder>? typeVariables,
+      TypeBuilder type,
+      int charOffset);
+
+  void addConstructor(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      String constructorName,
+      List<NominalVariableBuilder>? typeVariables,
+      List<FormalParameterBuilder>? formals,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      String? nativeMethodName,
+      {Token? beginInitializers,
+      required bool forAbstractClassOrMixin});
+
+  void addPrimaryConstructor(
+      {required OffsetMap offsetMap,
+      required Token beginToken,
+      required String constructorName,
+      required List<NominalVariableBuilder>? typeVariables,
+      required List<FormalParameterBuilder>? formals,
+      required int charOffset,
+      required bool isConst});
+
+  void addPrimaryConstructorField(
+      {required List<MetadataBuilder>? metadata,
+      required TypeBuilder type,
+      required String name,
+      required int charOffset});
+
+  void addFactoryMethod(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<FormalParameterBuilder>? formals,
+      ConstructorReferenceBuilder? redirectionTarget,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      String? nativeMethodName,
+      AsyncMarker asyncModifier);
+
+  void addProcedure(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      TypeBuilder? returnType,
+      Identifier identifier,
+      String name,
+      List<NominalVariableBuilder>? typeVariables,
+      List<FormalParameterBuilder>? formals,
+      ProcedureKind kind,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      String? nativeMethodName,
+      AsyncMarker asyncModifier,
+      {required bool isInstanceMember,
+      required bool isExtensionMember,
+      required bool isExtensionTypeMember});
+
+  void addFields(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      bool isTopLevel,
+      TypeBuilder? type,
+      List<FieldInfo> fieldInfos);
+
+  FormalParameterBuilder addFormalParameter(
+      List<MetadataBuilder>? metadata,
+      FormalParameterKind kind,
+      int modifiers,
+      TypeBuilder type,
+      String name,
+      bool hasThis,
+      bool hasSuper,
+      int charOffset,
+      Token? initializerToken);
+
+  ConstructorReferenceBuilder addConstructorReference(TypeName name,
+      List<TypeBuilder>? typeArguments, String? suffix, int charOffset);
+
+  TypeBuilder addNamedType(
+      TypeName typeName,
+      NullabilityBuilder nullabilityBuilder,
+      List<TypeBuilder>? arguments,
+      int charOffset,
+      {required InstanceTypeVariableAccessState instanceTypeVariableAccess});
+
+  FunctionTypeBuilder addFunctionType(
+      TypeBuilder returnType,
+      List<StructuralVariableBuilder>? structuralVariableBuilders,
+      List<FormalParameterBuilder>? formals,
+      NullabilityBuilder nullabilityBuilder,
+      Uri fileUri,
+      int charOffset,
+      {required bool hasFunctionFormalParameterSyntax});
+
+  TypeBuilder addVoidType(int charOffset);
+
+  InferableTypeBuilder addInferableType();
+
+  NominalVariableBuilder addNominalTypeVariable(List<MetadataBuilder>? metadata,
+      String name, TypeBuilder? bound, int charOffset, Uri fileUri,
+      {required TypeVariableKind kind});
+
+  StructuralVariableBuilder addStructuralTypeVariable(
+      List<MetadataBuilder>? metadata,
+      String name,
+      TypeBuilder? bound,
+      int charOffset,
+      Uri fileUri);
+
+  /// Creates a copy of [original] into the scope of [declaration].
+  ///
+  /// This is used for adding copies of class type parameters to factory
+  /// methods and unnamed mixin applications, and for adding copies of
+  /// extension type parameters to extension instance methods.
+  ///
+  /// If [synthesizeTypeParameterNames] is `true` the names of the
+  /// [TypeParameter] are prefix with '#' to indicate that their synthesized.
+  List<NominalVariableBuilder> copyTypeVariables(
+      List<NominalVariableBuilder> original,
+      TypeParameterScopeBuilder declaration,
+      {required TypeVariableKind kind});
+
+  /// Reports that [feature] is not enabled, using [charOffset] and
+  /// [length] for the location of the message.
+  ///
+  /// Return the primary message.
+  Message reportFeatureNotEnabled(
+      LibraryFeature feature, Uri fileUri, int charOffset, int length);
 }
 
 abstract class LibraryBuilder implements Builder {
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index a9e1e4d..b6f0b24 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -1912,7 +1912,7 @@
                     combinator.fileOffset, libraryBuilder.fileUri));
           }
 
-          debugLibrary.addImport(
+          debugLibrary.compilationUnit.addImport(
               metadata: null,
               isAugmentationImport: false,
               uri: dependency.importedLibraryReference.canonicalName!.name,
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index afae919..f587152 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -33,6 +33,7 @@
 import '../builder/fixed_type_builder.dart';
 import '../builder/formal_parameter_builder.dart';
 import '../builder/invalid_type_builder.dart';
+import '../builder/library_builder.dart';
 import '../builder/metadata_builder.dart';
 import '../builder/mixin_application_builder.dart';
 import '../builder/named_type_builder.dart';
@@ -504,6 +505,8 @@
   @override
   final SourceLibraryBuilder libraryBuilder;
 
+  final SourceCompilationUnit compilationUnit;
+
   final bool enableNative;
   bool inAbstractOrSealedClass = false;
   bool inConstructor = false;
@@ -540,9 +543,10 @@
 
   OffsetMap _offsetMap;
 
-  OutlineBuilder(this.libraryBuilder, this._offsetMap)
-      : enableNative = libraryBuilder.loader.target.backendTarget
-            .enableNative(libraryBuilder.importUri);
+  OutlineBuilder(this.compilationUnit, this._offsetMap)
+      : enableNative = compilationUnit.loader.target.backendTarget
+            .enableNative(compilationUnit.importUri),
+        libraryBuilder = compilationUnit.sourceLibraryBuilder;
 
   DeclarationContext get declarationContext => _declarationContext.head;
 
@@ -559,7 +563,7 @@
   }
 
   @override
-  Uri get uri => libraryBuilder.fileUri;
+  Uri get uri => compilationUnit.fileUri;
 
   int popCharOffset() => pop() as int;
 
@@ -638,7 +642,7 @@
       push(names);
     } else {
       push(new CombinatorBuilder.hide(names as Iterable<String>,
-          hideKeyword.charOffset, libraryBuilder.fileUri));
+          hideKeyword.charOffset, compilationUnit.fileUri));
     }
   }
 
@@ -650,7 +654,7 @@
       push(names);
     } else {
       push(new CombinatorBuilder.show(names as Iterable<String>,
-          showKeyword.charOffset, libraryBuilder.fileUri));
+          showKeyword.charOffset, compilationUnit.fileUri));
     }
   }
 
@@ -680,7 +684,7 @@
     int uriOffset = popCharOffset();
     String uri = pop() as String;
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-    libraryBuilder.addExport(_offsetMap, exportKeyword, metadata, uri,
+    compilationUnit.addExport(_offsetMap, exportKeyword, metadata, uri,
         configurations, combinators, exportKeyword.charOffset, uriOffset);
     checkEmpty(exportKeyword.charOffset);
   }
@@ -734,7 +738,7 @@
       }
     }
     bool isAugmentationImport = augmentToken != null;
-    libraryBuilder.addImport(
+    compilationUnit.addImport(
         offsetMap: _offsetMap,
         importKeyword: importKeyword,
         metadata: metadata,
@@ -815,7 +819,7 @@
     int charOffset = popCharOffset();
     String uri = pop() as String;
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-    libraryBuilder.addPart(_offsetMap, partKeyword, metadata, uri, charOffset);
+    compilationUnit.addPart(_offsetMap, partKeyword, metadata, uri, charOffset);
     checkEmpty(partKeyword.charOffset);
   }
 
@@ -955,13 +959,13 @@
     }
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     if (name != null && name is! ParserRecovery) {
-      libraryBuilder.name =
+      compilationUnit.name =
           flattenName(name, offsetForToken(libraryKeyword), uri);
     } else {
       reportIfNotEnabled(
           libraryFeatures.unnamedLibraries, semicolon.charOffset, noLength);
     }
-    libraryBuilder.metadata = metadata;
+    compilationUnit.metadata = metadata;
   }
 
   @override
@@ -977,7 +981,7 @@
     pop() as int;
     pop() as String;
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-    libraryBuilder.metadata = metadata;
+    compilationUnit.metadata = metadata;
   }
 
   @override
@@ -985,7 +989,7 @@
     debugEvent("beginClassOrNamedMixinApplicationPrelude");
     pushDeclarationContext(
         DeclarationContext.ClassOrMixinOrNamedMixinApplication);
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.classOrNamedMixinApplication,
         "class or mixin application");
   }
@@ -1045,9 +1049,9 @@
         mixinToken = null;
       }
     }
-    libraryBuilder.currentTypeParameterScopeBuilder
+    compilationUnit.currentTypeParameterScopeBuilder
         .markAsClassDeclaration(name.lexeme, name.charOffset, typeVariables);
-    libraryBuilder.beginIndexedContainer(name.lexeme,
+    compilationUnit.beginIndexedContainer(name.lexeme,
         isExtensionTypeDeclaration: false);
     inAbstractOrSealedClass = abstractToken != null || sealedToken != null;
     push(abstractToken != null ? abstractMask : 0);
@@ -1078,9 +1082,9 @@
     push(augmentToken ?? NullValues.Token);
     push(baseToken ?? NullValues.Token);
     push(typeVariables ?? NullValues.NominalVariables);
-    libraryBuilder.currentTypeParameterScopeBuilder
+    compilationUnit.currentTypeParameterScopeBuilder
         .markAsMixinDeclaration(name.lexeme, name.charOffset, typeVariables);
-    libraryBuilder.beginIndexedContainer(name.lexeme,
+    compilationUnit.beginIndexedContainer(name.lexeme,
         isExtensionTypeDeclaration: false);
   }
 
@@ -1115,7 +1119,7 @@
       Object? extensionThisType = peek();
 
       if (extensionThisType is TypeBuilder) {
-        libraryBuilder.currentTypeParameterScopeBuilder
+        compilationUnit.currentTypeParameterScopeBuilder
             .registerExtensionThisType(extensionThisType);
       } else {
         // TODO(johnniwinther): Supply an invalid type as the extension on type.
@@ -1125,8 +1129,8 @@
     // Resolve unresolved types from the class header (i.e., superclass, mixins,
     // and implemented types) before adding members from the class body which
     // should not shadow these unresolved types.
-    libraryBuilder.currentTypeParameterScopeBuilder.resolveNamedTypes(
-        libraryBuilder.currentTypeParameterScopeBuilder.typeVariables,
+    compilationUnit.currentTypeParameterScopeBuilder.resolveNamedTypes(
+        compilationUnit.currentTypeParameterScopeBuilder.typeVariables,
         libraryBuilder);
   }
 
@@ -1149,8 +1153,9 @@
     List<NominalVariableBuilder>? typeVariables =
         pop() as List<NominalVariableBuilder>?;
     push(typeVariables ?? NullValues.NominalVariables);
-    libraryBuilder.currentTypeParameterScopeBuilder.markAsNamedMixinApplication(
-        name.lexeme, name.charOffset, typeVariables);
+    compilationUnit.currentTypeParameterScopeBuilder
+        .markAsNamedMixinApplication(
+            name.lexeme, name.charOffset, typeVariables);
     push(abstractToken != null ? abstractMask : 0);
     if (macroToken != null) {
       if (reportIfNotEnabled(
@@ -1316,7 +1321,7 @@
     inAbstractOrSealedClass = false;
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) {
-      libraryBuilder
+      compilationUnit
           .endNestedDeclaration(
               TypeParameterScopeKind.classDeclaration, "<syntax-error>")
           .resolveNamedTypes(typeVariables, libraryBuilder);
@@ -1328,7 +1333,7 @@
       String classNameForErrors = identifier.name;
       if (supertype != null) {
         if (supertype.nullabilityBuilder.build() == Nullability.nullable) {
-          libraryBuilder.addProblem(
+          compilationUnit.addProblem(
               templateNullableSuperclassError
                   .withArguments(supertype.fullNameForErrors),
               identifier.nameOffset,
@@ -1340,7 +1345,7 @@
         List<TypeBuilder>? mixins = mixinApplication.mixins;
         for (TypeBuilder mixin in mixins) {
           if (mixin.nullabilityBuilder.build() == Nullability.nullable) {
-            libraryBuilder.addProblem(
+            compilationUnit.addProblem(
                 templateNullableMixinError
                     .withArguments(mixin.fullNameForErrors),
                 identifier.nameOffset,
@@ -1352,7 +1357,7 @@
       if (interfaces != null) {
         for (TypeBuilder interface in interfaces) {
           if (interface.nullabilityBuilder.build() == Nullability.nullable) {
-            libraryBuilder.addProblem(
+            compilationUnit.addProblem(
                 templateNullableInterfaceError
                     .withArguments(interface.fullNameForErrors),
                 identifier.nameOffset,
@@ -1365,7 +1370,7 @@
       if (sealedToken != null) {
         modifiers |= abstractMask;
       }
-      libraryBuilder.addClass(
+      compilationUnit.addClass(
           _offsetMap,
           metadata,
           modifiers,
@@ -1386,7 +1391,7 @@
           isAugmentation: augmentToken != null,
           isMixinClass: mixinToken != null);
     }
-    libraryBuilder.endIndexedContainer();
+    compilationUnit.endIndexedContainer();
     popDeclarationContext(DeclarationContext.Class);
   }
 
@@ -1423,7 +1428,7 @@
         pop(NullValues.Metadata) as List<MetadataBuilder>?;
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) {
-      libraryBuilder
+      compilationUnit
           .endNestedDeclaration(
               TypeParameterScopeKind.mixinDeclaration, "<syntax-error>")
           .resolveNamedTypes(typeVariables, libraryBuilder);
@@ -1435,7 +1440,7 @@
       if (supertypeConstraints != null) {
         for (TypeBuilder supertype in supertypeConstraints) {
           if (supertype.nullabilityBuilder.build() == Nullability.nullable) {
-            libraryBuilder.addProblem(
+            compilationUnit.addProblem(
                 templateNullableSuperclassError
                     .withArguments(supertype.fullNameForErrors),
                 identifier.nameOffset,
@@ -1447,7 +1452,7 @@
       if (interfaces != null) {
         for (TypeBuilder interface in interfaces) {
           if (interface.nullabilityBuilder.build() == Nullability.nullable) {
-            libraryBuilder.addProblem(
+            compilationUnit.addProblem(
                 templateNullableInterfaceError
                     .withArguments(interface.fullNameForErrors),
                 identifier.nameOffset,
@@ -1457,7 +1462,7 @@
         }
       }
 
-      libraryBuilder.addMixinDeclaration(
+      compilationUnit.addMixinDeclaration(
           _offsetMap,
           metadata,
           mixinDeclarationMask,
@@ -1472,7 +1477,7 @@
           isBase: baseToken != null,
           isAugmentation: augmentToken != null);
     }
-    libraryBuilder.endIndexedContainer();
+    compilationUnit.endIndexedContainer();
     popDeclarationContext(DeclarationContext.Mixin);
   }
 
@@ -1481,7 +1486,7 @@
     assert(checkState(extensionKeyword, [ValueKinds.MetadataListOrNull]));
     debugEvent("beginExtensionDeclaration");
     pushDeclarationContext(DeclarationContext.ExtensionOrExtensionType);
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.extensionOrExtensionTypeDeclaration,
         "extension");
   }
@@ -1501,7 +1506,7 @@
         ? new SimpleIdentifier(nameToken)
         : NullValues.Identifier);
     push(typeVariables ?? NullValues.NominalVariables);
-    libraryBuilder.currentTypeParameterScopeBuilder
+    compilationUnit.currentTypeParameterScopeBuilder
         .markAsExtensionDeclaration(nameToken?.lexeme, offset, typeVariables);
   }
 
@@ -1532,7 +1537,7 @@
     int startOffset = metadata == null
         ? extensionKeyword.charOffset
         : metadata.first.charOffset;
-    libraryBuilder.addExtensionDeclaration(
+    compilationUnit.addExtensionDeclaration(
         _offsetMap,
         beginToken,
         metadata,
@@ -1561,9 +1566,9 @@
     int offset = nameToken.charOffset;
     push(new SimpleIdentifier(nameToken));
     push(typeVariables ?? NullValues.NominalVariables);
-    libraryBuilder.currentTypeParameterScopeBuilder
+    compilationUnit.currentTypeParameterScopeBuilder
         .markAsExtensionTypeDeclaration(name, offset, typeVariables);
-    libraryBuilder.beginIndexedContainer(name,
+    compilationUnit.beginIndexedContainer(name,
         isExtensionTypeDeclaration: true);
   }
 
@@ -1593,7 +1598,7 @@
     int startOffset = metadata == null
         ? extensionKeyword.charOffset
         : metadata.first.charOffset;
-    libraryBuilder.addExtensionTypeDeclaration(
+    compilationUnit.addExtensionTypeDeclaration(
         _offsetMap,
         metadata,
         // TODO(johnniwinther): Support modifiers on extension types?
@@ -1604,7 +1609,7 @@
         startOffset,
         endToken.charOffset);
 
-    libraryBuilder.endIndexedContainer();
+    compilationUnit.endIndexedContainer();
     popDeclarationContext(DeclarationContext.ExtensionType);
   }
 
@@ -1641,7 +1646,7 @@
           TypeBuilder type = formal.type;
           if (type is FunctionTypeBuilder &&
               type.hasFunctionFormalParameterSyntax) {
-            libraryBuilder.addProblem(
+            compilationUnit.addProblem(
                 // ignore: lines_longer_than_80_chars
                 messageExtensionTypePrimaryConstructorFunctionFormalParameterSyntax,
                 formal.charOffset,
@@ -1649,7 +1654,7 @@
                 formal.fileUri);
           }
           if (type is ImplicitTypeBuilder) {
-            libraryBuilder.addProblem(messageExpectedRepresentationType,
+            compilationUnit.addProblem(messageExpectedRepresentationType,
                 formal.charOffset, formal.name.length, formal.fileUri);
             formal.type =
                 new InvalidTypeBuilderImpl(formal.fileUri, formal.charOffset);
@@ -1659,11 +1664,11 @@
               Modifier.removeCovariantMask(
                   // 'required' is reported in the parser.
                   Modifier.removeRequiredMask(formal.modifiers)))) {
-            libraryBuilder.addProblem(messageRepresentationFieldModifier,
+            compilationUnit.addProblem(messageRepresentationFieldModifier,
                 formal.charOffset, formal.name.length, formal.fileUri);
           }
           if (formal.isInitializingFormal) {
-            libraryBuilder.addProblem(
+            compilationUnit.addProblem(
                 messageExtensionTypePrimaryConstructorWithInitializingFormal,
                 formal.charOffset,
                 formal.name.length,
@@ -1681,7 +1686,7 @@
         if (formal.isNamed) {
           firstNamedParameterOffset = formal.charOffset;
         }
-        libraryBuilder.addPrimaryConstructorField(
+        compilationUnit.addPrimaryConstructorField(
             // TODO(johnniwinther): Support annotations on annotations on fields
             // defined through a primary constructor. This is not needed for
             // extension types where the field is not part of the AST but will
@@ -1694,40 +1699,40 @@
       }
       if (inExtensionType) {
         if (firstOptionalPositionalParameterOffset != null) {
-          libraryBuilder.addProblem(
+          compilationUnit.addProblem(
               messageOptionalParametersInExtensionTypeDeclaration,
               firstOptionalPositionalParameterOffset,
               1,
               uri);
         } else if (firstNamedParameterOffset != null) {
-          libraryBuilder.addProblem(
+          compilationUnit.addProblem(
               messageNamedParametersInExtensionTypeDeclaration,
               firstNamedParameterOffset,
               1,
               uri);
         } else if (requiredPositionalCount == 0) {
-          libraryBuilder.addProblem(
+          compilationUnit.addProblem(
               messageExpectedRepresentationField, charOffset, 1, uri);
         } else if (formals.length > 1) {
-          libraryBuilder.addProblem(
+          compilationUnit.addProblem(
               messageMultipleRepresentationFields, charOffset, 1, uri);
         }
       }
     }
 
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.constructor, "#method",
         hasMembers: false);
-    TypeParameterScopeBuilder scopeBuilder = libraryBuilder
+    TypeParameterScopeBuilder scopeBuilder = compilationUnit
         .endNestedDeclaration(TypeParameterScopeKind.constructor, "#method");
     var (
       List<NominalVariableBuilder>? typeVariables,
       _
     ) = _createSyntheticTypeVariables(
-        libraryBuilder.currentTypeParameterScopeBuilder, scopeBuilder, null);
+        compilationUnit.currentTypeParameterScopeBuilder, scopeBuilder, null);
     scopeBuilder.resolveNamedTypes(typeVariables, libraryBuilder);
 
-    libraryBuilder.addPrimaryConstructor(
+    compilationUnit.addPrimaryConstructor(
         offsetMap: _offsetMap,
         beginToken: beginToken,
         constructorName: constructorName == "new" ? "" : constructorName,
@@ -1749,7 +1754,7 @@
   void beginTopLevelMethod(
       Token lastConsumed, Token? augmentToken, Token? externalToken) {
     pushDeclarationContext(DeclarationContext.TopLevelMethod);
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.topLevelMethod, "#method",
         hasMembers: false);
     int modifiers = 0;
@@ -1806,13 +1811,13 @@
     }
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     checkEmpty(beginToken.charOffset);
-    libraryBuilder
+    compilationUnit
         .endNestedDeclaration(TypeParameterScopeKind.topLevelMethod, "#method")
         .resolveNamedTypes(typeVariables, libraryBuilder);
     if (identifier is Identifier) {
       final int startCharOffset =
           metadata == null ? beginToken.charOffset : metadata.first.charOffset;
-      libraryBuilder.addProcedure(
+      compilationUnit.addProcedure(
           _offsetMap,
           metadata,
           modifiers,
@@ -1887,7 +1892,7 @@
       Token? getOrSet,
       Token name) {
     inConstructor =
-        name.lexeme == libraryBuilder.currentTypeParameterScopeBuilder.name &&
+        name.lexeme == compilationUnit.currentTypeParameterScopeBuilder.name &&
             getOrSet == null;
     DeclarationContext declarationContext;
     switch (declarationKind) {
@@ -1987,7 +1992,7 @@
     } else {
       kind = TypeParameterScopeKind.instanceMethod;
     }
-    libraryBuilder.beginNestedDeclaration(kind, "#method", hasMembers: false);
+    compilationUnit.beginNestedDeclaration(kind, "#method", hasMembers: false);
   }
 
   @override
@@ -2065,7 +2070,7 @@
       // rename 'T' to '#T'. We cannot do it on the builders because their
       // names are used to create the scope.
       List<NominalVariableBuilder> synthesizedTypeVariables =
-          libraryBuilder.copyTypeVariables(
+          compilationUnit.copyTypeVariables(
               enclosingDeclarationScopeBuilder.typeVariables!,
               memberScopeBuilder,
               kind: TypeVariableKind.extensionSynthesized);
@@ -2127,7 +2132,7 @@
       scopeKind = TypeParameterScopeKind.instanceMethod;
     }
     TypeParameterScopeBuilder declarationBuilder =
-        libraryBuilder.endNestedDeclaration(scopeKind, "#method");
+        compilationUnit.endNestedDeclaration(scopeKind, "#method");
 
     if (identifier is! Identifier) {
       assert(identifier is ParserRecovery,
@@ -2236,7 +2241,7 @@
       case _MethodKind.extensionTypeConstructor:
       case _MethodKind.enumConstructor:
         constructorName =
-            libraryBuilder.computeAndValidateConstructorName(identifier) ??
+            compilationUnit.computeAndValidateConstructorName(identifier) ??
                 name;
         break;
       case _MethodKind.classMethod:
@@ -2249,7 +2254,7 @@
     bool isStatic = (modifiers & staticMask) != 0;
     bool isConstructor = constructorName != null;
     bool cloneTypeVariablesFromEnclosingDeclaration;
-    switch (libraryBuilder.currentTypeParameterScopeBuilder.kind) {
+    switch (compilationUnit.currentTypeParameterScopeBuilder.kind) {
       case TypeParameterScopeKind.extensionDeclaration:
       case TypeParameterScopeKind.extensionTypeDeclaration:
         cloneTypeVariablesFromEnclosingDeclaration = !isStatic;
@@ -2272,7 +2277,7 @@
     }
     if (cloneTypeVariablesFromEnclosingDeclaration) {
       TypeParameterScopeBuilder declaration =
-          libraryBuilder.currentTypeParameterScopeBuilder;
+          compilationUnit.currentTypeParameterScopeBuilder;
       Map<NominalVariableBuilder, TypeBuilder>? substitution;
       (typeVariables, substitution) = _createSyntheticTypeVariables(
           declaration, declarationBuilder, typeVariables);
@@ -2282,7 +2287,7 @@
         if (declaration.kind == TypeParameterScopeKind.extensionDeclaration) {
           thisType = declaration.extensionThisType;
         } else {
-          thisType = libraryBuilder.addNamedType(
+          thisType = compilationUnit.addNamedType(
               new SyntheticTypeName(declaration.name, charOffset),
               const NullabilityBuilder.omitted(),
               declaration.typeVariables != null
@@ -2308,7 +2313,7 @@
           for (NamedTypeBuilder unboundType in unboundTypes) {
             declaration.registerUnresolvedNamedType(unboundType);
           }
-          libraryBuilder.unboundStructuralVariables
+          compilationUnit.unboundStructuralVariables
               .addAll(unboundTypeVariables);
         }
         synthesizedFormals.add(new FormalParameterBuilder(
@@ -2343,7 +2348,7 @@
       }
       final int startCharOffset =
           metadata == null ? beginToken.charOffset : metadata.first.charOffset;
-      libraryBuilder.addConstructor(
+      compilationUnit.addConstructor(
           _offsetMap,
           metadata,
           modifiers,
@@ -2370,7 +2375,7 @@
       bool isExtensionMember = methodKind == _MethodKind.extensionMethod;
       bool isExtensionTypeMember =
           methodKind == _MethodKind.extensionTypeMethod;
-      libraryBuilder.addProcedure(
+      compilationUnit.addProcedure(
           _offsetMap,
           metadata,
           modifiers,
@@ -2412,7 +2417,7 @@
     if (mixins is ParserRecovery) {
       push(mixins);
     } else {
-      push(libraryBuilder.addMixinApplication(
+      push(compilationUnit.addMixinApplication(
           mixins as List<TypeBuilder>, withKeyword.charOffset));
     }
     assert(checkState(withKeyword, [
@@ -2499,7 +2504,7 @@
     if (name is ParserRecovery ||
         supertype is ParserRecovery ||
         mixinApplication is ParserRecovery) {
-      libraryBuilder
+      compilationUnit
           .endNestedDeclaration(
               TypeParameterScopeKind.namedMixinApplication, "<syntax-error>")
           .resolveNamedTypes(typeVariables, libraryBuilder);
@@ -2511,7 +2516,7 @@
       List<TypeBuilder> mixins = mixinApplicationBuilder.mixins;
       if (supertype is TypeBuilder && supertype is! MixinApplicationBuilder) {
         if (supertype.nullabilityBuilder.build() == Nullability.nullable) {
-          libraryBuilder.addProblem(
+          compilationUnit.addProblem(
               templateNullableSuperclassError
                   .withArguments(supertype.fullNameForErrors),
               identifier.nameOffset,
@@ -2521,7 +2526,7 @@
       }
       for (TypeBuilder mixin in mixins) {
         if (mixin.nullabilityBuilder.build() == Nullability.nullable) {
-          libraryBuilder.addProblem(
+          compilationUnit.addProblem(
               templateNullableMixinError.withArguments(mixin.fullNameForErrors),
               identifier.nameOffset,
               classNameForErrors.length,
@@ -2531,7 +2536,7 @@
       if (interfaces != null) {
         for (TypeBuilder interface in interfaces) {
           if (interface.nullabilityBuilder.build() == Nullability.nullable) {
-            libraryBuilder.addProblem(
+            compilationUnit.addProblem(
                 templateNullableInterfaceError
                     .withArguments(interface.fullNameForErrors),
                 identifier.nameOffset,
@@ -2547,7 +2552,7 @@
 
       int startCharOffset = beginToken.charOffset;
       int charEndOffset = endToken.charOffset;
-      libraryBuilder.addNamedMixinApplication(
+      compilationUnit.addNamedMixinApplication(
           metadata,
           identifier.name,
           typeVariables,
@@ -2592,7 +2597,7 @@
   @override
   void handleScript(Token token) {
     debugEvent("handleScript");
-    libraryBuilder.addScriptToken(token.charOffset);
+    compilationUnit.addScriptToken(token.charOffset);
   }
 
   @override
@@ -2612,7 +2617,7 @@
       push(name);
     } else {
       Identifier identifier = name as Identifier;
-      push(libraryBuilder.addNamedType(
+      push(compilationUnit.addNamedType(
           identifier.typeName,
           isMarkedAsNullable
               ? const NullabilityBuilder.nullable()
@@ -2659,14 +2664,14 @@
   @override
   void handleVoidKeyword(Token token) {
     debugEvent("VoidKeyword");
-    push(libraryBuilder.addVoidType(token.charOffset));
+    push(compilationUnit.addVoidType(token.charOffset));
   }
 
   @override
   void handleVoidKeywordWithTypeArguments(Token token) {
     debugEvent("VoidKeyword");
     /*List<TypeBuilder> arguments =*/ pop();
-    push(libraryBuilder.addVoidType(token.charOffset));
+    push(compilationUnit.addVoidType(token.charOffset));
   }
 
   @override
@@ -2714,13 +2719,13 @@
       push(name);
     } else {
       Identifier? identifier = name as Identifier?;
-      push(libraryBuilder.addFormalParameter(
+      push(compilationUnit.addFormalParameter(
           metadata,
           kind,
           modifiers,
           type ??
               (memberKind.isParameterInferable
-                  ? libraryBuilder.addInferableType()
+                  ? compilationUnit.addInferableType()
                   : const ImplicitTypeBuilder()),
           identifier == null
               ? FormalParameterBuilder.noNameSentinel
@@ -2793,7 +2798,7 @@
           optional(",", tokenBeforeEnd) &&
           kind == MemberKind.PrimaryConstructor &&
           declarationContext == DeclarationContext.ExtensionType) {
-        libraryBuilder.addProblem(messageRepresentationFieldTrailingComma,
+        compilationUnit.addProblem(messageRepresentationFieldTrailingComma,
             tokenBeforeEnd.charOffset, 1, uri);
       }
     } else if (count > 1) {
@@ -2871,7 +2876,7 @@
         formals != null) {
       for (FormalParameterBuilder formal in formals) {
         if (formal.isSuperInitializingFormal) {
-          libraryBuilder.addProblem(
+          compilationUnit.addProblem(
               messageExtensionTypeConstructorWithSuperFormalParameter,
               formal.charOffset,
               formal.name.length,
@@ -2909,10 +2914,10 @@
     } else {
       declarationName = '#enum';
     }
-    libraryBuilder.beginIndexedContainer(declarationName,
+    compilationUnit.beginIndexedContainer(declarationName,
         isExtensionTypeDeclaration: false);
     pushDeclarationContext(DeclarationContext.Enum);
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.enumDeclaration, declarationName);
   }
 
@@ -2963,11 +2968,11 @@
 
     Object? identifier = peek();
     if (identifier is Identifier) {
-      libraryBuilder.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
+      compilationUnit.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
           identifier.name, identifier.nameOffset, typeVariables);
     } else {
       identifier as ParserRecovery;
-      libraryBuilder.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
+      compilationUnit.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
           "<syntax-error>", identifier.charOffset, typeVariables);
     }
 
@@ -3054,7 +3059,7 @@
       if (interfaces != null) {
         for (TypeBuilder interface in interfaces) {
           if (interface.nullabilityBuilder.build() == Nullability.nullable) {
-            libraryBuilder.addProblem(
+            compilationUnit.addProblem(
                 templateNullableInterfaceError
                     .withArguments(interface.fullNameForErrors),
                 interface.charOffset ?? startCharOffset,
@@ -3064,7 +3069,7 @@
         }
       }
 
-      libraryBuilder.addEnum(
+      compilationUnit.addEnum(
           _offsetMap,
           metadata,
           identifier,
@@ -3075,13 +3080,13 @@
           startCharOffset,
           endCharOffset);
     } else {
-      libraryBuilder
+      compilationUnit
           .endNestedDeclaration(
               TypeParameterScopeKind.enumDeclaration, "<syntax-error>")
           .resolveNamedTypes(typeVariables, libraryBuilder);
     }
 
-    libraryBuilder.endIndexedContainer();
+    compilationUnit.endIndexedContainer();
     checkEmpty(enumKeyword.charOffset);
     popDeclarationContext(DeclarationContext.Enum);
   }
@@ -3089,7 +3094,7 @@
   @override
   void beginTypedef(Token token) {
     pushDeclarationContext(DeclarationContext.Typedef);
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.typedef, "#typedef",
         hasMembers: false);
   }
@@ -3098,7 +3103,7 @@
   void beginFunctionType(Token beginToken) {
     debugEvent("beginFunctionType");
     _structuralParameterDepthLevel++;
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.functionType, "#function_type",
         hasMembers: false);
   }
@@ -3107,7 +3112,7 @@
   void beginFunctionTypedFormalParameter(Token token) {
     debugEvent("beginFunctionTypedFormalParameter");
     _insideOfFormalParameterType = false;
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.functionType, "#function_type",
         hasMembers: false);
   }
@@ -3197,7 +3202,7 @@
     TypeBuilder? returnType = pop() as TypeBuilder?;
     List<StructuralVariableBuilder>? typeVariables =
         pop() as List<StructuralVariableBuilder>?;
-    push(libraryBuilder.addFunctionType(
+    push(compilationUnit.addFunctionType(
         returnType ?? const ImplicitTypeBuilder(),
         typeVariables,
         formals,
@@ -3218,7 +3223,7 @@
     TypeBuilder? returnType = pop() as TypeBuilder?;
     List<StructuralVariableBuilder>? typeVariables =
         pop() as List<StructuralVariableBuilder>?;
-    push(libraryBuilder.addFunctionType(
+    push(compilationUnit.addFunctionType(
         returnType ?? const ImplicitTypeBuilder(),
         typeVariables,
         formals,
@@ -3271,7 +3276,7 @@
       // `library.addFunctionType`.
       if (name is ParserRecovery) {
         pop(NullValues.Metadata); // Metadata.
-        libraryBuilder
+        compilationUnit
             .endNestedDeclaration(
                 TypeParameterScopeKind.typedef, "<syntax-error>")
             .resolveNamedTypes(typeVariables, libraryBuilder);
@@ -3279,11 +3284,11 @@
         return;
       }
       identifier = name as Identifier;
-      libraryBuilder.beginNestedDeclaration(
+      compilationUnit.beginNestedDeclaration(
           TypeParameterScopeKind.functionType, "#function_type",
           hasMembers: false);
       // TODO(cstefantsova): Make sure that RHS of typedefs can't have '?'.
-      aliasedType = libraryBuilder.addFunctionType(
+      aliasedType = compilationUnit.addFunctionType(
           returnType ?? const ImplicitTypeBuilder(),
           null,
           formals,
@@ -3298,7 +3303,7 @@
       name = pop();
       if (name is ParserRecovery) {
         pop(NullValues.Metadata); // Metadata.
-        libraryBuilder
+        compilationUnit
             .endNestedDeclaration(
                 TypeParameterScopeKind.functionType, "<syntax-error>")
             .resolveNamedTypes(typeVariables, libraryBuilder);
@@ -3309,9 +3314,6 @@
       if (type is FunctionTypeBuilder &&
           !libraryFeatures.nonfunctionTypeAliases.isEnabled) {
         if (type.nullabilityBuilder.build() == Nullability.nullable) {
-          // The error is reported when the non-nullable experiment is enabled.
-          // Otherwise, the attempt to use a nullable type will be reported
-          // elsewhere.
           addProblem(
               messageTypedefNullableType, equals.charOffset, equals.length);
           aliasedType = new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
@@ -3375,7 +3377,7 @@
         pop(NullValues.Metadata) as List<MetadataBuilder>?;
     checkEmpty(typedefKeyword.charOffset);
 
-    libraryBuilder.addFunctionTypeAlias(metadata, identifier.name,
+    compilationUnit.addFunctionTypeAlias(metadata, identifier.name,
         typeVariables, aliasedType, identifier.nameOffset);
     popDeclarationContext(DeclarationContext.Typedef);
   }
@@ -3478,7 +3480,7 @@
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     checkEmpty(beginToken.charOffset);
     if (fieldInfos != null) {
-      libraryBuilder.addFields(_offsetMap, metadata, modifiers,
+      compilationUnit.addFields(_offsetMap, metadata, modifiers,
           /* isTopLevel = */ true, type, fieldInfos);
     }
     popDeclarationContext();
@@ -3541,7 +3543,7 @@
     }
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     if (fieldInfos != null) {
-      libraryBuilder.addFields(_offsetMap, metadata, modifiers,
+      compilationUnit.addFields(_offsetMap, metadata, modifiers,
           /* isTopLevel = */ false, type, fieldInfos);
     }
     popDeclarationContext();
@@ -3591,10 +3593,10 @@
     } else {
       Identifier identifier = name as Identifier;
       if (inFunctionType) {
-        push(libraryBuilder.addStructuralTypeVariable(
+        push(compilationUnit.addStructuralTypeVariable(
             metadata, identifier.name, null, identifier.nameOffset, uri));
       } else {
-        push(libraryBuilder.addNominalTypeVariable(
+        push(compilationUnit.addNominalTypeVariable(
             metadata, identifier.name, null, identifier.nameOffset, uri,
             kind: declarationContext.typeVariableKind));
       }
@@ -3672,7 +3674,7 @@
     if (hasName) {
       Identifier containingLibrary = pop() as Identifier;
       List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-      libraryBuilder.addPartOf(
+      compilationUnit.addPartOf(
           metadata,
           flattenName(containingLibrary, containingLibrary.firstOffset, uri),
           null,
@@ -3681,7 +3683,7 @@
       int charOffset = popCharOffset();
       String uriString = pop() as String;
       List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-      libraryBuilder.addPartOf(metadata, null, uriString, charOffset);
+      compilationUnit.addPartOf(metadata, null, uriString, charOffset);
     }
   }
 
@@ -3702,19 +3704,19 @@
     if (name is ParserRecovery) {
       push(name);
     } else if (name is Identifier) {
-      push(libraryBuilder.addConstructorReference(
+      push(compilationUnit.addConstructorReference(
           name.typeName, typeArguments, suffix?.name, name.qualifierOffset));
     } else {
       assert(name == null);
       // At the moment, the name of the type in a constructor reference can be
       // omitted only within an enum element declaration.
-      if (libraryBuilder.currentTypeParameterScopeBuilder.kind ==
+      if (compilationUnit.currentTypeParameterScopeBuilder.kind ==
           TypeParameterScopeKind.enumDeclaration) {
         if (libraryFeatures.enhancedEnums.isEnabled) {
           int constructorNameOffset = suffix?.nameOffset ?? charOffset;
-          push(libraryBuilder.addConstructorReference(
+          push(compilationUnit.addConstructorReference(
               new SyntheticTypeName(
-                  libraryBuilder.currentTypeParameterScopeBuilder.name,
+                  compilationUnit.currentTypeParameterScopeBuilder.name,
                   constructorNameOffset),
               typeArguments,
               suffix?.name,
@@ -3723,7 +3725,7 @@
           // For entries that consist of their name only, all of the elements
           // of the constructor reference should be null.
           if (typeArguments != null || suffix != null) {
-            libraryBuilder.reportFeatureNotEnabled(
+            compilationUnit.reportFeatureNotEnabled(
                 libraryFeatures.enhancedEnums, uri, charOffset, noLength);
           }
           push(NullValues.ConstructorReference);
@@ -3763,7 +3765,7 @@
 
     pushDeclarationContext(declarationContext);
     inConstructor = true;
-    libraryBuilder.beginNestedDeclaration(
+    compilationUnit.beginNestedDeclaration(
         TypeParameterScopeKind.factoryMethod, "#factory_method",
         hasMembers: false);
     push((externalToken != null ? externalMask : 0) |
@@ -3812,10 +3814,10 @@
     if (name is! Identifier) {
       assert(name is ParserRecovery,
           "Unexpected name $name (${name.runtimeType}).");
-      libraryBuilder.endNestedDeclaration(
+      compilationUnit.endNestedDeclaration(
           TypeParameterScopeKind.factoryMethod, "<syntax-error>");
     } else {
-      libraryBuilder.addFactoryMethod(
+      compilationUnit.addFactoryMethod(
         _offsetMap,
         metadata,
         modifiers,
@@ -3999,7 +4001,7 @@
     if (supertype is ParserRecovery || mixins is ParserRecovery) {
       push(new ParserRecovery(withKeyword.charOffset));
     } else {
-      push(libraryBuilder.addMixinApplication(
+      push(compilationUnit.addMixinApplication(
           mixins as List<TypeBuilder>, withKeyword.charOffset));
     }
     assert(checkState(withKeyword, [
@@ -4053,7 +4055,7 @@
     if (mixins is ParserRecovery) {
       push(new ParserRecovery(withKeyword.charOffset));
     } else {
-      push(libraryBuilder.addMixinApplication(
+      push(compilationUnit.addMixinApplication(
           mixins as List<TypeBuilder>, withKeyword.charOffset));
     }
     assert(checkState(withKeyword, [
@@ -4113,7 +4115,7 @@
   @override
   void addProblem(Message message, int charOffset, int length,
       {bool wasHandled = false, List<LocatedMessage>? context}) {
-    libraryBuilder.addProblem(message, charOffset, length, uri,
+    compilationUnit.addProblem(message, charOffset, length, uri,
         wasHandled: wasHandled, context: context);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 627df40..df7d169 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -124,13 +124,96 @@
 
   LibraryBuilder? _libraryBuilder;
 
+  /// Map used to find objects created in the [OutlineBuilder] from within
+  /// the [DietListener].
+  ///
+  /// This is meant to be written once and read once.
+  OffsetMap? _offsetMap;
+
   SourceCompilationUnitImpl(this._sourceLibraryBuilder);
 
   @override
   SourceLibraryBuilder get sourceLibraryBuilder => _sourceLibraryBuilder;
 
   @override
-  OffsetMap get offsetMap => _sourceLibraryBuilder.offsetMap;
+  LibraryFeatures get libraryFeatures => _sourceLibraryBuilder.libraryFeatures;
+
+  /// Returns the map of objects created in the [OutlineBuilder].
+  ///
+  /// This should only be called once.
+  @override
+  OffsetMap get offsetMap {
+    assert(_offsetMap != null, "No OffsetMap for $this");
+    OffsetMap map = _offsetMap!;
+    _offsetMap = null;
+    return map;
+  }
+
+  /// Registers the map of objects created in the [OutlineBuilder].
+  ///
+  /// This should only be called once.
+  @override
+  void set offsetMap(OffsetMap value) {
+    assert(_offsetMap == null, "OffsetMap has already been set for $this");
+    _offsetMap = value;
+  }
+
+  @override
+  TypeParameterScopeBuilder get currentTypeParameterScopeBuilder =>
+      _sourceLibraryBuilder.currentTypeParameterScopeBuilder;
+
+  @override
+  void beginNestedDeclaration(TypeParameterScopeKind kind, String name,
+      {bool hasMembers = true}) {
+    _sourceLibraryBuilder.currentTypeParameterScopeBuilder =
+        currentTypeParameterScopeBuilder.createNested(kind, name, hasMembers);
+  }
+
+  @override
+  TypeParameterScopeBuilder endNestedDeclaration(
+      TypeParameterScopeKind kind, String? name) {
+    assert(
+        currentTypeParameterScopeBuilder.kind == kind,
+        "Unexpected declaration. "
+        "Trying to end a ${currentTypeParameterScopeBuilder.kind} as a $kind.");
+    assert(
+        (name?.startsWith(currentTypeParameterScopeBuilder.name) ??
+                (name == currentTypeParameterScopeBuilder.name)) ||
+            currentTypeParameterScopeBuilder.name == "operator" ||
+            (name == null &&
+                currentTypeParameterScopeBuilder.name ==
+                    UnnamedExtensionName.unnamedExtensionSentinel) ||
+            identical(name, "<syntax-error>"),
+        "${name} != ${currentTypeParameterScopeBuilder.name}");
+    TypeParameterScopeBuilder previous = currentTypeParameterScopeBuilder;
+    _sourceLibraryBuilder.currentTypeParameterScopeBuilder =
+        currentTypeParameterScopeBuilder.parent!;
+    return previous;
+  }
+
+  IndexedLibrary? get indexedLibrary => _sourceLibraryBuilder.indexedLibrary;
+
+  // TODO(johnniwinther): Use [_indexedContainer] for library members and make
+  // it [null] when there is null corresponding [IndexedContainer].
+  IndexedContainer? _indexedContainer;
+
+  @override
+  void beginIndexedContainer(String name,
+      {required bool isExtensionTypeDeclaration}) {
+    if (_sourceLibraryBuilder.indexedLibrary != null) {
+      if (isExtensionTypeDeclaration) {
+        _indexedContainer =
+            indexedLibrary!.lookupIndexedExtensionTypeDeclaration(name);
+      } else {
+        _indexedContainer = indexedLibrary!.lookupIndexedClass(name);
+      }
+    }
+  }
+
+  @override
+  void endIndexedContainer() {
+    _indexedContainer = null;
+  }
 
   @override
   LibraryBuilder get libraryBuilder {
@@ -274,6 +357,2002 @@
     _libraryBuilder = library ?? _sourceLibraryBuilder;
     _sourceLibraryBuilder.validatePart(library, usedParts);
   }
+
+  @override
+  void addPart(OffsetMap offsetMap, Token partKeyword,
+      List<MetadataBuilder>? metadata, String uri, int charOffset) {
+    Uri resolvedUri = _sourceLibraryBuilder
+        .resolve(this.importUri, uri, charOffset, isPart: true);
+    // To support absolute paths from within packages in the part uri, we try to
+    // translate the file uri from the resolved import uri before resolving
+    // through the file uri of this library. See issue #52964.
+    Uri newFileUri = loader.target.uriTranslator.translate(resolvedUri) ??
+        _sourceLibraryBuilder.resolve(fileUri, uri, charOffset);
+    // TODO(johnniwinther): Add a LibraryPartBuilder instead of using
+    // [LibraryBuilder] to represent both libraries and parts.
+    CompilationUnit compilationUnit = loader.read(resolvedUri, charOffset,
+        origin: isAugmenting ? _sourceLibraryBuilder.origin : null,
+        fileUri: newFileUri,
+        accessor: this,
+        isPatch: isAugmenting);
+    _sourceLibraryBuilder.parts.add(new Part(charOffset, compilationUnit));
+
+    // TODO(ahe): [metadata] should be stored, evaluated, and added to [part].
+    LibraryPart part = new LibraryPart(<Expression>[], uri)
+      ..fileOffset = charOffset;
+    library.addPart(part);
+    offsetMap.registerPart(partKeyword, part);
+  }
+
+  @override
+  void addPartOf(List<MetadataBuilder>? metadata, String? name, String? uri,
+      int uriOffset) {
+    _sourceLibraryBuilder.partOfName = name;
+    if (uri != null) {
+      Uri resolvedUri = _sourceLibraryBuilder.partOfUri =
+          _sourceLibraryBuilder.resolve(this.importUri, uri, uriOffset);
+      // To support absolute paths from within packages in the part of uri, we
+      // try to translate the file uri from the resolved import uri before
+      // resolving through the file uri of this library. See issue #52964.
+      Uri newFileUri = loader.target.uriTranslator.translate(resolvedUri) ??
+          _sourceLibraryBuilder.resolve(fileUri, uri, uriOffset);
+      loader.read(partOfUri!, uriOffset, fileUri: newFileUri, accessor: this);
+    }
+    if (_scriptTokenOffset != null) {
+      addProblem(
+          messageScriptTagInPartFile, _scriptTokenOffset!, noLength, fileUri);
+    }
+  }
+
+  /// Offset of the first script tag (`#!...`) in this library or part.
+  int? _scriptTokenOffset;
+
+  @override
+  void addScriptToken(int charOffset) {
+    _scriptTokenOffset ??= charOffset;
+  }
+
+  @override
+  void addImport(
+      {OffsetMap? offsetMap,
+      Token? importKeyword,
+      required List<MetadataBuilder>? metadata,
+      required bool isAugmentationImport,
+      required String uri,
+      required List<Configuration>? configurations,
+      required String? prefix,
+      required List<CombinatorBuilder>? combinators,
+      required bool deferred,
+      required int charOffset,
+      required int prefixCharOffset,
+      required int uriOffset,
+      required int importIndex}) {
+    if (configurations != null) {
+      for (Configuration config in configurations) {
+        if (loader.getLibrarySupportValue(config.dottedName) ==
+            config.condition) {
+          uri = config.importUri;
+          break;
+        }
+      }
+    }
+
+    CompilationUnit? compilationUnit = null;
+    Uri? resolvedUri;
+    String? nativePath;
+    const String nativeExtensionScheme = "dart-ext:";
+    if (uri.startsWith(nativeExtensionScheme)) {
+      addProblem(messageUnsupportedDartExt, charOffset, noLength, fileUri);
+      String strippedUri = uri.substring(nativeExtensionScheme.length);
+      if (strippedUri.startsWith("package")) {
+        resolvedUri = _sourceLibraryBuilder.resolve(this.importUri, strippedUri,
+            uriOffset + nativeExtensionScheme.length);
+        resolvedUri = loader.target.translateUri(resolvedUri);
+        nativePath = resolvedUri.toString();
+      } else {
+        resolvedUri = new Uri(scheme: "dart-ext", pathSegments: [uri]);
+        nativePath = uri;
+      }
+    } else {
+      resolvedUri =
+          _sourceLibraryBuilder.resolve(this.importUri, uri, uriOffset);
+      compilationUnit = loader.read(resolvedUri, uriOffset,
+          origin: isAugmentationImport ? _sourceLibraryBuilder : null,
+          accessor: this,
+          isAugmentation: isAugmentationImport,
+          referencesFromIndex: isAugmentationImport ? indexedLibrary : null);
+    }
+
+    Import import = new Import(
+        _sourceLibraryBuilder,
+        compilationUnit,
+        isAugmentationImport,
+        deferred,
+        prefix,
+        combinators,
+        configurations,
+        charOffset,
+        prefixCharOffset,
+        importIndex,
+        nativeImportPath: nativePath);
+    _sourceLibraryBuilder.imports.add(import);
+    offsetMap?.registerImport(importKeyword!, import);
+  }
+
+  @override
+  void addExport(
+      OffsetMap offsetMap,
+      Token exportKeyword,
+      List<MetadataBuilder>? metadata,
+      String uri,
+      List<Configuration>? configurations,
+      List<CombinatorBuilder>? combinators,
+      int charOffset,
+      int uriOffset) {
+    if (configurations != null) {
+      for (Configuration config in configurations) {
+        if (loader.getLibrarySupportValue(config.dottedName) ==
+            config.condition) {
+          uri = config.importUri;
+          break;
+        }
+      }
+    }
+
+    CompilationUnit exportedLibrary = loader.read(
+        _sourceLibraryBuilder.resolve(this.importUri, uri, uriOffset),
+        charOffset,
+        accessor: this);
+    exportedLibrary.addExporter(_sourceLibraryBuilder, combinators, charOffset);
+    Export export = new Export(
+        _sourceLibraryBuilder, exportedLibrary, combinators, charOffset);
+    _sourceLibraryBuilder.exports.add(export);
+    offsetMap.registerExport(exportKeyword, export);
+  }
+
+  @override
+  void addClass(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      TypeBuilder? supertype,
+      MixinApplicationBuilder? mixins,
+      List<TypeBuilder>? interfaces,
+      int startOffset,
+      int nameOffset,
+      int endOffset,
+      int supertypeOffset,
+      {required bool isMacro,
+      required bool isSealed,
+      required bool isBase,
+      required bool isInterface,
+      required bool isFinal,
+      required bool isAugmentation,
+      required bool isMixinClass}) {
+    _addClass(
+        offsetMap,
+        TypeParameterScopeKind.classDeclaration,
+        metadata,
+        modifiers,
+        identifier,
+        typeVariables,
+        supertype,
+        mixins,
+        interfaces,
+        startOffset,
+        nameOffset,
+        endOffset,
+        supertypeOffset,
+        isMacro: isMacro,
+        isSealed: isSealed,
+        isBase: isBase,
+        isInterface: isInterface,
+        isFinal: isFinal,
+        isAugmentation: isAugmentation,
+        isMixinClass: isMixinClass);
+  }
+
+  @override
+  void addEnum(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      MixinApplicationBuilder? supertypeBuilder,
+      List<TypeBuilder>? interfaceBuilders,
+      List<EnumConstantInfo?>? enumConstantInfos,
+      int startCharOffset,
+      int charEndOffset) {
+    String name = identifier.name;
+    int charOffset = identifier.nameOffset;
+
+    IndexedClass? referencesFromIndexedClass;
+    if (indexedLibrary != null) {
+      referencesFromIndexedClass = indexedLibrary!.lookupIndexedClass(name);
+    }
+    // Nested declaration began in `OutlineBuilder.beginEnum`.
+    TypeParameterScopeBuilder declaration =
+        endNestedDeclaration(TypeParameterScopeKind.enumDeclaration, name)
+          ..resolveNamedTypes(typeVariables, _sourceLibraryBuilder);
+    Map<String, Builder> members = declaration.members!;
+    Map<String, MemberBuilder> constructors = declaration.constructors!;
+    Map<String, MemberBuilder> setters = declaration.setters!;
+
+    SourceEnumBuilder enumBuilder = new SourceEnumBuilder(
+        metadata,
+        name,
+        typeVariables,
+        _applyMixins(
+            loader.target.underscoreEnumType,
+            supertypeBuilder,
+            startCharOffset,
+            charOffset,
+            charEndOffset,
+            name,
+            /* isMixinDeclaration = */
+            false,
+            typeVariables: typeVariables,
+            isMacro: false,
+            isSealed: false,
+            isBase: false,
+            isInterface: false,
+            isFinal: false,
+            isAugmentation: false,
+            isMixinClass: false),
+        interfaceBuilders,
+        enumConstantInfos,
+        _sourceLibraryBuilder,
+        new List<ConstructorReferenceBuilder>.of(constructorReferences),
+        startCharOffset,
+        charOffset,
+        charEndOffset,
+        referencesFromIndexedClass,
+        new Scope(
+            kind: ScopeKind.declaration,
+            local: members,
+            setters: setters,
+            parent: scope.withTypeVariables(typeVariables),
+            debugName: "enum $name",
+            isModifiable: false),
+        new ConstructorScope(name, constructors),
+        loader.coreLibrary);
+    constructorReferences.clear();
+
+    Map<String, NominalVariableBuilder>? typeVariablesByName =
+        _checkTypeVariables(typeVariables, enumBuilder);
+
+    void setParent(MemberBuilder? member) {
+      while (member != null) {
+        member.parent = enumBuilder;
+        member = member.next as MemberBuilder?;
+      }
+    }
+
+    void setParentAndCheckConflicts(String name, Builder member) {
+      if (typeVariablesByName != null) {
+        NominalVariableBuilder? tv = typeVariablesByName[name];
+        if (tv != null) {
+          enumBuilder.addProblem(
+              templateConflictsWithTypeVariable.withArguments(name),
+              member.charOffset,
+              name.length,
+              context: [
+                messageConflictsWithTypeVariableCause.withLocation(
+                    tv.fileUri!, tv.charOffset, name.length)
+              ]);
+        }
+      }
+      setParent(member as MemberBuilder);
+    }
+
+    members.forEach(setParentAndCheckConflicts);
+    constructors.forEach(setParentAndCheckConflicts);
+    setters.forEach(setParentAndCheckConflicts);
+    _sourceLibraryBuilder.addBuilder(name, enumBuilder, charOffset,
+        getterReference: referencesFromIndexedClass?.cls.reference);
+
+    offsetMap.registerNamedDeclaration(identifier, enumBuilder);
+  }
+
+  @override
+  void addMixinDeclaration(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      List<TypeBuilder>? supertypeConstraints,
+      List<TypeBuilder>? interfaces,
+      int startOffset,
+      int nameOffset,
+      int endOffset,
+      int supertypeOffset,
+      {required bool isBase,
+      required bool isAugmentation}) {
+    TypeBuilder? supertype;
+    MixinApplicationBuilder? mixinApplication;
+    if (supertypeConstraints != null && supertypeConstraints.isNotEmpty) {
+      supertype = supertypeConstraints.first;
+      if (supertypeConstraints.length > 1) {
+        mixinApplication = new MixinApplicationBuilder(
+            supertypeConstraints.skip(1).toList(),
+            supertype.fileUri!,
+            supertype.charOffset!);
+      }
+    }
+    _addClass(
+        offsetMap,
+        TypeParameterScopeKind.mixinDeclaration,
+        metadata,
+        modifiers,
+        identifier,
+        typeVariables,
+        supertype,
+        mixinApplication,
+        interfaces,
+        startOffset,
+        nameOffset,
+        endOffset,
+        supertypeOffset,
+        isMacro: false,
+        isSealed: false,
+        isBase: isBase,
+        isInterface: false,
+        isFinal: false,
+        isAugmentation: isAugmentation,
+        isMixinClass: false);
+  }
+
+  void _addClass(
+      OffsetMap offsetMap,
+      TypeParameterScopeKind kind,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      TypeBuilder? supertype,
+      MixinApplicationBuilder? mixins,
+      List<TypeBuilder>? interfaces,
+      int startOffset,
+      int nameOffset,
+      int endOffset,
+      int supertypeOffset,
+      {required bool isMacro,
+      required bool isSealed,
+      required bool isBase,
+      required bool isInterface,
+      required bool isFinal,
+      required bool isAugmentation,
+      required bool isMixinClass}) {
+    String className = identifier.name;
+    // Nested declaration began in `OutlineBuilder.beginClassDeclaration`.
+    TypeParameterScopeBuilder declaration =
+        endNestedDeclaration(kind, className)
+          ..resolveNamedTypes(typeVariables, _sourceLibraryBuilder);
+    assert(declaration.parent ==
+        _sourceLibraryBuilder._libraryTypeParameterScopeBuilder);
+    Map<String, Builder> members = declaration.members!;
+    Map<String, MemberBuilder> constructors = declaration.constructors!;
+    Map<String, MemberBuilder> setters = declaration.setters!;
+
+    Scope classScope = new Scope(
+        kind: ScopeKind.declaration,
+        local: members,
+        setters: setters,
+        parent: scope.withTypeVariables(typeVariables),
+        debugName: "class $className",
+        isModifiable: false);
+
+    // When looking up a constructor, we don't consider type variables or the
+    // library scope.
+    ConstructorScope constructorScope =
+        new ConstructorScope(className, constructors);
+    bool isMixinDeclaration = false;
+    if (modifiers & mixinDeclarationMask != 0) {
+      isMixinDeclaration = true;
+      modifiers = (modifiers & ~mixinDeclarationMask) | abstractMask;
+    }
+    if (declaration.declaresConstConstructor) {
+      modifiers |= declaresConstConstructorMask;
+    }
+    SourceClassBuilder classBuilder = new SourceClassBuilder(
+        metadata,
+        modifiers,
+        className,
+        typeVariables,
+        _applyMixins(supertype, mixins, startOffset, nameOffset, endOffset,
+            className, isMixinDeclaration,
+            typeVariables: typeVariables,
+            isMacro: false,
+            isSealed: false,
+            isBase: false,
+            isInterface: false,
+            isFinal: false,
+            // TODO(johnniwinther): How can we support class with mixins?
+            isAugmentation: false,
+            isMixinClass: false),
+        interfaces,
+        // TODO(johnniwinther): Add the `on` clause types of a mixin declaration
+        // here.
+        null,
+        classScope,
+        constructorScope,
+        _sourceLibraryBuilder,
+        new List<ConstructorReferenceBuilder>.of(constructorReferences),
+        startOffset,
+        nameOffset,
+        endOffset,
+        _indexedContainer,
+        isMixinDeclaration: isMixinDeclaration,
+        isMacro: isMacro,
+        isSealed: isSealed,
+        isBase: isBase,
+        isInterface: isInterface,
+        isFinal: isFinal,
+        isAugmentation: isAugmentation,
+        isMixinClass: isMixinClass);
+
+    constructorReferences.clear();
+    Map<String, NominalVariableBuilder>? typeVariablesByName =
+        _checkTypeVariables(typeVariables, classBuilder);
+    void setParent(MemberBuilder? member) {
+      while (member != null) {
+        member.parent = classBuilder;
+        member = member.next as MemberBuilder?;
+      }
+    }
+
+    void setParentAndCheckConflicts(String name, Builder member) {
+      if (typeVariablesByName != null) {
+        NominalVariableBuilder? tv = typeVariablesByName[name];
+        if (tv != null) {
+          classBuilder.addProblem(
+              templateConflictsWithTypeVariable.withArguments(name),
+              member.charOffset,
+              name.length,
+              context: [
+                messageConflictsWithTypeVariableCause.withLocation(
+                    tv.fileUri!, tv.charOffset, name.length)
+              ]);
+        }
+      }
+      setParent(member as MemberBuilder);
+    }
+
+    members.forEach(setParentAndCheckConflicts);
+    constructors.forEach(setParentAndCheckConflicts);
+    setters.forEach(setParentAndCheckConflicts);
+    _sourceLibraryBuilder.addBuilder(className, classBuilder, nameOffset,
+        getterReference: _indexedContainer?.reference);
+    offsetMap.registerNamedDeclaration(identifier, classBuilder);
+  }
+
+  @override
+  MixinApplicationBuilder addMixinApplication(
+      List<TypeBuilder> mixins, int charOffset) {
+    return new MixinApplicationBuilder(mixins, fileUri, charOffset);
+  }
+
+  @override
+  void addNamedMixinApplication(
+      List<MetadataBuilder>? metadata,
+      String name,
+      List<NominalVariableBuilder>? typeVariables,
+      int modifiers,
+      TypeBuilder? supertype,
+      MixinApplicationBuilder mixinApplication,
+      List<TypeBuilder>? interfaces,
+      int startCharOffset,
+      int charOffset,
+      int charEndOffset,
+      {required bool isMacro,
+      required bool isSealed,
+      required bool isBase,
+      required bool isInterface,
+      required bool isFinal,
+      required bool isAugmentation,
+      required bool isMixinClass}) {
+    // Nested declaration began in `OutlineBuilder.beginNamedMixinApplication`.
+    endNestedDeclaration(TypeParameterScopeKind.namedMixinApplication, name)
+        .resolveNamedTypes(typeVariables, _sourceLibraryBuilder);
+    supertype = _applyMixins(supertype, mixinApplication, startCharOffset,
+        charOffset, charEndOffset, name, false,
+        metadata: metadata,
+        name: name,
+        typeVariables: typeVariables,
+        modifiers: modifiers,
+        interfaces: interfaces,
+        isMacro: isMacro,
+        isSealed: isSealed,
+        isBase: isBase,
+        isInterface: isInterface,
+        isFinal: isFinal,
+        isAugmentation: isAugmentation,
+        isMixinClass: isMixinClass)!;
+    _checkTypeVariables(typeVariables, supertype.declaration);
+  }
+
+  TypeBuilder? _applyMixins(
+      TypeBuilder? supertype,
+      MixinApplicationBuilder? mixinApplications,
+      int startCharOffset,
+      int charOffset,
+      int charEndOffset,
+      String subclassName,
+      bool isMixinDeclaration,
+      {List<MetadataBuilder>? metadata,
+      String? name,
+      List<NominalVariableBuilder>? typeVariables,
+      int modifiers = 0,
+      List<TypeBuilder>? interfaces,
+      required bool isMacro,
+      required bool isSealed,
+      required bool isBase,
+      required bool isInterface,
+      required bool isFinal,
+      required bool isAugmentation,
+      required bool isMixinClass}) {
+    if (name == null) {
+      // The following parameters should only be used when building a named
+      // mixin application.
+      if (metadata != null) {
+        unhandled("metadata", "unnamed mixin application", charOffset, fileUri);
+      } else if (interfaces != null) {
+        unhandled(
+            "interfaces", "unnamed mixin application", charOffset, fileUri);
+      }
+    }
+    if (mixinApplications != null) {
+      // Documentation below assumes the given mixin application is in one of
+      // these forms:
+      //
+      //     class C extends S with M1, M2, M3;
+      //     class Named = S with M1, M2, M3;
+      //
+      // When we refer to the subclass, we mean `C` or `Named`.
+
+      /// The current supertype.
+      ///
+      /// Starts out having the value `S` and on each iteration of the loop
+      /// below, it will take on the value corresponding to:
+      ///
+      /// 1. `S with M1`.
+      /// 2. `(S with M1) with M2`.
+      /// 3. `((S with M1) with M2) with M3`.
+      supertype ??= loader.target.objectType;
+
+      /// The variable part of the mixin application's synthetic name. It
+      /// starts out as the name of the superclass, but is only used after it
+      /// has been combined with the name of the current mixin. In the examples
+      /// from above, it will take these values:
+      ///
+      /// 1. `S&M1`
+      /// 2. `S&M1&M2`
+      /// 3. `S&M1&M2&M3`.
+      ///
+      /// The full name of the mixin application is obtained by prepending the
+      /// name of the subclass (`C` or `Named` in the above examples) to the
+      /// running name. For the example `C`, that leads to these full names:
+      ///
+      /// 1. `_C&S&M1`
+      /// 2. `_C&S&M1&M2`
+      /// 3. `_C&S&M1&M2&M3`.
+      ///
+      /// For a named mixin application, the last name has been given by the
+      /// programmer, so for the example `Named` we see these full names:
+      ///
+      /// 1. `_Named&S&M1`
+      /// 2. `_Named&S&M1&M2`
+      /// 3. `Named`.
+      String runningName;
+      if (supertype.typeName == null) {
+        assert(supertype is FunctionTypeBuilder);
+
+        // Function types don't have names, and we can supply any string that
+        // doesn't have to be unique. The actual supertype of the mixin will
+        // not be built in that case.
+        runningName = "";
+      } else {
+        runningName = supertype.typeName!.name;
+      }
+
+      /// True when we're building a named mixin application. Notice that for
+      /// the `Named` example above, this is only true on the last
+      /// iteration because only the full mixin application is named.
+      bool isNamedMixinApplication;
+
+      /// The names of the type variables of the subclass.
+      Set<String>? typeVariableNames;
+      if (typeVariables != null) {
+        typeVariableNames = new Set<String>();
+        for (NominalVariableBuilder typeVariable in typeVariables) {
+          typeVariableNames.add(typeVariable.name);
+        }
+      }
+
+      /// Helper function that returns `true` if a type variable with a name
+      /// from [typeVariableNames] is referenced in [type].
+      bool usesTypeVariables(TypeBuilder? type) {
+        switch (type) {
+          case NamedTypeBuilder(
+              :TypeDeclarationBuilder? declaration,
+              typeArguments: List<TypeBuilder>? arguments
+            ):
+            if (declaration is NominalVariableBuilder) {
+              return typeVariableNames!.contains(declaration.name);
+            }
+            if (declaration is StructuralVariableBuilder) {
+              return typeVariableNames!.contains(declaration.name);
+            }
+
+            if (arguments != null && typeVariables != null) {
+              for (TypeBuilder argument in arguments) {
+                if (usesTypeVariables(argument)) {
+                  return true;
+                }
+              }
+            }
+          case FunctionTypeBuilder(
+              :List<ParameterBuilder>? formals,
+              :List<StructuralVariableBuilder>? typeVariables
+            ):
+            if (formals != null) {
+              for (ParameterBuilder formal in formals) {
+                if (usesTypeVariables(formal.type)) {
+                  return true;
+                }
+              }
+            }
+            if (typeVariables != null) {
+              for (StructuralVariableBuilder variable in typeVariables) {
+                if (usesTypeVariables(variable.bound)) {
+                  return true;
+                }
+              }
+            }
+            return usesTypeVariables(type.returnType);
+          case RecordTypeBuilder(
+              :List<RecordTypeFieldBuilder>? positionalFields,
+              :List<RecordTypeFieldBuilder>? namedFields
+            ):
+            if (positionalFields != null) {
+              for (RecordTypeFieldBuilder fieldBuilder in positionalFields) {
+                if (usesTypeVariables(fieldBuilder.type)) {
+                  return true;
+                }
+              }
+            }
+            if (namedFields != null) {
+              for (RecordTypeFieldBuilder fieldBuilder in namedFields) {
+                if (usesTypeVariables(fieldBuilder.type)) {
+                  return true;
+                }
+              }
+            }
+          case FixedTypeBuilder():
+          case InvalidTypeBuilder():
+          case OmittedTypeBuilder():
+          case null:
+            return false;
+        }
+        return false;
+      }
+
+      /// Iterate over the mixins from left to right. At the end of each
+      /// iteration, a new [supertype] is computed that is the mixin
+      /// application of [supertype] with the current mixin.
+      for (int i = 0; i < mixinApplications.mixins.length; i++) {
+        TypeBuilder mixin = mixinApplications.mixins[i];
+        isNamedMixinApplication =
+            name != null && mixin == mixinApplications.mixins.last;
+        bool isGeneric = false;
+        if (!isNamedMixinApplication) {
+          if (supertype is NamedTypeBuilder) {
+            isGeneric = isGeneric || usesTypeVariables(supertype);
+          }
+          if (mixin is NamedTypeBuilder) {
+            runningName += "&${mixin.typeName.name}";
+            isGeneric = isGeneric || usesTypeVariables(mixin);
+          }
+        }
+        String fullname =
+            isNamedMixinApplication ? name : "_$subclassName&$runningName";
+        List<NominalVariableBuilder>? applicationTypeVariables;
+        List<TypeBuilder>? applicationTypeArguments;
+        if (isNamedMixinApplication) {
+          // If this is a named mixin application, it must be given all the
+          // declared type variables.
+          applicationTypeVariables = typeVariables;
+        } else {
+          // Otherwise, we pass the fresh type variables to the mixin
+          // application in the same order as they're declared on the subclass.
+          if (isGeneric) {
+            this.beginNestedDeclaration(
+                TypeParameterScopeKind.unnamedMixinApplication,
+                "mixin application");
+
+            applicationTypeVariables = copyTypeVariables(
+                typeVariables!, currentTypeParameterScopeBuilder,
+                kind: TypeVariableKind.extensionSynthesized);
+
+            List<NamedTypeBuilder> newTypes = <NamedTypeBuilder>[];
+            if (supertype is NamedTypeBuilder &&
+                supertype.typeArguments != null) {
+              for (int i = 0; i < supertype.typeArguments!.length; ++i) {
+                supertype.typeArguments![i] = supertype.typeArguments![i].clone(
+                    newTypes,
+                    _sourceLibraryBuilder,
+                    currentTypeParameterScopeBuilder);
+              }
+            }
+            if (mixin is NamedTypeBuilder && mixin.typeArguments != null) {
+              for (int i = 0; i < mixin.typeArguments!.length; ++i) {
+                mixin.typeArguments![i] = mixin.typeArguments![i].clone(
+                    newTypes,
+                    _sourceLibraryBuilder,
+                    currentTypeParameterScopeBuilder);
+              }
+            }
+            for (NamedTypeBuilder newType in newTypes) {
+              currentTypeParameterScopeBuilder
+                  .registerUnresolvedNamedType(newType);
+            }
+
+            TypeParameterScopeBuilder mixinDeclaration = this
+                .endNestedDeclaration(
+                    TypeParameterScopeKind.unnamedMixinApplication,
+                    "mixin application");
+            mixinDeclaration.resolveNamedTypes(
+                applicationTypeVariables, _sourceLibraryBuilder);
+
+            applicationTypeArguments = <TypeBuilder>[];
+            for (NominalVariableBuilder typeVariable in typeVariables) {
+              applicationTypeArguments.add(
+                  new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
+                      // The type variable types passed as arguments to the
+                      // generic class representing the anonymous mixin
+                      // application should refer back to the type variables of
+                      // the class that extend the anonymous mixin application.
+                      typeVariable,
+                      const NullabilityBuilder.omitted(),
+                      fileUri: fileUri,
+                      charOffset: charOffset,
+                      instanceTypeVariableAccess:
+                          InstanceTypeVariableAccessState.Allowed));
+            }
+          }
+        }
+        final int computedStartCharOffset =
+            !isNamedMixinApplication || metadata == null
+                ? startCharOffset
+                : metadata.first.charOffset;
+
+        IndexedClass? referencesFromIndexedClass;
+        if (indexedLibrary != null) {
+          referencesFromIndexedClass =
+              indexedLibrary!.lookupIndexedClass(fullname);
+        }
+
+        SourceClassBuilder application = new SourceClassBuilder(
+            isNamedMixinApplication ? metadata : null,
+            isNamedMixinApplication
+                ? modifiers | namedMixinApplicationMask
+                : abstractMask,
+            fullname,
+            applicationTypeVariables,
+            isMixinDeclaration ? null : supertype,
+            isNamedMixinApplication
+                ? interfaces
+                : isMixinDeclaration
+                    ? [supertype!, mixin]
+                    : null,
+            null,
+            // No `on` clause types.
+            new Scope(
+                kind: ScopeKind.declaration,
+                local: <String, MemberBuilder>{},
+                setters: <String, MemberBuilder>{},
+                parent: scope.withTypeVariables(typeVariables),
+                debugName: "mixin $fullname ",
+                isModifiable: false),
+            new ConstructorScope(fullname, <String, MemberBuilder>{}),
+            _sourceLibraryBuilder,
+            <ConstructorReferenceBuilder>[],
+            computedStartCharOffset,
+            charOffset,
+            charEndOffset,
+            referencesFromIndexedClass,
+            mixedInTypeBuilder: isMixinDeclaration ? null : mixin,
+            isMacro: isNamedMixinApplication && isMacro,
+            isSealed: isNamedMixinApplication && isSealed,
+            isBase: isNamedMixinApplication && isBase,
+            isInterface: isNamedMixinApplication && isInterface,
+            isFinal: isNamedMixinApplication && isFinal,
+            isAugmentation: isNamedMixinApplication && isAugmentation,
+            isMixinClass: isNamedMixinApplication && isMixinClass);
+        // TODO(ahe, kmillikin): Should always be true?
+        // pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart can't
+        // handle that :(
+        application.cls.isAnonymousMixin = !isNamedMixinApplication;
+        _sourceLibraryBuilder.addBuilder(fullname, application, charOffset,
+            getterReference: referencesFromIndexedClass?.cls.reference);
+        supertype = new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
+            application, const NullabilityBuilder.omitted(),
+            arguments: applicationTypeArguments,
+            fileUri: fileUri,
+            charOffset: charOffset,
+            instanceTypeVariableAccess:
+                InstanceTypeVariableAccessState.Allowed);
+        _registerMixinApplication(application, mixin);
+      }
+      return supertype;
+    } else {
+      return supertype;
+    }
+  }
+
+  /// Registers that [mixinApplication] is a mixin application introduced by
+  /// the [mixedInType] in a with-clause.
+  ///
+  /// This is used to check that super access in mixin declarations have a
+  /// concrete target.
+  void _registerMixinApplication(
+      SourceClassBuilder mixinApplication, TypeBuilder mixedInType) {
+    assert(_sourceLibraryBuilder._mixinApplications != null,
+        "Late registration of mixin application.");
+    _sourceLibraryBuilder._mixinApplications![mixinApplication] = mixedInType;
+  }
+
+  @override
+  void addExtensionDeclaration(
+      OffsetMap offsetMap,
+      Token beginToken,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier? identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      TypeBuilder type,
+      int startOffset,
+      int nameOffset,
+      int endOffset) {
+    String? name = identifier?.name;
+    // Nested declaration began in
+    // `OutlineBuilder.beginExtensionDeclarationPrelude`.
+    TypeParameterScopeBuilder declaration =
+        endNestedDeclaration(TypeParameterScopeKind.extensionDeclaration, name)
+          ..resolveNamedTypes(typeVariables, _sourceLibraryBuilder);
+    assert(declaration.parent ==
+        _sourceLibraryBuilder._libraryTypeParameterScopeBuilder);
+    Map<String, Builder> members = declaration.members!;
+    Map<String, MemberBuilder> constructors = declaration.constructors!;
+    Map<String, MemberBuilder> setters = declaration.setters!;
+
+    Scope classScope = new Scope(
+        kind: ScopeKind.declaration,
+        local: members,
+        setters: setters,
+        parent: scope.withTypeVariables(typeVariables),
+        debugName: "extension $name",
+        isModifiable: false);
+
+    Extension? referenceFrom;
+    ExtensionName extensionName = declaration.extensionName!;
+    if (name != null) {
+      referenceFrom = indexedLibrary?.lookupExtension(name);
+    }
+
+    ExtensionBuilder extensionBuilder = new SourceExtensionBuilder(
+        metadata,
+        modifiers,
+        extensionName,
+        typeVariables,
+        type,
+        classScope,
+        _sourceLibraryBuilder,
+        startOffset,
+        nameOffset,
+        endOffset,
+        referenceFrom);
+    constructorReferences.clear();
+    Map<String, NominalVariableBuilder>? typeVariablesByName =
+        _checkTypeVariables(typeVariables, extensionBuilder);
+    void setParent(MemberBuilder? member) {
+      while (member != null) {
+        member.parent = extensionBuilder;
+        member = member.next as MemberBuilder?;
+      }
+    }
+
+    void setParentAndCheckConflicts(String name, Builder member) {
+      if (typeVariablesByName != null) {
+        NominalVariableBuilder? tv = typeVariablesByName[name];
+        if (tv != null) {
+          extensionBuilder.addProblem(
+              templateConflictsWithTypeVariable.withArguments(name),
+              member.charOffset,
+              name.length,
+              context: [
+                messageConflictsWithTypeVariableCause.withLocation(
+                    tv.fileUri!, tv.charOffset, name.length)
+              ]);
+        }
+      }
+      setParent(member as MemberBuilder);
+    }
+
+    members.forEach(setParentAndCheckConflicts);
+    constructors.forEach(setParentAndCheckConflicts);
+    setters.forEach(setParentAndCheckConflicts);
+    _sourceLibraryBuilder.addBuilder(
+        extensionBuilder.name, extensionBuilder, nameOffset,
+        getterReference: referenceFrom?.reference);
+    if (identifier != null) {
+      offsetMap.registerNamedDeclaration(identifier, extensionBuilder);
+    } else {
+      offsetMap.registerUnnamedDeclaration(beginToken, extensionBuilder);
+    }
+  }
+
+  @override
+  void addExtensionTypeDeclaration(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<NominalVariableBuilder>? typeVariables,
+      List<TypeBuilder>? interfaces,
+      int startOffset,
+      int endOffset) {
+    String name = identifier.name;
+    // Nested declaration began in `OutlineBuilder.beginExtensionDeclaration`.
+    TypeParameterScopeBuilder declaration = endNestedDeclaration(
+        TypeParameterScopeKind.extensionTypeDeclaration, name)
+      ..resolveNamedTypes(typeVariables, _sourceLibraryBuilder);
+    assert(declaration.parent ==
+        _sourceLibraryBuilder._libraryTypeParameterScopeBuilder);
+    Map<String, Builder> members = declaration.members!;
+    Map<String, MemberBuilder> constructors = declaration.constructors!;
+    Map<String, MemberBuilder> setters = declaration.setters!;
+
+    Scope memberScope = new Scope(
+        kind: ScopeKind.declaration,
+        local: members,
+        setters: setters,
+        parent: scope.withTypeVariables(typeVariables),
+        debugName: "extension type $name",
+        isModifiable: false);
+    ConstructorScope constructorScope =
+        new ConstructorScope(name, constructors);
+
+    IndexedContainer? indexedContainer =
+        indexedLibrary?.lookupIndexedExtensionTypeDeclaration(name);
+
+    SourceFieldBuilder? representationFieldBuilder;
+    outer:
+    for (Builder? member in members.values) {
+      while (member != null) {
+        if (!member.isDuplicate &&
+            member is SourceFieldBuilder &&
+            !member.isStatic) {
+          representationFieldBuilder = member;
+          break outer;
+        }
+        member = member.next;
+      }
+    }
+
+    ExtensionTypeDeclarationBuilder extensionTypeDeclarationBuilder =
+        new SourceExtensionTypeDeclarationBuilder(
+            metadata,
+            modifiers,
+            declaration.name,
+            typeVariables,
+            interfaces,
+            memberScope,
+            constructorScope,
+            _sourceLibraryBuilder,
+            new List<ConstructorReferenceBuilder>.of(constructorReferences),
+            startOffset,
+            identifier.nameOffset,
+            endOffset,
+            indexedContainer,
+            representationFieldBuilder);
+    constructorReferences.clear();
+    Map<String, NominalVariableBuilder>? typeVariablesByName =
+        _checkTypeVariables(typeVariables, extensionTypeDeclarationBuilder);
+    void setParent(MemberBuilder? member) {
+      while (member != null) {
+        member.parent = extensionTypeDeclarationBuilder;
+        member = member.next as MemberBuilder?;
+      }
+    }
+
+    void setParentAndCheckConflicts(String name, Builder member) {
+      if (typeVariablesByName != null) {
+        NominalVariableBuilder? tv = typeVariablesByName[name];
+        if (tv != null) {
+          extensionTypeDeclarationBuilder.addProblem(
+              templateConflictsWithTypeVariable.withArguments(name),
+              member.charOffset,
+              name.length,
+              context: [
+                messageConflictsWithTypeVariableCause.withLocation(
+                    tv.fileUri!, tv.charOffset, name.length)
+              ]);
+        }
+      }
+      setParent(member as MemberBuilder);
+    }
+
+    members.forEach(setParentAndCheckConflicts);
+    constructors.forEach(setParentAndCheckConflicts);
+    setters.forEach(setParentAndCheckConflicts);
+    _sourceLibraryBuilder.addBuilder(extensionTypeDeclarationBuilder.name,
+        extensionTypeDeclarationBuilder, identifier.nameOffset,
+        getterReference: indexedContainer?.reference);
+    offsetMap.registerNamedDeclaration(
+        identifier, extensionTypeDeclarationBuilder);
+  }
+
+  @override
+  void addFunctionTypeAlias(
+      List<MetadataBuilder>? metadata,
+      String name,
+      List<NominalVariableBuilder>? typeVariables,
+      TypeBuilder type,
+      int charOffset) {
+    if (typeVariables != null) {
+      for (NominalVariableBuilder typeVariable in typeVariables) {
+        typeVariable.varianceCalculationValue =
+            VarianceCalculationValue.pending;
+      }
+    }
+    Typedef? referenceFrom = indexedLibrary?.lookupTypedef(name);
+    TypeAliasBuilder typedefBuilder = new SourceTypeAliasBuilder(
+        metadata, name, typeVariables, type, _sourceLibraryBuilder, charOffset,
+        referenceFrom: referenceFrom);
+    _checkTypeVariables(typeVariables, typedefBuilder);
+    // Nested declaration began in `OutlineBuilder.beginFunctionTypeAlias`.
+    endNestedDeclaration(TypeParameterScopeKind.typedef, "#typedef")
+        .resolveNamedTypes(typeVariables, _sourceLibraryBuilder);
+    _sourceLibraryBuilder.addBuilder(name, typedefBuilder, charOffset,
+        getterReference: referenceFrom?.reference);
+  }
+
+  @override
+  void addConstructor(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      String constructorName,
+      List<NominalVariableBuilder>? typeVariables,
+      List<FormalParameterBuilder>? formals,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      String? nativeMethodName,
+      {Token? beginInitializers,
+      required bool forAbstractClassOrMixin}) {
+    SourceFunctionBuilder builder = _addConstructor(
+        metadata,
+        modifiers,
+        constructorName,
+        typeVariables,
+        formals,
+        startCharOffset,
+        charOffset,
+        charOpenParenOffset,
+        charEndOffset,
+        nativeMethodName,
+        beginInitializers: beginInitializers,
+        forAbstractClassOrMixin: forAbstractClassOrMixin);
+    offsetMap.registerConstructor(identifier, builder);
+  }
+
+  @override
+  void addPrimaryConstructor(
+      {required OffsetMap offsetMap,
+      required Token beginToken,
+      required String constructorName,
+      required List<NominalVariableBuilder>? typeVariables,
+      required List<FormalParameterBuilder>? formals,
+      required int charOffset,
+      required bool isConst}) {
+    SourceFunctionBuilder builder = _addConstructor(
+        null,
+        isConst ? constMask : 0,
+        constructorName,
+        typeVariables,
+        formals,
+        /* startCharOffset = */ charOffset,
+        charOffset,
+        /* charOpenParenOffset = */ charOffset,
+        /* charEndOffset = */ charOffset,
+        /* nativeMethodName = */ null,
+        forAbstractClassOrMixin: false);
+    offsetMap.registerPrimaryConstructor(beginToken, builder);
+  }
+
+  @override
+  void addPrimaryConstructorField(
+      {required List<MetadataBuilder>? metadata,
+      required TypeBuilder type,
+      required String name,
+      required int charOffset}) {
+    _addField(
+        metadata,
+        finalMask,
+        /* isTopLevel = */ false,
+        type,
+        name,
+        /* charOffset = */ charOffset,
+        /* charEndOffset = */ charOffset,
+        /* initializerToken = */ null,
+        /* hasInitializer = */ false);
+  }
+
+  SourceFunctionBuilder _addConstructor(
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      String constructorName,
+      List<NominalVariableBuilder>? typeVariables,
+      List<FormalParameterBuilder>? formals,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      String? nativeMethodName,
+      {Token? beginInitializers,
+      required bool forAbstractClassOrMixin}) {
+    ContainerType containerType =
+        currentTypeParameterScopeBuilder.containerType;
+    ContainerName? containerName =
+        currentTypeParameterScopeBuilder.containerName;
+    NameScheme nameScheme = new NameScheme(
+        isInstanceMember: false,
+        containerName: containerName,
+        containerType: containerType,
+        libraryName: indexedLibrary != null
+            ? new LibraryName(indexedLibrary!.library.reference)
+            : libraryName);
+
+    Reference? constructorReference;
+    Reference? tearOffReference;
+
+    IndexedContainer? indexedContainer = _indexedContainer;
+    if (indexedContainer != null) {
+      constructorReference = indexedContainer.lookupConstructorReference(
+          nameScheme
+              .getConstructorMemberName(constructorName, isTearOff: false)
+              .name);
+      tearOffReference = indexedContainer.lookupGetterReference(nameScheme
+          .getConstructorMemberName(constructorName, isTearOff: true)
+          .name);
+    }
+    AbstractSourceConstructorBuilder constructorBuilder;
+
+    if (currentTypeParameterScopeBuilder.kind ==
+        TypeParameterScopeKind.extensionTypeDeclaration) {
+      constructorBuilder = new SourceExtensionTypeConstructorBuilder(
+          metadata,
+          modifiers & ~abstractMask,
+          addInferableType(),
+          constructorName,
+          typeVariables,
+          formals,
+          _sourceLibraryBuilder,
+          startCharOffset,
+          charOffset,
+          charOpenParenOffset,
+          charEndOffset,
+          constructorReference,
+          tearOffReference,
+          nameScheme,
+          nativeMethodName: nativeMethodName,
+          forAbstractClassOrEnumOrMixin: forAbstractClassOrMixin);
+    } else {
+      constructorBuilder = new DeclaredSourceConstructorBuilder(
+          metadata,
+          modifiers & ~abstractMask,
+          addInferableType(),
+          constructorName,
+          typeVariables,
+          formals,
+          _sourceLibraryBuilder,
+          startCharOffset,
+          charOffset,
+          charOpenParenOffset,
+          charEndOffset,
+          constructorReference,
+          tearOffReference,
+          nameScheme,
+          nativeMethodName: nativeMethodName,
+          forAbstractClassOrEnumOrMixin: forAbstractClassOrMixin);
+    }
+    _checkTypeVariables(typeVariables, constructorBuilder);
+    // TODO(johnniwinther): There is no way to pass the tear off reference here.
+    _sourceLibraryBuilder.addBuilder(
+        constructorName, constructorBuilder, charOffset,
+        getterReference: constructorReference);
+    if (nativeMethodName != null) {
+      _addNativeMethod(constructorBuilder);
+    }
+    if (constructorBuilder.isConst) {
+      currentTypeParameterScopeBuilder.declaresConstConstructor = true;
+    }
+    if (constructorBuilder.isConst ||
+        libraryFeatures.superParameters.isEnabled) {
+      // const constructors will have their initializers compiled and written
+      // into the outline. In case of super-parameters language feature, the
+      // super initializers are required to infer the types of super parameters.
+      constructorBuilder.beginInitializers =
+          beginInitializers ?? new Token.eof(-1);
+    }
+    return constructorBuilder;
+  }
+
+  @override
+  void addFactoryMethod(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      Identifier identifier,
+      List<FormalParameterBuilder>? formals,
+      ConstructorReferenceBuilder? redirectionTarget,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      String? nativeMethodName,
+      AsyncMarker asyncModifier) {
+    TypeBuilder returnType;
+    if (currentTypeParameterScopeBuilder.parent?.kind ==
+        TypeParameterScopeKind.extensionDeclaration) {
+      // Make the synthesized return type invalid for extensions.
+      String name = currentTypeParameterScopeBuilder.parent!.name;
+      returnType = new NamedTypeBuilderImpl.forInvalidType(
+          currentTypeParameterScopeBuilder.parent!.name,
+          const NullabilityBuilder.omitted(),
+          messageExtensionDeclaresConstructor.withLocation(
+              fileUri, charOffset, name.length));
+    } else {
+      returnType = addNamedType(
+          new SyntheticTypeName(
+              currentTypeParameterScopeBuilder.parent!.name, charOffset),
+          const NullabilityBuilder.omitted(),
+          <TypeBuilder>[],
+          charOffset,
+          instanceTypeVariableAccess: InstanceTypeVariableAccessState.Allowed);
+    }
+    // Nested declaration began in `OutlineBuilder.beginFactoryMethod`.
+    TypeParameterScopeBuilder factoryDeclaration = endNestedDeclaration(
+        TypeParameterScopeKind.factoryMethod, "#factory_method");
+
+    // Prepare the simple procedure name.
+    String procedureName;
+    String? constructorName =
+        computeAndValidateConstructorName(identifier, isFactory: true);
+    if (constructorName != null) {
+      procedureName = constructorName;
+    } else {
+      procedureName = identifier.name;
+    }
+
+    ContainerType containerType =
+        currentTypeParameterScopeBuilder.containerType;
+    ContainerName? containerName =
+        currentTypeParameterScopeBuilder.containerName;
+
+    NameScheme procedureNameScheme = new NameScheme(
+        containerName: containerName,
+        containerType: containerType,
+        isInstanceMember: false,
+        libraryName: indexedLibrary != null
+            ? new LibraryName(
+                (_indexedContainer ?? indexedLibrary)!.library.reference)
+            : libraryName);
+
+    Reference? constructorReference;
+    Reference? tearOffReference;
+    if (_indexedContainer != null) {
+      constructorReference = _indexedContainer!.lookupConstructorReference(
+          procedureNameScheme
+              .getConstructorMemberName(procedureName, isTearOff: false)
+              .name);
+      tearOffReference = _indexedContainer!.lookupGetterReference(
+          procedureNameScheme
+              .getConstructorMemberName(procedureName, isTearOff: true)
+              .name);
+    } else if (indexedLibrary != null) {
+      constructorReference = indexedLibrary!.lookupGetterReference(
+          procedureNameScheme
+              .getConstructorMemberName(procedureName, isTearOff: false)
+              .name);
+      tearOffReference = indexedLibrary!.lookupGetterReference(
+          procedureNameScheme
+              .getConstructorMemberName(procedureName, isTearOff: true)
+              .name);
+    }
+
+    SourceFactoryBuilder procedureBuilder;
+    List<NominalVariableBuilder> typeVariables;
+    if (redirectionTarget != null) {
+      procedureBuilder = new RedirectingFactoryBuilder(
+          metadata,
+          staticMask | modifiers,
+          returnType,
+          procedureName,
+          typeVariables = copyTypeVariables(
+              currentTypeParameterScopeBuilder.typeVariables ??
+                  const <NominalVariableBuilder>[],
+              factoryDeclaration,
+              kind: TypeVariableKind.function),
+          formals,
+          _sourceLibraryBuilder,
+          startCharOffset,
+          charOffset,
+          charOpenParenOffset,
+          charEndOffset,
+          constructorReference,
+          tearOffReference,
+          procedureNameScheme,
+          nativeMethodName,
+          redirectionTarget);
+    } else {
+      procedureBuilder = new SourceFactoryBuilder(
+          metadata,
+          staticMask | modifiers,
+          returnType,
+          procedureName,
+          typeVariables = copyTypeVariables(
+              currentTypeParameterScopeBuilder.typeVariables ??
+                  const <NominalVariableBuilder>[],
+              factoryDeclaration,
+              kind: TypeVariableKind.function),
+          formals,
+          _sourceLibraryBuilder,
+          startCharOffset,
+          charOffset,
+          charOpenParenOffset,
+          charEndOffset,
+          constructorReference,
+          tearOffReference,
+          asyncModifier,
+          procedureNameScheme,
+          nativeMethodName: nativeMethodName);
+    }
+
+    TypeParameterScopeBuilder savedDeclaration =
+        currentTypeParameterScopeBuilder;
+    _sourceLibraryBuilder.currentTypeParameterScopeBuilder = factoryDeclaration;
+    if (returnType is NamedTypeBuilderImpl && !typeVariables.isEmpty) {
+      returnType.typeArguments =
+          new List<TypeBuilder>.generate(typeVariables.length, (int index) {
+        return addNamedType(
+            new SyntheticTypeName(
+                typeVariables[index].name, procedureBuilder.charOffset),
+            const NullabilityBuilder.omitted(),
+            null,
+            procedureBuilder.charOffset,
+            instanceTypeVariableAccess:
+                InstanceTypeVariableAccessState.Allowed);
+      });
+    }
+    _sourceLibraryBuilder.currentTypeParameterScopeBuilder = savedDeclaration;
+
+    factoryDeclaration.resolveNamedTypes(
+        procedureBuilder.typeVariables, _sourceLibraryBuilder);
+    _sourceLibraryBuilder.addBuilder(
+        procedureName, procedureBuilder, charOffset,
+        getterReference: constructorReference);
+    if (nativeMethodName != null) {
+      _addNativeMethod(procedureBuilder);
+    }
+    offsetMap.registerConstructor(identifier, procedureBuilder);
+  }
+
+  void _addNativeMethod(SourceFunctionBuilder method) {
+    nativeMethods.add(method);
+  }
+
+  @override
+  String? computeAndValidateConstructorName(Identifier identifier,
+      {isFactory = false}) {
+    String className = currentTypeParameterScopeBuilder.name;
+    String prefix;
+    String? suffix;
+    int charOffset;
+    if (identifier is QualifiedName) {
+      Identifier qualifier = identifier.qualifier as Identifier;
+      prefix = qualifier.name;
+      suffix = identifier.name;
+      charOffset = qualifier.nameOffset;
+    } else {
+      prefix = identifier.name;
+      suffix = null;
+      charOffset = identifier.nameOffset;
+    }
+    if (libraryFeatures.constructorTearoffs.isEnabled) {
+      suffix = suffix == "new" ? "" : suffix;
+    }
+    if (prefix == className) {
+      return suffix ?? "";
+    }
+    if (suffix == null && !isFactory) {
+      // A legal name for a regular method, but not for a constructor.
+      return null;
+    }
+
+    addProblem(
+        messageConstructorWithWrongName, charOffset, prefix.length, fileUri,
+        context: [
+          templateConstructorWithWrongNameContext
+              .withArguments(currentTypeParameterScopeBuilder.name)
+              .withLocation(
+                  importUri,
+                  currentTypeParameterScopeBuilder.charOffset,
+                  currentTypeParameterScopeBuilder.name.length)
+        ]);
+
+    return suffix;
+  }
+
+  @override
+  ConstructorReferenceBuilder addConstructorReference(TypeName name,
+      List<TypeBuilder>? typeArguments, String? suffix, int charOffset) {
+    ConstructorReferenceBuilder ref = new ConstructorReferenceBuilder(
+        name, typeArguments, suffix, fileUri, charOffset);
+    constructorReferences.add(ref);
+    return ref;
+  }
+
+  @override
+  void addProcedure(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      TypeBuilder? returnType,
+      Identifier identifier,
+      String name,
+      List<NominalVariableBuilder>? typeVariables,
+      List<FormalParameterBuilder>? formals,
+      ProcedureKind kind,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      String? nativeMethodName,
+      AsyncMarker asyncModifier,
+      {required bool isInstanceMember,
+      required bool isExtensionMember,
+      required bool isExtensionTypeMember}) {
+    assert(!isExtensionMember ||
+        currentTypeParameterScopeBuilder.kind ==
+            TypeParameterScopeKind.extensionDeclaration);
+    assert(!isExtensionTypeMember ||
+        currentTypeParameterScopeBuilder.kind ==
+            TypeParameterScopeKind.extensionTypeDeclaration);
+    ContainerType containerType =
+        currentTypeParameterScopeBuilder.containerType;
+    ContainerName? containerName =
+        currentTypeParameterScopeBuilder.containerName;
+    NameScheme nameScheme = new NameScheme(
+        containerName: containerName,
+        containerType: containerType,
+        isInstanceMember: isInstanceMember,
+        libraryName: indexedLibrary != null
+            ? new LibraryName(indexedLibrary!.library.reference)
+            : libraryName);
+
+    if (returnType == null) {
+      if (kind == ProcedureKind.Operator &&
+          identical(name, indexSetName.text)) {
+        returnType = addVoidType(charOffset);
+      } else if (kind == ProcedureKind.Setter) {
+        returnType = addVoidType(charOffset);
+      }
+    }
+    Reference? procedureReference;
+    Reference? tearOffReference;
+    IndexedContainer? indexedContainer =
+        _indexedContainer ?? _sourceLibraryBuilder.indexedLibrary;
+
+    bool isAugmentation = isAugmenting && (modifiers & augmentMask) != 0;
+    if (indexedContainer != null && !isAugmentation) {
+      Name nameToLookup = nameScheme.getProcedureMemberName(kind, name).name;
+      if (kind == ProcedureKind.Setter) {
+        if ((isExtensionMember || isExtensionTypeMember) && isInstanceMember) {
+          // Extension (type) instance setters are encoded as methods.
+          procedureReference =
+              indexedContainer.lookupGetterReference(nameToLookup);
+        } else {
+          procedureReference =
+              indexedContainer.lookupSetterReference(nameToLookup);
+        }
+      } else {
+        procedureReference =
+            indexedContainer.lookupGetterReference(nameToLookup);
+        if ((isExtensionMember || isExtensionTypeMember) &&
+            kind == ProcedureKind.Method) {
+          tearOffReference = indexedContainer.lookupGetterReference(nameScheme
+              .getProcedureMemberName(ProcedureKind.Getter, name)
+              .name);
+        }
+      }
+    }
+    SourceProcedureBuilder procedureBuilder = new SourceProcedureBuilder(
+        metadata,
+        modifiers,
+        returnType ?? addInferableType(),
+        name,
+        typeVariables,
+        formals,
+        kind,
+        _sourceLibraryBuilder,
+        startCharOffset,
+        charOffset,
+        charOpenParenOffset,
+        charEndOffset,
+        procedureReference,
+        tearOffReference,
+        asyncModifier,
+        nameScheme,
+        nativeMethodName: nativeMethodName);
+    _checkTypeVariables(typeVariables, procedureBuilder);
+    _sourceLibraryBuilder.addBuilder(name, procedureBuilder, charOffset,
+        getterReference: procedureReference);
+    if (nativeMethodName != null) {
+      _addNativeMethod(procedureBuilder);
+    }
+    offsetMap.registerProcedure(identifier, procedureBuilder);
+  }
+
+  @override
+  void addFields(
+      OffsetMap offsetMap,
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      bool isTopLevel,
+      TypeBuilder? type,
+      List<FieldInfo> fieldInfos) {
+    for (FieldInfo info in fieldInfos) {
+      bool isConst = modifiers & constMask != 0;
+      bool isFinal = modifiers & finalMask != 0;
+      bool potentiallyNeedInitializerInOutline = isConst || isFinal;
+      Token? startToken;
+      if (potentiallyNeedInitializerInOutline || type == null) {
+        startToken = info.initializerToken;
+      }
+      if (startToken != null) {
+        // Extract only the tokens for the initializer expression from the
+        // token stream.
+        Token endToken = info.beforeLast!;
+        endToken.setNext(new Token.eof(endToken.next!.offset));
+        new Token.eof(startToken.previous!.offset).setNext(startToken);
+      }
+      bool hasInitializer = info.initializerToken != null;
+      offsetMap.registerField(
+          info.identifier,
+          _addField(
+              metadata,
+              modifiers,
+              isTopLevel,
+              type ?? addInferableType(),
+              info.identifier.name,
+              info.identifier.nameOffset,
+              info.charEndOffset,
+              startToken,
+              hasInitializer,
+              constInitializerToken:
+                  potentiallyNeedInitializerInOutline ? startToken : null));
+    }
+  }
+
+  SourceFieldBuilder _addField(
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      bool isTopLevel,
+      TypeBuilder type,
+      String name,
+      int charOffset,
+      int charEndOffset,
+      Token? initializerToken,
+      bool hasInitializer,
+      {Token? constInitializerToken}) {
+    if (hasInitializer) {
+      modifiers |= hasInitializerMask;
+    }
+    bool isLate = (modifiers & lateMask) != 0;
+    bool isFinal = (modifiers & finalMask) != 0;
+    bool isStatic = (modifiers & staticMask) != 0;
+    bool isExternal = (modifiers & externalMask) != 0;
+    final bool fieldIsLateWithLowering = isLate &&
+        (loader.target.backendTarget.isLateFieldLoweringEnabled(
+                hasInitializer: hasInitializer,
+                isFinal: isFinal,
+                isStatic: isTopLevel || isStatic) ||
+            (loader.target.backendTarget.useStaticFieldLowering &&
+                (isStatic || isTopLevel)));
+
+    final bool isInstanceMember = currentTypeParameterScopeBuilder.kind !=
+            TypeParameterScopeKind.library &&
+        (modifiers & staticMask) == 0;
+    final bool isExtensionMember = currentTypeParameterScopeBuilder.kind ==
+        TypeParameterScopeKind.extensionDeclaration;
+    final bool isExtensionTypeMember = currentTypeParameterScopeBuilder.kind ==
+        TypeParameterScopeKind.extensionTypeDeclaration;
+    ContainerType containerType =
+        currentTypeParameterScopeBuilder.containerType;
+    ContainerName? containerName =
+        currentTypeParameterScopeBuilder.containerName;
+
+    Reference? fieldReference;
+    Reference? fieldGetterReference;
+    Reference? fieldSetterReference;
+    Reference? lateIsSetFieldReference;
+    Reference? lateIsSetGetterReference;
+    Reference? lateIsSetSetterReference;
+    Reference? lateGetterReference;
+    Reference? lateSetterReference;
+
+    NameScheme nameScheme = new NameScheme(
+        isInstanceMember: isInstanceMember,
+        containerName: containerName,
+        containerType: containerType,
+        libraryName: _sourceLibraryBuilder.indexedLibrary != null
+            ? new LibraryName(_sourceLibraryBuilder.indexedLibrary!.reference)
+            : libraryName);
+    IndexedContainer? indexedContainer =
+        _indexedContainer ?? _sourceLibraryBuilder.indexedLibrary;
+    if (indexedContainer != null) {
+      if ((isExtensionMember || isExtensionTypeMember) &&
+          isInstanceMember &&
+          isExternal) {
+        /// An external extension (type) instance field is special. It is
+        /// treated as an external getter/setter pair and is therefore encoded
+        /// as a pair of top level methods using the extension instance member
+        /// naming convention.
+        fieldGetterReference = indexedContainer.lookupGetterReference(
+            nameScheme.getProcedureMemberName(ProcedureKind.Getter, name).name);
+        fieldSetterReference = indexedContainer.lookupGetterReference(
+            nameScheme.getProcedureMemberName(ProcedureKind.Setter, name).name);
+      } else if (isExtensionTypeMember && isInstanceMember) {
+        Name nameToLookup = nameScheme
+            .getFieldMemberName(FieldNameType.RepresentationField, name,
+                isSynthesized: true)
+            .name;
+        fieldGetterReference =
+            indexedContainer.lookupGetterReference(nameToLookup);
+      } else {
+        Name nameToLookup = nameScheme
+            .getFieldMemberName(FieldNameType.Field, name,
+                isSynthesized: fieldIsLateWithLowering)
+            .name;
+        fieldReference = indexedContainer.lookupFieldReference(nameToLookup);
+        fieldGetterReference =
+            indexedContainer.lookupGetterReference(nameToLookup);
+        fieldSetterReference =
+            indexedContainer.lookupSetterReference(nameToLookup);
+      }
+
+      if (fieldIsLateWithLowering) {
+        Name lateIsSetName = nameScheme
+            .getFieldMemberName(FieldNameType.IsSetField, name,
+                isSynthesized: fieldIsLateWithLowering)
+            .name;
+        lateIsSetFieldReference =
+            indexedContainer.lookupFieldReference(lateIsSetName);
+        lateIsSetGetterReference =
+            indexedContainer.lookupGetterReference(lateIsSetName);
+        lateIsSetSetterReference =
+            indexedContainer.lookupSetterReference(lateIsSetName);
+        lateGetterReference = indexedContainer.lookupGetterReference(nameScheme
+            .getFieldMemberName(FieldNameType.Getter, name,
+                isSynthesized: fieldIsLateWithLowering)
+            .name);
+        lateSetterReference = indexedContainer.lookupSetterReference(nameScheme
+            .getFieldMemberName(FieldNameType.Setter, name,
+                isSynthesized: fieldIsLateWithLowering)
+            .name);
+      }
+    }
+
+    SourceFieldBuilder fieldBuilder = new SourceFieldBuilder(
+        metadata,
+        type,
+        name,
+        modifiers,
+        isTopLevel,
+        _sourceLibraryBuilder,
+        charOffset,
+        charEndOffset,
+        nameScheme,
+        fieldReference: fieldReference,
+        fieldGetterReference: fieldGetterReference,
+        fieldSetterReference: fieldSetterReference,
+        lateIsSetFieldReference: lateIsSetFieldReference,
+        lateIsSetGetterReference: lateIsSetGetterReference,
+        lateIsSetSetterReference: lateIsSetSetterReference,
+        lateGetterReference: lateGetterReference,
+        lateSetterReference: lateSetterReference,
+        initializerToken: initializerToken,
+        constInitializerToken: constInitializerToken);
+    _sourceLibraryBuilder.addBuilder(name, fieldBuilder, charOffset,
+        getterReference: fieldGetterReference,
+        setterReference: fieldSetterReference);
+    return fieldBuilder;
+  }
+
+  @override
+  FormalParameterBuilder addFormalParameter(
+      List<MetadataBuilder>? metadata,
+      FormalParameterKind kind,
+      int modifiers,
+      TypeBuilder type,
+      String name,
+      bool hasThis,
+      bool hasSuper,
+      int charOffset,
+      Token? initializerToken) {
+    assert(!hasThis || !hasSuper,
+        "Formal parameter '${name}' has both 'this' and 'super' prefixes.");
+    if (hasThis) {
+      modifiers |= initializingFormalMask;
+    }
+    if (hasSuper) {
+      modifiers |= superInitializingFormalMask;
+    }
+    FormalParameterBuilder formal = new FormalParameterBuilder(
+        kind, modifiers, type, name, _sourceLibraryBuilder, charOffset,
+        fileUri: fileUri,
+        hasImmediatelyDeclaredInitializer: initializerToken != null)
+      ..initializerToken = initializerToken;
+    return formal;
+  }
+
+  @override
+  TypeBuilder addNamedType(
+      TypeName typeName,
+      NullabilityBuilder nullabilityBuilder,
+      List<TypeBuilder>? arguments,
+      int charOffset,
+      {required InstanceTypeVariableAccessState instanceTypeVariableAccess}) {
+    if (_sourceLibraryBuilder._omittedTypeDeclarationBuilders != null) {
+      Builder? builder =
+          _sourceLibraryBuilder._omittedTypeDeclarationBuilders[typeName.name];
+      if (builder is OmittedTypeDeclarationBuilder) {
+        return new DependentTypeBuilder(builder.omittedTypeBuilder);
+      }
+    }
+    return _registerUnresolvedNamedType(new NamedTypeBuilderImpl(
+        typeName, nullabilityBuilder,
+        arguments: arguments,
+        fileUri: fileUri,
+        charOffset: charOffset,
+        instanceTypeVariableAccess: instanceTypeVariableAccess));
+  }
+
+  NamedTypeBuilder _registerUnresolvedNamedType(NamedTypeBuilder type) {
+    currentTypeParameterScopeBuilder.registerUnresolvedNamedType(type);
+    return type;
+  }
+
+  @override
+  FunctionTypeBuilder addFunctionType(
+      TypeBuilder returnType,
+      List<StructuralVariableBuilder>? structuralVariableBuilders,
+      List<FormalParameterBuilder>? formals,
+      NullabilityBuilder nullabilityBuilder,
+      Uri fileUri,
+      int charOffset,
+      {required bool hasFunctionFormalParameterSyntax}) {
+    FunctionTypeBuilder builder = new FunctionTypeBuilderImpl(
+        returnType,
+        structuralVariableBuilders,
+        formals,
+        nullabilityBuilder,
+        fileUri,
+        charOffset,
+        hasFunctionFormalParameterSyntax: hasFunctionFormalParameterSyntax);
+    _checkStructuralVariables(structuralVariableBuilders, null);
+    if (structuralVariableBuilders != null) {
+      for (StructuralVariableBuilder builder in structuralVariableBuilders) {
+        if (builder.metadata != null) {
+          if (!libraryFeatures.genericMetadata.isEnabled) {
+            addProblem(messageAnnotationOnFunctionTypeTypeVariable,
+                builder.charOffset, builder.name.length, builder.fileUri);
+          }
+        }
+      }
+    }
+    // Nested declaration began in `OutlineBuilder.beginFunctionType` or
+    // `OutlineBuilder.beginFunctionTypedFormalParameter`.
+    endNestedDeclaration(TypeParameterScopeKind.functionType, "#function_type")
+        .resolveNamedTypesWithStructuralVariables(
+            structuralVariableBuilders, _sourceLibraryBuilder);
+    return builder;
+  }
+
+  Map<String, StructuralVariableBuilder>? _checkStructuralVariables(
+      List<StructuralVariableBuilder>? typeVariables, Builder? owner) {
+    if (typeVariables == null || typeVariables.isEmpty) return null;
+    Map<String, StructuralVariableBuilder> typeVariablesByName =
+        <String, StructuralVariableBuilder>{};
+    for (StructuralVariableBuilder tv in typeVariables) {
+      StructuralVariableBuilder? existing = typeVariablesByName[tv.name];
+      if (existing != null) {
+        addProblem(messageTypeVariableDuplicatedName, tv.charOffset,
+            tv.name.length, fileUri,
+            context: [
+              templateTypeVariableDuplicatedNameCause
+                  .withArguments(tv.name)
+                  .withLocation(
+                      fileUri, existing.charOffset, existing.name.length)
+            ]);
+      } else {
+        typeVariablesByName[tv.name] = tv;
+        if (owner is ClassBuilder) {
+          // Only classes and type variables can't have the same name. See
+          // [#29555](https://github.com/dart-lang/sdk/issues/29555).
+          if (tv.name == owner.name) {
+            addProblem(messageTypeVariableSameNameAsEnclosing, tv.charOffset,
+                tv.name.length, fileUri);
+          }
+        }
+      }
+    }
+    return typeVariablesByName;
+  }
+
+  @override
+  TypeBuilder addVoidType(int charOffset) {
+    // 'void' is always nullable.
+    return new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
+        new VoidTypeDeclarationBuilder(
+            const VoidType(), _sourceLibraryBuilder, charOffset),
+        const NullabilityBuilder.inherent(),
+        charOffset: charOffset,
+        fileUri: fileUri,
+        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
+  }
+
+  @override
+  NominalVariableBuilder addNominalTypeVariable(List<MetadataBuilder>? metadata,
+      String name, TypeBuilder? bound, int charOffset, Uri fileUri,
+      {required TypeVariableKind kind}) {
+    NominalVariableBuilder builder = new NominalVariableBuilder(
+        name, _sourceLibraryBuilder, charOffset, fileUri,
+        bound: bound, metadata: metadata, kind: kind);
+
+    unboundNominalVariables.add(builder);
+    return builder;
+  }
+
+  @override
+  StructuralVariableBuilder addStructuralTypeVariable(
+      List<MetadataBuilder>? metadata,
+      String name,
+      TypeBuilder? bound,
+      int charOffset,
+      Uri fileUri) {
+    StructuralVariableBuilder builder = new StructuralVariableBuilder(
+        name, _sourceLibraryBuilder, charOffset, fileUri,
+        bound: bound, metadata: metadata);
+
+    unboundStructuralVariables.add(builder);
+    return builder;
+  }
+
+  Map<String, NominalVariableBuilder>? _checkTypeVariables(
+      List<NominalVariableBuilder>? typeVariables, Builder? owner) {
+    if (typeVariables == null || typeVariables.isEmpty) return null;
+    Map<String, NominalVariableBuilder> typeVariablesByName =
+        <String, NominalVariableBuilder>{};
+    for (NominalVariableBuilder tv in typeVariables) {
+      NominalVariableBuilder? existing = typeVariablesByName[tv.name];
+      if (existing != null) {
+        if (existing.kind == TypeVariableKind.extensionSynthesized) {
+          // The type parameter from the extension is shadowed by the type
+          // parameter from the member. Rename the shadowed type parameter.
+          existing.parameter.name = '#${existing.name}';
+          typeVariablesByName[tv.name] = tv;
+        } else {
+          addProblem(messageTypeVariableDuplicatedName, tv.charOffset,
+              tv.name.length, fileUri,
+              context: [
+                templateTypeVariableDuplicatedNameCause
+                    .withArguments(tv.name)
+                    .withLocation(
+                        fileUri, existing.charOffset, existing.name.length)
+              ]);
+        }
+      } else {
+        typeVariablesByName[tv.name] = tv;
+        if (owner is TypeDeclarationBuilder) {
+          // Only classes and extension types and type variables can't have the
+          // same name. See
+          // [#29555](https://github.com/dart-lang/sdk/issues/29555) and
+          // [#54602](https://github.com/dart-lang/sdk/issues/54602).
+          switch (owner) {
+            case ClassBuilder():
+            case ExtensionBuilder():
+            case ExtensionTypeDeclarationBuilder():
+              if (tv.name == owner.name) {
+                addProblem(messageTypeVariableSameNameAsEnclosing,
+                    tv.charOffset, tv.name.length, fileUri);
+              }
+            case TypeAliasBuilder():
+            case NominalVariableBuilder():
+            case StructuralVariableBuilder():
+            case InvalidTypeDeclarationBuilder():
+            case BuiltinTypeDeclarationBuilder():
+            // TODO(johnniwinther): How should we handle this case?
+            case OmittedTypeDeclarationBuilder():
+          }
+        }
+      }
+    }
+    return typeVariablesByName;
+  }
+
+  @override
+  List<NominalVariableBuilder> copyTypeVariables(
+      List<NominalVariableBuilder> original,
+      TypeParameterScopeBuilder declaration,
+      {required TypeVariableKind kind}) {
+    List<NamedTypeBuilder> newTypes = <NamedTypeBuilder>[];
+    List<NominalVariableBuilder> copy = <NominalVariableBuilder>[];
+    for (NominalVariableBuilder variable in original) {
+      NominalVariableBuilder newVariable = new NominalVariableBuilder(
+          variable.name,
+          _sourceLibraryBuilder,
+          variable.charOffset,
+          variable.fileUri,
+          bound: variable.bound
+              ?.clone(newTypes, _sourceLibraryBuilder, declaration),
+          kind: kind,
+          variableVariance:
+              variable.parameter.isLegacyCovariant ? null : variable.variance);
+      copy.add(newVariable);
+      unboundNominalVariables.add(newVariable);
+    }
+    for (NamedTypeBuilder newType in newTypes) {
+      declaration.registerUnresolvedNamedType(newType);
+    }
+    return copy;
+  }
+
+  @override
+  List<MetadataBuilder>? get metadata => _sourceLibraryBuilder.metadata;
+
+  @override
+  void set metadata(List<MetadataBuilder>? value) {
+    _sourceLibraryBuilder.metadata = value;
+  }
+
+  @override
+  String? get name => _sourceLibraryBuilder.name;
+
+  @override
+  void set name(String? value) {
+    _sourceLibraryBuilder.name = value;
+  }
+
+  @override
+  InferableTypeBuilder addInferableType() {
+    return _sourceLibraryBuilder.addInferableType();
+  }
+
+  @override
+  Message reportFeatureNotEnabled(
+      LibraryFeature feature, Uri fileUri, int charOffset, int length) {
+    return _sourceLibraryBuilder.reportFeatureNotEnabled(
+        feature, fileUri, charOffset, length);
+  }
 }
 
 class SourceLibraryBuilder extends LibraryBuilderImpl {
@@ -285,12 +2364,7 @@
   @override
   final SourceLoader loader;
 
-  /// Map used to find objects created in the [OutlineBuilder] from within
-  /// the [DietListener].
-  ///
-  /// This is meant to be written once and read once.
-  OffsetMap? _offsetMap;
-
+  // TODO(johnniwinther): Move this to [SourceCompilationUnitImpl].
   final TypeParameterScopeBuilder _libraryTypeParameterScopeBuilder;
 
   final List<ConstructorReferenceBuilder> constructorReferences =
@@ -326,15 +2400,13 @@
   @override
   LibraryBuilder? partOfLibrary;
 
-  /// Offset of the first script tag (`#!...`) in this library or part.
-  int? _scriptTokenOffset;
-
   List<MetadataBuilder>? metadata;
 
   /// The current declaration that is being built. When we start parsing a
   /// declaration (class, method, and so on), we don't have enough information
   /// to create a builder and this object records its members and types until,
   /// for example, [addClass] is called.
+  // TODO(johnniwinther): Move this to [SourceCompilationUnitImpl].
   TypeParameterScopeBuilder currentTypeParameterScopeBuilder;
 
   /// Non-null if this library causes an error upon access, that is, there was
@@ -381,12 +2453,9 @@
   final LibraryBuilder? _nameOrigin;
 
   /// Index of the library we use references for.
+  // TODO(johnniwinther): Move this to [SourceCompilationUnitImpl].
   final IndexedLibrary? indexedLibrary;
 
-  // TODO(johnniwinther): Use [_indexedContainer] for library members and make
-  // it [null] when there is null corresponding [IndexedContainer].
-  IndexedContainer? _indexedContainer;
-
   /// Exports that can't be serialized.
   ///
   /// The key is the name of the exported member.
@@ -437,6 +2506,7 @@
   ///
   /// This is used in macro generated code to create type annotations from
   /// inferred types in the original code.
+  // TODO(johnniwinther): Move to [SourceCompilationUnitImpl].
   final Map<String, Builder>? _omittedTypeDeclarationBuilders;
 
   MergedLibraryScope? _mergedScope;
@@ -520,24 +2590,6 @@
         "'${importUri}'.");
   }
 
-  /// Returns the map of objects created in the [OutlineBuilder].
-  ///
-  /// This should only be called once.
-  OffsetMap get offsetMap {
-    assert(_offsetMap != null, "No OffsetMap for $this");
-    OffsetMap map = _offsetMap!;
-    _offsetMap = null;
-    return map;
-  }
-
-  /// Registers the map of objects created in the [OutlineBuilder].
-  ///
-  /// This should only be called once.
-  void set offsetMap(OffsetMap value) {
-    assert(_offsetMap == null, "OffsetMap has already been set for $this");
-    _offsetMap = value;
-  }
-
   MergedLibraryScope get mergedScope {
     return _mergedScope ??=
         isAugmenting ? origin.mergedScope : new MergedLibraryScope(this);
@@ -723,7 +2775,8 @@
         referencesFromIndex: indexedLibrary,
         omittedTypes: omittedTypeDeclarationBuilders);
     addAugmentationLibrary(augmentationLibrary);
-    loader.registerUnparsedLibrarySource(augmentationLibrary, source);
+    loader.registerUnparsedLibrarySource(
+        augmentationLibrary.compilationUnit, source);
     return augmentationLibrary;
   }
 
@@ -733,11 +2786,6 @@
   @override
   bool get isSynthetic => accessProblem != null;
 
-  NamedTypeBuilder registerUnresolvedNamedType(NamedTypeBuilder type) {
-    currentTypeParameterScopeBuilder.registerUnresolvedNamedType(type);
-    return type;
-  }
-
   bool get isInferenceUpdate1Enabled =>
       libraryFeatures.inferenceUpdate1.isSupported &&
       languageVersion.version >=
@@ -805,42 +2853,9 @@
     _languageVersion.isFinal = true;
   }
 
-  ConstructorReferenceBuilder addConstructorReference(TypeName name,
-      List<TypeBuilder>? typeArguments, String? suffix, int charOffset) {
-    ConstructorReferenceBuilder ref = new ConstructorReferenceBuilder(
-        name, typeArguments, suffix, fileUri, charOffset);
-    constructorReferences.add(ref);
-    return ref;
-  }
-
-  void beginNestedDeclaration(TypeParameterScopeKind kind, String name,
-      {bool hasMembers = true}) {
-    currentTypeParameterScopeBuilder =
-        currentTypeParameterScopeBuilder.createNested(kind, name, hasMembers);
-  }
-
-  TypeParameterScopeBuilder endNestedDeclaration(
-      TypeParameterScopeKind kind, String? name) {
-    assert(
-        currentTypeParameterScopeBuilder.kind == kind,
-        "Unexpected declaration. "
-        "Trying to end a ${currentTypeParameterScopeBuilder.kind} as a $kind.");
-    assert(
-        (name?.startsWith(currentTypeParameterScopeBuilder.name) ??
-                (name == currentTypeParameterScopeBuilder.name)) ||
-            currentTypeParameterScopeBuilder.name == "operator" ||
-            (name == null &&
-                currentTypeParameterScopeBuilder.name ==
-                    UnnamedExtensionName.unnamedExtensionSentinel) ||
-            identical(name, "<syntax-error>"),
-        "${name} != ${currentTypeParameterScopeBuilder.name}");
-    TypeParameterScopeBuilder previous = currentTypeParameterScopeBuilder;
-    currentTypeParameterScopeBuilder = currentTypeParameterScopeBuilder.parent!;
-    return previous;
-  }
-
   bool uriIsValid(Uri uri) => !uri.isScheme(MALFORMED_URI_SCHEME);
 
+  // TODO(johnniwinther): Move this to [SourceCompilationUnitImpl].
   Uri resolve(Uri baseUri, String? uri, int uriOffset, {isPart = false}) {
     if (uri == null) {
       addProblem(messageExpectedUri, uriOffset, noLength, fileUri);
@@ -866,47 +2881,6 @@
     }
   }
 
-  String? computeAndValidateConstructorName(Identifier identifier,
-      {isFactory = false}) {
-    String className = currentTypeParameterScopeBuilder.name;
-    String prefix;
-    String? suffix;
-    int charOffset;
-    if (identifier is QualifiedName) {
-      Identifier qualifier = identifier.qualifier as Identifier;
-      prefix = qualifier.name;
-      suffix = identifier.name;
-      charOffset = qualifier.nameOffset;
-    } else {
-      prefix = identifier.name;
-      suffix = null;
-      charOffset = identifier.nameOffset;
-    }
-    if (libraryFeatures.constructorTearoffs.isEnabled) {
-      suffix = suffix == "new" ? "" : suffix;
-    }
-    if (prefix == className) {
-      return suffix ?? "";
-    }
-    if (suffix == null && !isFactory) {
-      // A legal name for a regular method, but not for a constructor.
-      return null;
-    }
-
-    addProblem(
-        messageConstructorWithWrongName, charOffset, prefix.length, fileUri,
-        context: [
-          templateConstructorWithWrongNameContext
-              .withArguments(currentTypeParameterScopeBuilder.name)
-              .withLocation(
-                  importUri,
-                  currentTypeParameterScopeBuilder.charOffset,
-                  currentTypeParameterScopeBuilder.name.length)
-        ]);
-
-    return suffix;
-  }
-
   @override
   Iterable<Uri> get dependencies sync* {
     for (Export export in exports) {
@@ -920,186 +2894,6 @@
     }
   }
 
-  void addExport(
-      OffsetMap offsetMap,
-      Token exportKeyword,
-      List<MetadataBuilder>? metadata,
-      String uri,
-      List<Configuration>? configurations,
-      List<CombinatorBuilder>? combinators,
-      int charOffset,
-      int uriOffset) {
-    if (configurations != null) {
-      for (Configuration config in configurations) {
-        if (loader.getLibrarySupportValue(config.dottedName) ==
-            config.condition) {
-          uri = config.importUri;
-          break;
-        }
-      }
-    }
-
-    CompilationUnit exportedLibrary = loader.read(
-        resolve(this.importUri, uri, uriOffset), charOffset,
-        accessor: compilationUnit);
-    exportedLibrary.addExporter(this, combinators, charOffset);
-    Export export = new Export(this, exportedLibrary, combinators, charOffset);
-    exports.add(export);
-    offsetMap.registerExport(exportKeyword, export);
-  }
-
-  void addImport(
-      {OffsetMap? offsetMap,
-      Token? importKeyword,
-      required List<MetadataBuilder>? metadata,
-      required bool isAugmentationImport,
-      required String uri,
-      required List<Configuration>? configurations,
-      required String? prefix,
-      required List<CombinatorBuilder>? combinators,
-      required bool deferred,
-      required int charOffset,
-      required int prefixCharOffset,
-      required int uriOffset,
-      required int importIndex}) {
-    if (configurations != null) {
-      for (Configuration config in configurations) {
-        if (loader.getLibrarySupportValue(config.dottedName) ==
-            config.condition) {
-          uri = config.importUri;
-          break;
-        }
-      }
-    }
-
-    CompilationUnit? compilationUnit = null;
-    Uri? resolvedUri;
-    String? nativePath;
-    const String nativeExtensionScheme = "dart-ext:";
-    if (uri.startsWith(nativeExtensionScheme)) {
-      addProblem(messageUnsupportedDartExt, charOffset, noLength, fileUri);
-      String strippedUri = uri.substring(nativeExtensionScheme.length);
-      if (strippedUri.startsWith("package")) {
-        resolvedUri = resolve(this.importUri, strippedUri,
-            uriOffset + nativeExtensionScheme.length);
-        resolvedUri = loader.target.translateUri(resolvedUri);
-        nativePath = resolvedUri.toString();
-      } else {
-        resolvedUri = new Uri(scheme: "dart-ext", pathSegments: [uri]);
-        nativePath = uri;
-      }
-    } else {
-      resolvedUri = resolve(this.importUri, uri, uriOffset);
-      compilationUnit = loader.read(resolvedUri, uriOffset,
-          origin: isAugmentationImport ? this : null,
-          accessor: this.compilationUnit,
-          isAugmentation: isAugmentationImport,
-          referencesFromIndex: isAugmentationImport ? indexedLibrary : null);
-    }
-
-    Import import = new Import(
-        this,
-        compilationUnit,
-        isAugmentationImport,
-        deferred,
-        prefix,
-        combinators,
-        configurations,
-        charOffset,
-        prefixCharOffset,
-        importIndex,
-        nativeImportPath: nativePath);
-    imports.add(import);
-    offsetMap?.registerImport(importKeyword!, import);
-  }
-
-  void addPart(OffsetMap offsetMap, Token partKeyword,
-      List<MetadataBuilder>? metadata, String uri, int charOffset) {
-    Uri resolvedUri = resolve(this.importUri, uri, charOffset, isPart: true);
-    // To support absolute paths from within packages in the part uri, we try to
-    // translate the file uri from the resolved import uri before resolving
-    // through the file uri of this library. See issue #52964.
-    Uri newFileUri = loader.target.uriTranslator.translate(resolvedUri) ??
-        resolve(fileUri, uri, charOffset);
-    // TODO(johnniwinther): Add a LibraryPartBuilder instead of using
-    // [LibraryBuilder] to represent both libraries and parts.
-    CompilationUnit compilationUnit = loader.read(resolvedUri, charOffset,
-        origin: isAugmenting ? origin : null,
-        fileUri: newFileUri,
-        accessor: this.compilationUnit,
-        isPatch: isAugmenting);
-    parts.add(new Part(charOffset, compilationUnit));
-
-    // TODO(ahe): [metadata] should be stored, evaluated, and added to [part].
-    LibraryPart part = new LibraryPart(<Expression>[], uri)
-      ..fileOffset = charOffset;
-    library.addPart(part);
-    offsetMap.registerPart(partKeyword, part);
-  }
-
-  void addPartOf(List<MetadataBuilder>? metadata, String? name, String? uri,
-      int uriOffset) {
-    partOfName = name;
-    if (uri != null) {
-      Uri resolvedUri = partOfUri = resolve(this.importUri, uri, uriOffset);
-      // To support absolute paths from within packages in the part of uri, we
-      // try to translate the file uri from the resolved import uri before
-      // resolving through the file uri of this library. See issue #52964.
-      Uri newFileUri = loader.target.uriTranslator.translate(resolvedUri) ??
-          resolve(fileUri, uri, uriOffset);
-      loader.read(partOfUri!, uriOffset,
-          fileUri: newFileUri, accessor: compilationUnit);
-    }
-    if (_scriptTokenOffset != null) {
-      addProblem(
-          messageScriptTagInPartFile, _scriptTokenOffset!, noLength, fileUri);
-    }
-  }
-
-  void addScriptToken(int charOffset) {
-    _scriptTokenOffset ??= charOffset;
-  }
-
-  void addFields(
-      OffsetMap offsetMap,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      bool isTopLevel,
-      TypeBuilder? type,
-      List<FieldInfo> fieldInfos) {
-    for (FieldInfo info in fieldInfos) {
-      bool isConst = modifiers & constMask != 0;
-      bool isFinal = modifiers & finalMask != 0;
-      bool potentiallyNeedInitializerInOutline = isConst || isFinal;
-      Token? startToken;
-      if (potentiallyNeedInitializerInOutline || type == null) {
-        startToken = info.initializerToken;
-      }
-      if (startToken != null) {
-        // Extract only the tokens for the initializer expression from the
-        // token stream.
-        Token endToken = info.beforeLast!;
-        endToken.setNext(new Token.eof(endToken.next!.offset));
-        new Token.eof(startToken.previous!.offset).setNext(startToken);
-      }
-      bool hasInitializer = info.initializerToken != null;
-      offsetMap.registerField(
-          info.identifier,
-          addField(
-              metadata,
-              modifiers,
-              isTopLevel,
-              type ?? addInferableType(),
-              info.identifier.name,
-              info.identifier.nameOffset,
-              info.charEndOffset,
-              startToken,
-              hasInitializer,
-              constInitializerToken:
-                  potentiallyNeedInitializerInOutline ? startToken : null));
-    }
-  }
-
   Builder addBuilder(String name, Builder declaration, int charOffset,
       {Reference? getterReference, Reference? setterReference}) {
     // TODO(ahe): Set the parent correctly here. Could then change the
@@ -2018,41 +3812,6 @@
     _inferableTypes = null;
   }
 
-  TypeBuilder addNamedType(
-      TypeName typeName,
-      NullabilityBuilder nullabilityBuilder,
-      List<TypeBuilder>? arguments,
-      int charOffset,
-      {required InstanceTypeVariableAccessState instanceTypeVariableAccess}) {
-    if (_omittedTypeDeclarationBuilders != null) {
-      Builder? builder = _omittedTypeDeclarationBuilders[typeName.name];
-      if (builder is OmittedTypeDeclarationBuilder) {
-        return new DependentTypeBuilder(builder.omittedTypeBuilder);
-      }
-    }
-    return registerUnresolvedNamedType(new NamedTypeBuilderImpl(
-        typeName, nullabilityBuilder,
-        arguments: arguments,
-        fileUri: fileUri,
-        charOffset: charOffset,
-        instanceTypeVariableAccess: instanceTypeVariableAccess));
-  }
-
-  MixinApplicationBuilder addMixinApplication(
-      List<TypeBuilder> mixins, int charOffset) {
-    return new MixinApplicationBuilder(mixins, fileUri, charOffset);
-  }
-
-  TypeBuilder addVoidType(int charOffset) {
-    // 'void' is always nullable.
-    return new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
-        new VoidTypeDeclarationBuilder(const VoidType(), this, charOffset),
-        const NullabilityBuilder.inherent(),
-        charOffset: charOffset,
-        fileUri: fileUri,
-        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
-  }
-
   /// Add a problem that might not be reported immediately.
   ///
   /// Problems will be issued after source information has been added.
@@ -2110,303 +3869,6 @@
     factory.setRedirectingFactoryError(text);
   }
 
-  void addClass(
-      OffsetMap offsetMap,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      Identifier identifier,
-      List<NominalVariableBuilder>? typeVariables,
-      TypeBuilder? supertype,
-      MixinApplicationBuilder? mixins,
-      List<TypeBuilder>? interfaces,
-      int startOffset,
-      int nameOffset,
-      int endOffset,
-      int supertypeOffset,
-      {required bool isMacro,
-      required bool isSealed,
-      required bool isBase,
-      required bool isInterface,
-      required bool isFinal,
-      required bool isAugmentation,
-      required bool isMixinClass}) {
-    _addClass(
-        offsetMap,
-        TypeParameterScopeKind.classDeclaration,
-        metadata,
-        modifiers,
-        identifier,
-        typeVariables,
-        supertype,
-        mixins,
-        interfaces,
-        startOffset,
-        nameOffset,
-        endOffset,
-        supertypeOffset,
-        isMacro: isMacro,
-        isSealed: isSealed,
-        isBase: isBase,
-        isInterface: isInterface,
-        isFinal: isFinal,
-        isAugmentation: isAugmentation,
-        isMixinClass: isMixinClass);
-  }
-
-  void addMixinDeclaration(
-      OffsetMap offsetMap,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      Identifier identifier,
-      List<NominalVariableBuilder>? typeVariables,
-      List<TypeBuilder>? supertypeConstraints,
-      List<TypeBuilder>? interfaces,
-      int startOffset,
-      int nameOffset,
-      int endOffset,
-      int supertypeOffset,
-      {required bool isBase,
-      required bool isAugmentation}) {
-    TypeBuilder? supertype;
-    MixinApplicationBuilder? mixinApplication;
-    if (supertypeConstraints != null && supertypeConstraints.isNotEmpty) {
-      supertype = supertypeConstraints.first;
-      if (supertypeConstraints.length > 1) {
-        mixinApplication = new MixinApplicationBuilder(
-            supertypeConstraints.skip(1).toList(),
-            supertype.fileUri!,
-            supertype.charOffset!);
-      }
-    }
-    _addClass(
-        offsetMap,
-        TypeParameterScopeKind.mixinDeclaration,
-        metadata,
-        modifiers,
-        identifier,
-        typeVariables,
-        supertype,
-        mixinApplication,
-        interfaces,
-        startOffset,
-        nameOffset,
-        endOffset,
-        supertypeOffset,
-        isMacro: false,
-        isSealed: false,
-        isBase: isBase,
-        isInterface: false,
-        isFinal: false,
-        isAugmentation: isAugmentation,
-        isMixinClass: false);
-  }
-
-  void _addClass(
-      OffsetMap offsetMap,
-      TypeParameterScopeKind kind,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      Identifier identifier,
-      List<NominalVariableBuilder>? typeVariables,
-      TypeBuilder? supertype,
-      MixinApplicationBuilder? mixins,
-      List<TypeBuilder>? interfaces,
-      int startOffset,
-      int nameOffset,
-      int endOffset,
-      int supertypeOffset,
-      {required bool isMacro,
-      required bool isSealed,
-      required bool isBase,
-      required bool isInterface,
-      required bool isFinal,
-      required bool isAugmentation,
-      required bool isMixinClass}) {
-    String className = identifier.name;
-    // Nested declaration began in `OutlineBuilder.beginClassDeclaration`.
-    TypeParameterScopeBuilder declaration =
-        endNestedDeclaration(kind, className)
-          ..resolveNamedTypes(typeVariables, this);
-    assert(declaration.parent == _libraryTypeParameterScopeBuilder);
-    Map<String, Builder> members = declaration.members!;
-    Map<String, MemberBuilder> constructors = declaration.constructors!;
-    Map<String, MemberBuilder> setters = declaration.setters!;
-
-    Scope classScope = new Scope(
-        kind: ScopeKind.declaration,
-        local: members,
-        setters: setters,
-        parent: scope.withTypeVariables(typeVariables),
-        debugName: "class $className",
-        isModifiable: false);
-
-    // When looking up a constructor, we don't consider type variables or the
-    // library scope.
-    ConstructorScope constructorScope =
-        new ConstructorScope(className, constructors);
-    bool isMixinDeclaration = false;
-    if (modifiers & mixinDeclarationMask != 0) {
-      isMixinDeclaration = true;
-      modifiers = (modifiers & ~mixinDeclarationMask) | abstractMask;
-    }
-    if (declaration.declaresConstConstructor) {
-      modifiers |= declaresConstConstructorMask;
-    }
-    SourceClassBuilder classBuilder = new SourceClassBuilder(
-        metadata,
-        modifiers,
-        className,
-        typeVariables,
-        _applyMixins(supertype, mixins, startOffset, nameOffset, endOffset,
-            className, isMixinDeclaration,
-            typeVariables: typeVariables,
-            isMacro: false,
-            isSealed: false,
-            isBase: false,
-            isInterface: false,
-            isFinal: false,
-            // TODO(johnniwinther): How can we support class with mixins?
-            isAugmentation: false,
-            isMixinClass: false),
-        interfaces,
-        // TODO(johnniwinther): Add the `on` clause types of a mixin declaration
-        // here.
-        null,
-        classScope,
-        constructorScope,
-        this,
-        new List<ConstructorReferenceBuilder>.of(constructorReferences),
-        startOffset,
-        nameOffset,
-        endOffset,
-        _indexedContainer,
-        isMixinDeclaration: isMixinDeclaration,
-        isMacro: isMacro,
-        isSealed: isSealed,
-        isBase: isBase,
-        isInterface: isInterface,
-        isFinal: isFinal,
-        isAugmentation: isAugmentation,
-        isMixinClass: isMixinClass);
-
-    constructorReferences.clear();
-    Map<String, NominalVariableBuilder>? typeVariablesByName =
-        checkTypeVariables(typeVariables, classBuilder);
-    void setParent(MemberBuilder? member) {
-      while (member != null) {
-        member.parent = classBuilder;
-        member = member.next as MemberBuilder?;
-      }
-    }
-
-    void setParentAndCheckConflicts(String name, Builder member) {
-      if (typeVariablesByName != null) {
-        NominalVariableBuilder? tv = typeVariablesByName[name];
-        if (tv != null) {
-          classBuilder.addProblem(
-              templateConflictsWithTypeVariable.withArguments(name),
-              member.charOffset,
-              name.length,
-              context: [
-                messageConflictsWithTypeVariableCause.withLocation(
-                    tv.fileUri!, tv.charOffset, name.length)
-              ]);
-        }
-      }
-      setParent(member as MemberBuilder);
-    }
-
-    members.forEach(setParentAndCheckConflicts);
-    constructors.forEach(setParentAndCheckConflicts);
-    setters.forEach(setParentAndCheckConflicts);
-    addBuilder(className, classBuilder, nameOffset,
-        getterReference: _indexedContainer?.reference);
-    offsetMap.registerNamedDeclaration(identifier, classBuilder);
-  }
-
-  Map<String, NominalVariableBuilder>? checkTypeVariables(
-      List<NominalVariableBuilder>? typeVariables, Builder? owner) {
-    if (typeVariables == null || typeVariables.isEmpty) return null;
-    Map<String, NominalVariableBuilder> typeVariablesByName =
-        <String, NominalVariableBuilder>{};
-    for (NominalVariableBuilder tv in typeVariables) {
-      NominalVariableBuilder? existing = typeVariablesByName[tv.name];
-      if (existing != null) {
-        if (existing.kind == TypeVariableKind.extensionSynthesized) {
-          // The type parameter from the extension is shadowed by the type
-          // parameter from the member. Rename the shadowed type parameter.
-          existing.parameter.name = '#${existing.name}';
-          typeVariablesByName[tv.name] = tv;
-        } else {
-          addProblem(messageTypeVariableDuplicatedName, tv.charOffset,
-              tv.name.length, fileUri,
-              context: [
-                templateTypeVariableDuplicatedNameCause
-                    .withArguments(tv.name)
-                    .withLocation(
-                        fileUri, existing.charOffset, existing.name.length)
-              ]);
-        }
-      } else {
-        typeVariablesByName[tv.name] = tv;
-        if (owner is TypeDeclarationBuilder) {
-          // Only classes and extension types and type variables can't have the
-          // same name. See
-          // [#29555](https://github.com/dart-lang/sdk/issues/29555) and
-          // [#54602](https://github.com/dart-lang/sdk/issues/54602).
-          switch (owner) {
-            case ClassBuilder():
-            case ExtensionBuilder():
-            case ExtensionTypeDeclarationBuilder():
-              if (tv.name == owner.name) {
-                addProblem(messageTypeVariableSameNameAsEnclosing,
-                    tv.charOffset, tv.name.length, fileUri);
-              }
-            case TypeAliasBuilder():
-            case NominalVariableBuilder():
-            case StructuralVariableBuilder():
-            case InvalidTypeDeclarationBuilder():
-            case BuiltinTypeDeclarationBuilder():
-            // TODO(johnniwinther): How should we handle this case?
-            case OmittedTypeDeclarationBuilder():
-          }
-        }
-      }
-    }
-    return typeVariablesByName;
-  }
-
-  Map<String, StructuralVariableBuilder>? checkStructuralVariables(
-      List<StructuralVariableBuilder>? typeVariables, Builder? owner) {
-    if (typeVariables == null || typeVariables.isEmpty) return null;
-    Map<String, StructuralVariableBuilder> typeVariablesByName =
-        <String, StructuralVariableBuilder>{};
-    for (StructuralVariableBuilder tv in typeVariables) {
-      StructuralVariableBuilder? existing = typeVariablesByName[tv.name];
-      if (existing != null) {
-        addProblem(messageTypeVariableDuplicatedName, tv.charOffset,
-            tv.name.length, fileUri,
-            context: [
-              templateTypeVariableDuplicatedNameCause
-                  .withArguments(tv.name)
-                  .withLocation(
-                      fileUri, existing.charOffset, existing.name.length)
-            ]);
-      } else {
-        typeVariablesByName[tv.name] = tv;
-        if (owner is ClassBuilder) {
-          // Only classes and type variables can't have the same name. See
-          // [#29555](https://github.com/dart-lang/sdk/issues/29555).
-          if (tv.name == owner.name) {
-            addProblem(messageTypeVariableSameNameAsEnclosing, tv.charOffset,
-                tv.name.length, fileUri);
-          }
-        }
-      }
-    }
-    return typeVariablesByName;
-  }
-
   void checkGetterSetterTypes(ProcedureBuilder getterBuilder,
       ProcedureBuilder setterBuilder, TypeEnvironment typeEnvironment) {
     DartType getterType;
@@ -2494,520 +3956,11 @@
     }
   }
 
-  void addExtensionDeclaration(
-      OffsetMap offsetMap,
-      Token beginToken,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      Identifier? identifier,
-      List<NominalVariableBuilder>? typeVariables,
-      TypeBuilder type,
-      int startOffset,
-      int nameOffset,
-      int endOffset) {
-    String? name = identifier?.name;
-    // Nested declaration began in
-    // `OutlineBuilder.beginExtensionDeclarationPrelude`.
-    TypeParameterScopeBuilder declaration =
-        endNestedDeclaration(TypeParameterScopeKind.extensionDeclaration, name)
-          ..resolveNamedTypes(typeVariables, this);
-    assert(declaration.parent == _libraryTypeParameterScopeBuilder);
-    Map<String, Builder> members = declaration.members!;
-    Map<String, MemberBuilder> constructors = declaration.constructors!;
-    Map<String, MemberBuilder> setters = declaration.setters!;
-
-    Scope classScope = new Scope(
-        kind: ScopeKind.declaration,
-        local: members,
-        setters: setters,
-        parent: scope.withTypeVariables(typeVariables),
-        debugName: "extension $name",
-        isModifiable: false);
-
-    Extension? referenceFrom;
-    ExtensionName extensionName = declaration.extensionName!;
-    if (name != null) {
-      referenceFrom = indexedLibrary?.lookupExtension(name);
-    }
-
-    ExtensionBuilder extensionBuilder = new SourceExtensionBuilder(
-        metadata,
-        modifiers,
-        extensionName,
-        typeVariables,
-        type,
-        classScope,
-        this,
-        startOffset,
-        nameOffset,
-        endOffset,
-        referenceFrom);
-    constructorReferences.clear();
-    Map<String, NominalVariableBuilder>? typeVariablesByName =
-        checkTypeVariables(typeVariables, extensionBuilder);
-    void setParent(MemberBuilder? member) {
-      while (member != null) {
-        member.parent = extensionBuilder;
-        member = member.next as MemberBuilder?;
-      }
-    }
-
-    void setParentAndCheckConflicts(String name, Builder member) {
-      if (typeVariablesByName != null) {
-        NominalVariableBuilder? tv = typeVariablesByName[name];
-        if (tv != null) {
-          extensionBuilder.addProblem(
-              templateConflictsWithTypeVariable.withArguments(name),
-              member.charOffset,
-              name.length,
-              context: [
-                messageConflictsWithTypeVariableCause.withLocation(
-                    tv.fileUri!, tv.charOffset, name.length)
-              ]);
-        }
-      }
-      setParent(member as MemberBuilder);
-    }
-
-    members.forEach(setParentAndCheckConflicts);
-    constructors.forEach(setParentAndCheckConflicts);
-    setters.forEach(setParentAndCheckConflicts);
-    addBuilder(extensionBuilder.name, extensionBuilder, nameOffset,
-        getterReference: referenceFrom?.reference);
-    if (identifier != null) {
-      offsetMap.registerNamedDeclaration(identifier, extensionBuilder);
-    } else {
-      offsetMap.registerUnnamedDeclaration(beginToken, extensionBuilder);
-    }
-  }
-
-  void addExtensionTypeDeclaration(
-      OffsetMap offsetMap,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      Identifier identifier,
-      List<NominalVariableBuilder>? typeVariables,
-      List<TypeBuilder>? interfaces,
-      int startOffset,
-      int endOffset) {
-    String name = identifier.name;
-    // Nested declaration began in `OutlineBuilder.beginExtensionDeclaration`.
-    TypeParameterScopeBuilder declaration = endNestedDeclaration(
-        TypeParameterScopeKind.extensionTypeDeclaration, name)
-      ..resolveNamedTypes(typeVariables, this);
-    assert(declaration.parent == _libraryTypeParameterScopeBuilder);
-    Map<String, Builder> members = declaration.members!;
-    Map<String, MemberBuilder> constructors = declaration.constructors!;
-    Map<String, MemberBuilder> setters = declaration.setters!;
-
-    Scope memberScope = new Scope(
-        kind: ScopeKind.declaration,
-        local: members,
-        setters: setters,
-        parent: scope.withTypeVariables(typeVariables),
-        debugName: "extension type $name",
-        isModifiable: false);
-    ConstructorScope constructorScope =
-        new ConstructorScope(name, constructors);
-
-    IndexedContainer? indexedContainer =
-        indexedLibrary?.lookupIndexedExtensionTypeDeclaration(name);
-
-    SourceFieldBuilder? representationFieldBuilder;
-    outer:
-    for (Builder? member in members.values) {
-      while (member != null) {
-        if (!member.isDuplicate &&
-            member is SourceFieldBuilder &&
-            !member.isStatic) {
-          representationFieldBuilder = member;
-          break outer;
-        }
-        member = member.next;
-      }
-    }
-
-    ExtensionTypeDeclarationBuilder extensionTypeDeclarationBuilder =
-        new SourceExtensionTypeDeclarationBuilder(
-            metadata,
-            modifiers,
-            declaration.name,
-            typeVariables,
-            interfaces,
-            memberScope,
-            constructorScope,
-            this,
-            new List<ConstructorReferenceBuilder>.of(constructorReferences),
-            startOffset,
-            identifier.nameOffset,
-            endOffset,
-            indexedContainer,
-            representationFieldBuilder);
-    constructorReferences.clear();
-    Map<String, NominalVariableBuilder>? typeVariablesByName =
-        checkTypeVariables(typeVariables, extensionTypeDeclarationBuilder);
-    void setParent(MemberBuilder? member) {
-      while (member != null) {
-        member.parent = extensionTypeDeclarationBuilder;
-        member = member.next as MemberBuilder?;
-      }
-    }
-
-    void setParentAndCheckConflicts(String name, Builder member) {
-      if (typeVariablesByName != null) {
-        NominalVariableBuilder? tv = typeVariablesByName[name];
-        if (tv != null) {
-          extensionTypeDeclarationBuilder.addProblem(
-              templateConflictsWithTypeVariable.withArguments(name),
-              member.charOffset,
-              name.length,
-              context: [
-                messageConflictsWithTypeVariableCause.withLocation(
-                    tv.fileUri!, tv.charOffset, name.length)
-              ]);
-        }
-      }
-      setParent(member as MemberBuilder);
-    }
-
-    members.forEach(setParentAndCheckConflicts);
-    constructors.forEach(setParentAndCheckConflicts);
-    setters.forEach(setParentAndCheckConflicts);
-    addBuilder(extensionTypeDeclarationBuilder.name,
-        extensionTypeDeclarationBuilder, identifier.nameOffset,
-        getterReference: indexedContainer?.reference);
-    offsetMap.registerNamedDeclaration(
-        identifier, extensionTypeDeclarationBuilder);
-  }
-
-  TypeBuilder? _applyMixins(
-      TypeBuilder? supertype,
-      MixinApplicationBuilder? mixinApplications,
-      int startCharOffset,
-      int charOffset,
-      int charEndOffset,
-      String subclassName,
-      bool isMixinDeclaration,
-      {List<MetadataBuilder>? metadata,
-      String? name,
-      List<NominalVariableBuilder>? typeVariables,
-      int modifiers = 0,
-      List<TypeBuilder>? interfaces,
-      required bool isMacro,
-      required bool isSealed,
-      required bool isBase,
-      required bool isInterface,
-      required bool isFinal,
-      required bool isAugmentation,
-      required bool isMixinClass}) {
-    if (name == null) {
-      // The following parameters should only be used when building a named
-      // mixin application.
-      if (metadata != null) {
-        unhandled("metadata", "unnamed mixin application", charOffset, fileUri);
-      } else if (interfaces != null) {
-        unhandled(
-            "interfaces", "unnamed mixin application", charOffset, fileUri);
-      }
-    }
-    if (mixinApplications != null) {
-      // Documentation below assumes the given mixin application is in one of
-      // these forms:
-      //
-      //     class C extends S with M1, M2, M3;
-      //     class Named = S with M1, M2, M3;
-      //
-      // When we refer to the subclass, we mean `C` or `Named`.
-
-      /// The current supertype.
-      ///
-      /// Starts out having the value `S` and on each iteration of the loop
-      /// below, it will take on the value corresponding to:
-      ///
-      /// 1. `S with M1`.
-      /// 2. `(S with M1) with M2`.
-      /// 3. `((S with M1) with M2) with M3`.
-      supertype ??= loader.target.objectType;
-
-      /// The variable part of the mixin application's synthetic name. It
-      /// starts out as the name of the superclass, but is only used after it
-      /// has been combined with the name of the current mixin. In the examples
-      /// from above, it will take these values:
-      ///
-      /// 1. `S&M1`
-      /// 2. `S&M1&M2`
-      /// 3. `S&M1&M2&M3`.
-      ///
-      /// The full name of the mixin application is obtained by prepending the
-      /// name of the subclass (`C` or `Named` in the above examples) to the
-      /// running name. For the example `C`, that leads to these full names:
-      ///
-      /// 1. `_C&S&M1`
-      /// 2. `_C&S&M1&M2`
-      /// 3. `_C&S&M1&M2&M3`.
-      ///
-      /// For a named mixin application, the last name has been given by the
-      /// programmer, so for the example `Named` we see these full names:
-      ///
-      /// 1. `_Named&S&M1`
-      /// 2. `_Named&S&M1&M2`
-      /// 3. `Named`.
-      String runningName;
-      if (supertype.typeName == null) {
-        assert(supertype is FunctionTypeBuilder);
-
-        // Function types don't have names, and we can supply any string that
-        // doesn't have to be unique. The actual supertype of the mixin will
-        // not be built in that case.
-        runningName = "";
-      } else {
-        runningName = supertype.typeName!.name;
-      }
-
-      /// True when we're building a named mixin application. Notice that for
-      /// the `Named` example above, this is only true on the last
-      /// iteration because only the full mixin application is named.
-      bool isNamedMixinApplication;
-
-      /// The names of the type variables of the subclass.
-      Set<String>? typeVariableNames;
-      if (typeVariables != null) {
-        typeVariableNames = new Set<String>();
-        for (NominalVariableBuilder typeVariable in typeVariables) {
-          typeVariableNames.add(typeVariable.name);
-        }
-      }
-
-      /// Helper function that returns `true` if a type variable with a name
-      /// from [typeVariableNames] is referenced in [type].
-      bool usesTypeVariables(TypeBuilder? type) {
-        switch (type) {
-          case NamedTypeBuilder(
-              :TypeDeclarationBuilder? declaration,
-              typeArguments: List<TypeBuilder>? arguments
-            ):
-            if (declaration is NominalVariableBuilder) {
-              return typeVariableNames!.contains(declaration.name);
-            }
-            if (declaration is StructuralVariableBuilder) {
-              return typeVariableNames!.contains(declaration.name);
-            }
-
-            if (arguments != null && typeVariables != null) {
-              for (TypeBuilder argument in arguments) {
-                if (usesTypeVariables(argument)) {
-                  return true;
-                }
-              }
-            }
-          case FunctionTypeBuilder(
-              :List<ParameterBuilder>? formals,
-              :List<StructuralVariableBuilder>? typeVariables
-            ):
-            if (formals != null) {
-              for (ParameterBuilder formal in formals) {
-                if (usesTypeVariables(formal.type)) {
-                  return true;
-                }
-              }
-            }
-            if (typeVariables != null) {
-              for (StructuralVariableBuilder variable in typeVariables) {
-                if (usesTypeVariables(variable.bound)) {
-                  return true;
-                }
-              }
-            }
-            return usesTypeVariables(type.returnType);
-          case RecordTypeBuilder(
-              :List<RecordTypeFieldBuilder>? positionalFields,
-              :List<RecordTypeFieldBuilder>? namedFields
-            ):
-            if (positionalFields != null) {
-              for (RecordTypeFieldBuilder fieldBuilder in positionalFields) {
-                if (usesTypeVariables(fieldBuilder.type)) {
-                  return true;
-                }
-              }
-            }
-            if (namedFields != null) {
-              for (RecordTypeFieldBuilder fieldBuilder in namedFields) {
-                if (usesTypeVariables(fieldBuilder.type)) {
-                  return true;
-                }
-              }
-            }
-          case FixedTypeBuilder():
-          case InvalidTypeBuilder():
-          case OmittedTypeBuilder():
-          case null:
-            return false;
-        }
-        return false;
-      }
-
-      /// Iterate over the mixins from left to right. At the end of each
-      /// iteration, a new [supertype] is computed that is the mixin
-      /// application of [supertype] with the current mixin.
-      for (int i = 0; i < mixinApplications.mixins.length; i++) {
-        TypeBuilder mixin = mixinApplications.mixins[i];
-        isNamedMixinApplication =
-            name != null && mixin == mixinApplications.mixins.last;
-        bool isGeneric = false;
-        if (!isNamedMixinApplication) {
-          if (supertype is NamedTypeBuilder) {
-            isGeneric = isGeneric || usesTypeVariables(supertype);
-          }
-          if (mixin is NamedTypeBuilder) {
-            runningName += "&${mixin.typeName.name}";
-            isGeneric = isGeneric || usesTypeVariables(mixin);
-          }
-        }
-        String fullname =
-            isNamedMixinApplication ? name : "_$subclassName&$runningName";
-        List<NominalVariableBuilder>? applicationTypeVariables;
-        List<TypeBuilder>? applicationTypeArguments;
-        if (isNamedMixinApplication) {
-          // If this is a named mixin application, it must be given all the
-          // declared type variables.
-          applicationTypeVariables = typeVariables;
-        } else {
-          // Otherwise, we pass the fresh type variables to the mixin
-          // application in the same order as they're declared on the subclass.
-          if (isGeneric) {
-            this.beginNestedDeclaration(
-                TypeParameterScopeKind.unnamedMixinApplication,
-                "mixin application");
-
-            applicationTypeVariables = copyTypeVariables(
-                typeVariables!, currentTypeParameterScopeBuilder,
-                kind: TypeVariableKind.extensionSynthesized);
-
-            List<NamedTypeBuilder> newTypes = <NamedTypeBuilder>[];
-            if (supertype is NamedTypeBuilder &&
-                supertype.typeArguments != null) {
-              for (int i = 0; i < supertype.typeArguments!.length; ++i) {
-                supertype.typeArguments![i] = supertype.typeArguments![i]
-                    .clone(newTypes, this, currentTypeParameterScopeBuilder);
-              }
-            }
-            if (mixin is NamedTypeBuilder && mixin.typeArguments != null) {
-              for (int i = 0; i < mixin.typeArguments!.length; ++i) {
-                mixin.typeArguments![i] = mixin.typeArguments![i]
-                    .clone(newTypes, this, currentTypeParameterScopeBuilder);
-              }
-            }
-            for (NamedTypeBuilder newType in newTypes) {
-              currentTypeParameterScopeBuilder
-                  .registerUnresolvedNamedType(newType);
-            }
-
-            TypeParameterScopeBuilder mixinDeclaration = this
-                .endNestedDeclaration(
-                    TypeParameterScopeKind.unnamedMixinApplication,
-                    "mixin application");
-            mixinDeclaration.resolveNamedTypes(applicationTypeVariables, this);
-
-            applicationTypeArguments = <TypeBuilder>[];
-            for (NominalVariableBuilder typeVariable in typeVariables) {
-              applicationTypeArguments.add(
-                  new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
-                      // The type variable types passed as arguments to the
-                      // generic class representing the anonymous mixin
-                      // application should refer back to the type variables of
-                      // the class that extend the anonymous mixin application.
-                      typeVariable,
-                      const NullabilityBuilder.omitted(),
-                      fileUri: fileUri,
-                      charOffset: charOffset,
-                      instanceTypeVariableAccess:
-                          InstanceTypeVariableAccessState.Allowed));
-            }
-          }
-        }
-        final int computedStartCharOffset =
-            !isNamedMixinApplication || metadata == null
-                ? startCharOffset
-                : metadata.first.charOffset;
-
-        IndexedClass? referencesFromIndexedClass;
-        if (indexedLibrary != null) {
-          referencesFromIndexedClass =
-              indexedLibrary!.lookupIndexedClass(fullname);
-        }
-
-        SourceClassBuilder application = new SourceClassBuilder(
-            isNamedMixinApplication ? metadata : null,
-            isNamedMixinApplication
-                ? modifiers | namedMixinApplicationMask
-                : abstractMask,
-            fullname,
-            applicationTypeVariables,
-            isMixinDeclaration ? null : supertype,
-            isNamedMixinApplication
-                ? interfaces
-                : isMixinDeclaration
-                    ? [supertype!, mixin]
-                    : null,
-            null,
-            // No `on` clause types.
-            new Scope(
-                kind: ScopeKind.declaration,
-                local: <String, MemberBuilder>{},
-                setters: <String, MemberBuilder>{},
-                parent: scope.withTypeVariables(typeVariables),
-                debugName: "mixin $fullname ",
-                isModifiable: false),
-            new ConstructorScope(fullname, <String, MemberBuilder>{}),
-            this,
-            <ConstructorReferenceBuilder>[],
-            computedStartCharOffset,
-            charOffset,
-            charEndOffset,
-            referencesFromIndexedClass,
-            mixedInTypeBuilder: isMixinDeclaration ? null : mixin,
-            isMacro: isNamedMixinApplication && isMacro,
-            isSealed: isNamedMixinApplication && isSealed,
-            isBase: isNamedMixinApplication && isBase,
-            isInterface: isNamedMixinApplication && isInterface,
-            isFinal: isNamedMixinApplication && isFinal,
-            isAugmentation: isNamedMixinApplication && isAugmentation,
-            isMixinClass: isNamedMixinApplication && isMixinClass);
-        // TODO(ahe, kmillikin): Should always be true?
-        // pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart can't
-        // handle that :(
-        application.cls.isAnonymousMixin = !isNamedMixinApplication;
-        addBuilder(fullname, application, charOffset,
-            getterReference: referencesFromIndexedClass?.cls.reference);
-        supertype = new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
-            application, const NullabilityBuilder.omitted(),
-            arguments: applicationTypeArguments,
-            fileUri: fileUri,
-            charOffset: charOffset,
-            instanceTypeVariableAccess:
-                InstanceTypeVariableAccessState.Allowed);
-        registerMixinApplication(application, mixin);
-      }
-      return supertype;
-    } else {
-      return supertype;
-    }
-  }
-
+  // TODO(johnniwinther): Move this to [SourceCompilationUnitImpl].
   Map<SourceClassBuilder, TypeBuilder>? _mixinApplications = {};
 
-  /// Registers that [mixinApplication] is a mixin application introduced by
-  /// the [mixedInType] in a with-clause.
-  ///
-  /// This is used to check that super access in mixin declarations have a
-  /// concrete target.
-  void registerMixinApplication(
-      SourceClassBuilder mixinApplication, TypeBuilder mixedInType) {
-    assert(
-        _mixinApplications != null, "Late registration of mixin application.");
-    _mixinApplications![mixinApplication] = mixedInType;
-  }
-
+  // TODO(johnniwinther): Move access to [_mixinApplications] to
+  //  [SourceCompilationUnitImpl].
   void takeMixinApplications(
       Map<SourceClassBuilder, TypeBuilder> mixinApplications) {
     assert(_mixinApplications != null,
@@ -3023,815 +3976,6 @@
     }
   }
 
-  void addNamedMixinApplication(
-      List<MetadataBuilder>? metadata,
-      String name,
-      List<NominalVariableBuilder>? typeVariables,
-      int modifiers,
-      TypeBuilder? supertype,
-      MixinApplicationBuilder mixinApplication,
-      List<TypeBuilder>? interfaces,
-      int startCharOffset,
-      int charOffset,
-      int charEndOffset,
-      {required bool isMacro,
-      required bool isSealed,
-      required bool isBase,
-      required bool isInterface,
-      required bool isFinal,
-      required bool isAugmentation,
-      required bool isMixinClass}) {
-    // Nested declaration began in `OutlineBuilder.beginNamedMixinApplication`.
-    endNestedDeclaration(TypeParameterScopeKind.namedMixinApplication, name)
-        .resolveNamedTypes(typeVariables, this);
-    supertype = _applyMixins(supertype, mixinApplication, startCharOffset,
-        charOffset, charEndOffset, name, false,
-        metadata: metadata,
-        name: name,
-        typeVariables: typeVariables,
-        modifiers: modifiers,
-        interfaces: interfaces,
-        isMacro: isMacro,
-        isSealed: isSealed,
-        isBase: isBase,
-        isInterface: isInterface,
-        isFinal: isFinal,
-        isAugmentation: isAugmentation,
-        isMixinClass: isMixinClass)!;
-    checkTypeVariables(typeVariables, supertype.declaration);
-  }
-
-  SourceFieldBuilder addField(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      bool isTopLevel,
-      TypeBuilder type,
-      String name,
-      int charOffset,
-      int charEndOffset,
-      Token? initializerToken,
-      bool hasInitializer,
-      {Token? constInitializerToken}) {
-    if (hasInitializer) {
-      modifiers |= hasInitializerMask;
-    }
-    bool isLate = (modifiers & lateMask) != 0;
-    bool isFinal = (modifiers & finalMask) != 0;
-    bool isStatic = (modifiers & staticMask) != 0;
-    bool isExternal = (modifiers & externalMask) != 0;
-    final bool fieldIsLateWithLowering = isLate &&
-        (loader.target.backendTarget.isLateFieldLoweringEnabled(
-                hasInitializer: hasInitializer,
-                isFinal: isFinal,
-                isStatic: isTopLevel || isStatic) ||
-            (loader.target.backendTarget.useStaticFieldLowering &&
-                (isStatic || isTopLevel)));
-
-    final bool isInstanceMember = currentTypeParameterScopeBuilder.kind !=
-            TypeParameterScopeKind.library &&
-        (modifiers & staticMask) == 0;
-    final bool isExtensionMember = currentTypeParameterScopeBuilder.kind ==
-        TypeParameterScopeKind.extensionDeclaration;
-    final bool isExtensionTypeMember = currentTypeParameterScopeBuilder.kind ==
-        TypeParameterScopeKind.extensionTypeDeclaration;
-    ContainerType containerType =
-        currentTypeParameterScopeBuilder.containerType;
-    ContainerName? containerName =
-        currentTypeParameterScopeBuilder.containerName;
-
-    Reference? fieldReference;
-    Reference? fieldGetterReference;
-    Reference? fieldSetterReference;
-    Reference? lateIsSetFieldReference;
-    Reference? lateIsSetGetterReference;
-    Reference? lateIsSetSetterReference;
-    Reference? lateGetterReference;
-    Reference? lateSetterReference;
-
-    NameScheme nameScheme = new NameScheme(
-        isInstanceMember: isInstanceMember,
-        containerName: containerName,
-        containerType: containerType,
-        libraryName: indexedLibrary != null
-            ? new LibraryName(indexedLibrary!.reference)
-            : libraryName);
-    IndexedContainer? indexedContainer = _indexedContainer ?? indexedLibrary;
-    if (indexedContainer != null) {
-      if ((isExtensionMember || isExtensionTypeMember) &&
-          isInstanceMember &&
-          isExternal) {
-        /// An external extension (type) instance field is special. It is
-        /// treated as an external getter/setter pair and is therefore encoded
-        /// as a pair of top level methods using the extension instance member
-        /// naming convention.
-        fieldGetterReference = indexedContainer.lookupGetterReference(
-            nameScheme.getProcedureMemberName(ProcedureKind.Getter, name).name);
-        fieldSetterReference = indexedContainer.lookupGetterReference(
-            nameScheme.getProcedureMemberName(ProcedureKind.Setter, name).name);
-      } else if (isExtensionTypeMember && isInstanceMember) {
-        Name nameToLookup = nameScheme
-            .getFieldMemberName(FieldNameType.RepresentationField, name,
-                isSynthesized: true)
-            .name;
-        fieldGetterReference =
-            indexedContainer.lookupGetterReference(nameToLookup);
-      } else {
-        Name nameToLookup = nameScheme
-            .getFieldMemberName(FieldNameType.Field, name,
-                isSynthesized: fieldIsLateWithLowering)
-            .name;
-        fieldReference = indexedContainer.lookupFieldReference(nameToLookup);
-        fieldGetterReference =
-            indexedContainer.lookupGetterReference(nameToLookup);
-        fieldSetterReference =
-            indexedContainer.lookupSetterReference(nameToLookup);
-      }
-
-      if (fieldIsLateWithLowering) {
-        Name lateIsSetName = nameScheme
-            .getFieldMemberName(FieldNameType.IsSetField, name,
-                isSynthesized: fieldIsLateWithLowering)
-            .name;
-        lateIsSetFieldReference =
-            indexedContainer.lookupFieldReference(lateIsSetName);
-        lateIsSetGetterReference =
-            indexedContainer.lookupGetterReference(lateIsSetName);
-        lateIsSetSetterReference =
-            indexedContainer.lookupSetterReference(lateIsSetName);
-        lateGetterReference = indexedContainer.lookupGetterReference(nameScheme
-            .getFieldMemberName(FieldNameType.Getter, name,
-                isSynthesized: fieldIsLateWithLowering)
-            .name);
-        lateSetterReference = indexedContainer.lookupSetterReference(nameScheme
-            .getFieldMemberName(FieldNameType.Setter, name,
-                isSynthesized: fieldIsLateWithLowering)
-            .name);
-      }
-    }
-
-    SourceFieldBuilder fieldBuilder = new SourceFieldBuilder(
-        metadata,
-        type,
-        name,
-        modifiers,
-        isTopLevel,
-        this,
-        charOffset,
-        charEndOffset,
-        nameScheme,
-        fieldReference: fieldReference,
-        fieldGetterReference: fieldGetterReference,
-        fieldSetterReference: fieldSetterReference,
-        lateIsSetFieldReference: lateIsSetFieldReference,
-        lateIsSetGetterReference: lateIsSetGetterReference,
-        lateIsSetSetterReference: lateIsSetSetterReference,
-        lateGetterReference: lateGetterReference,
-        lateSetterReference: lateSetterReference,
-        initializerToken: initializerToken,
-        constInitializerToken: constInitializerToken);
-    addBuilder(name, fieldBuilder, charOffset,
-        getterReference: fieldGetterReference,
-        setterReference: fieldSetterReference);
-    return fieldBuilder;
-  }
-
-  void addPrimaryConstructorField(
-      {required List<MetadataBuilder>? metadata,
-      required TypeBuilder type,
-      required String name,
-      required int charOffset}) {
-    addField(
-        metadata,
-        finalMask,
-        /* isTopLevel = */ false,
-        type,
-        name,
-        /* charOffset = */ charOffset,
-        /* charEndOffset = */ charOffset,
-        /* initializerToken = */ null,
-        /* hasInitializer = */ false);
-  }
-
-  void addPrimaryConstructor(
-      {required OffsetMap offsetMap,
-      required Token beginToken,
-      required String constructorName,
-      required List<NominalVariableBuilder>? typeVariables,
-      required List<FormalParameterBuilder>? formals,
-      required int charOffset,
-      required bool isConst}) {
-    SourceFunctionBuilder builder = _addConstructor(
-        null,
-        isConst ? constMask : 0,
-        constructorName,
-        typeVariables,
-        formals,
-        /* startCharOffset = */ charOffset,
-        charOffset,
-        /* charOpenParenOffset = */ charOffset,
-        /* charEndOffset = */ charOffset,
-        /* nativeMethodName = */ null,
-        forAbstractClassOrMixin: false);
-    offsetMap.registerPrimaryConstructor(beginToken, builder);
-  }
-
-  void addConstructor(
-      OffsetMap offsetMap,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      Identifier identifier,
-      String constructorName,
-      List<NominalVariableBuilder>? typeVariables,
-      List<FormalParameterBuilder>? formals,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      String? nativeMethodName,
-      {Token? beginInitializers,
-      required bool forAbstractClassOrMixin}) {
-    SourceFunctionBuilder builder = _addConstructor(
-        metadata,
-        modifiers,
-        constructorName,
-        typeVariables,
-        formals,
-        startCharOffset,
-        charOffset,
-        charOpenParenOffset,
-        charEndOffset,
-        nativeMethodName,
-        beginInitializers: beginInitializers,
-        forAbstractClassOrMixin: forAbstractClassOrMixin);
-    offsetMap.registerConstructor(identifier, builder);
-  }
-
-  SourceFunctionBuilder _addConstructor(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      String constructorName,
-      List<NominalVariableBuilder>? typeVariables,
-      List<FormalParameterBuilder>? formals,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      String? nativeMethodName,
-      {Token? beginInitializers,
-      required bool forAbstractClassOrMixin}) {
-    ContainerType containerType =
-        currentTypeParameterScopeBuilder.containerType;
-    ContainerName? containerName =
-        currentTypeParameterScopeBuilder.containerName;
-    NameScheme nameScheme = new NameScheme(
-        isInstanceMember: false,
-        containerName: containerName,
-        containerType: containerType,
-        libraryName: indexedLibrary != null
-            ? new LibraryName(indexedLibrary!.library.reference)
-            : libraryName);
-
-    Reference? constructorReference;
-    Reference? tearOffReference;
-
-    IndexedContainer? indexedContainer = _indexedContainer;
-    if (indexedContainer != null) {
-      constructorReference = indexedContainer.lookupConstructorReference(
-          nameScheme
-              .getConstructorMemberName(constructorName, isTearOff: false)
-              .name);
-      tearOffReference = indexedContainer.lookupGetterReference(nameScheme
-          .getConstructorMemberName(constructorName, isTearOff: true)
-          .name);
-    }
-    AbstractSourceConstructorBuilder constructorBuilder;
-
-    if (currentTypeParameterScopeBuilder.kind ==
-        TypeParameterScopeKind.extensionTypeDeclaration) {
-      constructorBuilder = new SourceExtensionTypeConstructorBuilder(
-          metadata,
-          modifiers & ~abstractMask,
-          addInferableType(),
-          constructorName,
-          typeVariables,
-          formals,
-          this,
-          startCharOffset,
-          charOffset,
-          charOpenParenOffset,
-          charEndOffset,
-          constructorReference,
-          tearOffReference,
-          nameScheme,
-          nativeMethodName: nativeMethodName,
-          forAbstractClassOrEnumOrMixin: forAbstractClassOrMixin);
-    } else {
-      constructorBuilder = new DeclaredSourceConstructorBuilder(
-          metadata,
-          modifiers & ~abstractMask,
-          addInferableType(),
-          constructorName,
-          typeVariables,
-          formals,
-          this,
-          startCharOffset,
-          charOffset,
-          charOpenParenOffset,
-          charEndOffset,
-          constructorReference,
-          tearOffReference,
-          nameScheme,
-          nativeMethodName: nativeMethodName,
-          forAbstractClassOrEnumOrMixin: forAbstractClassOrMixin);
-    }
-    checkTypeVariables(typeVariables, constructorBuilder);
-    // TODO(johnniwinther): There is no way to pass the tear off reference here.
-    addBuilder(constructorName, constructorBuilder, charOffset,
-        getterReference: constructorReference);
-    if (nativeMethodName != null) {
-      addNativeMethod(constructorBuilder);
-    }
-    if (constructorBuilder.isConst) {
-      currentTypeParameterScopeBuilder.declaresConstConstructor = true;
-    }
-    if (constructorBuilder.isConst ||
-        libraryFeatures.superParameters.isEnabled) {
-      // const constructors will have their initializers compiled and written
-      // into the outline. In case of super-parameters language feature, the
-      // super initializers are required to infer the types of super parameters.
-      constructorBuilder.beginInitializers =
-          beginInitializers ?? new Token.eof(-1);
-    }
-    return constructorBuilder;
-  }
-
-  void addProcedure(
-      OffsetMap offsetMap,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder? returnType,
-      Identifier identifier,
-      String name,
-      List<NominalVariableBuilder>? typeVariables,
-      List<FormalParameterBuilder>? formals,
-      ProcedureKind kind,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      String? nativeMethodName,
-      AsyncMarker asyncModifier,
-      {required bool isInstanceMember,
-      required bool isExtensionMember,
-      required bool isExtensionTypeMember}) {
-    assert(!isExtensionMember ||
-        currentTypeParameterScopeBuilder.kind ==
-            TypeParameterScopeKind.extensionDeclaration);
-    assert(!isExtensionTypeMember ||
-        currentTypeParameterScopeBuilder.kind ==
-            TypeParameterScopeKind.extensionTypeDeclaration);
-    ContainerType containerType =
-        currentTypeParameterScopeBuilder.containerType;
-    ContainerName? containerName =
-        currentTypeParameterScopeBuilder.containerName;
-    NameScheme nameScheme = new NameScheme(
-        containerName: containerName,
-        containerType: containerType,
-        isInstanceMember: isInstanceMember,
-        libraryName: indexedLibrary != null
-            ? new LibraryName(indexedLibrary!.library.reference)
-            : libraryName);
-
-    if (returnType == null) {
-      if (kind == ProcedureKind.Operator &&
-          identical(name, indexSetName.text)) {
-        returnType = addVoidType(charOffset);
-      } else if (kind == ProcedureKind.Setter) {
-        returnType = addVoidType(charOffset);
-      }
-    }
-    Reference? procedureReference;
-    Reference? tearOffReference;
-    IndexedContainer? indexedContainer = _indexedContainer ?? indexedLibrary;
-
-    bool isAugmentation = isAugmenting && (modifiers & augmentMask) != 0;
-    if (indexedContainer != null && !isAugmentation) {
-      Name nameToLookup = nameScheme.getProcedureMemberName(kind, name).name;
-      if (kind == ProcedureKind.Setter) {
-        if ((isExtensionMember || isExtensionTypeMember) && isInstanceMember) {
-          // Extension (type) instance setters are encoded as methods.
-          procedureReference =
-              indexedContainer.lookupGetterReference(nameToLookup);
-        } else {
-          procedureReference =
-              indexedContainer.lookupSetterReference(nameToLookup);
-        }
-      } else {
-        procedureReference =
-            indexedContainer.lookupGetterReference(nameToLookup);
-        if ((isExtensionMember || isExtensionTypeMember) &&
-            kind == ProcedureKind.Method) {
-          tearOffReference = indexedContainer.lookupGetterReference(nameScheme
-              .getProcedureMemberName(ProcedureKind.Getter, name)
-              .name);
-        }
-      }
-    }
-    SourceProcedureBuilder procedureBuilder = new SourceProcedureBuilder(
-        metadata,
-        modifiers,
-        returnType ?? addInferableType(),
-        name,
-        typeVariables,
-        formals,
-        kind,
-        this,
-        startCharOffset,
-        charOffset,
-        charOpenParenOffset,
-        charEndOffset,
-        procedureReference,
-        tearOffReference,
-        asyncModifier,
-        nameScheme,
-        nativeMethodName: nativeMethodName);
-    checkTypeVariables(typeVariables, procedureBuilder);
-    addBuilder(name, procedureBuilder, charOffset,
-        getterReference: procedureReference);
-    if (nativeMethodName != null) {
-      addNativeMethod(procedureBuilder);
-    }
-    offsetMap.registerProcedure(identifier, procedureBuilder);
-  }
-
-  void addFactoryMethod(
-      OffsetMap offsetMap,
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      Identifier identifier,
-      List<FormalParameterBuilder>? formals,
-      ConstructorReferenceBuilder? redirectionTarget,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      String? nativeMethodName,
-      AsyncMarker asyncModifier) {
-    TypeBuilder returnType;
-    if (currentTypeParameterScopeBuilder.parent?.kind ==
-        TypeParameterScopeKind.extensionDeclaration) {
-      // Make the synthesized return type invalid for extensions.
-      String name = currentTypeParameterScopeBuilder.parent!.name;
-      returnType = new NamedTypeBuilderImpl.forInvalidType(
-          currentTypeParameterScopeBuilder.parent!.name,
-          const NullabilityBuilder.omitted(),
-          messageExtensionDeclaresConstructor.withLocation(
-              fileUri, charOffset, name.length));
-    } else {
-      returnType = addNamedType(
-          new SyntheticTypeName(
-              currentTypeParameterScopeBuilder.parent!.name, charOffset),
-          const NullabilityBuilder.omitted(),
-          <TypeBuilder>[],
-          charOffset,
-          instanceTypeVariableAccess: InstanceTypeVariableAccessState.Allowed);
-    }
-    // Nested declaration began in `OutlineBuilder.beginFactoryMethod`.
-    TypeParameterScopeBuilder factoryDeclaration = endNestedDeclaration(
-        TypeParameterScopeKind.factoryMethod, "#factory_method");
-
-    // Prepare the simple procedure name.
-    String procedureName;
-    String? constructorName =
-        computeAndValidateConstructorName(identifier, isFactory: true);
-    if (constructorName != null) {
-      procedureName = constructorName;
-    } else {
-      procedureName = identifier.name;
-    }
-
-    ContainerType containerType =
-        currentTypeParameterScopeBuilder.containerType;
-    ContainerName? containerName =
-        currentTypeParameterScopeBuilder.containerName;
-
-    NameScheme procedureNameScheme = new NameScheme(
-        containerName: containerName,
-        containerType: containerType,
-        isInstanceMember: false,
-        libraryName: indexedLibrary != null
-            ? new LibraryName(
-                (_indexedContainer ?? indexedLibrary)!.library.reference)
-            : libraryName);
-
-    Reference? constructorReference;
-    Reference? tearOffReference;
-    if (_indexedContainer != null) {
-      constructorReference = _indexedContainer!.lookupConstructorReference(
-          procedureNameScheme
-              .getConstructorMemberName(procedureName, isTearOff: false)
-              .name);
-      tearOffReference = _indexedContainer!.lookupGetterReference(
-          procedureNameScheme
-              .getConstructorMemberName(procedureName, isTearOff: true)
-              .name);
-    } else if (indexedLibrary != null) {
-      constructorReference = indexedLibrary!.lookupGetterReference(
-          procedureNameScheme
-              .getConstructorMemberName(procedureName, isTearOff: false)
-              .name);
-      tearOffReference = indexedLibrary!.lookupGetterReference(
-          procedureNameScheme
-              .getConstructorMemberName(procedureName, isTearOff: true)
-              .name);
-    }
-
-    SourceFactoryBuilder procedureBuilder;
-    List<NominalVariableBuilder> typeVariables;
-    if (redirectionTarget != null) {
-      procedureBuilder = new RedirectingFactoryBuilder(
-          metadata,
-          staticMask | modifiers,
-          returnType,
-          procedureName,
-          typeVariables = copyTypeVariables(
-              currentTypeParameterScopeBuilder.typeVariables ??
-                  const <NominalVariableBuilder>[],
-              factoryDeclaration,
-              kind: TypeVariableKind.function),
-          formals,
-          this,
-          startCharOffset,
-          charOffset,
-          charOpenParenOffset,
-          charEndOffset,
-          constructorReference,
-          tearOffReference,
-          procedureNameScheme,
-          nativeMethodName,
-          redirectionTarget);
-    } else {
-      procedureBuilder = new SourceFactoryBuilder(
-          metadata,
-          staticMask | modifiers,
-          returnType,
-          procedureName,
-          typeVariables = copyTypeVariables(
-              currentTypeParameterScopeBuilder.typeVariables ??
-                  const <NominalVariableBuilder>[],
-              factoryDeclaration,
-              kind: TypeVariableKind.function),
-          formals,
-          this,
-          startCharOffset,
-          charOffset,
-          charOpenParenOffset,
-          charEndOffset,
-          constructorReference,
-          tearOffReference,
-          asyncModifier,
-          procedureNameScheme,
-          nativeMethodName: nativeMethodName);
-    }
-
-    TypeParameterScopeBuilder savedDeclaration =
-        currentTypeParameterScopeBuilder;
-    currentTypeParameterScopeBuilder = factoryDeclaration;
-    if (returnType is NamedTypeBuilderImpl && !typeVariables.isEmpty) {
-      returnType.typeArguments =
-          new List<TypeBuilder>.generate(typeVariables.length, (int index) {
-        return addNamedType(
-            new SyntheticTypeName(
-                typeVariables[index].name, procedureBuilder.charOffset),
-            const NullabilityBuilder.omitted(),
-            null,
-            procedureBuilder.charOffset,
-            instanceTypeVariableAccess:
-                InstanceTypeVariableAccessState.Allowed);
-      });
-    }
-    currentTypeParameterScopeBuilder = savedDeclaration;
-
-    factoryDeclaration.resolveNamedTypes(procedureBuilder.typeVariables, this);
-    addBuilder(procedureName, procedureBuilder, charOffset,
-        getterReference: constructorReference);
-    if (nativeMethodName != null) {
-      addNativeMethod(procedureBuilder);
-    }
-    offsetMap.registerConstructor(identifier, procedureBuilder);
-  }
-
-  void addEnum(
-      OffsetMap offsetMap,
-      List<MetadataBuilder>? metadata,
-      Identifier identifier,
-      List<NominalVariableBuilder>? typeVariables,
-      MixinApplicationBuilder? supertypeBuilder,
-      List<TypeBuilder>? interfaceBuilders,
-      List<EnumConstantInfo?>? enumConstantInfos,
-      int startCharOffset,
-      int charEndOffset) {
-    String name = identifier.name;
-    int charOffset = identifier.nameOffset;
-
-    IndexedClass? referencesFromIndexedClass;
-    if (indexedLibrary != null) {
-      referencesFromIndexedClass = indexedLibrary!.lookupIndexedClass(name);
-    }
-    // Nested declaration began in `OutlineBuilder.beginEnum`.
-    TypeParameterScopeBuilder declaration =
-        endNestedDeclaration(TypeParameterScopeKind.enumDeclaration, name)
-          ..resolveNamedTypes(typeVariables, this);
-    Map<String, Builder> members = declaration.members!;
-    Map<String, MemberBuilder> constructors = declaration.constructors!;
-    Map<String, MemberBuilder> setters = declaration.setters!;
-
-    SourceEnumBuilder enumBuilder = new SourceEnumBuilder(
-        metadata,
-        name,
-        typeVariables,
-        _applyMixins(
-            loader.target.underscoreEnumType,
-            supertypeBuilder,
-            startCharOffset,
-            charOffset,
-            charEndOffset,
-            name,
-            /* isMixinDeclaration = */
-            false,
-            typeVariables: typeVariables,
-            isMacro: false,
-            isSealed: false,
-            isBase: false,
-            isInterface: false,
-            isFinal: false,
-            isAugmentation: false,
-            isMixinClass: false),
-        interfaceBuilders,
-        enumConstantInfos,
-        this,
-        new List<ConstructorReferenceBuilder>.of(constructorReferences),
-        startCharOffset,
-        charOffset,
-        charEndOffset,
-        referencesFromIndexedClass,
-        new Scope(
-            kind: ScopeKind.declaration,
-            local: members,
-            setters: setters,
-            parent: scope.withTypeVariables(typeVariables),
-            debugName: "enum $name",
-            isModifiable: false),
-        new ConstructorScope(name, constructors),
-        loader.coreLibrary);
-    constructorReferences.clear();
-
-    Map<String, NominalVariableBuilder>? typeVariablesByName =
-        checkTypeVariables(typeVariables, enumBuilder);
-
-    void setParent(MemberBuilder? member) {
-      while (member != null) {
-        member.parent = enumBuilder;
-        member = member.next as MemberBuilder?;
-      }
-    }
-
-    void setParentAndCheckConflicts(String name, Builder member) {
-      if (typeVariablesByName != null) {
-        NominalVariableBuilder? tv = typeVariablesByName[name];
-        if (tv != null) {
-          enumBuilder.addProblem(
-              templateConflictsWithTypeVariable.withArguments(name),
-              member.charOffset,
-              name.length,
-              context: [
-                messageConflictsWithTypeVariableCause.withLocation(
-                    tv.fileUri!, tv.charOffset, name.length)
-              ]);
-        }
-      }
-      setParent(member as MemberBuilder);
-    }
-
-    members.forEach(setParentAndCheckConflicts);
-    constructors.forEach(setParentAndCheckConflicts);
-    setters.forEach(setParentAndCheckConflicts);
-    addBuilder(name, enumBuilder, charOffset,
-        getterReference: referencesFromIndexedClass?.cls.reference);
-
-    offsetMap.registerNamedDeclaration(identifier, enumBuilder);
-  }
-
-  void addFunctionTypeAlias(
-      List<MetadataBuilder>? metadata,
-      String name,
-      List<NominalVariableBuilder>? typeVariables,
-      TypeBuilder type,
-      int charOffset) {
-    if (typeVariables != null) {
-      for (NominalVariableBuilder typeVariable in typeVariables) {
-        typeVariable.varianceCalculationValue =
-            VarianceCalculationValue.pending;
-      }
-    }
-    Typedef? referenceFrom = indexedLibrary?.lookupTypedef(name);
-    TypeAliasBuilder typedefBuilder = new SourceTypeAliasBuilder(
-        metadata, name, typeVariables, type, this, charOffset,
-        referenceFrom: referenceFrom);
-    checkTypeVariables(typeVariables, typedefBuilder);
-    // Nested declaration began in `OutlineBuilder.beginFunctionTypeAlias`.
-    endNestedDeclaration(TypeParameterScopeKind.typedef, "#typedef")
-        .resolveNamedTypes(typeVariables, this);
-    addBuilder(name, typedefBuilder, charOffset,
-        getterReference: referenceFrom?.reference);
-  }
-
-  FunctionTypeBuilder addFunctionType(
-      TypeBuilder returnType,
-      List<StructuralVariableBuilder>? structuralVariableBuilders,
-      List<FormalParameterBuilder>? formals,
-      NullabilityBuilder nullabilityBuilder,
-      Uri fileUri,
-      int charOffset,
-      {required bool hasFunctionFormalParameterSyntax}) {
-    FunctionTypeBuilder builder = new FunctionTypeBuilderImpl(
-        returnType,
-        structuralVariableBuilders,
-        formals,
-        nullabilityBuilder,
-        fileUri,
-        charOffset,
-        hasFunctionFormalParameterSyntax: hasFunctionFormalParameterSyntax);
-    checkStructuralVariables(structuralVariableBuilders, null);
-    if (structuralVariableBuilders != null) {
-      for (StructuralVariableBuilder builder in structuralVariableBuilders) {
-        if (builder.metadata != null) {
-          if (!libraryFeatures.genericMetadata.isEnabled) {
-            addProblem(messageAnnotationOnFunctionTypeTypeVariable,
-                builder.charOffset, builder.name.length, builder.fileUri);
-          }
-        }
-      }
-    }
-    // Nested declaration began in `OutlineBuilder.beginFunctionType` or
-    // `OutlineBuilder.beginFunctionTypedFormalParameter`.
-    endNestedDeclaration(TypeParameterScopeKind.functionType, "#function_type")
-        .resolveNamedTypesWithStructuralVariables(
-            structuralVariableBuilders, this);
-    return builder;
-  }
-
-  FormalParameterBuilder addFormalParameter(
-      List<MetadataBuilder>? metadata,
-      FormalParameterKind kind,
-      int modifiers,
-      TypeBuilder type,
-      String name,
-      bool hasThis,
-      bool hasSuper,
-      int charOffset,
-      Token? initializerToken) {
-    assert(!hasThis || !hasSuper,
-        "Formal parameter '${name}' has both 'this' and 'super' prefixes.");
-    if (hasThis) {
-      modifiers |= initializingFormalMask;
-    }
-    if (hasSuper) {
-      modifiers |= superInitializingFormalMask;
-    }
-    FormalParameterBuilder formal = new FormalParameterBuilder(
-        kind, modifiers, type, name, this, charOffset,
-        fileUri: fileUri,
-        hasImmediatelyDeclaredInitializer: initializerToken != null)
-      ..initializerToken = initializerToken;
-    return formal;
-  }
-
-  NominalVariableBuilder addNominalTypeVariable(List<MetadataBuilder>? metadata,
-      String name, TypeBuilder? bound, int charOffset, Uri fileUri,
-      {required TypeVariableKind kind}) {
-    NominalVariableBuilder builder = new NominalVariableBuilder(
-        name, this, charOffset, fileUri,
-        bound: bound, metadata: metadata, kind: kind);
-
-    unboundNominalVariables.add(builder);
-    return builder;
-  }
-
-  StructuralVariableBuilder addStructuralTypeVariable(
-      List<MetadataBuilder>? metadata,
-      String name,
-      TypeBuilder? bound,
-      int charOffset,
-      Uri fileUri) {
-    StructuralVariableBuilder builder = new StructuralVariableBuilder(
-        name, this, charOffset, fileUri,
-        bound: bound, metadata: metadata);
-
-    unboundStructuralVariables.add(builder);
-    return builder;
-  }
-
   BodyBuilderContext createBodyBuilderContext(
       {required bool inOutlineBuildingPhase,
       required bool inMetadata,
@@ -4238,10 +4382,6 @@
     return count;
   }
 
-  void addNativeMethod(SourceFunctionBuilder method) {
-    nativeMethods.add(method);
-  }
-
   int finishNativeMethods() {
     int count = 0;
 
@@ -4261,36 +4401,6 @@
     return count;
   }
 
-  /// Creates a copy of [original] into the scope of [declaration].
-  ///
-  /// This is used for adding copies of class type parameters to factory
-  /// methods and unnamed mixin applications, and for adding copies of
-  /// extension type parameters to extension instance methods.
-  ///
-  /// If [synthesizeTypeParameterNames] is `true` the names of the
-  /// [TypeParameter] are prefix with '#' to indicate that their synthesized.
-  List<NominalVariableBuilder> copyTypeVariables(
-      List<NominalVariableBuilder> original,
-      TypeParameterScopeBuilder declaration,
-      {required TypeVariableKind kind}) {
-    List<NamedTypeBuilder> newTypes = <NamedTypeBuilder>[];
-    List<NominalVariableBuilder> copy = <NominalVariableBuilder>[];
-    for (NominalVariableBuilder variable in original) {
-      NominalVariableBuilder newVariable = new NominalVariableBuilder(
-          variable.name, this, variable.charOffset, variable.fileUri,
-          bound: variable.bound?.clone(newTypes, this, declaration),
-          kind: kind,
-          variableVariance:
-              variable.parameter.isLegacyCovariant ? null : variable.variance);
-      copy.add(newVariable);
-      unboundNominalVariables.add(newVariable);
-    }
-    for (NamedTypeBuilder newType in newTypes) {
-      declaration.registerUnresolvedNamedType(newType);
-    }
-    return copy;
-  }
-
   List<StructuralVariableBuilder> copyStructuralVariables(
       List<StructuralVariableBuilder> original,
       TypeParameterScopeBuilder declaration,
@@ -5534,37 +5644,6 @@
     _extensionsInScope = null;
   }
 
-  /// Call this when entering a class, mixin, enum, or extension type
-  /// declaration.
-  ///
-  /// This is done to set up the current [_indexedContainer] used to lookup
-  /// references of members from a previous incremental compilation.
-  ///
-  /// Called in `OutlineBuilder.beginClassDeclaration`,
-  /// `OutlineBuilder.beginEnum`, `OutlineBuilder.beginMixinDeclaration` and
-  /// `OutlineBuilder.beginExtensionTypeDeclaration`.
-  void beginIndexedContainer(String name,
-      {required bool isExtensionTypeDeclaration}) {
-    if (indexedLibrary != null) {
-      if (isExtensionTypeDeclaration) {
-        _indexedContainer =
-            indexedLibrary!.lookupIndexedExtensionTypeDeclaration(name);
-      } else {
-        _indexedContainer = indexedLibrary!.lookupIndexedClass(name);
-      }
-    }
-  }
-
-  /// Call this when leaving a class, mixin, enum, or extension type
-  /// declaration.
-  ///
-  /// Called in `OutlineBuilder.endClassDeclaration`,
-  /// `OutlineBuilder.endEnum`, `OutlineBuilder.endMixinDeclaration` and
-  /// `OutlineBuilder.endExtensionTypeDeclaration`.
-  void endIndexedContainer() {
-    _indexedContainer = null;
-  }
-
   void registerPendingNullability(
       Uri fileUri, int charOffset, TypeParameterType type) {
     _pendingNullabilities
@@ -6507,12 +6586,4 @@
   final CompilationUnit compilationUnit;
 
   Part(this.offset, this.compilationUnit);
-
-  OffsetMap get offsetMap {
-    if (compilationUnit is SourceCompilationUnit) {
-      return (compilationUnit as SourceCompilationUnit).offsetMap;
-    }
-    assert(false, "No offset map for $compilationUnit.");
-    return new OffsetMap(compilationUnit.fileUri);
-  }
 }
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 2545c9e..b5c9bff 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -156,8 +156,8 @@
 
   List<SourceLibraryBuilder>? _sourceLibraryBuilders;
 
-  final Queue<SourceLibraryBuilder> _unparsedLibraries =
-      new Queue<SourceLibraryBuilder>();
+  final Queue<SourceCompilationUnit> _unparsedLibraries =
+      new Queue<SourceCompilationUnit>();
 
   final List<Library> libraries = <Library>[];
 
@@ -523,7 +523,7 @@
     if (uri.isScheme("dart")) {
       target.readPatchFiles(libraryBuilder);
     }
-    _unparsedLibraries.addLast(libraryBuilder);
+    _unparsedLibraries.addLast(libraryBuilder.compilationUnit);
 
     return libraryBuilder;
   }
@@ -876,8 +876,9 @@
   /// part of the error message.
   Set<SourceLibraryBuilder> _unavailableDartLibraries = {};
 
-  Future<Token> tokenize(SourceLibraryBuilder libraryBuilder,
+  Future<Token> tokenize(SourceCompilationUnit compilationUnit,
       {bool suppressLexicalErrors = false}) async {
+    SourceLibraryBuilder libraryBuilder = compilationUnit.sourceLibraryBuilder;
     target.benchmarker?.beginSubdivide(BenchmarkSubdivides.tokenize);
     Uri fileUri = libraryBuilder.fileUri;
 
@@ -1040,26 +1041,26 @@
     _typeInferenceEngine!.typeDependencies[member] = typeDependency;
   }
 
-  /// Registers the [library] as unparsed with the given [source] code.
+  /// Registers the [compilationUnit] as unparsed with the given [source] code.
   ///
   /// This is used for creating synthesized augmentation libraries.
   void registerUnparsedLibrarySource(
-      SourceLibraryBuilder library, String source) {
+      SourceCompilationUnit compilationUnit, String source) {
     List<int> codeUnits = source.codeUnits;
     Uint8List bytes = new Uint8List(codeUnits.length + 1);
     bytes.setRange(0, codeUnits.length, codeUnits);
-    sourceBytes[library.fileUri] = bytes;
-    _unparsedLibraries.addLast(library);
+    sourceBytes[compilationUnit.fileUri] = bytes;
+    _unparsedLibraries.addLast(compilationUnit);
   }
 
   /// Runs the [OutlineBuilder] on the source of all [_unparsedLibraries].
   Future<void> buildOutlines() async {
     _ensureCoreLibrary();
     while (_unparsedLibraries.isNotEmpty) {
-      SourceLibraryBuilder library = _unparsedLibraries.removeFirst();
+      SourceCompilationUnit compilationUnit = _unparsedLibraries.removeFirst();
       currentUriForCrashReporting =
-          new UriOffset(library.importUri, TreeNode.noOffset);
-      await buildOutline(library);
+          new UriOffset(compilationUnit.importUri, TreeNode.noOffset);
+      await buildOutline(compilationUnit);
     }
     currentUriForCrashReporting = null;
     logSummary(outlineSummaryTemplate);
@@ -1150,14 +1151,14 @@
     return bytes.sublist(0, bytes.length - 1);
   }
 
-  Future<Null> buildOutline(SourceLibraryBuilder library) async {
-    Token tokens = await tokenize(library);
-    OffsetMap offsetMap = new OffsetMap(library.fileUri);
-    OutlineBuilder listener = new OutlineBuilder(library, offsetMap);
+  Future<Null> buildOutline(SourceCompilationUnit compilationUnit) async {
+    Token tokens = await tokenize(compilationUnit);
+    OffsetMap offsetMap = new OffsetMap(compilationUnit.fileUri);
+    OutlineBuilder listener = new OutlineBuilder(compilationUnit, offsetMap);
     new ClassMemberParser(listener,
-            allowPatterns: library.libraryFeatures.patterns.isEnabled)
+            allowPatterns: compilationUnit.libraryFeatures.patterns.isEnabled)
         .parseUnit(tokens);
-    library.offsetMap = offsetMap;
+    compilationUnit.offsetMap = offsetMap;
   }
 
   /// Builds all the method bodies found in the given [library].
@@ -1176,7 +1177,8 @@
     // We tokenize source files twice to keep memory usage low. This is the
     // second time, and the first time was in [buildOutline] above. So this
     // time we suppress lexical errors.
-    Token tokens = await tokenize(library, suppressLexicalErrors: true);
+    SourceCompilationUnit compilationUnit = library.compilationUnit;
+    Token tokens = await tokenize(compilationUnit, suppressLexicalErrors: true);
 
     if (target.benchmarker != null) {
       // When benchmarking we do extra parsing on it's own to get a timing of
@@ -1204,17 +1206,20 @@
       }
     }
 
-    DietListener listener = createDietListener(library, library.offsetMap);
+    DietListener listener =
+        createDietListener(library, compilationUnit.offsetMap);
     DietParser parser = new DietParser(listener,
         allowPatterns: library.libraryFeatures.patterns.isEnabled);
     parser.parseUnit(tokens);
     for (Part part in library.parts) {
       assert(part.compilationUnit.partOfLibrary == library,
           "Part ${part.compilationUnit} is not part of ${library}.");
-      Token tokens = await tokenize(
-          (part.compilationUnit as SourceCompilationUnit).sourceLibraryBuilder,
-          suppressLexicalErrors: true);
-      DietListener listener = createDietListener(library, part.offsetMap);
+      SourceCompilationUnit compilationUnit =
+          part.compilationUnit as SourceCompilationUnit;
+      Token tokens =
+          await tokenize(compilationUnit, suppressLexicalErrors: true);
+      DietListener listener =
+          createDietListener(library, compilationUnit.offsetMap);
       DietParser parser = new DietParser(listener,
           allowPatterns: library.libraryFeatures.patterns.isEnabled);
       parser.parseUnit(tokens);
@@ -1227,7 +1232,8 @@
       bool isClassInstanceMember,
       FunctionNode parameters,
       VariableDeclaration? extensionThis) async {
-    Token token = await tokenize(libraryBuilder, suppressLexicalErrors: false);
+    Token token = await tokenize(libraryBuilder.compilationUnit,
+        suppressLexicalErrors: false);
     DietListener dietListener = createDietListener(
         libraryBuilder,
         // Expression compilation doesn't build an outline, and thus doesn't
diff --git a/pkg/front_end/test/comments_on_certain_arguments_tool.dart b/pkg/front_end/test/comments_on_certain_arguments_tool.dart
index dfc2a3a..2a9d482 100644
--- a/pkg/front_end/test/comments_on_certain_arguments_tool.dart
+++ b/pkg/front_end/test/comments_on_certain_arguments_tool.dart
@@ -3,51 +3,34 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:convert' show utf8;
-
 import 'dart:io'
     show Directory, File, FileSystemEntity, exitCode, stdin, stdout;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-
 import 'package:_fe_analyzer_shared/src/scanner/token.dart'
     show CommentToken, Token;
-
 import 'package:front_end/src/api_prototype/compiler_options.dart' as api
     show CompilerOptions, DiagnosticMessage;
-
 import 'package:front_end/src/api_prototype/file_system.dart' as api
     show FileSystem;
 import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
     show IncrementalCompilerResult;
-
 import 'package:front_end/src/base/processed_options.dart'
     show ProcessedOptions;
-
 import 'package:front_end/src/compute_platform_binaries_location.dart'
     show computePlatformBinariesLocation;
-
+import 'package:front_end/src/fasta/builder/library_builder.dart';
 import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-
 import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
-
 import 'package:front_end/src/fasta/incremental_compiler.dart'
     show IncrementalCompiler, IncrementalKernelTarget;
-
 import 'package:front_end/src/fasta/kernel/kernel_target.dart'
     show KernelTarget;
-
-import 'package:front_end/src/fasta/source/source_library_builder.dart'
-    show SourceLibraryBuilder;
-
 import 'package:front_end/src/fasta/source/source_loader.dart'
     show SourceLoader;
-
 import 'package:front_end/src/fasta/uri_translator.dart' show UriTranslator;
-
 import 'package:kernel/ast.dart';
-
 import 'package:kernel/target/targets.dart' show TargetFlags;
-
 import "package:vm/modular/target/vm.dart" show VmTarget;
 
 import "utils/io_utils.dart" show computeRepoDirUri;
@@ -414,11 +397,11 @@
       : super(fileSystem, includeComments, target);
 
   @override
-  Future<Token> tokenize(SourceLibraryBuilder library,
+  Future<Token> tokenize(SourceCompilationUnit sourceCompilationUnit,
       {bool suppressLexicalErrors = false}) async {
-    Token result = await super
-        .tokenize(library, suppressLexicalErrors: suppressLexicalErrors);
-    cache[library.fileUri] = result;
+    Token result = await super.tokenize(sourceCompilationUnit,
+        suppressLexicalErrors: suppressLexicalErrors);
+    cache[sourceCompilationUnit.fileUri] = result;
     return result;
   }
 }
diff --git a/pkg/front_end/tool/dart_doctest_impl.dart b/pkg/front_end/tool/dart_doctest_impl.dart
index 76379a4..8663c63 100644
--- a/pkg/front_end/tool/dart_doctest_impl.dart
+++ b/pkg/front_end/tool/dart_doctest_impl.dart
@@ -847,7 +847,7 @@
                   combinator.fileOffset, libraryBuilder.fileUri));
         }
 
-        dartDocTestLibrary.addImport(
+        dartDocTestLibrary.compilationUnit.addImport(
             metadata: null,
             isAugmentationImport: false,
             uri: dependency.importedLibraryReference.asLibrary.importUri
@@ -862,7 +862,7 @@
             importIndex: -1);
       }
 
-      dartDocTestLibrary.addImport(
+      dartDocTestLibrary.compilationUnit.addImport(
           metadata: null,
           isAugmentationImport: false,
           uri: libraryBuilder.importUri.toString(),