[cfe] Add BuilderFactory interface to use in OutlineBuilder

This moves SourceCompilationUnit methods only used in the OutlineBuilder
to a separate BuilderFactory interface.

Change-Id: I6bb270404c3c0e19856513674608c5d493f38924
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373500
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/base/incremental_compiler.dart b/pkg/front_end/lib/src/base/incremental_compiler.dart
index 151ef00..5075844 100644
--- a/pkg/front_end/lib/src/base/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/base/incremental_compiler.dart
@@ -1912,18 +1912,11 @@
                     combinator.fileOffset, libraryBuilder.fileUri));
           }
 
-          debugLibrary.compilationUnit.addImport(
-              metadata: null,
-              isAugmentationImport: false,
+          debugLibrary.compilationUnit.addSyntheticImport(
               uri: dependency.importedLibraryReference.canonicalName!.name,
-              configurations: null,
               prefix: dependency.name,
               combinators: combinators,
-              deferred: dependency.isDeferred,
-              charOffset: -1,
-              prefixCharOffset: -1,
-              uriOffset: -1,
-              importIndex: -1);
+              deferred: dependency.isDeferred);
         }
 
         debugLibrary.addImportsToScope();
diff --git a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
index d9cdc27..bb15a6f 100644
--- a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
@@ -18,6 +18,7 @@
 import '../kernel/body_builder_context.dart';
 import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
 import '../source/constructor_declaration.dart';
+import '../source/builder_factory.dart';
 import '../source/source_factory_builder.dart';
 import '../source/source_field_builder.dart';
 import '../source/source_library_builder.dart';
@@ -193,10 +194,9 @@
         kind, type.clone(newTypes, contextLibrary, contextDeclaration), name);
   }
 
-  FormalParameterBuilder forPrimaryConstructor(
-      SourceCompilationUnit compilationUnit) {
+  FormalParameterBuilder forPrimaryConstructor(BuilderFactory builderFactory) {
     return new FormalParameterBuilder(kind, modifiers | initializingFormalMask,
-        compilationUnit.addInferableType(), name, null, charOffset,
+        builderFactory.addInferableType(), name, null, charOffset,
         fileUri: fileUri,
         isExtensionThis: isExtensionThis,
         hasImmediatelyDeclaredInitializer: hasImmediatelyDeclaredInitializer)
diff --git a/pkg/front_end/lib/src/builder/library_builder.dart b/pkg/front_end/lib/src/builder/library_builder.dart
index 253c72c..27e2a29 100644
--- a/pkg/front_end/lib/src/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/builder/library_builder.dart
@@ -5,15 +5,10 @@
 library fasta.library_builder;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-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, Reference;
+import 'package:kernel/ast.dart' show Class, Library;
 
 import '../api_prototype/experimental_flags.dart';
 import '../base/combinator.dart' show CombinatorBuilder;
-import '../base/configuration.dart';
 import '../base/export.dart' show Export;
 import '../base/identifiers.dart';
 import '../base/loader.dart' show Loader;
@@ -28,26 +23,22 @@
         templateInternalProblemPrivateConstructorAccess;
 import '../base/problems.dart' show internalProblem;
 import '../base/scope.dart';
+import '../kernel/hierarchy/members_builder.dart';
 import '../source/name_scheme.dart';
 import '../source/offset_map.dart';
+import '../source/outline_builder.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';
 
@@ -110,8 +101,9 @@
 
 abstract class DillCompilationUnit implements CompilationUnit {}
 
-abstract class SourceCompilationUnit
-    implements CompilationUnit, ProblemReporting {
+abstract class SourceCompilationUnit implements CompilationUnit {
+  OutlineBuilder createOutlineBuilder();
+
   SourceLibraryBuilder createLibrary();
 
   @override
@@ -120,45 +112,13 @@
   // TODO(johnniwinther): Remove this.
   SourceLibraryBuilder get sourceLibraryBuilder;
 
-  abstract OffsetMap offsetMap;
+  OffsetMap get offsetMap;
 
   LibraryFeatures get libraryFeatures;
 
   /// Returns `true` if the compilation unit is part of a `dart:` library.
   bool get isDartLibrary;
 
-  /// 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});
 
@@ -206,271 +166,6 @@
 
   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});
-
-  Builder addBuilder(String name, Builder declaration, int charOffset,
-      {Reference? getterReference, Reference? setterReference});
-
   /// Reports that [feature] is not enabled, using [charOffset] and
   /// [length] for the location of the message.
   ///
@@ -478,6 +173,12 @@
   Message reportFeatureNotEnabled(
       LibraryFeature feature, Uri fileUri, int charOffset, int length);
 
+  void addSyntheticImport(
+      {required String uri,
+      required String? prefix,
+      required List<CombinatorBuilder>? combinators,
+      required bool deferred});
+
   void addImportsToScope();
 
   int finishDeferredLoadTearoffs();
@@ -498,6 +199,11 @@
   /// The variance property of type parameters on typedefs is computed from the
   /// use of the parameters in the right-hand side of the typedef definition.
   int computeVariances();
+
+  void computeShowHideElements(ClassMembersBuilder membersBuilder);
+
+  // TODO(johnniwinther): Remove this.
+  Builder addBuilder(String name, Builder declaration, int charOffset);
 }
 
 abstract class LibraryBuilder implements Builder, ProblemReporting {
diff --git a/pkg/front_end/lib/src/source/builder_factory.dart b/pkg/front_end/lib/src/source/builder_factory.dart
new file mode 100644
index 0000000..12c671c
--- /dev/null
+++ b/pkg/front_end/lib/src/source/builder_factory.dart
@@ -0,0 +1,323 @@
+// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+import 'package:kernel/ast.dart' hide Combinator, MapLiteralEntry;
+
+import '../base/combinator.dart' show CombinatorBuilder;
+import '../base/configuration.dart' show Configuration;
+import '../base/identifiers.dart' show Identifier;
+import '../builder/builder.dart';
+import '../builder/constructor_reference_builder.dart';
+import '../builder/declaration_builders.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/mixin_application_builder.dart';
+import '../builder/named_type_builder.dart';
+import '../builder/nullability_builder.dart';
+import '../builder/omitted_type_builder.dart';
+import '../builder/type_builder.dart';
+import 'offset_map.dart';
+import 'source_enum_builder.dart';
+import 'source_library_builder.dart';
+
+abstract class BuilderFactory {
+  /// 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();
+
+  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});
+
+  Builder addBuilder(String name, Builder declaration, int charOffset,
+      {Reference? getterReference, Reference? setterReference});
+}
diff --git a/pkg/front_end/lib/src/source/outline_builder.dart b/pkg/front_end/lib/src/source/outline_builder.dart
index 92183a6..8740907 100644
--- a/pkg/front_end/lib/src/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/source/outline_builder.dart
@@ -33,6 +33,7 @@
 import '../base/identifiers.dart'
     show Identifier, OperatorIdentifier, SimpleIdentifier, flattenName;
 import '../base/ignored_parser_errors.dart' show isIgnoredParserError;
+import '../base/messages.dart';
 import '../base/modifier.dart'
     show
         Augment,
