[cfe] Create SourceProcedureBuilder through fragments

Change-Id: If7fe7cc1b7779950e2d2a0227dde20c02eafddbf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385440
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/builder/member_builder.dart b/pkg/front_end/lib/src/builder/member_builder.dart
index 2c7ba80..2064e3e 100644
--- a/pkg/front_end/lib/src/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/builder/member_builder.dart
@@ -123,6 +123,7 @@
   @override
   LibraryBuilder get libraryBuilder {
     if (parent is LibraryBuilder) {
+      // Coverage-ignore-block(suite): Not run.
       LibraryBuilder library = parent as LibraryBuilder;
       return library.partOfLibrary ?? library;
     } else if (parent is ExtensionBuilder) {
diff --git a/pkg/front_end/lib/src/fragment/fragment.dart b/pkg/front_end/lib/src/fragment/fragment.dart
index 4611b77..6239b0e 100644
--- a/pkg/front_end/lib/src/fragment/fragment.dart
+++ b/pkg/front_end/lib/src/fragment/fragment.dart
@@ -10,6 +10,7 @@
 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/type_builder.dart';
@@ -19,6 +20,7 @@
 import '../source/source_extension_builder.dart';
 import '../source/source_extension_type_declaration_builder.dart';
 import '../source/source_field_builder.dart';
+import '../source/source_procedure_builder.dart';
 import '../source/source_type_alias_builder.dart';
 import '../source/type_parameter_scope_builder.dart';
 
@@ -525,3 +527,62 @@
   @override
   String toString() => '$runtimeType($name,$fileUri,$charOffset)';
 }
+
+class MethodFragment implements Fragment {
+  final String name;
+  final Uri fileUri;
+  final int startCharOffset;
+  final int charOffset;
+  final int charOpenParenOffset;
+  final int charEndOffset;
+  final List<MetadataBuilder>? metadata;
+  final int modifiers;
+  final TypeBuilder returnType;
+  final List<NominalVariableBuilder>? typeParameters;
+  final List<FormalParameterBuilder>? formals;
+  final ProcedureKind kind;
+  final Reference? procedureReference;
+  final Reference? tearOffReference;
+  final AsyncMarker asyncModifier;
+  final NameScheme nameScheme;
+  final String? nativeMethodName;
+
+  SourceProcedureBuilder? _builder;
+
+  MethodFragment(
+      {required this.name,
+      required this.fileUri,
+      required this.startCharOffset,
+      required this.charOffset,
+      required this.charOpenParenOffset,
+      required this.charEndOffset,
+      required this.metadata,
+      required this.modifiers,
+      required this.returnType,
+      required this.typeParameters,
+      required this.formals,
+      required this.kind,
+      required this.procedureReference,
+      required this.tearOffReference,
+      required this.asyncModifier,
+      required this.nameScheme,
+      required this.nativeMethodName});
+
+  @override
+  SourceProcedureBuilder get builder {
+    assert(
+        _builder != null, // Coverage-ignore(suite): Not run.
+        "Builder has not been computed for $this.");
+    return _builder!;
+  }
+
+  void set builder(SourceProcedureBuilder value) {
+    assert(
+        _builder == null, // Coverage-ignore(suite): Not run.
+        "Builder has already been computed for $this.");
+    _builder = value;
+  }
+
+  @override
+  String toString() => '$runtimeType($name,$fileUri,$charOffset)';
+}
diff --git a/pkg/front_end/lib/src/source/offset_map.dart b/pkg/front_end/lib/src/source/offset_map.dart
index b3cc3f3..6c06b5e 100644
--- a/pkg/front_end/lib/src/source/offset_map.dart
+++ b/pkg/front_end/lib/src/source/offset_map.dart
@@ -26,7 +26,7 @@
   final Map<int, DeclarationFragment> _declarationFragments = {};
   final Map<int, FieldFragment> _fields = {};
   final Map<int, SourceFunctionBuilder> _constructors = {};
-  final Map<int, SourceFunctionBuilder> _procedures = {};
+  final Map<int, MethodFragment> _procedures = {};
   final Map<int, LibraryPart> _parts = {};
   final Map<int, Import> _imports = {};
   final Map<int, Export> _exports = {};
@@ -121,13 +121,13 @@
         identifier.nameOffset);
   }
 
-  void registerProcedure(Identifier identifier, SourceFunctionBuilder builder) {
-    _procedures[identifier.nameOffset] = builder;
+  void registerProcedure(Identifier identifier, MethodFragment fragment) {
+    _procedures[identifier.nameOffset] = fragment;
   }
 
   SourceFunctionBuilder lookupProcedure(Identifier identifier) {
-    return _checkBuilder(_procedures[identifier.nameOffset], identifier.name,
-        identifier.nameOffset);
+    return _checkBuilder(_procedures[identifier.nameOffset]?.builder,
+        identifier.name, identifier.nameOffset);
   }
 
   T _checkDirective<T>(T? directive, String name, int charOffset) {
diff --git a/pkg/front_end/lib/src/source/source_builder_factory.dart b/pkg/front_end/lib/src/source/source_builder_factory.dart
index be0a28f..c491aa8 100644
--- a/pkg/front_end/lib/src/source/source_builder_factory.dart
+++ b/pkg/front_end/lib/src/source/source_builder_factory.dart
@@ -63,7 +63,6 @@
 import 'source_function_builder.dart';
 import 'source_library_builder.dart';
 import 'source_loader.dart' show SourceLoader;
-import 'source_procedure_builder.dart';
 import 'type_parameter_scope_builder.dart';
 
 class BuilderFactoryImpl implements BuilderFactory, BuilderFactoryResult {
@@ -125,6 +124,8 @@
 
   final List<SourceFunctionBuilder> _nativeMethods = [];
 
+  final List<MethodFragment> _nativeMethodFragments = [];
+
   final LibraryName libraryName;
 
   final LookupScope _compilationUnitScope;
@@ -2124,6 +2125,10 @@
     return suffix;
   }
 
+  void _addNativeMethodFragment(MethodFragment fragment) {
+    _nativeMethodFragments.add(fragment);
+  }
+
   void _addNativeMethod(SourceFunctionBuilder method) {
     _nativeMethods.add(method);
   }
@@ -2203,34 +2208,32 @@
         }
       }
     }
-    SourceProcedureBuilder procedureBuilder = new SourceProcedureBuilder(
-        metadata,
-        modifiers,
-        returnType ?? addInferableType(),
-        name,
-        typeVariables,
-        formals,
-        kind,
-        _parent,
-        _compilationUnit.fileUri,
-        startCharOffset,
-        charOffset,
-        charOpenParenOffset,
-        charEndOffset,
-        procedureReference,
-        tearOffReference,
-        asyncModifier,
-        nameScheme,
+    MethodFragment fragment = new MethodFragment(
+        name: name,
+        fileUri: _compilationUnit.fileUri,
+        startCharOffset: startCharOffset,
+        charOffset: charOffset,
+        charOpenParenOffset: charOpenParenOffset,
+        charEndOffset: charEndOffset,
+        metadata: metadata,
+        modifiers: modifiers,
+        returnType: returnType ?? addInferableType(),
+        typeParameters: typeVariables,
+        formals: formals,
+        kind: kind,
+        procedureReference: procedureReference,
+        tearOffReference: tearOffReference,
+        asyncModifier: asyncModifier,
+        nameScheme: nameScheme,
         nativeMethodName: nativeMethodName);
     _nominalParameterNameSpaces.pop().addTypeVariables(
         _problemReporting, typeVariables,
-        ownerName: procedureBuilder.name, allowNameConflict: true);
-    _addBuilder(name, procedureBuilder, charOffset,
-        getterReference: procedureReference);
+        ownerName: name, allowNameConflict: true);
+    _addFragment(fragment, getterReference: procedureReference);
     if (nativeMethodName != null) {
-      _addNativeMethod(procedureBuilder);
+      _addNativeMethodFragment(fragment);
     }
-    offsetMap.registerProcedure(identifier, procedureBuilder);
+    offsetMap.registerProcedure(identifier, fragment);
   }
 
   @override