@@ -53,9 +54,6 @@
         mixinDeclarationMask,
         requiredMask,
         staticMask;
-import '../base/operator.dart' show Operator;
-import '../base/problems.dart' show unhandled;
-import '../base/uris.dart';
 import '../builder/constructor_reference_builder.dart';
 import '../builder/declaration_builders.dart';
 import '../builder/fixed_type_builder.dart';
@@ -69,9 +67,12 @@
 import '../builder/omitted_type_builder.dart';
 import '../builder/record_type_builder.dart';
 import '../builder/type_builder.dart';
-import '../codes/cfe_codes.dart';
+import '../base/operator.dart' show Operator;
+import '../base/problems.dart' show unhandled;
+import '../base/uris.dart';
 import '../kernel/type_algorithms.dart';
 import '../kernel/utils.dart';
+import 'builder_factory.dart';
 import 'offset_map.dart';
 import 'source_enum_builder.dart';
 import 'source_library_builder.dart'
@@ -499,7 +500,9 @@
 }
 
 class OutlineBuilder extends StackListenerImpl {
-  final SourceCompilationUnit compilationUnit;
+  final SourceCompilationUnit _compilationUnit;
+  final ProblemReporting _problemReporting;
+  final BuilderFactory _builderFactory;
 
   final bool enableNative;
   bool inAbstractOrSealedClass = false;
@@ -537,20 +540,21 @@
 
   OffsetMap _offsetMap;
 
-  OutlineBuilder(this.compilationUnit, this._offsetMap)
-      : enableNative = compilationUnit.loader.target.backendTarget
-            .enableNative(compilationUnit.importUri);
+  OutlineBuilder(this._compilationUnit, this._problemReporting,
+      this._builderFactory, this._offsetMap)
+      : enableNative = _compilationUnit.loader.target.backendTarget
+            .enableNative(_compilationUnit.importUri);
 
   @override
-  LibraryFeatures get libraryFeatures => compilationUnit.libraryFeatures;
+  LibraryFeatures get libraryFeatures => _compilationUnit.libraryFeatures;
 
   @override
-  bool get isDartLibrary => compilationUnit.isDartLibrary;
+  bool get isDartLibrary => _compilationUnit.isDartLibrary;
 
   @override
   Message reportFeatureNotEnabled(
       LibraryFeature feature, int charOffset, int length) {
-    return compilationUnit.reportFeatureNotEnabled(
+    return _compilationUnit.reportFeatureNotEnabled(
         feature, uri, charOffset, length);
   }
 
@@ -569,7 +573,7 @@
   }
 
   @override
-  Uri get uri => compilationUnit.fileUri;
+  Uri get uri => _compilationUnit.fileUri;
 
   int popCharOffset() => pop() as int;
 
@@ -648,7 +652,7 @@
       push(names);
     } else {
       push(new CombinatorBuilder.hide(names as Iterable<String>,
-          hideKeyword.charOffset, compilationUnit.fileUri));
+          hideKeyword.charOffset, _compilationUnit.fileUri));
     }
   }
 
@@ -660,7 +664,7 @@
       push(names);
     } else {
       push(new CombinatorBuilder.show(names as Iterable<String>,
-          showKeyword.charOffset, compilationUnit.fileUri));
+          showKeyword.charOffset, _compilationUnit.fileUri));
     }
   }
 
@@ -690,7 +694,7 @@
     int uriOffset = popCharOffset();
     String uri = pop() as String;
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-    compilationUnit.addExport(_offsetMap, exportKeyword, metadata, uri,
+    _builderFactory.addExport(_offsetMap, exportKeyword, metadata, uri,
         configurations, combinators, exportKeyword.charOffset, uriOffset);
     checkEmpty(exportKeyword.charOffset);
   }
@@ -744,7 +748,7 @@
       }
     }
     bool isAugmentationImport = augmentToken != null;
-    compilationUnit.addImport(
+    _builderFactory.addImport(
         offsetMap: _offsetMap,
         importKeyword: importKeyword,
         metadata: metadata,
@@ -825,7 +829,7 @@
     int charOffset = popCharOffset();
     String uri = pop() as String;
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-    compilationUnit.addPart(_offsetMap, partKeyword, metadata, uri, charOffset);
+    _builderFactory.addPart(_offsetMap, partKeyword, metadata, uri, charOffset);
     checkEmpty(partKeyword.charOffset);
   }
 
@@ -965,13 +969,13 @@
     }
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     if (name != null && name is! ParserRecovery) {
-      compilationUnit.name =
+      _compilationUnit.name =
           flattenName(name, offsetForToken(libraryKeyword), uri);
     } else {
       reportIfNotEnabled(
           libraryFeatures.unnamedLibraries, semicolon.charOffset, noLength);
     }
-    compilationUnit.metadata = metadata;
+    _compilationUnit.metadata = metadata;
   }
 
   @override
@@ -987,7 +991,7 @@
     pop() as int;
     pop() as String;
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-    compilationUnit.metadata = metadata;
+    _compilationUnit.metadata = metadata;
   }
 
   @override
@@ -995,7 +999,7 @@
     debugEvent("beginClassOrNamedMixinApplicationPrelude");
     pushDeclarationContext(
         DeclarationContext.ClassOrMixinOrNamedMixinApplication);
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.classOrNamedMixinApplication,
         "class or mixin application");
   }
@@ -1055,9 +1059,9 @@
         mixinToken = null;
       }
     }
-    compilationUnit.currentTypeParameterScopeBuilder
+    _builderFactory.currentTypeParameterScopeBuilder
         .markAsClassDeclaration(name.lexeme, name.charOffset, typeVariables);