@@ -2662,6 +2665,7 @@
       loader.buildersCreatedWithReferences[setterReference] = declaration;
     }
     if (_declarationFragments.isEmpty) {
+      // Coverage-ignore-block(suite): Not run.
       _libraryNameSpaceBuilder.addBuilder(
           name, declaration, _compilationUnit.fileUri, charOffset);
     } else {
@@ -2742,6 +2746,9 @@
     for (SourceFunctionBuilder method in _nativeMethods) {
       method.becomeNative(loader);
     }
+    for (MethodFragment fragment in _nativeMethodFragments) {
+      fragment.builder.becomeNative(loader);
+    }
     return _nativeMethods.length;
   }
 
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart
index d87e951..2429e3b 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -408,6 +408,7 @@
         /* formals = */ null,
         ProcedureKind.Method,
         libraryBuilder,
+        this,
         fileUri,
         charOffset,
         charOffset,
diff --git a/pkg/front_end/lib/src/source/source_function_builder.dart b/pkg/front_end/lib/src/source/source_function_builder.dart
index 2c6a53d..41e34d6 100644
--- a/pkg/front_end/lib/src/source/source_function_builder.dart
+++ b/pkg/front_end/lib/src/source/source_function_builder.dart
@@ -8,20 +8,8 @@
 import 'package:kernel/class_hierarchy.dart';
 
 import '../api_prototype/lowering_predicates.dart';
-import '../base/local_scope.dart';
-import '../builder/builder.dart';
-import '../builder/constructor_builder.dart';
-import '../builder/declaration_builders.dart';
-import '../builder/formal_parameter_builder.dart';
-import '../builder/function_builder.dart';
-import '../builder/library_builder.dart';
-import '../builder/member_builder.dart';
-import '../builder/metadata_builder.dart';
-import '../builder/omitted_type_builder.dart';
-import '../builder/type_builder.dart';
 import '../base/identifiers.dart';
-import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-import '../kernel/kernel_helper.dart';
+import '../base/local_scope.dart';
 import '../base/messages.dart'
     show
         messagePatchDeclarationMismatch,
@@ -31,11 +19,22 @@
         templateRequiredNamedParameterHasDefaultValueError;
 import '../base/modifier.dart';
 import '../base/scope.dart';
-import 'source_loader.dart' show SourceLoader;
+import '../builder/builder.dart';
+import '../builder/constructor_builder.dart';
+import '../builder/declaration_builders.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/function_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/omitted_type_builder.dart';
+import '../builder/type_builder.dart';
+import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
+import '../kernel/kernel_helper.dart';
 import '../type_inference/type_inference_engine.dart'
     show IncludesTypeParametersNonCovariantly;
 import 'source_builder_mixins.dart';
 import 'source_extension_type_declaration_builder.dart';
+import 'source_loader.dart' show SourceLoader;
 import 'source_member_builder.dart';
 
 abstract class SourceFunctionBuilder
@@ -155,11 +154,11 @@
       this.name,
       this.typeVariables,
       this.formals,
-      LibraryBuilder compilationUnit,
+      Builder parent,
       Uri fileUri,
       int charOffset,
       this.nativeMethodName)
-      : super(compilationUnit, fileUri, charOffset) {
+      : super(parent, fileUri, charOffset) {
     returnType.registerInferredTypeListener(this);
     if (formals != null) {
       for (int i = 0; i < formals!.length; i++) {
diff --git a/pkg/front_end/lib/src/source/source_loader.dart b/pkg/front_end/lib/src/source/source_loader.dart
index e569f42..694cf3c 100644
--- a/pkg/front_end/lib/src/source/source_loader.dart
+++ b/pkg/front_end/lib/src/source/source_loader.dart
@@ -1383,6 +1383,7 @@
         /* formals = */ null,
         ProcedureKind.Method,
         libraryBuilder,
+        null,
         libraryBuilder.fileUri,
         /* start char offset = */ 0,
         /* char offset = */ 0,
diff --git a/pkg/front_end/lib/src/source/source_procedure_builder.dart b/pkg/front_end/lib/src/source/source_procedure_builder.dart
index 1fcb101..91d2d99 100644
--- a/pkg/front_end/lib/src/source/source_procedure_builder.dart
+++ b/pkg/front_end/lib/src/source/source_procedure_builder.dart
@@ -31,6 +31,9 @@
 
 class SourceProcedureBuilder extends SourceFunctionBuilderImpl
     implements ProcedureBuilder {
+  @override
+  final SourceLibraryBuilder libraryBuilder;
+
   final int charOpenParenOffset;
 
   AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
@@ -84,7 +87,8 @@
       List<NominalVariableBuilder>? typeVariables,
       List<FormalParameterBuilder>? formals,
       this.kind,
-      SourceLibraryBuilder libraryBuilder,
+      this.libraryBuilder,
+      DeclarationBuilder? declarationBuilder,
       Uri fileUri,
       int startCharOffset,
       int charOffset,
@@ -102,8 +106,16 @@
         this.isExtensionTypeInstanceMember =
             nameScheme.isInstanceMember && nameScheme.isExtensionTypeMember,
         _memberName = nameScheme.getDeclaredName(name),
-        super(metadata, modifiers, name, typeVariables, formals, libraryBuilder,
-            fileUri, charOffset, nativeMethodName) {
+        super(
+            metadata,
+            modifiers,
+            name,
+            typeVariables,
+            formals,
+            declarationBuilder ?? libraryBuilder,
+            fileUri,
+            charOffset,
+            nativeMethodName) {
     _procedure = new Procedure(
         dummyName,
         isExtensionInstanceMember || isExtensionTypeInstanceMember
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index 31e0a24..6b5cd46 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -25,6 +25,7 @@
 import 'source_field_builder.dart';
 import 'source_library_builder.dart';
 import 'source_loader.dart';
+import 'source_procedure_builder.dart';
 import 'source_type_alias_builder.dart';
 
 sealed class _Added {
@@ -383,6 +384,30 @@
         fragment.builder = fieldBuilder;
         builders.add(new _AddBuilder(fragment.name, fieldBuilder,
             fragment.fileUri, fragment.charOffset));
+      case MethodFragment():
+        SourceProcedureBuilder procedureBuilder = new SourceProcedureBuilder(
+            fragment.metadata,
+            fragment.modifiers,
+            fragment.returnType,
+            fragment.name,
+            fragment.typeParameters,
+            fragment.formals,
+            fragment.kind,
+            enclosingLibraryBuilder,
+            declarationBuilder,
+            fragment.fileUri,
+            fragment.startCharOffset,
+            fragment.charOffset,
+            fragment.charOpenParenOffset,
+            fragment.charEndOffset,
+            fragment.procedureReference,
+            fragment.tearOffReference,
+            fragment.asyncModifier,
+            fragment.nameScheme,
+            nativeMethodName: fragment.nativeMethodName);
+        fragment.builder = procedureBuilder;
+        builders.add(new _AddBuilder(fragment.name, procedureBuilder,
+            fragment.fileUri, fragment.charOffset));
     }
   }
 }
@@ -394,6 +419,7 @@
 
   List<_Added> _added = [];
 
+  // Coverage-ignore(suite): Not run.
   void addBuilder(
       String name, Builder declaration, Uri fileUri, int charOffset) {
     _added.add(new _AddedBuilder(
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index 3a7568d..a657052 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -325,7 +325,7 @@
   ),
   // 100.0%.
   "package:front_end/src/builder/member_builder.dart": (
-    hitCount: 148,
+    hitCount: 146,
     missCount: 0,
   ),
   // 100.0%.
@@ -480,7 +480,7 @@
   ),
   // 100.0%.
   "package:front_end/src/fragment/fragment.dart": (
-    hitCount: 96,
+    hitCount: 103,
     missCount: 0,
   ),
   // 100.0%.
@@ -790,7 +790,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/offset_map.dart": (
-    hitCount: 121,
+    hitCount: 122,
     missCount: 0,
   ),
   // 100.0%.
@@ -805,7 +805,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_builder_factory.dart": (
-    hitCount: 1399,
+    hitCount: 1401,
     missCount: 0,
   ),
   // 100.0%.
@@ -891,7 +891,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/type_parameter_scope_builder.dart": (
-    hitCount: 524,
+    hitCount: 544,
     missCount: 0,
   ),
   // 100.0%.