-    compilationUnit.beginIndexedContainer(name.lexeme,
+    _builderFactory.beginIndexedContainer(name.lexeme,
         isExtensionTypeDeclaration: false);
     inAbstractOrSealedClass = abstractToken != null || sealedToken != null;
     push(abstractToken != null ? abstractMask : 0);
@@ -1088,9 +1092,9 @@
     push(augmentToken ?? NullValues.Token);
     push(baseToken ?? NullValues.Token);
     push(typeVariables ?? NullValues.NominalVariables);
-    compilationUnit.currentTypeParameterScopeBuilder
+    _builderFactory.currentTypeParameterScopeBuilder
         .markAsMixinDeclaration(name.lexeme, name.charOffset, typeVariables);
-    compilationUnit.beginIndexedContainer(name.lexeme,
+    _builderFactory.beginIndexedContainer(name.lexeme,
         isExtensionTypeDeclaration: false);
   }
 
@@ -1125,7 +1129,7 @@
       Object? extensionThisType = peek();
 
       if (extensionThisType is TypeBuilder) {
-        compilationUnit.currentTypeParameterScopeBuilder
+        _builderFactory.currentTypeParameterScopeBuilder
             .registerExtensionThisType(extensionThisType);
       } else {
         // TODO(johnniwinther): Supply an invalid type as the extension on type.
@@ -1135,9 +1139,9 @@
     // 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.
-    compilationUnit.currentTypeParameterScopeBuilder.resolveNamedTypes(
-        compilationUnit.currentTypeParameterScopeBuilder.typeVariables,
-        compilationUnit);
+    _builderFactory.currentTypeParameterScopeBuilder.resolveNamedTypes(
+        _builderFactory.currentTypeParameterScopeBuilder.typeVariables,
+        _problemReporting);
   }
 
   @override
@@ -1159,7 +1163,7 @@
     List<NominalVariableBuilder>? typeVariables =
         pop() as List<NominalVariableBuilder>?;
     push(typeVariables ?? NullValues.NominalVariables);
-    compilationUnit.currentTypeParameterScopeBuilder
+    _builderFactory.currentTypeParameterScopeBuilder
         .markAsNamedMixinApplication(
             name.lexeme, name.charOffset, typeVariables);
     push(abstractToken != null ? abstractMask : 0);
@@ -1327,10 +1331,10 @@
     inAbstractOrSealedClass = false;
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) {
-      compilationUnit
+      _builderFactory
           .endNestedDeclaration(
               TypeParameterScopeKind.classDeclaration, "<syntax-error>")
-          .resolveNamedTypes(typeVariables, compilationUnit);
+          .resolveNamedTypes(typeVariables, _problemReporting);
     } else {
       Identifier identifier = name as Identifier;
       final int startCharOffset =
@@ -1339,7 +1343,7 @@
       String classNameForErrors = identifier.name;
       if (supertype != null) {
         if (supertype.nullabilityBuilder.build() == Nullability.nullable) {
-          compilationUnit.addProblem(
+          _compilationUnit.addProblem(
               templateNullableSuperclassError
                   .withArguments(supertype.fullNameForErrors),
               identifier.nameOffset,
@@ -1351,7 +1355,7 @@
         List<TypeBuilder>? mixins = mixinApplication.mixins;
         for (TypeBuilder mixin in mixins) {
           if (mixin.nullabilityBuilder.build() == Nullability.nullable) {
-            compilationUnit.addProblem(
+            _compilationUnit.addProblem(
                 templateNullableMixinError
                     .withArguments(mixin.fullNameForErrors),
                 identifier.nameOffset,
@@ -1363,7 +1367,7 @@
       if (interfaces != null) {
         for (TypeBuilder interface in interfaces) {
           if (interface.nullabilityBuilder.build() == Nullability.nullable) {
-            compilationUnit.addProblem(
+            _compilationUnit.addProblem(
                 templateNullableInterfaceError
                     .withArguments(interface.fullNameForErrors),
                 identifier.nameOffset,
@@ -1376,7 +1380,7 @@
       if (sealedToken != null) {
         modifiers |= abstractMask;
       }
-      compilationUnit.addClass(
+      _builderFactory.addClass(
           _offsetMap,
           metadata,
           modifiers,
@@ -1397,7 +1401,7 @@
           isAugmentation: augmentToken != null,
           isMixinClass: mixinToken != null);
     }
-    compilationUnit.endIndexedContainer();
+    _builderFactory.endIndexedContainer();
     popDeclarationContext(DeclarationContext.Class);
   }
 
@@ -1434,10 +1438,10 @@
         pop(NullValues.Metadata) as List<MetadataBuilder>?;
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) {
-      compilationUnit
+      _builderFactory
           .endNestedDeclaration(
               TypeParameterScopeKind.mixinDeclaration, "<syntax-error>")
-          .resolveNamedTypes(typeVariables, compilationUnit);
+          .resolveNamedTypes(typeVariables, _problemReporting);
     } else {
       Identifier identifier = name as Identifier;
       int startOffset =
@@ -1446,7 +1450,7 @@
       if (supertypeConstraints != null) {
         for (TypeBuilder supertype in supertypeConstraints) {
           if (supertype.nullabilityBuilder.build() == Nullability.nullable) {
-            compilationUnit.addProblem(
+            _compilationUnit.addProblem(
                 templateNullableSuperclassError
                     .withArguments(supertype.fullNameForErrors),
                 identifier.nameOffset,
@@ -1458,7 +1462,7 @@
       if (interfaces != null) {
         for (TypeBuilder interface in interfaces) {
           if (interface.nullabilityBuilder.build() == Nullability.nullable) {
-            compilationUnit.addProblem(
+            _compilationUnit.addProblem(
                 templateNullableInterfaceError
                     .withArguments(interface.fullNameForErrors),
                 identifier.nameOffset,
@@ -1468,7 +1472,7 @@
         }
       }
 
-      compilationUnit.addMixinDeclaration(
+      _builderFactory.addMixinDeclaration(
           _offsetMap,
           metadata,
           mixinDeclarationMask,
@@ -1483,7 +1487,7 @@
           isBase: baseToken != null,
           isAugmentation: augmentToken != null);
     }
-    compilationUnit.endIndexedContainer();
+    _builderFactory.endIndexedContainer();
     popDeclarationContext(DeclarationContext.Mixin);
   }
 
@@ -1492,7 +1496,7 @@
     assert(checkState(extensionKeyword, [ValueKinds.MetadataListOrNull]));
     debugEvent("beginExtensionDeclaration");
     pushDeclarationContext(DeclarationContext.ExtensionOrExtensionType);
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.extensionOrExtensionTypeDeclaration,
         "extension");
   }
@@ -1512,7 +1516,7 @@
         ? new SimpleIdentifier(nameToken)
         : NullValues.Identifier);
     push(typeVariables ?? NullValues.NominalVariables);
-    compilationUnit.currentTypeParameterScopeBuilder
+    _builderFactory.currentTypeParameterScopeBuilder
         .markAsExtensionDeclaration(nameToken?.lexeme, offset, typeVariables);
   }
 
@@ -1543,7 +1547,7 @@
     int startOffset = metadata == null
         ? extensionKeyword.charOffset
         : metadata.first.charOffset;
-    compilationUnit.addExtensionDeclaration(
+    _builderFactory.addExtensionDeclaration(
         _offsetMap,
         beginToken,
         metadata,
@@ -1572,9 +1576,9 @@
     int offset = nameToken.charOffset;
     push(new SimpleIdentifier(nameToken));
     push(typeVariables ?? NullValues.NominalVariables);
-    compilationUnit.currentTypeParameterScopeBuilder
+    _builderFactory.currentTypeParameterScopeBuilder
         .markAsExtensionTypeDeclaration(name, offset, typeVariables);
-    compilationUnit.beginIndexedContainer(name,
+    _builderFactory.beginIndexedContainer(name,
         isExtensionTypeDeclaration: true);
   }
 
@@ -1604,7 +1608,7 @@
     int startOffset = metadata == null
         ? extensionKeyword.charOffset
         : metadata.first.charOffset;
-    compilationUnit.addExtensionTypeDeclaration(
+    _builderFactory.addExtensionTypeDeclaration(
         _offsetMap,
         metadata,
         // TODO(johnniwinther): Support modifiers on extension types?
@@ -1615,7 +1619,7 @@
         startOffset,
         endToken.charOffset);
 
-    compilationUnit.endIndexedContainer();
+    _builderFactory.endIndexedContainer();
     popDeclarationContext(DeclarationContext.ExtensionType);
   }
 
@@ -1652,7 +1656,7 @@
           TypeBuilder type = formal.type;
           if (type is FunctionTypeBuilder &&
               type.hasFunctionFormalParameterSyntax) {
-            compilationUnit.addProblem(
+            _compilationUnit.addProblem(
                 // ignore: lines_longer_than_80_chars
                 messageExtensionTypePrimaryConstructorFunctionFormalParameterSyntax,
                 formal.charOffset,
@@ -1660,7 +1664,7 @@
                 formal.fileUri);
           }
           if (type is ImplicitTypeBuilder) {
-            compilationUnit.addProblem(messageExpectedRepresentationType,
+            _compilationUnit.addProblem(messageExpectedRepresentationType,
                 formal.charOffset, formal.name.length, formal.fileUri);
             formal.type =
                 new InvalidTypeBuilderImpl(formal.fileUri, formal.charOffset);
@@ -1670,11 +1674,11 @@
               Modifier.removeCovariantMask(
                   // 'required' is reported in the parser.
                   Modifier.removeRequiredMask(formal.modifiers)))) {
-            compilationUnit.addProblem(messageRepresentationFieldModifier,
+            _compilationUnit.addProblem(messageRepresentationFieldModifier,
                 formal.charOffset, formal.name.length, formal.fileUri);
           }
           if (formal.isInitializingFormal) {
-            compilationUnit.addProblem(
+            _compilationUnit.addProblem(
                 messageExtensionTypePrimaryConstructorWithInitializingFormal,
                 formal.charOffset,
                 formal.name.length,
@@ -1692,7 +1696,7 @@
         if (formal.isNamed) {
           firstNamedParameterOffset = formal.charOffset;
         }
-        compilationUnit.addPrimaryConstructorField(
+        _builderFactory.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
@@ -1701,44 +1705,44 @@
             type: formal.type,
             name: formal.name,
             charOffset: formal.charOffset);
-        formals[i] = formal.forPrimaryConstructor(compilationUnit);
+        formals[i] = formal.forPrimaryConstructor(_builderFactory);
       }
       if (inExtensionType) {
         if (firstOptionalPositionalParameterOffset != null) {
-          compilationUnit.addProblem(
+          _compilationUnit.addProblem(
               messageOptionalParametersInExtensionTypeDeclaration,
               firstOptionalPositionalParameterOffset,
               1,
               uri);
         } else if (firstNamedParameterOffset != null) {
-          compilationUnit.addProblem(
+          _compilationUnit.addProblem(
               messageNamedParametersInExtensionTypeDeclaration,
               firstNamedParameterOffset,
               1,
               uri);
         } else if (requiredPositionalCount == 0) {
-          compilationUnit.addProblem(
+          _compilationUnit.addProblem(
               messageExpectedRepresentationField, charOffset, 1, uri);
         } else if (formals.length > 1) {
-          compilationUnit.addProblem(
+          _compilationUnit.addProblem(
               messageMultipleRepresentationFields, charOffset, 1, uri);
         }
       }
     }
 
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.constructor, "#method",
         hasMembers: false);
-    TypeParameterScopeBuilder scopeBuilder = compilationUnit
+    TypeParameterScopeBuilder scopeBuilder = _builderFactory
         .endNestedDeclaration(TypeParameterScopeKind.constructor, "#method");
     var (
       List<NominalVariableBuilder>? typeVariables,
       _
     ) = _createSyntheticTypeVariables(
-        compilationUnit.currentTypeParameterScopeBuilder, scopeBuilder, null);
-    scopeBuilder.resolveNamedTypes(typeVariables, compilationUnit);
+        _builderFactory.currentTypeParameterScopeBuilder, scopeBuilder, null);
+    scopeBuilder.resolveNamedTypes(typeVariables, _problemReporting);
 
-    compilationUnit.addPrimaryConstructor(
+    _builderFactory.addPrimaryConstructor(
         offsetMap: _offsetMap,
         beginToken: beginToken,
         constructorName: constructorName == "new" ? "" : constructorName,
@@ -1760,7 +1764,7 @@
   void beginTopLevelMethod(
       Token lastConsumed, Token? augmentToken, Token? externalToken) {
     pushDeclarationContext(DeclarationContext.TopLevelMethod);
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.topLevelMethod, "#method",
         hasMembers: false);
     int modifiers = 0;
@@ -1817,13 +1821,13 @@
     }
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     checkEmpty(beginToken.charOffset);
-    compilationUnit
+    _builderFactory
         .endNestedDeclaration(TypeParameterScopeKind.topLevelMethod, "#method")
-        .resolveNamedTypes(typeVariables, compilationUnit);
+        .resolveNamedTypes(typeVariables, _problemReporting);
     if (identifier is Identifier) {
       final int startCharOffset =
           metadata == null ? beginToken.charOffset : metadata.first.charOffset;
-      compilationUnit.addProcedure(
+      _builderFactory.addProcedure(
           _offsetMap,
           metadata,
           modifiers,
@@ -1898,7 +1902,7 @@
       Token? getOrSet,
       Token name) {
     inConstructor =
-        name.lexeme == compilationUnit.currentTypeParameterScopeBuilder.name &&
+        name.lexeme == _builderFactory.currentTypeParameterScopeBuilder.name &&
             getOrSet == null;
     DeclarationContext declarationContext;
     switch (declarationKind) {
@@ -1998,7 +2002,7 @@
     } else {
       kind = TypeParameterScopeKind.instanceMethod;
     }
-    compilationUnit.beginNestedDeclaration(kind, "#method", hasMembers: false);
+    _builderFactory.beginNestedDeclaration(kind, "#method", hasMembers: false);
   }
 
   @override
@@ -2076,7 +2080,7 @@
       // rename 'T' to '#T'. We cannot do it on the builders because their
       // names are used to create the scope.
       List<NominalVariableBuilder> synthesizedTypeVariables =
-          compilationUnit.copyTypeVariables(
+          _builderFactory.copyTypeVariables(
               enclosingDeclarationScopeBuilder.typeVariables!,
               memberScopeBuilder,
               kind: TypeVariableKind.extensionSynthesized);
@@ -2138,14 +2142,14 @@
       scopeKind = TypeParameterScopeKind.instanceMethod;
     }
     TypeParameterScopeBuilder declarationBuilder =
-        compilationUnit.endNestedDeclaration(scopeKind, "#method");
+        _builderFactory.endNestedDeclaration(scopeKind, "#method");
 
     if (identifier is! Identifier) {
       assert(identifier is ParserRecovery,
           "Unexpected identifier $identifier (${identifier.runtimeType})");
       nativeMethodName = null;
       inConstructor = false;
-      declarationBuilder.resolveNamedTypes(typeVariables, compilationUnit);
+      declarationBuilder.resolveNamedTypes(typeVariables, _problemReporting);
       popDeclarationContext();
       return;
     }
@@ -2247,7 +2251,7 @@
       case _MethodKind.extensionTypeConstructor:
       case _MethodKind.enumConstructor:
         constructorName =
-            compilationUnit.computeAndValidateConstructorName(identifier) ??
+            _compilationUnit.computeAndValidateConstructorName(identifier) ??
                 name;
         break;
       case _MethodKind.classMethod:
@@ -2260,7 +2264,7 @@
     bool isStatic = (modifiers & staticMask) != 0;
     bool isConstructor = constructorName != null;
     bool cloneTypeVariablesFromEnclosingDeclaration;
-    switch (compilationUnit.currentTypeParameterScopeBuilder.kind) {
+    switch (_builderFactory.currentTypeParameterScopeBuilder.kind) {
       case TypeParameterScopeKind.extensionDeclaration:
       case TypeParameterScopeKind.extensionTypeDeclaration:
         cloneTypeVariablesFromEnclosingDeclaration = !isStatic;
@@ -2283,7 +2287,7 @@
     }
     if (cloneTypeVariablesFromEnclosingDeclaration) {
       TypeParameterScopeBuilder declaration =
-          compilationUnit.currentTypeParameterScopeBuilder;
+          _builderFactory.currentTypeParameterScopeBuilder;
       Map<NominalVariableBuilder, TypeBuilder>? substitution;
       (typeVariables, substitution) = _createSyntheticTypeVariables(
           declaration, declarationBuilder, typeVariables);
@@ -2293,7 +2297,7 @@
         if (declaration.kind == TypeParameterScopeKind.extensionDeclaration) {
           thisType = declaration.extensionThisType;
         } else {
-          thisType = compilationUnit.addNamedType(
+          thisType = _builderFactory.addNamedType(
               new SyntheticTypeName(declaration.name, charOffset),
               const NullabilityBuilder.omitted(),
               declaration.typeVariables != null
@@ -2319,7 +2323,7 @@
           for (NamedTypeBuilder unboundType in unboundTypes) {
             declaration.registerUnresolvedNamedType(unboundType);
           }
-          compilationUnit.unboundStructuralVariables
+          _compilationUnit.unboundStructuralVariables
               .addAll(unboundTypeVariables);
         }
         synthesizedFormals.add(new FormalParameterBuilder(
@@ -2339,7 +2343,7 @@
       }
     }
 
-    declarationBuilder.resolveNamedTypes(typeVariables, compilationUnit);
+    declarationBuilder.resolveNamedTypes(typeVariables, _problemReporting);
     if (constructorName != null) {
       if (isConst &&
           bodyKind != MethodBody.Abstract &&
@@ -2354,7 +2358,7 @@
       }
       final int startCharOffset =
           metadata == null ? beginToken.charOffset : metadata.first.charOffset;
-      compilationUnit.addConstructor(
+      _builderFactory.addConstructor(
           _offsetMap,
           metadata,
           modifiers,
@@ -2381,7 +2385,7 @@
       bool isExtensionMember = methodKind == _MethodKind.extensionMethod;
       bool isExtensionTypeMember =
           methodKind == _MethodKind.extensionTypeMethod;
-      compilationUnit.addProcedure(
+      _builderFactory.addProcedure(
           _offsetMap,
           metadata,
           modifiers,
@@ -2423,7 +2427,7 @@
     if (mixins is ParserRecovery) {
       push(mixins);
     } else {
-      push(compilationUnit.addMixinApplication(
+      push(_builderFactory.addMixinApplication(
           mixins as List<TypeBuilder>, withKeyword.charOffset));
     }
     assert(checkState(withKeyword, [
@@ -2510,10 +2514,10 @@
     if (name is ParserRecovery ||
         supertype is ParserRecovery ||
         mixinApplication is ParserRecovery) {
-      compilationUnit
+      _builderFactory
           .endNestedDeclaration(
               TypeParameterScopeKind.namedMixinApplication, "<syntax-error>")
-          .resolveNamedTypes(typeVariables, compilationUnit);
+          .resolveNamedTypes(typeVariables, _problemReporting);
     } else {
       Identifier identifier = name as Identifier;
       String classNameForErrors = identifier.name;
@@ -2522,7 +2526,7 @@
       List<TypeBuilder> mixins = mixinApplicationBuilder.mixins;
       if (supertype is TypeBuilder && supertype is! MixinApplicationBuilder) {
         if (supertype.nullabilityBuilder.build() == Nullability.nullable) {
-          compilationUnit.addProblem(
+          _compilationUnit.addProblem(
               templateNullableSuperclassError
                   .withArguments(supertype.fullNameForErrors),
               identifier.nameOffset,
@@ -2532,7 +2536,7 @@
       }
       for (TypeBuilder mixin in mixins) {
         if (mixin.nullabilityBuilder.build() == Nullability.nullable) {
-          compilationUnit.addProblem(
+          _compilationUnit.addProblem(
               templateNullableMixinError.withArguments(mixin.fullNameForErrors),
               identifier.nameOffset,
               classNameForErrors.length,
@@ -2542,7 +2546,7 @@
       if (interfaces != null) {
         for (TypeBuilder interface in interfaces) {
           if (interface.nullabilityBuilder.build() == Nullability.nullable) {
-            compilationUnit.addProblem(
+            _compilationUnit.addProblem(
                 templateNullableInterfaceError
                     .withArguments(interface.fullNameForErrors),
                 identifier.nameOffset,
@@ -2558,7 +2562,7 @@
 
       int startCharOffset = beginToken.charOffset;
       int charEndOffset = endToken.charOffset;
-      compilationUnit.addNamedMixinApplication(
+      _builderFactory.addNamedMixinApplication(
           metadata,
           identifier.name,
           typeVariables,
@@ -2603,7 +2607,7 @@
   @override
   void handleScript(Token token) {
     debugEvent("handleScript");
-    compilationUnit.addScriptToken(token.charOffset);
+    _builderFactory.addScriptToken(token.charOffset);
   }
 
   @override
@@ -2623,7 +2627,7 @@
       push(name);
     } else {
       Identifier identifier = name as Identifier;
-      push(compilationUnit.addNamedType(
+      push(_builderFactory.addNamedType(
           identifier.typeName,
           isMarkedAsNullable
               ? const NullabilityBuilder.nullable()
@@ -2670,14 +2674,14 @@
   @override
   void handleVoidKeyword(Token token) {
     debugEvent("VoidKeyword");
-    push(compilationUnit.addVoidType(token.charOffset));
+    push(_builderFactory.addVoidType(token.charOffset));
   }
 
   @override
   void handleVoidKeywordWithTypeArguments(Token token) {
     debugEvent("VoidKeyword");
     /*List<TypeBuilder> arguments =*/ pop();
-    push(compilationUnit.addVoidType(token.charOffset));
+    push(_builderFactory.addVoidType(token.charOffset));
   }
 
   @override
@@ -2725,13 +2729,13 @@
       push(name);
     } else {
       Identifier? identifier = name as Identifier?;
-      push(compilationUnit.addFormalParameter(
+      push(_builderFactory.addFormalParameter(
           metadata,
           kind,
           modifiers,
           type ??
               (memberKind.isParameterInferable
-                  ? compilationUnit.addInferableType()
+                  ? _builderFactory.addInferableType()
                   : const ImplicitTypeBuilder()),
           identifier == null
               ? FormalParameterBuilder.noNameSentinel
@@ -2804,7 +2808,7 @@
           optional(",", tokenBeforeEnd) &&
           kind == MemberKind.PrimaryConstructor &&
           declarationContext == DeclarationContext.ExtensionType) {
-        compilationUnit.addProblem(messageRepresentationFieldTrailingComma,
+        _compilationUnit.addProblem(messageRepresentationFieldTrailingComma,
             tokenBeforeEnd.charOffset, 1, uri);
       }
     } else if (count > 1) {
@@ -2886,7 +2890,7 @@
         formals != null) {
       for (FormalParameterBuilder formal in formals) {
         if (formal.isSuperInitializingFormal) {
-          compilationUnit.addProblem(
+          _compilationUnit.addProblem(
               messageExtensionTypeConstructorWithSuperFormalParameter,
               formal.charOffset,
               formal.name.length,
@@ -2924,10 +2928,10 @@
     } else {
       declarationName = '#enum';
     }
-    compilationUnit.beginIndexedContainer(declarationName,
+    _builderFactory.beginIndexedContainer(declarationName,
         isExtensionTypeDeclaration: false);
     pushDeclarationContext(DeclarationContext.Enum);
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.enumDeclaration, declarationName);
   }
 
@@ -2978,11 +2982,11 @@
 
     Object? identifier = peek();
     if (identifier is Identifier) {
-      compilationUnit.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
+      _builderFactory.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
           identifier.name, identifier.nameOffset, typeVariables);
     } else {
       identifier as ParserRecovery;
-      compilationUnit.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
+      _builderFactory.currentTypeParameterScopeBuilder.markAsEnumDeclaration(
           "<syntax-error>", identifier.charOffset, typeVariables);
     }
 
@@ -3069,7 +3073,7 @@
       if (interfaces != null) {
         for (TypeBuilder interface in interfaces) {
           if (interface.nullabilityBuilder.build() == Nullability.nullable) {
-            compilationUnit.addProblem(
+            _compilationUnit.addProblem(
                 templateNullableInterfaceError
                     .withArguments(interface.fullNameForErrors),
                 interface.charOffset ?? startCharOffset,
@@ -3079,7 +3083,7 @@
         }
       }
 
-      compilationUnit.addEnum(
+      _builderFactory.addEnum(
           _offsetMap,
           metadata,
           identifier,
@@ -3090,13 +3094,13 @@
           startCharOffset,
           endCharOffset);
     } else {
-      compilationUnit
+      _builderFactory
           .endNestedDeclaration(
               TypeParameterScopeKind.enumDeclaration, "<syntax-error>")
-          .resolveNamedTypes(typeVariables, compilationUnit);
+          .resolveNamedTypes(typeVariables, _problemReporting);
     }
 
-    compilationUnit.endIndexedContainer();
+    _builderFactory.endIndexedContainer();
     checkEmpty(enumKeyword.charOffset);
     popDeclarationContext(DeclarationContext.Enum);
   }
@@ -3104,7 +3108,7 @@
   @override
   void beginTypedef(Token token) {
     pushDeclarationContext(DeclarationContext.Typedef);
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.typedef, "#typedef",
         hasMembers: false);
   }
@@ -3113,7 +3117,7 @@
   void beginFunctionType(Token beginToken) {
     debugEvent("beginFunctionType");
     _structuralParameterDepthLevel++;
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.functionType, "#function_type",
         hasMembers: false);
   }
@@ -3122,7 +3126,7 @@
   void beginFunctionTypedFormalParameter(Token token) {
     debugEvent("beginFunctionTypedFormalParameter");
     _insideOfFormalParameterType = false;
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.functionType, "#function_type",
         hasMembers: false);
   }
@@ -3216,7 +3220,7 @@
     TypeBuilder? returnType = pop() as TypeBuilder?;
     List<StructuralVariableBuilder>? typeVariables =
         pop() as List<StructuralVariableBuilder>?;
-    push(compilationUnit.addFunctionType(
+    push(_builderFactory.addFunctionType(
         returnType ?? const ImplicitTypeBuilder(),
         typeVariables,
         formals,
@@ -3237,7 +3241,7 @@
     TypeBuilder? returnType = pop() as TypeBuilder?;
     List<StructuralVariableBuilder>? typeVariables =
         pop() as List<StructuralVariableBuilder>?;
-    push(compilationUnit.addFunctionType(
+    push(_builderFactory.addFunctionType(
         returnType ?? const ImplicitTypeBuilder(),
         typeVariables,
         formals,
@@ -3290,19 +3294,19 @@
       // `library.addFunctionType`.
       if (name is ParserRecovery) {
         pop(NullValues.Metadata); // Metadata.
-        compilationUnit
+        _builderFactory
             .endNestedDeclaration(
                 TypeParameterScopeKind.typedef, "<syntax-error>")
-            .resolveNamedTypes(typeVariables, compilationUnit);
+            .resolveNamedTypes(typeVariables, _problemReporting);
         popDeclarationContext(DeclarationContext.Typedef);
         return;
       }
       identifier = name as Identifier;
-      compilationUnit.beginNestedDeclaration(
+      _builderFactory.beginNestedDeclaration(
           TypeParameterScopeKind.functionType, "#function_type",
           hasMembers: false);
       // TODO(cstefantsova): Make sure that RHS of typedefs can't have '?'.
-      aliasedType = compilationUnit.addFunctionType(
+      aliasedType = _builderFactory.addFunctionType(
           returnType ?? const ImplicitTypeBuilder(),
           null,
           formals,
@@ -3317,10 +3321,10 @@
       name = pop();
       if (name is ParserRecovery) {
         pop(NullValues.Metadata); // Metadata.
-        compilationUnit
+        _builderFactory
             .endNestedDeclaration(
                 TypeParameterScopeKind.functionType, "<syntax-error>")
-            .resolveNamedTypes(typeVariables, compilationUnit);
+            .resolveNamedTypes(typeVariables, _problemReporting);
         popDeclarationContext(DeclarationContext.Typedef);
         return;
       }
@@ -3391,7 +3395,7 @@
         pop(NullValues.Metadata) as List<MetadataBuilder>?;
     checkEmpty(typedefKeyword.charOffset);
 
-    compilationUnit.addFunctionTypeAlias(metadata, identifier.name,
+    _builderFactory.addFunctionTypeAlias(metadata, identifier.name,
         typeVariables, aliasedType, identifier.nameOffset);
     popDeclarationContext(DeclarationContext.Typedef);
   }
@@ -3494,7 +3498,7 @@
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     checkEmpty(beginToken.charOffset);
     if (fieldInfos != null) {
-      compilationUnit.addFields(_offsetMap, metadata, modifiers,
+      _builderFactory.addFields(_offsetMap, metadata, modifiers,
           /* isTopLevel = */ true, type, fieldInfos);
     }
     popDeclarationContext();
@@ -3557,7 +3561,7 @@
     }
     List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
     if (fieldInfos != null) {
-      compilationUnit.addFields(_offsetMap, metadata, modifiers,
+      _builderFactory.addFields(_offsetMap, metadata, modifiers,
           /* isTopLevel = */ false, type, fieldInfos);
     }
     popDeclarationContext();
@@ -3607,10 +3611,10 @@
     } else {
       Identifier identifier = name as Identifier;
       if (inFunctionType) {
-        push(compilationUnit.addStructuralTypeVariable(
+        push(_builderFactory.addStructuralTypeVariable(
             metadata, identifier.name, null, identifier.nameOffset, uri));
       } else {
-        push(compilationUnit.addNominalTypeVariable(
+        push(_builderFactory.addNominalTypeVariable(
             metadata, identifier.name, null, identifier.nameOffset, uri,
             kind: declarationContext.typeVariableKind));
       }
@@ -3688,7 +3692,7 @@
     if (hasName) {
       Identifier containingLibrary = pop() as Identifier;
       List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-      compilationUnit.addPartOf(
+      _builderFactory.addPartOf(
           metadata,
           flattenName(containingLibrary, containingLibrary.firstOffset, uri),
           null,
@@ -3697,7 +3701,7 @@
       int charOffset = popCharOffset();
       String uriString = pop() as String;
       List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
-      compilationUnit.addPartOf(metadata, null, uriString, charOffset);
+      _builderFactory.addPartOf(metadata, null, uriString, charOffset);
     }
   }
 
@@ -3718,19 +3722,19 @@
     if (name is ParserRecovery) {
       push(name);
     } else if (name is Identifier) {
-      push(compilationUnit.addConstructorReference(
+      push(_builderFactory.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 (compilationUnit.currentTypeParameterScopeBuilder.kind ==
+      if (_builderFactory.currentTypeParameterScopeBuilder.kind ==
           TypeParameterScopeKind.enumDeclaration) {
         if (libraryFeatures.enhancedEnums.isEnabled) {
           int constructorNameOffset = suffix?.nameOffset ?? charOffset;
-          push(compilationUnit.addConstructorReference(
+          push(_builderFactory.addConstructorReference(
               new SyntheticTypeName(
-                  compilationUnit.currentTypeParameterScopeBuilder.name,
+                  _builderFactory.currentTypeParameterScopeBuilder.name,
                   constructorNameOffset),
               typeArguments,
               suffix?.name,
@@ -3739,7 +3743,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) {
-            compilationUnit.reportFeatureNotEnabled(
+            _compilationUnit.reportFeatureNotEnabled(
                 libraryFeatures.enhancedEnums, uri, charOffset, noLength);
           }
           push(NullValues.ConstructorReference);
@@ -3779,7 +3783,7 @@
 
     pushDeclarationContext(declarationContext);
     inConstructor = true;
-    compilationUnit.beginNestedDeclaration(
+    _builderFactory.beginNestedDeclaration(
         TypeParameterScopeKind.factoryMethod, "#factory_method",
         hasMembers: false);
     push((externalToken != null ? externalMask : 0) |
@@ -3828,10 +3832,10 @@
     if (name is! Identifier) {
       assert(name is ParserRecovery,
           "Unexpected name $name (${name.runtimeType}).");
-      compilationUnit.endNestedDeclaration(
+      _builderFactory.endNestedDeclaration(
           TypeParameterScopeKind.factoryMethod, "<syntax-error>");
     } else {
-      compilationUnit.addFactoryMethod(
+      _builderFactory.addFactoryMethod(
         _offsetMap,
         metadata,
         modifiers,
@@ -4015,7 +4019,7 @@
     if (supertype is ParserRecovery || mixins is ParserRecovery) {
       push(new ParserRecovery(withKeyword.charOffset));
     } else {
-      push(compilationUnit.addMixinApplication(
+      push(_builderFactory.addMixinApplication(
           mixins as List<TypeBuilder>, withKeyword.charOffset));
     }
     assert(checkState(withKeyword, [
@@ -4069,7 +4073,7 @@
     if (mixins is ParserRecovery) {
       push(new ParserRecovery(withKeyword.charOffset));
     } else {
-      push(compilationUnit.addMixinApplication(
+      push(_builderFactory.addMixinApplication(
           mixins as List<TypeBuilder>, withKeyword.charOffset));
     }
     assert(checkState(withKeyword, [
@@ -4129,7 +4133,7 @@
   @override
   void addProblem(Message message, int charOffset, int length,
       {bool wasHandled = false, List<LocatedMessage>? context}) {
-    compilationUnit.addProblem(message, charOffset, length, uri,
+    _compilationUnit.addProblem(message, charOffset, length, uri,
         wasHandled: wasHandled, context: context);
   }
 
diff --git a/pkg/front_end/lib/src/source/source_library_builder.dart b/pkg/front_end/lib/src/source/source_library_builder.dart
index 89fc1d0..70b2287 100644
--- a/pkg/front_end/lib/src/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/source/source_library_builder.dart
@@ -38,6 +38,7 @@
 import '../base/export.dart' show Export;
 import '../base/identifiers.dart' show Identifier, QualifiedName;
 import '../base/import.dart' show Import;
+import '../base/messages.dart';
 import '../base/modifier.dart'
     show
         abstractMask,
@@ -80,7 +81,6 @@
 import '../builder/record_type_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/void_type_declaration_builder.dart';
-import '../codes/cfe_codes.dart';
 import '../kernel/body_builder_context.dart';
 import '../kernel/hierarchy/members_builder.dart';
 import '../kernel/internal_ast.dart';
@@ -104,9 +104,11 @@
         toKernelCombinators,
         unserializableExportName;
 import '../util/helpers.dart';
+import 'builder_factory.dart';
 import 'class_declaration.dart';
 import 'name_scheme.dart';
 import 'offset_map.dart';
+import 'outline_builder.dart';
 import 'source_class_builder.dart' show SourceClassBuilder;
 import 'source_constructor_builder.dart';
 import 'source_enum_builder.dart';
@@ -120,7 +122,8 @@
 import 'source_procedure_builder.dart';
 import 'source_type_alias_builder.dart';
 
-class SourceCompilationUnitImpl implements SourceCompilationUnit {
+class SourceCompilationUnitImpl
+    implements SourceCompilationUnit, ProblemReporting, BuilderFactory {
   final SourceLibraryBuilder _sourceLibraryBuilder;
 
   SourceLibraryBuilder? _libraryBuilder;
@@ -176,15 +179,6 @@
     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
   void beginNestedDeclaration(TypeParameterScopeKind kind, String name,
       {bool hasMembers = true}) {
@@ -317,6 +311,13 @@
   }
 
   @override
+  OutlineBuilder createOutlineBuilder() {
+    assert(_offsetMap == null, "OffsetMap has already been set for $this");
+    return new OutlineBuilder(
+        this, this, this, _offsetMap = new OffsetMap(fileUri));
+  }
+
+  @override
   SourceLibraryBuilder createLibrary() {
     assert(_libraryBuilder == null,
         "Source library builder as already been created for $this.");
@@ -801,6 +802,26 @@
   }
 
   @override
+  void addSyntheticImport(
+      {required String uri,
+      required String? prefix,
+      required List<CombinatorBuilder>? combinators,
+      required bool deferred}) {
+    addImport(
+        metadata: null,
+        isAugmentationImport: false,
+        uri: uri,
+        configurations: null,
+        prefix: prefix,
+        combinators: combinators,
+        deferred: deferred,
+        charOffset: -1,
+        prefixCharOffset: -1,
+        uriOffset: -1,
+        importIndex: -1);
+  }
+
+  @override
   void addImportsToScope() {
     bool explicitCoreImport = _sourceLibraryBuilder == loader.coreLibrary;
     for (Import import in imports) {
@@ -3230,6 +3251,29 @@
     }
     return count;
   }
+
+  @override
+  void computeShowHideElements(ClassMembersBuilder membersBuilder) {
+    assert(currentTypeParameterScopeBuilder.kind ==
+        TypeParameterScopeKind.library);
+    for (ExtensionBuilder _extensionBuilder
+        in currentTypeParameterScopeBuilder.extensions!) {
+      ExtensionBuilder extensionBuilder = _extensionBuilder;
+      if (extensionBuilder is! SourceExtensionBuilder) continue;
+      DartType onType = extensionBuilder.extension.onType;
+      if (onType is InterfaceType) {
+        // TODO(cstefantsova): Handle private names.
+        List<Supertype> supertypes = membersBuilder.hierarchyBuilder
+            .getNodeFromClass(onType.classNode)
+            .superclasses;
+        Map<String, Supertype> supertypesByName = <String, Supertype>{};
+        for (Supertype supertype in supertypes) {
+          // TODO(cstefantsova): Should only non-generic supertypes be allowed?
+          supertypesByName[supertype.classNode.name] = supertype;
+        }
+      }
+    }
+  }
 }
 
 class SourceLibraryBuilder extends LibraryBuilderImpl {
@@ -5683,25 +5727,7 @@
       }
     }
 
-    assert(compilationUnit.currentTypeParameterScopeBuilder.kind ==
-        TypeParameterScopeKind.library);
-    for (ExtensionBuilder _extensionBuilder
-        in compilationUnit.currentTypeParameterScopeBuilder.extensions!) {
-      ExtensionBuilder extensionBuilder = _extensionBuilder;
-      if (extensionBuilder is! SourceExtensionBuilder) continue;
-      DartType onType = extensionBuilder.extension.onType;
-      if (onType is InterfaceType) {
-        // TODO(cstefantsova): Handle private names.
-        List<Supertype> supertypes = membersBuilder.hierarchyBuilder
-            .getNodeFromClass(onType.classNode)
-            .superclasses;
-        Map<String, Supertype> supertypesByName = <String, Supertype>{};
-        for (Supertype supertype in supertypes) {
-          // TODO(cstefantsova): Should only non-generic supertypes be allowed?
-          supertypesByName[supertype.classNode.name] = supertype;
-        }
-      }
-    }
+    compilationUnit.computeShowHideElements(membersBuilder);
   }
 
   void forEachExtensionInScope(void Function(ExtensionBuilder) f) {
@@ -6228,7 +6254,7 @@
   /// Resolves type variables in [unresolvedNamedTypes] and propagate other
   /// types to [parent].
   void resolveNamedTypes(List<NominalVariableBuilder>? typeVariables,
-      SourceCompilationUnit compilationUnit) {
+      ProblemReporting problemReporting) {
     Map<String, NominalVariableBuilder>? map;
     if (typeVariables != null) {
       map = <String, NominalVariableBuilder>{};
@@ -6259,17 +6285,17 @@
         int nameLength = typeName.fullNameLength;
         Message message = templateNotAPrefixInTypeAnnotation.withArguments(
             qualifier, typeName.name);
-        compilationUnit.addProblem(
+        problemReporting.addProblem(
             message, nameOffset, nameLength, namedTypeBuilder.fileUri!);
         namedTypeBuilder.bind(
-            compilationUnit,
+            problemReporting,
             namedTypeBuilder.buildInvalidTypeDeclarationBuilder(
                 message.withLocation(
                     namedTypeBuilder.fileUri!, nameOffset, nameLength)));
       } else {
         scope ??= toScope(null).withTypeVariables(typeVariables);
         namedTypeBuilder.resolveIn(scope, namedTypeBuilder.charOffset!,
-            namedTypeBuilder.fileUri!, compilationUnit);
+            namedTypeBuilder.fileUri!, problemReporting);
       }
     }
     unresolvedNamedTypes.clear();
diff --git a/pkg/front_end/lib/src/source/source_loader.dart b/pkg/front_end/lib/src/source/source_loader.dart
index 135dbc9..3db2022 100644
--- a/pkg/front_end/lib/src/source/source_loader.dart
+++ b/pkg/front_end/lib/src/source/source_loader.dart
@@ -1152,12 +1152,10 @@
 
   Future<Null> buildOutline(SourceCompilationUnit compilationUnit) async {
     Token tokens = await tokenize(compilationUnit);
-    OffsetMap offsetMap = new OffsetMap(compilationUnit.fileUri);
-    OutlineBuilder listener = new OutlineBuilder(compilationUnit, offsetMap);
+    OutlineBuilder listener = compilationUnit.createOutlineBuilder();
     new ClassMemberParser(listener,
             allowPatterns: compilationUnit.libraryFeatures.patterns.isEnabled)
         .parseUnit(tokens);
-    compilationUnit.offsetMap = offsetMap;
   }
 
   /// Builds all the method bodies found in the given [library].
diff --git a/pkg/front_end/tool/dart_doctest_impl.dart b/pkg/front_end/tool/dart_doctest_impl.dart
index 7c8df3a..87af3a4 100644
--- a/pkg/front_end/tool/dart_doctest_impl.dart
+++ b/pkg/front_end/tool/dart_doctest_impl.dart
@@ -841,33 +841,19 @@
                   combinator.fileOffset, libraryBuilder.fileUri));
         }
 
-        dartDocTestLibrary.compilationUnit.addImport(
-            metadata: null,
-            isAugmentationImport: false,
+        dartDocTestLibrary.compilationUnit.addSyntheticImport(
             uri: dependency.importedLibraryReference.asLibrary.importUri
                 .toString(),
-            configurations: null,
             prefix: dependency.name,
             combinators: combinators,
-            deferred: dependency.isDeferred,
-            charOffset: -1,
-            prefixCharOffset: -1,
-            uriOffset: -1,
-            importIndex: -1);
+            deferred: dependency.isDeferred);
       }
 
-      dartDocTestLibrary.compilationUnit.addImport(
-          metadata: null,
-          isAugmentationImport: false,
+      dartDocTestLibrary.compilationUnit.addSyntheticImport(
           uri: libraryBuilder.importUri.toString(),
-          configurations: null,
           prefix: null,
           combinators: null,
-          deferred: false,
-          charOffset: -1,
-          prefixCharOffset: -1,
-          uriOffset: -1,
-          importIndex: -1);
+          deferred: false);
 
       dartDocTestLibrary.addImportsToScope();
     } else {